@shop-os/modelkit 0.2.27 → 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/dist/index.cjs CHANGED
@@ -50,6 +50,7 @@ __export(index_exports, {
50
50
  SURFACES: () => SURFACES2,
51
51
  SurfaceSchema: () => SurfaceSchema,
52
52
  VIDEO_INPUT_SPEC_KEYS: () => VIDEO_INPUT_SPEC_KEYS,
53
+ VIDEO_TOOL_MODELS: () => VIDEO_TOOL_MODELS,
53
54
  adapterServesType: () => adapterServesType,
54
55
  aiSdkTextAdapter: () => aiSdkTextAdapter,
55
56
  arkAdapter: () => arkAdapter,
@@ -63,6 +64,7 @@ __export(index_exports, {
63
64
  describeThrown: () => describeThrown,
64
65
  experimental_generateImage: () => generateImage,
65
66
  falAdapter: () => falAdapter,
67
+ falWebhookBodySchema: () => falWebhookBodySchema,
66
68
  fileCatalogCache: () => fileCatalogCache,
67
69
  generateAudio: () => generateAudio,
68
70
  generateImage: () => generateImage,
@@ -87,6 +89,7 @@ __export(index_exports, {
87
89
  normalizeExposure: () => normalizeExposure,
88
90
  openaiImageAdapter: () => openaiImageAdapter,
89
91
  passthroughTextModel: () => passthroughTextModel,
92
+ planVideoTool: () => planVideoTool,
90
93
  pollUntil: () => pollUntil,
91
94
  prepareMediaPart: () => prepareMediaPart,
92
95
  primeCatalog: () => primeCatalog,
@@ -94,6 +97,7 @@ __export(index_exports, {
94
97
  readErrorBody: () => readErrorBody,
95
98
  replicateAdapter: () => replicateAdapter,
96
99
  resetLiveCatalog: () => resetLiveCatalog,
100
+ resolutionTier: () => resolutionTier,
97
101
  resolveAudioOptions: () => resolveAudioOptions,
98
102
  resolveImageOptions: () => resolveImageOptions,
99
103
  resolveKeys: () => resolveKeys,
@@ -107,6 +111,7 @@ __export(index_exports, {
107
111
  toGeneratedImage: () => toGeneratedImage,
108
112
  validateInputSpec: () => validateInputSpec,
109
113
  videoLengthViolation: () => videoLengthViolation,
114
+ videoToolConstraints: () => videoToolConstraints,
110
115
  withRetry: () => withRetry,
111
116
  xaiVideoAdapter: () => xaiVideoAdapter
112
117
  });
@@ -1416,6 +1421,11 @@ var NEGATIVE_PROMPT = "blur, distort, and low quality";
1416
1421
  var FRAMES_EXCLUDE_REFERENCES = { framesExcludeReferences: true };
1417
1422
  var KLING_PROMPT = { referenceSyntax: "numbered", maxChars: 2500 };
1418
1423
  var SEEDANCE_PROMPT = { referenceSyntax: "numbered", maxChars: 3e4 };
1424
+ var SEEDANCE_2_AUDIO = {
1425
+ audioSeconds: { min: 2, max: 15, total: 15 },
1426
+ audioFormats: ["wav", "mp3"],
1427
+ audioMaxBytes: 15 * 1024 * 1024
1428
+ };
1419
1429
  var H3_PROMPT = { referenceSyntax: "numbered", maxChars: 5e4 };
1420
1430
  var OMNI_PROMPT = { referenceSyntax: "caption", maxChars: 5e4 };
1421
1431
  var BYTEDANCE_LOGO = "https://d31vvfpk2ppdyq.cloudfront.net/assets/image/3bba5d81-4e57-4e71-911b-cdfa05acca2c_compressed.png";
@@ -1552,7 +1562,7 @@ var VIDEO_MODELS = [
1552
1562
  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.",
1553
1563
  logo: GOOGLE_LOGO2
1554
1564
  },
1555
- capabilities: { acceptsSourceVideo: true }
1565
+ capabilities: { acceptsSourceVideo: true, videoEdit: true }
1556
1566
  },
1557
1567
  {
1558
1568
  id: "gemini-omni-1.1-flash",
@@ -1577,7 +1587,7 @@ var VIDEO_MODELS = [
1577
1587
  // with a video task, so those calls carry the prompt alone).
1578
1588
  // First-to-last-frame interpolation: `<LAST_FRAME>` goes with `<FIRST_FRAME>`.
1579
1589
  supports: ["videoExtension", "lastFrame"],
1580
- extension: { segmentSeconds: 10, maxTotalSeconds: 40 },
1590
+ extension: { segmentSeconds: 10, maxTotalSeconds: 40, returns: "joined" },
1581
1591
  prompt: OMNI_PROMPT,
1582
1592
  audio: "always"
1583
1593
  },
@@ -1589,7 +1599,11 @@ var VIDEO_MODELS = [
1589
1599
  logo: GOOGLE_LOGO2,
1590
1600
  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."
1591
1601
  },
1592
- capabilities: { acceptsSourceVideo: true, lastFrameRequiresFirstFrame: true }
1602
+ capabilities: {
1603
+ acceptsSourceVideo: true,
1604
+ videoEdit: true,
1605
+ lastFrameRequiresFirstFrame: true
1606
+ }
1593
1607
  },
1594
1608
  {
1595
1609
  // vibe-triggers and Space Builder drop the ratio when a frame is wired; Cowork always sends it.
@@ -1611,7 +1625,8 @@ var VIDEO_MODELS = [
1611
1625
  videos: 3,
1612
1626
  audios: 3,
1613
1627
  audioOnly: false,
1614
- videoSeconds: { min: 2, max: 15, total: 15 }
1628
+ videoSeconds: { min: 2, max: 15, total: 15 },
1629
+ ...SEEDANCE_2_AUDIO
1615
1630
  },
1616
1631
  sourceVideoSeconds: { min: 2, max: 15, inReferenceTotal: true },
1617
1632
  ratioIgnoredWith: ["firstFrame", "sourceVideo"],
@@ -1633,7 +1648,7 @@ var VIDEO_MODELS = [
1633
1648
  description: "High-quality AI video generation with reference image conditioning. Supports 4-15 second clips with human preprocessing.",
1634
1649
  logo: BYTEDANCE_LOGO
1635
1650
  },
1636
- capabilities: { acceptsSourceVideo: true, ...FRAMES_EXCLUDE_REFERENCES }
1651
+ capabilities: { acceptsSourceVideo: true, videoEdit: false, ...FRAMES_EXCLUDE_REFERENCES }
1637
1652
  },
1638
1653
  {
1639
1654
  id: "seedance-2.0-fast",
@@ -1653,7 +1668,8 @@ var VIDEO_MODELS = [
1653
1668
  videos: 3,
1654
1669
  audios: 3,
1655
1670
  audioOnly: false,
1656
- videoSeconds: { min: 2, max: 15, total: 15 }
1671
+ videoSeconds: { min: 2, max: 15, total: 15 },
1672
+ ...SEEDANCE_2_AUDIO
1657
1673
  },
1658
1674
  sourceVideoSeconds: { min: 2, max: 15, inReferenceTotal: true },
1659
1675
  ratioIgnoredWith: ["firstFrame", "sourceVideo"],
@@ -1675,7 +1691,7 @@ var VIDEO_MODELS = [
1675
1691
  logo: BYTEDANCE_LOGO,
1676
1692
  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."
1677
1693
  },
1678
- capabilities: { acceptsSourceVideo: true, ...FRAMES_EXCLUDE_REFERENCES }
1694
+ capabilities: { acceptsSourceVideo: true, videoEdit: false, ...FRAMES_EXCLUDE_REFERENCES }
1679
1695
  },
1680
1696
  {
1681
1697
  // omni_reference_task_type edit/extend: adaptive ratio, edit sends duration -1.
@@ -1695,12 +1711,20 @@ var VIDEO_MODELS = [
1695
1711
  images: 30,
1696
1712
  videos: 10,
1697
1713
  audios: 10,
1698
- videoSeconds: { min: 2, max: 30, total: 30, editMin: 4 }
1714
+ videoSeconds: { min: 2, max: 30, total: 30, editMin: 4 },
1715
+ // BytePlus: 2-30 s per clip, 30 s in all, wav/mp3, 15 MB each.
1716
+ audioSeconds: { min: 2, max: 30, total: 30 },
1717
+ audioFormats: ["wav", "mp3"],
1718
+ audioMaxBytes: 15 * 1024 * 1024
1699
1719
  },
1700
1720
  sourceVideoSeconds: { min: 2, max: 30, editMin: 4, inReferenceTotal: true },
1701
1721
  ratioIgnoredWith: ["firstFrame", "sourceVideo"],
1702
1722
  // No seed: 2.x echoes it but does not honour it (two seeded runs differed, 2026-10-01).
1703
- supports: ["generateAudio", "lastFrame", "watermark", "taskType"],
1723
+ supports: ["generateAudio", "lastFrame", "watermark", "taskType", "videoExtension"],
1724
+ // Extend (probe 2026-10-02, 480p): returns ONLY the added footage, continuing from
1725
+ // the source's last frame at the source's framing and fps but at the requested
1726
+ // resolution, so the caller joins the clips. Forward only in practice.
1727
+ extension: { segmentSeconds: 30, maxTotalSeconds: 60, returns: "new" },
1704
1728
  prompt: SEEDANCE_PROMPT,
1705
1729
  audio: "optional"
1706
1730
  },
@@ -1717,7 +1741,7 @@ var VIDEO_MODELS = [
1717
1741
  logo: BYTEDANCE_LOGO,
1718
1742
  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."
1719
1743
  },
1720
- capabilities: { acceptsSourceVideo: true, ...FRAMES_EXCLUDE_REFERENCES }
1744
+ capabilities: { acceptsSourceVideo: true, videoEdit: true, ...FRAMES_EXCLUDE_REFERENCES }
1721
1745
  },
1722
1746
  {
1723
1747
  id: "grok-imagine",
@@ -2081,11 +2105,116 @@ var VIDEO_MODELS = [
2081
2105
  }
2082
2106
  ];
2083
2107
 
2108
+ // src/catalog/video-tools.ts
2109
+ var TOPAZ_LOGO = "https://cdn.jsdelivr.net/npm/@lobehub/icons-static-png@1.97.0/light/topazlabs.png";
2110
+ var TOPAZ_SOURCE_SECONDS = { max: 300 };
2111
+ var TOPAZ_USAGE = { unit: "seconds" };
2112
+ var VIDEO_TOOL_MODELS = [
2113
+ {
2114
+ id: "topaz-precision",
2115
+ aliases: [],
2116
+ label: "Topaz Precision",
2117
+ type: "video-tool",
2118
+ adapter: "fal",
2119
+ providerModelId: "topaz/upscale/video/precision",
2120
+ lifecycle: "active",
2121
+ exposure: ["cowork"],
2122
+ constraints: {
2123
+ supports: [],
2124
+ sourceVideoSeconds: TOPAZ_SOURCE_SECONDS,
2125
+ tool: { kind: "upscale", upscaleFactor: { min: 1, max: 4 }, maxOutputLongEdge: 3840 }
2126
+ },
2127
+ defaults: {},
2128
+ providerOptions: { fal: { model: "Proteus" } },
2129
+ usage: TOPAZ_USAGE,
2130
+ pricingKind: "video_per_second",
2131
+ display: {
2132
+ provider: "topaz",
2133
+ logo: TOPAZ_LOGO,
2134
+ description: "Topaz Proteus upscaling: sharper, cleaner footage up to 4K while staying faithful to the source.",
2135
+ sortOrder: 20
2136
+ }
2137
+ },
2138
+ {
2139
+ id: "topaz-starlight",
2140
+ aliases: [],
2141
+ label: "Topaz Starlight",
2142
+ type: "video-tool",
2143
+ adapter: "fal",
2144
+ providerModelId: "topaz/upscale/video/generative",
2145
+ lifecycle: "active",
2146
+ exposure: ["cowork"],
2147
+ constraints: {
2148
+ supports: [],
2149
+ sourceVideoSeconds: TOPAZ_SOURCE_SECONDS,
2150
+ tool: { kind: "upscale", upscaleFactor: { min: 1, max: 4 }, maxOutputLongEdge: 3840 }
2151
+ },
2152
+ defaults: {},
2153
+ providerOptions: { fal: { model: "Starlight Precise 2.6" } },
2154
+ usage: TOPAZ_USAGE,
2155
+ pricingKind: "video_per_second",
2156
+ display: {
2157
+ provider: "topaz",
2158
+ logo: TOPAZ_LOGO,
2159
+ description: "Topaz Starlight Precise 2.6: generative upscaling that rebuilds fine detail, up to 4K. Slower and costlier than Precision.",
2160
+ sortOrder: 10
2161
+ }
2162
+ },
2163
+ {
2164
+ id: "topaz-apollo",
2165
+ aliases: [],
2166
+ label: "Topaz Apollo",
2167
+ type: "video-tool",
2168
+ adapter: "fal",
2169
+ providerModelId: "topaz/interpolate/video",
2170
+ lifecycle: "active",
2171
+ exposure: ["cowork"],
2172
+ constraints: {
2173
+ supports: [],
2174
+ sourceVideoSeconds: TOPAZ_SOURCE_SECONDS,
2175
+ tool: { kind: "interpolate", fps: { min: 16, max: 120 } }
2176
+ },
2177
+ defaults: {},
2178
+ providerOptions: { fal: { model: "Apollo" } },
2179
+ usage: TOPAZ_USAGE,
2180
+ pricingKind: "video_per_second",
2181
+ display: {
2182
+ provider: "topaz",
2183
+ logo: TOPAZ_LOGO,
2184
+ description: "Topaz Apollo frame interpolation: smoother motion at up to 120 fps, same length as the source."
2185
+ }
2186
+ },
2187
+ {
2188
+ id: "topaz-hyperion-2.5",
2189
+ aliases: [],
2190
+ label: "Topaz Hyperion 2.5",
2191
+ type: "video-tool",
2192
+ adapter: "fal",
2193
+ providerModelId: "topaz/sdr-to-hdr/video",
2194
+ lifecycle: "active",
2195
+ exposure: ["cowork"],
2196
+ constraints: {
2197
+ supports: [],
2198
+ sourceVideoSeconds: TOPAZ_SOURCE_SECONDS,
2199
+ tool: { kind: "hdr", outputFormats: ["h265", "prores"] }
2200
+ },
2201
+ defaults: {},
2202
+ usage: TOPAZ_USAGE,
2203
+ pricingKind: "video_per_second",
2204
+ display: {
2205
+ provider: "topaz",
2206
+ logo: TOPAZ_LOGO,
2207
+ 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."
2208
+ }
2209
+ }
2210
+ ];
2211
+
2084
2212
  // src/catalog/models.ts
2085
2213
  var MODELS = [
2086
2214
  ...TEXT_MODELS,
2087
2215
  ...IMAGE_MODELS,
2088
2216
  ...VIDEO_MODELS,
2217
+ ...VIDEO_TOOL_MODELS,
2089
2218
  ...OTHER_MODELS
2090
2219
  ];
2091
2220
 
@@ -2382,7 +2511,15 @@ var ADAPTER_IDS = [
2382
2511
  "higgsfield",
2383
2512
  "xai-video"
2384
2513
  ];
2385
- var ModelTypeSchema = import_zod3.z.enum(["text", "image", "video", "audio", "upscale", "bg-remove"]);
2514
+ var ModelTypeSchema = import_zod3.z.enum([
2515
+ "text",
2516
+ "image",
2517
+ "video",
2518
+ "audio",
2519
+ "upscale",
2520
+ "bg-remove",
2521
+ "video-tool"
2522
+ ]);
2386
2523
  var LifecycleSchema = import_zod3.z.enum(["active", "deprecated", "retired"]);
2387
2524
  var SurfaceSchema = import_zod3.z.enum(["cowork", "space_builder"]);
2388
2525
  var SURFACES2 = SurfaceSchema.options;
@@ -2462,7 +2599,22 @@ var ReferenceLimitsSchema = import_zod3.z.looseObject({
2462
2599
  audios: import_zod3.z.number().optional(),
2463
2600
  total: import_zod3.z.number().optional(),
2464
2601
  audioOnly: import_zod3.z.boolean().optional(),
2465
- videoSeconds: VideoSecondsLimitsSchema.optional()
2602
+ videoSeconds: VideoSecondsLimitsSchema.optional(),
2603
+ audioSeconds: import_zod3.z.looseObject({
2604
+ min: import_zod3.z.number().optional(),
2605
+ max: import_zod3.z.number().optional(),
2606
+ total: import_zod3.z.number().optional()
2607
+ }).optional(),
2608
+ audioFormats: import_zod3.z.array(import_zod3.z.string()).optional(),
2609
+ audioMaxBytes: import_zod3.z.number().positive().optional()
2610
+ });
2611
+ var RangeSchema = import_zod3.z.looseObject({ min: import_zod3.z.number(), max: import_zod3.z.number() });
2612
+ var VideoToolConstraintsSchema = import_zod3.z.looseObject({
2613
+ kind: import_zod3.z.enum(["upscale", "interpolate", "hdr"]),
2614
+ upscaleFactor: RangeSchema.optional(),
2615
+ maxOutputLongEdge: import_zod3.z.number().positive().optional(),
2616
+ fps: RangeSchema.optional(),
2617
+ outputFormats: import_zod3.z.array(import_zod3.z.enum(["h265", "prores"])).min(1).optional()
2466
2618
  });
2467
2619
  var ModelConstraintsSchema = import_zod3.z.looseObject({
2468
2620
  aspectRatios: import_zod3.z.array(AspectRatioSchema).optional(),
@@ -2477,7 +2629,14 @@ var ModelConstraintsSchema = import_zod3.z.looseObject({
2477
2629
  supports: import_zod3.z.array(SupportedOptionSchema).optional(),
2478
2630
  ratioIgnoredWith: import_zod3.z.array(import_zod3.z.enum(["firstFrame", "sourceVideo"])).optional(),
2479
2631
  sourceVideoSeconds: VideoSecondsLimitsSchema.omit({ total: true }).extend({ inReferenceTotal: import_zod3.z.boolean().optional() }).optional(),
2480
- extension: import_zod3.z.looseObject({ segmentSeconds: import_zod3.z.number(), maxTotalSeconds: import_zod3.z.number() }).optional(),
2632
+ // segmentSeconds/maxTotalSeconds stay required: a kit before 0.3.0 drops a row whose
2633
+ // extension lacks them, so every extension block keeps them.
2634
+ extension: import_zod3.z.looseObject({
2635
+ segmentSeconds: import_zod3.z.number(),
2636
+ maxTotalSeconds: import_zod3.z.number(),
2637
+ returns: import_zod3.z.enum(["new", "joined"]).optional()
2638
+ }).optional(),
2639
+ tool: VideoToolConstraintsSchema.optional(),
2481
2640
  // Loose on purpose: the read path keeps a row whose value is invalid (the accessors in
2482
2641
  // conventions.ts read it as "not set"); CatalogModelSchema below rejects it on write.
2483
2642
  audio: import_zod3.z.unknown().optional(),
@@ -2549,6 +2708,7 @@ var CatalogDisplaySchema = import_zod3.z.looseObject({
2549
2708
  });
2550
2709
  var CatalogCapabilitiesSchema = import_zod3.z.looseObject({
2551
2710
  acceptsSourceVideo: import_zod3.z.boolean().optional(),
2711
+ videoEdit: import_zod3.z.boolean().optional(),
2552
2712
  framesExcludeReferences: import_zod3.z.boolean().optional(),
2553
2713
  lastFrameRequiresFirstFrame: import_zod3.z.boolean().optional(),
2554
2714
  reasoning: import_zod3.z.boolean().optional(),
@@ -2591,6 +2751,13 @@ var CatalogModelSchemaBase = import_zod3.z.looseObject({
2591
2751
  message: "active text rows need contextWindow"
2592
2752
  });
2593
2753
  }
2754
+ if (row.type === "video-tool" && row.constraints.tool === void 0) {
2755
+ ctx.addIssue({
2756
+ code: "custom",
2757
+ path: ["constraints", "tool"],
2758
+ message: "video-tool rows need constraints.tool"
2759
+ });
2760
+ }
2594
2761
  if (row.replacedBy !== void 0 && row.replacedBy === row.id) {
2595
2762
  ctx.addIssue({
2596
2763
  code: "custom",
@@ -3597,7 +3764,7 @@ async function generateSeedanceVideo(req, ctx) {
3597
3764
  }
3598
3765
 
3599
3766
  // src/adapters/fal.ts
3600
- var import_zod9 = require("zod");
3767
+ var import_zod12 = require("zod");
3601
3768
  var import_client = require("@fal-ai/client");
3602
3769
 
3603
3770
  // src/adapters/fal-http.ts
@@ -3685,6 +3852,364 @@ function createFalHttpClient(opts) {
3685
3852
  };
3686
3853
  }
3687
3854
 
3855
+ // src/adapters/fal-gateway.ts
3856
+ var import_zod9 = require("zod");
3857
+ var falDetailSchema = import_zod9.z.object({ detail: JsonValueSchema });
3858
+ function liftDetail(body) {
3859
+ const parsed = falDetailSchema.safeParse(body);
3860
+ const detail = parsed.success ? parsed.data.detail : void 0;
3861
+ return detail ?? body;
3862
+ }
3863
+ function falError(status, body, model) {
3864
+ return classifyHttpError(status, liftDetail(body), "fal", model);
3865
+ }
3866
+ function gatewayConfig(ctx) {
3867
+ const cf = ctx.routing.cloudflare;
3868
+ const falKey = ctx.keys.fal;
3869
+ const cfToken = ctx.keys.cloudflare;
3870
+ if (!cf?.accountId || !cf?.gatewayId || !falKey && !cfToken) {
3871
+ throw new ModelKitError({
3872
+ code: "auth",
3873
+ message: "fal passthrough is not configured. Set routing.cloudflare and FAL_KEY or the gateway token (BYOK).",
3874
+ provider: "fal",
3875
+ model: ctx.model.id,
3876
+ retryable: false
3877
+ });
3878
+ }
3879
+ const config = {
3880
+ baseUrl: `https://gateway.ai.cloudflare.com/v1/${cf.accountId}/${cf.gatewayId}/fal`
3881
+ };
3882
+ if (falKey) config.falKey = falKey;
3883
+ if (cfToken) config.cfToken = cfToken;
3884
+ if (ctx.call.maxRetries !== void 0) config.singleAttempt = true;
3885
+ if (ctx.signal !== void 0) config.signal = ctx.signal;
3886
+ return config;
3887
+ }
3888
+ async function gatewayFetch(cfg, fetchImpl, targetUrl, init) {
3889
+ const headers2 = { "x-fal-target-url": targetUrl };
3890
+ if (cfg.falKey) headers2.Authorization = `Bearer ${cfg.falKey}`;
3891
+ if (init.body) headers2["Content-Type"] = "application/json";
3892
+ if (cfg.cfToken) headers2["cf-aig-authorization"] = `Bearer ${cfg.cfToken}`;
3893
+ if (cfg.singleAttempt) headers2["cf-aig-max-attempts"] = "1";
3894
+ const request = { method: init.method, headers: headers2 };
3895
+ if (cfg.signal !== void 0) request.signal = cfg.signal;
3896
+ if (init.body !== void 0) request.body = init.body;
3897
+ return fetchImpl(cfg.baseUrl, request);
3898
+ }
3899
+
3900
+ // src/adapters/fal-video-tools.ts
3901
+ var import_zod11 = require("zod");
3902
+
3903
+ // src/catalog/video-tools-spec.ts
3904
+ var import_zod10 = require("zod");
3905
+ var RangeSchema2 = import_zod10.z.object({ min: import_zod10.z.number(), max: import_zod10.z.number() });
3906
+ var ToolSchema = import_zod10.z.object({
3907
+ kind: import_zod10.z.enum(["upscale", "interpolate", "hdr"]),
3908
+ upscaleFactor: RangeSchema2.optional(),
3909
+ maxOutputLongEdge: import_zod10.z.number().positive().optional(),
3910
+ fps: RangeSchema2.optional(),
3911
+ outputFormats: import_zod10.z.array(import_zod10.z.enum(["h265", "prores"])).min(1).optional()
3912
+ });
3913
+ function videoToolConstraints(row) {
3914
+ if (row.type !== "video-tool") return void 0;
3915
+ const parsed = ToolSchema.safeParse(row.constraints.tool);
3916
+ if (!parsed.success) return void 0;
3917
+ const { kind, upscaleFactor, maxOutputLongEdge, fps, outputFormats } = parsed.data;
3918
+ return {
3919
+ kind,
3920
+ ...upscaleFactor !== void 0 && { upscaleFactor },
3921
+ ...maxOutputLongEdge !== void 0 && { maxOutputLongEdge },
3922
+ ...fps !== void 0 && { fps },
3923
+ ...outputFormats !== void 0 && { outputFormats }
3924
+ };
3925
+ }
3926
+ function resolutionTier(width, height) {
3927
+ const shortEdge = Math.min(width, height);
3928
+ if (shortEdge <= 360) return "360p";
3929
+ if (shortEdge <= 480) return "480p";
3930
+ if (shortEdge <= 720) return "720p";
3931
+ if (shortEdge <= 1080) return "1080p";
3932
+ if (shortEdge <= 1440) return "2k";
3933
+ return "4k";
3934
+ }
3935
+ function fail(error) {
3936
+ return { ok: false, error };
3937
+ }
3938
+ function planVideoTool(row, req) {
3939
+ const tool = videoToolConstraints(row);
3940
+ if (!tool) return fail(`${row.id} is not a video tool`);
3941
+ const { width, height, durationSeconds, fps } = req.source;
3942
+ if (!(width > 0 && height > 0 && durationSeconds > 0)) {
3943
+ return fail("The source video's width, height and duration are required");
3944
+ }
3945
+ const maxSeconds = row.constraints.sourceVideoSeconds?.max;
3946
+ if (maxSeconds !== void 0 && durationSeconds > maxSeconds) {
3947
+ return fail(`${row.label} takes source videos up to ${maxSeconds} seconds.`);
3948
+ }
3949
+ const base = {
3950
+ durationSeconds,
3951
+ ...fps !== void 0 && { fps }
3952
+ };
3953
+ if (tool.kind === "upscale") {
3954
+ const factor = req.upscaleFactor;
3955
+ if (factor === void 0) return fail("An upscale factor is required");
3956
+ const range = tool.upscaleFactor;
3957
+ if (range && (factor < range.min || factor > range.max)) {
3958
+ return fail(`${row.label} upscales by ${range.min}x to ${range.max}x.`);
3959
+ }
3960
+ const outWidth = Math.round(width * factor);
3961
+ const outHeight = Math.round(height * factor);
3962
+ const limit = tool.maxOutputLongEdge;
3963
+ if (limit !== void 0 && Math.max(outWidth, outHeight) > limit) {
3964
+ return fail(
3965
+ `A ${factor}x upscale of a ${width}x${height} video passes the ${limit}px limit.`
3966
+ );
3967
+ }
3968
+ return {
3969
+ ok: true,
3970
+ output: {
3971
+ ...base,
3972
+ width: outWidth,
3973
+ height: outHeight,
3974
+ resolution: resolutionTier(outWidth, outHeight),
3975
+ format: "h264"
3976
+ }
3977
+ };
3978
+ }
3979
+ if (tool.kind === "interpolate") {
3980
+ const target = req.targetFps;
3981
+ if (target === void 0 || !Number.isInteger(target)) {
3982
+ return fail("A whole-number target frame rate is required");
3983
+ }
3984
+ const range = tool.fps;
3985
+ if (range && (target < range.min || target > range.max)) {
3986
+ return fail(`${row.label} outputs ${range.min} to ${range.max} fps.`);
3987
+ }
3988
+ return {
3989
+ ok: true,
3990
+ output: {
3991
+ durationSeconds,
3992
+ fps: target,
3993
+ width,
3994
+ height,
3995
+ resolution: resolutionTier(width, height),
3996
+ format: "h264"
3997
+ }
3998
+ };
3999
+ }
4000
+ const formats = tool.outputFormats ?? ["h265"];
4001
+ const format = req.outputFormat ?? formats[0] ?? "h265";
4002
+ if (!formats.includes(format)) {
4003
+ return fail(`${row.label} writes ${formats.join(" or ")}.`);
4004
+ }
4005
+ return {
4006
+ ok: true,
4007
+ output: { ...base, width, height, resolution: resolutionTier(width, height), format }
4008
+ };
4009
+ }
4010
+
4011
+ // src/adapters/fal-video-tools.ts
4012
+ var FAL_QUEUE_ORIGIN = "https://queue.fal.run";
4013
+ var queueUrlSchema = import_zod11.z.url().refine((value) => new URL(value).origin === FAL_QUEUE_ORIGIN, {
4014
+ message: "not a fal queue URL"
4015
+ });
4016
+ var submitResponseSchema = import_zod11.z.object({
4017
+ request_id: import_zod11.z.string().min(1),
4018
+ status_url: queueUrlSchema,
4019
+ response_url: queueUrlSchema,
4020
+ cancel_url: queueUrlSchema
4021
+ });
4022
+ var statusResponseSchema = import_zod11.z.object({ status: import_zod11.z.string() });
4023
+ var videoFileSchema = import_zod11.z.object({
4024
+ url: import_zod11.z.url(),
4025
+ content_type: import_zod11.z.string().nullish(),
4026
+ file_size: import_zod11.z.number().nullish()
4027
+ });
4028
+ var toolOutputSchema = import_zod11.z.object({ video: videoFileSchema });
4029
+ var falWebhookBodySchema = import_zod11.z.object({
4030
+ request_id: import_zod11.z.string().min(1),
4031
+ gateway_request_id: import_zod11.z.string().nullish(),
4032
+ status: import_zod11.z.enum(["OK", "ERROR"]),
4033
+ payload: JsonValueSchema.nullish(),
4034
+ error: import_zod11.z.string().nullish(),
4035
+ payload_error: JsonValueSchema.nullish()
4036
+ });
4037
+ async function queueFetch(ctx, url, method, body) {
4038
+ const payload = body === void 0 ? void 0 : JSON.stringify(body);
4039
+ try {
4040
+ if (ctx.routing.fal === "cloudflare-passthrough") {
4041
+ return await gatewayFetch(gatewayConfig(ctx), ctx.fetch, url, {
4042
+ method,
4043
+ ...payload !== void 0 && { body: payload }
4044
+ });
4045
+ }
4046
+ const falKey = ctx.keys.fal;
4047
+ if (!falKey) {
4048
+ throw new ModelKitError({
4049
+ code: "auth",
4050
+ message: "Missing API key for fal",
4051
+ provider: "fal",
4052
+ model: ctx.model.id,
4053
+ retryable: false
4054
+ });
4055
+ }
4056
+ return await ctx.fetch(url, {
4057
+ method,
4058
+ headers: {
4059
+ Authorization: `Key ${falKey}`,
4060
+ ...payload !== void 0 && { "Content-Type": "application/json" }
4061
+ },
4062
+ ...payload !== void 0 && { body: payload },
4063
+ ...ctx.signal !== void 0 && { signal: ctx.signal }
4064
+ });
4065
+ } catch (cause) {
4066
+ if (cause instanceof ModelKitError) throw cause;
4067
+ throw classifyThrown("fal", cause, ctx.model.id);
4068
+ }
4069
+ }
4070
+ async function readJson(ctx, res) {
4071
+ if (!res.ok) throw falError(res.status, await readBody(res), ctx.model.id);
4072
+ return JsonValueSchema.parse(await res.json());
4073
+ }
4074
+ function providerModelName(ctx) {
4075
+ return import_zod11.z.string().safeParse(ctx.model.providerOptions?.["fal"]?.["model"]).data;
4076
+ }
4077
+ function toolInput(ctx, req, output) {
4078
+ const tool = videoToolConstraints(ctx.model);
4079
+ const model = providerModelName(ctx);
4080
+ const input = { video_url: req.source.url };
4081
+ if (tool?.kind === "upscale") {
4082
+ if (model !== void 0) input["model"] = model;
4083
+ input["upscale_factor"] = req.upscaleFactor ?? 1;
4084
+ input["H264_output"] = true;
4085
+ } else if (tool?.kind === "interpolate") {
4086
+ if (model !== void 0) input["model"] = model;
4087
+ input["target_fps"] = req.targetFps ?? 60;
4088
+ input["slowdown_factor"] = 1;
4089
+ input["H264_output"] = true;
4090
+ } else {
4091
+ input["output_format"] = output.format === "prores" ? "prores" : "mp4";
4092
+ }
4093
+ return input;
4094
+ }
4095
+ async function submitFalVideoTool(req, ctx, opts) {
4096
+ const plan = planVideoTool(ctx.model, req);
4097
+ if (!plan.ok) {
4098
+ throw new ModelKitError({
4099
+ code: "unsupported_option",
4100
+ message: plan.error,
4101
+ provider: "fal",
4102
+ model: ctx.model.id,
4103
+ retryable: false
4104
+ });
4105
+ }
4106
+ const target = new URL(`${FAL_QUEUE_ORIGIN}/${ctx.model.providerModelId}`);
4107
+ if (opts.webhookUrl !== void 0) target.searchParams.set("fal_webhook", opts.webhookUrl);
4108
+ const res = await queueFetch(ctx, target.toString(), "POST", toolInput(ctx, req, plan.output));
4109
+ const parsed = submitResponseSchema.safeParse(await readJson(ctx, res));
4110
+ if (!parsed.success) {
4111
+ throw new ModelKitError({
4112
+ code: "provider_rejected",
4113
+ message: `fal ${ctx.model.providerModelId} submit returned no queue URLs`,
4114
+ provider: "fal",
4115
+ model: ctx.model.id,
4116
+ retryable: false
4117
+ });
4118
+ }
4119
+ return {
4120
+ model: ctx.model.id,
4121
+ provider: "fal",
4122
+ requestId: parsed.data.request_id,
4123
+ statusUrl: parsed.data.status_url,
4124
+ responseUrl: parsed.data.response_url,
4125
+ cancelUrl: parsed.data.cancel_url,
4126
+ output: plan.output
4127
+ };
4128
+ }
4129
+ function checkedQueueUrl(ctx, url) {
4130
+ if (!queueUrlSchema.safeParse(url).success) {
4131
+ throw new ModelKitError({
4132
+ code: "provider_rejected",
4133
+ message: "Video-tool submission carries a URL outside fal's queue",
4134
+ provider: "fal",
4135
+ model: ctx.model.id,
4136
+ retryable: false
4137
+ });
4138
+ }
4139
+ return url;
4140
+ }
4141
+ async function falVideoToolStatus(sub, ctx) {
4142
+ const res = await queueFetch(ctx, checkedQueueUrl(ctx, sub.statusUrl), "GET");
4143
+ const { status } = statusResponseSchema.parse(await readJson(ctx, res));
4144
+ if (status === "IN_QUEUE") return "queued";
4145
+ if (status === "COMPLETED") return "completed";
4146
+ return "running";
4147
+ }
4148
+ function usageOf(ctx, output) {
4149
+ return {
4150
+ model: ctx.model.id,
4151
+ provider: "fal",
4152
+ modality: "VIDEO",
4153
+ unit: "seconds",
4154
+ quantity: output.durationSeconds,
4155
+ durationSeconds: output.durationSeconds,
4156
+ resolution: output.resolution,
4157
+ ...output.fps !== void 0 && { fps: output.fps }
4158
+ };
4159
+ }
4160
+ function resultOf(ctx, sub, payload) {
4161
+ const parsed = toolOutputSchema.safeParse(payload);
4162
+ if (!parsed.success) {
4163
+ throw new ModelKitError({
4164
+ code: "provider_rejected",
4165
+ message: `fal ${ctx.model.providerModelId} returned no video`,
4166
+ provider: "fal",
4167
+ model: ctx.model.id,
4168
+ retryable: false
4169
+ });
4170
+ }
4171
+ const file = parsed.data.video;
4172
+ return {
4173
+ video: {
4174
+ url: file.url,
4175
+ ...file.content_type != null && { mime: file.content_type },
4176
+ ...file.file_size != null && { bytes: file.file_size }
4177
+ },
4178
+ output: sub.output,
4179
+ usage: usageOf(ctx, sub.output),
4180
+ raw: payload
4181
+ };
4182
+ }
4183
+ async function falVideoToolResult(sub, ctx, webhook) {
4184
+ if (webhook !== void 0) {
4185
+ if (webhook.request_id !== sub.requestId) {
4186
+ throw new ModelKitError({
4187
+ code: "provider_rejected",
4188
+ message: "fal webhook is for a different request",
4189
+ provider: "fal",
4190
+ model: ctx.model.id,
4191
+ retryable: false
4192
+ });
4193
+ }
4194
+ if (webhook.status === "ERROR") {
4195
+ throw falError(
4196
+ void 0,
4197
+ webhook.payload ?? webhook.error ?? "fal job failed",
4198
+ ctx.model.id
4199
+ );
4200
+ }
4201
+ return resultOf(ctx, sub, webhook.payload);
4202
+ }
4203
+ const res = await queueFetch(ctx, checkedQueueUrl(ctx, sub.responseUrl), "GET");
4204
+ return resultOf(ctx, sub, await readJson(ctx, res));
4205
+ }
4206
+ async function cancelFalVideoTool(sub, ctx) {
4207
+ const res = await queueFetch(ctx, checkedQueueUrl(ctx, sub.cancelUrl), "PUT");
4208
+ if (res.ok) return true;
4209
+ if (res.status === 400) return false;
4210
+ throw falError(res.status, await readBody(res), ctx.model.id);
4211
+ }
4212
+
3688
4213
  // src/adapters/fal.ts
3689
4214
  var MUSE_T2I_ENDPOINT = "meta/muse-image/text-to-image";
3690
4215
  var MUSE_EDIT_ENDPOINT = "meta/muse-image/edit";
@@ -3692,7 +4217,7 @@ var KLING_O1_ENDPOINT = "fal-ai/kling-video/o1/video-to-video/reference";
3692
4217
  var FAL_QUEUE_HOST = "https://queue.fal.run";
3693
4218
  var PASSTHROUGH_POLL_MS = 2e3;
3694
4219
  var PASSTHROUGH_MAX_WAIT_MS = 18e4;
3695
- var falSubscribePayloadSchema = import_zod9.z.object({ data: JsonValueSchema });
4220
+ var falSubscribePayloadSchema = import_zod12.z.object({ data: JsonValueSchema });
3696
4221
  function defaultCreateFalClient(opts) {
3697
4222
  if (opts.maxRetries !== void 0)
3698
4223
  return createFalHttpClient({
@@ -3745,24 +4270,19 @@ function createFalAdapter(deps = defaultDeps) {
3745
4270
  generateVideo: (req, ctx) => {
3746
4271
  throwIfAborted(ctx.signal);
3747
4272
  return generateFalVideo(req, ctx, deps);
3748
- }
4273
+ },
4274
+ submitVideoTool: submitFalVideoTool,
4275
+ videoToolStatus: falVideoToolStatus,
4276
+ videoToolResult: falVideoToolResult,
4277
+ cancelVideoTool: cancelFalVideoTool
3749
4278
  };
3750
4279
  }
3751
4280
  var falAdapter = createFalAdapter();
3752
- var falDetailSchema = import_zod9.z.object({ detail: JsonValueSchema });
3753
- function liftDetail(body) {
3754
- const parsed = falDetailSchema.safeParse(body);
3755
- const detail = parsed.success ? parsed.data.detail : void 0;
3756
- return detail ?? body;
3757
- }
3758
- function falError(status, body, model) {
3759
- return classifyHttpError(status, liftDetail(body), "fal", model);
3760
- }
3761
- var falSdkThrownSchema = import_zod9.z.object({
3762
- status: import_zod9.z.number().optional(),
3763
- statusCode: import_zod9.z.number().optional(),
4281
+ var falSdkThrownSchema = import_zod12.z.object({
4282
+ status: import_zod12.z.number().optional(),
4283
+ statusCode: import_zod12.z.number().optional(),
3764
4284
  body: JsonValueSchema.optional(),
3765
- message: import_zod9.z.string().optional()
4285
+ message: import_zod12.z.string().optional()
3766
4286
  });
3767
4287
  function falSdkError(cause, model) {
3768
4288
  const parsed = falSdkThrownSchema.safeParse(cause);
@@ -3777,45 +4297,12 @@ function falSdkError(cause, model) {
3777
4297
  body: liftDetail(info.body)
3778
4298
  });
3779
4299
  }
3780
- function gatewayConfig(ctx) {
3781
- const cf = ctx.routing.cloudflare;
3782
- const falKey = ctx.keys.fal;
3783
- const cfToken = ctx.keys.cloudflare;
3784
- if (!cf?.accountId || !cf?.gatewayId || !falKey && !cfToken) {
3785
- throw new ModelKitError({
3786
- code: "auth",
3787
- message: "fal passthrough is not configured. Set routing.cloudflare and FAL_KEY or the gateway token (BYOK).",
3788
- provider: "fal",
3789
- model: ctx.model.id,
3790
- retryable: false
3791
- });
3792
- }
3793
- const config = {
3794
- baseUrl: `https://gateway.ai.cloudflare.com/v1/${cf.accountId}/${cf.gatewayId}/fal`
3795
- };
3796
- if (falKey) config.falKey = falKey;
3797
- if (cfToken) config.cfToken = cfToken;
3798
- if (ctx.call.maxRetries !== void 0) config.singleAttempt = true;
3799
- if (ctx.signal !== void 0) config.signal = ctx.signal;
3800
- return config;
3801
- }
3802
- async function gatewayFetch(cfg, fetchImpl, targetUrl, init) {
3803
- const headers2 = { "x-fal-target-url": targetUrl };
3804
- if (cfg.falKey) headers2.Authorization = `Bearer ${cfg.falKey}`;
3805
- if (init.body) headers2["Content-Type"] = "application/json";
3806
- if (cfg.cfToken) headers2["cf-aig-authorization"] = `Bearer ${cfg.cfToken}`;
3807
- if (cfg.singleAttempt) headers2["cf-aig-max-attempts"] = "1";
3808
- const request = { method: init.method, headers: headers2 };
3809
- if (cfg.signal !== void 0) request.signal = cfg.signal;
3810
- if (init.body !== void 0) request.body = init.body;
3811
- return fetchImpl(cfg.baseUrl, request);
3812
- }
3813
- var falQueueSubmitSchema = import_zod9.z.object({
3814
- request_id: import_zod9.z.string(),
3815
- status_url: import_zod9.z.string(),
3816
- response_url: import_zod9.z.string()
4300
+ var falQueueSubmitSchema = import_zod12.z.object({
4301
+ request_id: import_zod12.z.string(),
4302
+ status_url: import_zod12.z.string(),
4303
+ response_url: import_zod12.z.string()
3817
4304
  });
3818
- var falQueueStatusSchema = import_zod9.z.object({ status: import_zod9.z.string() });
4305
+ var falQueueStatusSchema = import_zod12.z.object({ status: import_zod12.z.string() });
3819
4306
  async function passthroughRequest(ctx, endpoint, input) {
3820
4307
  const cfg = gatewayConfig(ctx);
3821
4308
  const submitRes = await gatewayFetch(cfg, ctx.fetch, `${FAL_QUEUE_HOST}/${endpoint}`, {
@@ -3948,11 +4435,11 @@ async function decodeImage(ctx, url, contentType) {
3948
4435
  const mime = res.headers.get("content-type") ?? contentType ?? "image/png";
3949
4436
  return { bytes: new Uint8Array(await res.arrayBuffer()), mime };
3950
4437
  }
3951
- var museImageResultSchema = import_zod9.z.object({
3952
- images: import_zod9.z.array(
3953
- import_zod9.z.object({
3954
- url: import_zod9.z.string().optional(),
3955
- content_type: import_zod9.z.string().nullable().optional()
4438
+ var museImageResultSchema = import_zod12.z.object({
4439
+ images: import_zod12.z.array(
4440
+ import_zod12.z.object({
4441
+ url: import_zod12.z.string().optional(),
4442
+ content_type: import_zod12.z.string().nullable().optional()
3956
4443
  })
3957
4444
  ).optional()
3958
4445
  });
@@ -4122,8 +4609,8 @@ function klingO1Input(req) {
4122
4609
  if (refs.length > 0) input.image_urls = refs;
4123
4610
  return input;
4124
4611
  }
4125
- var falVideoResultSchema = import_zod9.z.object({
4126
- video: import_zod9.z.object({ url: import_zod9.z.string().optional() }).optional()
4612
+ var falVideoResultSchema = import_zod12.z.object({
4613
+ video: import_zod12.z.object({ url: import_zod12.z.string().optional() }).optional()
4127
4614
  });
4128
4615
  function extractVideoUrl(result, endpoint, model) {
4129
4616
  const parsed = falVideoResultSchema.safeParse(result);
@@ -4324,11 +4811,11 @@ async function passthroughVideoJob(ctx, req, endpoint, input) {
4324
4811
  }
4325
4812
 
4326
4813
  // src/adapters/google-genai.ts
4327
- var import_zod11 = require("zod");
4814
+ var import_zod14 = require("zod");
4328
4815
  var import_genai = require("@google/genai");
4329
4816
 
4330
4817
  // src/adapters/google-files.ts
4331
- var import_zod10 = require("zod");
4818
+ var import_zod13 = require("zod");
4332
4819
  var GOOGLE_FILES_BASE = "https://generativelanguage.googleapis.com";
4333
4820
  var GOOGLE_FILES_POLL_INTERVAL_MS = 2e3;
4334
4821
  var GOOGLE_FILES_POLL_TIMEOUT_MS = 5 * 60 * 1e3;
@@ -4338,17 +4825,17 @@ var GENERIC_MEDIA_TYPES = /* @__PURE__ */ new Set([
4338
4825
  "binary/octet-stream",
4339
4826
  "application/binary"
4340
4827
  ]);
4341
- var uploadedFileSchema = import_zod10.z.object({
4342
- file: import_zod10.z.object({
4343
- uri: import_zod10.z.string().optional(),
4344
- name: import_zod10.z.string().optional(),
4345
- state: import_zod10.z.string().optional(),
4346
- mimeType: import_zod10.z.string().optional()
4828
+ var uploadedFileSchema = import_zod13.z.object({
4829
+ file: import_zod13.z.object({
4830
+ uri: import_zod13.z.string().optional(),
4831
+ name: import_zod13.z.string().optional(),
4832
+ state: import_zod13.z.string().optional(),
4833
+ mimeType: import_zod13.z.string().optional()
4347
4834
  }).optional()
4348
4835
  });
4349
- var fileStateSchema = import_zod10.z.object({
4350
- state: import_zod10.z.string().optional(),
4351
- error: import_zod10.z.object({ message: import_zod10.z.string().optional() }).optional()
4836
+ var fileStateSchema = import_zod13.z.object({
4837
+ state: import_zod13.z.string().optional(),
4838
+ error: import_zod13.z.object({ message: import_zod13.z.string().optional() }).optional()
4352
4839
  });
4353
4840
  function resolveMime(declared, fallback) {
4354
4841
  const clean = declared?.split(";")[0]?.trim().toLowerCase();
@@ -4565,7 +5052,7 @@ var OMNI_POLL_INTERVAL_MS = 1e4;
4565
5052
  var RESULT_TIMEOUT_MS2 = 15 * 60 * 1e3;
4566
5053
  var OMNI_INLINE_LIMIT_BYTES = 4 * 1024 * 1024;
4567
5054
  var MEDIA_PART_INLINE_LIMIT_BYTES = 20 * 1024 * 1024;
4568
- var errorTextSchema = import_zod11.z.string();
5055
+ var errorTextSchema = import_zod14.z.string();
4569
5056
  function isGoogleGenaiVideoKnown(providerModelId) {
4570
5057
  return providerModelId.startsWith("veo-") || providerModelId.startsWith("gemini-omni");
4571
5058
  }
@@ -5171,15 +5658,15 @@ async function prepareGoogleMediaPart(ref, mediaType, ctx) {
5171
5658
  // src/adapters/google-image.ts
5172
5659
  var import_google2 = require("@ai-sdk/google");
5173
5660
  var import_ai2 = require("ai");
5174
- var import_zod12 = require("zod");
5661
+ var import_zod15 = require("zod");
5175
5662
  var GEMINI_IMAGE_TIMEOUT_MS = 6e5;
5176
5663
  var defaultGoogleImageDeps = {
5177
5664
  createGoogleClient: (opts) => (0, import_google2.createGoogleGenerativeAI)(opts),
5178
5665
  runTextGeneration: (opts) => (0, import_ai2.generateText)(opts)
5179
5666
  };
5180
- var causeChainNodeSchema = import_zod12.z.object({
5181
- message: import_zod12.z.string().optional(),
5182
- cause: import_zod12.z.unknown().optional()
5667
+ var causeChainNodeSchema = import_zod15.z.object({
5668
+ message: import_zod15.z.string().optional(),
5669
+ cause: import_zod15.z.unknown().optional()
5183
5670
  });
5184
5671
  function extractBlockReason(cause) {
5185
5672
  let current = cause;
@@ -5299,7 +5786,7 @@ function createGoogleImageAdapter(deps = defaultGoogleImageDeps) {
5299
5786
  var googleImageAdapter = createGoogleImageAdapter();
5300
5787
 
5301
5788
  // src/adapters/higgsfield.ts
5302
- var import_zod13 = require("zod");
5789
+ var import_zod16 = require("zod");
5303
5790
 
5304
5791
  // src/adapters/higgsfield-motions.ts
5305
5792
  var MOTION_MAP = {
@@ -5518,14 +6005,14 @@ function klingEndpointFields(providerModelId) {
5518
6005
  const path = (providerModelId.startsWith("/") ? providerModelId.slice(1) : providerModelId).toLowerCase();
5519
6006
  return KLING_ENDPOINT_FIELDS.get(path) ?? UNLISTED_KLING_FIELDS;
5520
6007
  }
5521
- var klingCreateSchema = import_zod13.z.object({ status_url: import_zod13.z.string() });
5522
- var klingStatusSchema = import_zod13.z.object({
5523
- status: import_zod13.z.string().optional(),
5524
- video: import_zod13.z.object({ url: import_zod13.z.string().optional() }).optional(),
6008
+ var klingCreateSchema = import_zod16.z.object({ status_url: import_zod16.z.string() });
6009
+ var klingStatusSchema = import_zod16.z.object({
6010
+ status: import_zod16.z.string().optional(),
6011
+ video: import_zod16.z.object({ url: import_zod16.z.string().optional() }).optional(),
5525
6012
  error: JsonValueSchema.optional()
5526
6013
  });
5527
- var errorMessageSchema = import_zod13.z.object({ message: import_zod13.z.string().optional() });
5528
- var textValueSchema = import_zod13.z.string();
6014
+ var errorMessageSchema = import_zod16.z.object({ message: import_zod16.z.string().optional() });
6015
+ var textValueSchema = import_zod16.z.string();
5529
6016
  function klingErrorDetail(error) {
5530
6017
  if (error === void 0) return "unknown_error";
5531
6018
  const asText = textValueSchema.safeParse(error);
@@ -5681,8 +6168,8 @@ async function generateKlingVideo(req, ctx) {
5681
6168
  }
5682
6169
  };
5683
6170
  }
5684
- var dopMotionOptionsSchema = import_zod13.z.object({
5685
- modelkit: import_zod13.z.object({ motion: import_zod13.z.string().optional() }).optional()
6171
+ var dopMotionOptionsSchema = import_zod16.z.object({
6172
+ modelkit: import_zod16.z.object({ motion: import_zod16.z.string().optional() }).optional()
5686
6173
  });
5687
6174
  function dopMotionId(ctx) {
5688
6175
  const parsed = dopMotionOptionsSchema.safeParse(ctx.model.providerOptions);
@@ -5698,7 +6185,7 @@ function dopMotionId(ctx) {
5698
6185
  });
5699
6186
  return id;
5700
6187
  }
5701
- var jsonRecordSchema = import_zod13.z.record(import_zod13.z.string(), JsonValueSchema);
6188
+ var jsonRecordSchema = import_zod16.z.record(import_zod16.z.string(), JsonValueSchema);
5702
6189
  var DOP_URL_KEYS = ["url", "video_url", "output_url", "result_url", "download_url"];
5703
6190
  var DOP_NESTED_KEYS = ["video", "result", "results"];
5704
6191
  function dopUrl(body) {
@@ -5726,8 +6213,8 @@ function dopUrl(body) {
5726
6213
  }
5727
6214
  return void 0;
5728
6215
  }
5729
- var dopCreateSchema = import_zod13.z.object({ id: import_zod13.z.string() });
5730
- var dopStatusSchema = import_zod13.z.object({ status: import_zod13.z.string().optional() });
6216
+ var dopCreateSchema = import_zod16.z.object({ id: import_zod16.z.string() });
6217
+ var dopStatusSchema = import_zod16.z.object({ status: import_zod16.z.string().optional() });
5731
6218
  async function generateDopVideo(req, ctx) {
5732
6219
  const firstFrame = req.firstFrame ? refToUrl(req.firstFrame) : void 0;
5733
6220
  if (!firstFrame) {
@@ -5855,7 +6342,7 @@ var higgsfieldAdapter = {
5855
6342
 
5856
6343
  // src/adapters/openai-image.ts
5857
6344
  var import_openai2 = __toESM(require("openai"), 1);
5858
- var import_zod14 = require("zod");
6345
+ var import_zod17 = require("zod");
5859
6346
  var MAX_EDIT_REFERENCES = 16;
5860
6347
  function aspectRatioToSize(ratio, tier) {
5861
6348
  const TIER_LONG_EDGE = {
@@ -5938,9 +6425,9 @@ function toProviderError2(cause, ctx) {
5938
6425
  ctx.model.id
5939
6426
  );
5940
6427
  }
5941
- var openaiUsageSchema = import_zod14.z.object({
5942
- input_tokens: import_zod14.z.number().optional(),
5943
- output_tokens: import_zod14.z.number().optional()
6428
+ var openaiUsageSchema = import_zod17.z.object({
6429
+ input_tokens: import_zod17.z.number().optional(),
6430
+ output_tokens: import_zod17.z.number().optional()
5944
6431
  });
5945
6432
  var openaiImageAdapter = {
5946
6433
  id: "openai-image",
@@ -6351,13 +6838,13 @@ var prodiaAdapter = {
6351
6838
  var import_replicate = __toESM(require("replicate"), 1);
6352
6839
 
6353
6840
  // src/adapters/replicate-http.ts
6354
- var import_zod15 = require("zod");
6355
- var predictionSchema = import_zod15.z.object({
6356
- id: import_zod15.z.string(),
6357
- status: import_zod15.z.string(),
6841
+ var import_zod18 = require("zod");
6842
+ var predictionSchema = import_zod18.z.object({
6843
+ id: import_zod18.z.string(),
6844
+ status: import_zod18.z.string(),
6358
6845
  output: JsonValueSchema.optional(),
6359
6846
  error: JsonValueSchema.optional(),
6360
- metrics: import_zod15.z.object({ predict_time: import_zod15.z.number().optional() }).optional()
6847
+ metrics: import_zod18.z.object({ predict_time: import_zod18.z.number().optional() }).optional()
6361
6848
  });
6362
6849
  function createReplicateHttpClient(opts) {
6363
6850
  async function request(path, body, signal) {
@@ -6408,7 +6895,7 @@ function createReplicateHttpClient(opts) {
6408
6895
  }
6409
6896
 
6410
6897
  // src/adapters/replicate.ts
6411
- var import_zod16 = require("zod");
6898
+ var import_zod19 = require("zod");
6412
6899
 
6413
6900
  // src/adapters/input-spec-mapper.ts
6414
6901
  function canonicalValue(req, key) {
@@ -6483,8 +6970,8 @@ function route(providerModelId) {
6483
6970
  if (!providerModelId.includes("/")) return { version: providerModelId };
6484
6971
  return { model: providerModelId };
6485
6972
  }
6486
- var replicateResponseStatusSchema = import_zod16.z.object({
6487
- response: import_zod16.z.object({ status: import_zod16.z.number() }).partial()
6973
+ var replicateResponseStatusSchema = import_zod19.z.object({
6974
+ response: import_zod19.z.object({ status: import_zod19.z.number() }).partial()
6488
6975
  });
6489
6976
  function replicateError(cause, ctx) {
6490
6977
  if (isModelKitError(cause)) return cause;
@@ -6511,7 +6998,7 @@ function isUrlFn(value) {
6511
6998
  function extractOutputUrl(output) {
6512
6999
  const root = Array.isArray(output) ? output[0] : output;
6513
7000
  if (root === void 0) throw noOutput();
6514
- const asString = import_zod16.z.string().safeParse(root);
7001
+ const asString = import_zod19.z.string().safeParse(root);
6515
7002
  if (asString.success && asString.data) return asString.data;
6516
7003
  if (root instanceof URL) return root.href;
6517
7004
  if (isObjectOutput(root)) {
@@ -6520,15 +7007,15 @@ function extractOutputUrl(output) {
6520
7007
  if (urlValue !== void 0 && isUrlFn(urlValue)) {
6521
7008
  const called = urlValue();
6522
7009
  if (called instanceof URL) return called.href;
6523
- const calledString = import_zod16.z.string().safeParse(called);
7010
+ const calledString = import_zod19.z.string().safeParse(called);
6524
7011
  if (calledString.success && calledString.data) return calledString.data;
6525
7012
  } else {
6526
- const direct = import_zod16.z.string().safeParse(urlValue);
7013
+ const direct = import_zod19.z.string().safeParse(urlValue);
6527
7014
  if (direct.success && direct.data) return direct.data;
6528
7015
  }
6529
7016
  }
6530
7017
  if ("default" in root) {
6531
- const fallback = import_zod16.z.string().safeParse(root.default);
7018
+ const fallback = import_zod19.z.string().safeParse(root.default);
6532
7019
  if (fallback.success && fallback.data) return fallback.data;
6533
7020
  }
6534
7021
  }
@@ -6589,7 +7076,7 @@ async function runPrediction(ctx, input, deps) {
6589
7076
  }
6590
7077
  return void 0;
6591
7078
  }, pollOpts);
6592
- const predictTime = import_zod16.z.number().safeParse(done.metrics?.predict_time);
7079
+ const predictTime = import_zod19.z.number().safeParse(done.metrics?.predict_time);
6593
7080
  if (done.output === void 0) throw noOutput();
6594
7081
  return {
6595
7082
  url: extractOutputUrl(done.output),
@@ -6978,7 +7465,7 @@ async function generateReplicateVideo(req, ctx, deps) {
6978
7465
  throw replicateError(cause, ctx);
6979
7466
  }
6980
7467
  if (current.status === "succeeded") {
6981
- const predictTime = import_zod16.z.number().safeParse(current.metrics?.predict_time);
7468
+ const predictTime = import_zod19.z.number().safeParse(current.metrics?.predict_time);
6982
7469
  if (current.output === void 0) throw noOutput();
6983
7470
  return {
6984
7471
  url: extractOutputUrl(current.output),
@@ -7119,7 +7606,7 @@ async function generateReplicateAudio(req, ctx, deps) {
7119
7606
  // src/adapters/xai-video.ts
7120
7607
  var import_ai3 = require("ai");
7121
7608
  var import_xai2 = require("@ai-sdk/xai");
7122
- var import_zod17 = require("zod");
7609
+ var import_zod20 = require("zod");
7123
7610
  var POLL_INTERVAL_MS2 = 1e4;
7124
7611
  var POLL_TIMEOUT_MS2 = 15 * 6e4;
7125
7612
  var defaultXaiDeps = {
@@ -7132,8 +7619,8 @@ function createXaiVideoAdapter(deps = defaultXaiDeps) {
7132
7619
  };
7133
7620
  }
7134
7621
  var xaiVideoAdapter = createXaiVideoAdapter();
7135
- var xaiResponseStatusSchema = import_zod17.z.object({
7136
- response: import_zod17.z.object({ status: import_zod17.z.number() }).partial()
7622
+ var xaiResponseStatusSchema = import_zod20.z.object({
7623
+ response: import_zod20.z.object({ status: import_zod20.z.number() }).partial()
7137
7624
  });
7138
7625
  function xaiError(cause, ctx) {
7139
7626
  const info = describeThrown(cause);
@@ -7141,12 +7628,12 @@ function xaiError(cause, ctx) {
7141
7628
  const status = info.status ?? (nested.success ? nested.data.response?.status : void 0);
7142
7629
  return classifyThrown("xai-video", cause, ctx.model.id, { status, body: info.body });
7143
7630
  }
7144
- var xaiMetaSchema = import_zod17.z.object({
7631
+ var xaiMetaSchema = import_zod20.z.object({
7145
7632
  videoUrl: JsonValueSchema.optional(),
7146
7633
  costInUsdTicks: JsonValueSchema.optional(),
7147
7634
  duration: JsonValueSchema.optional()
7148
7635
  });
7149
- var xaiProviderMetadataSchema = import_zod17.z.object({ xai: xaiMetaSchema });
7636
+ var xaiProviderMetadataSchema = import_zod20.z.object({ xai: xaiMetaSchema });
7150
7637
  function metaOf(result) {
7151
7638
  const parsed = xaiProviderMetadataSchema.partial().safeParse(result.providerMetadata);
7152
7639
  if (!parsed.success) return {};
@@ -7254,7 +7741,7 @@ async function mapResult(ctx, req, result) {
7254
7741
  };
7255
7742
  }
7256
7743
  const meta = metaOf(result);
7257
- const videoUrl = import_zod17.z.string().safeParse(meta.videoUrl);
7744
+ const videoUrl = import_zod20.z.string().safeParse(meta.videoUrl);
7258
7745
  if (videoUrl.success && videoUrl.data) {
7259
7746
  const res = await ctx.fetch(videoUrl.data);
7260
7747
  if (!res.ok) {
@@ -7277,7 +7764,7 @@ async function mapResult(ctx, req, result) {
7277
7764
  });
7278
7765
  }
7279
7766
  function usage(ctx, req, meta) {
7280
- const costTicks = import_zod17.z.number().safeParse(meta.costInUsdTicks);
7767
+ const costTicks = import_zod20.z.number().safeParse(meta.costInUsdTicks);
7281
7768
  const cost = costTicks.success ? costTicks.data / 1e10 : void 0;
7282
7769
  const event = {
7283
7770
  model: ctx.model.id,
@@ -7410,22 +7897,22 @@ var liveState = store[KEY] ??= {
7410
7897
  var liveCatalog = liveState.catalog;
7411
7898
 
7412
7899
  // src/catalog/load.ts
7413
- var import_zod18 = require("zod");
7900
+ var import_zod21 = require("zod");
7414
7901
  function rowCount() {
7415
7902
  return liveCatalog.list({ lifecycle: ["active", "deprecated", "retired"] }).length;
7416
7903
  }
7417
7904
  function authHeaders(auth) {
7418
7905
  return "bearer" in auth ? { Authorization: `Bearer ${auth.bearer}` } : { "x-api-key": auth.apiKey };
7419
7906
  }
7420
- var EnvelopeSchema = import_zod18.z.object({
7421
- rows: import_zod18.z.array(JsonValueSchema),
7422
- revision: import_zod18.z.string().optional()
7907
+ var EnvelopeSchema = import_zod21.z.object({
7908
+ rows: import_zod21.z.array(JsonValueSchema),
7909
+ revision: import_zod21.z.string().optional()
7423
7910
  });
7424
7911
  function dropReason(path, message) {
7425
7912
  return path.length === 0 ? message : `${path.map((part) => String(part)).join(".")} ${message}`;
7426
7913
  }
7427
7914
  function rowId(raw) {
7428
- const parsed = import_zod18.z.object({ id: import_zod18.z.string().min(1) }).loose().safeParse(raw);
7915
+ const parsed = import_zod21.z.object({ id: import_zod21.z.string().min(1) }).loose().safeParse(raw);
7429
7916
  if (!parsed.success) return "?";
7430
7917
  return parsed.data.id;
7431
7918
  }
@@ -8282,7 +8769,7 @@ function createTextSteps(initial, resolve, callerProviderOptions) {
8282
8769
 
8283
8770
  // src/client.ts
8284
8771
  var import_ai5 = require("ai");
8285
- var import_zod19 = require("zod");
8772
+ var import_zod22 = require("zod");
8286
8773
 
8287
8774
  // src/generated-image.ts
8288
8775
  function toGeneratedImage(image) {
@@ -8364,10 +8851,10 @@ function textAbortOptions(sdk, context) {
8364
8851
  if (abortSignal) return { abortSignal };
8365
8852
  return {};
8366
8853
  }
8367
- var catalogId = import_zod19.z.string();
8368
- var exactSize = import_zod19.z.templateLiteral([import_zod19.z.number(), "x", import_zod19.z.number()]);
8369
- var sdkRatio = import_zod19.z.templateLiteral([import_zod19.z.number(), ":", import_zod19.z.number()]);
8370
- var sizeTier = import_zod19.z.enum(["512", "1K", "2K", "4K"]);
8854
+ var catalogId = import_zod22.z.string();
8855
+ var exactSize = import_zod22.z.templateLiteral([import_zod22.z.number(), "x", import_zod22.z.number()]);
8856
+ var sdkRatio = import_zod22.z.templateLiteral([import_zod22.z.number(), ":", import_zod22.z.number()]);
8857
+ var sizeTier = import_zod22.z.enum(["512", "1K", "2K", "4K"]);
8371
8858
  function isCatalogId(model) {
8372
8859
  return catalogId.safeParse(model).success;
8373
8860
  }
@@ -8477,6 +8964,24 @@ function createModelKit(config, adapters) {
8477
8964
  if (call.signal) ctx.signal = call.signal;
8478
8965
  return { adapter, ctx };
8479
8966
  }
8967
+ function videoToolTarget(modelId, call) {
8968
+ mediaRetryOptions(call);
8969
+ const model = catalog.require(modelId);
8970
+ if (model.type !== "video-tool")
8971
+ throw new ModelKitError({
8972
+ code: "unsupported_option",
8973
+ message: `${model.id} is not a video tool`,
8974
+ model: model.id
8975
+ });
8976
+ return context(model, call, []);
8977
+ }
8978
+ function noVideoTools(adapter, model) {
8979
+ return new ModelKitError({
8980
+ code: "unsupported_option",
8981
+ message: `${adapter.id} has no video tools`,
8982
+ model: model.id
8983
+ });
8984
+ }
8480
8985
  async function emit(event) {
8481
8986
  try {
8482
8987
  await config.onUsage?.(event);
@@ -8832,6 +9337,34 @@ function createModelKit(config, adapters) {
8832
9337
  usageProvider: provider
8833
9338
  };
8834
9339
  },
9340
+ async submitVideoTool(req, call = {}) {
9341
+ const { webhookUrl, ...rest } = call;
9342
+ const { adapter, ctx } = videoToolTarget(req.model, rest);
9343
+ if (!adapter.submitVideoTool) throw noVideoTools(adapter, ctx.model);
9344
+ return adapter.submitVideoTool(
9345
+ req,
9346
+ ctx,
9347
+ webhookUrl !== void 0 ? { webhookUrl } : {}
9348
+ );
9349
+ },
9350
+ async videoToolStatus(sub, call = {}) {
9351
+ const { adapter, ctx } = videoToolTarget(sub.model, call);
9352
+ if (!adapter.videoToolStatus) throw noVideoTools(adapter, ctx.model);
9353
+ return adapter.videoToolStatus(sub, ctx);
9354
+ },
9355
+ async videoToolResult(sub, call = {}) {
9356
+ const { webhook, ...rest } = call;
9357
+ const { adapter, ctx } = videoToolTarget(sub.model, rest);
9358
+ if (!adapter.videoToolResult) throw noVideoTools(adapter, ctx.model);
9359
+ const result = await adapter.videoToolResult(sub, ctx, webhook);
9360
+ await emit({ ...result.usage, model: ctx.model.id, unit: ctx.model.usage.unit });
9361
+ return result;
9362
+ },
9363
+ async cancelVideoTool(sub, call = {}) {
9364
+ const { adapter, ctx } = videoToolTarget(sub.model, call);
9365
+ if (!adapter.cancelVideoTool) throw noVideoTools(adapter, ctx.model);
9366
+ return adapter.cancelVideoTool(sub, ctx);
9367
+ },
8835
9368
  usageProvider(modelId, call = {}) {
8836
9369
  const entry = catalog.require(modelId);
8837
9370
  if (entry.type !== "text") return entry.adapter;
@@ -8958,6 +9491,7 @@ var describe = (modelId) => createDefaultModelKit().describe(modelId);
8958
9491
  SURFACES,
8959
9492
  SurfaceSchema,
8960
9493
  VIDEO_INPUT_SPEC_KEYS,
9494
+ VIDEO_TOOL_MODELS,
8961
9495
  adapterServesType,
8962
9496
  aiSdkTextAdapter,
8963
9497
  arkAdapter,
@@ -8971,6 +9505,7 @@ var describe = (modelId) => createDefaultModelKit().describe(modelId);
8971
9505
  describeThrown,
8972
9506
  experimental_generateImage,
8973
9507
  falAdapter,
9508
+ falWebhookBodySchema,
8974
9509
  fileCatalogCache,
8975
9510
  generateAudio,
8976
9511
  generateImage,
@@ -8995,6 +9530,7 @@ var describe = (modelId) => createDefaultModelKit().describe(modelId);
8995
9530
  normalizeExposure,
8996
9531
  openaiImageAdapter,
8997
9532
  passthroughTextModel,
9533
+ planVideoTool,
8998
9534
  pollUntil,
8999
9535
  prepareMediaPart,
9000
9536
  primeCatalog,
@@ -9002,6 +9538,7 @@ var describe = (modelId) => createDefaultModelKit().describe(modelId);
9002
9538
  readErrorBody,
9003
9539
  replicateAdapter,
9004
9540
  resetLiveCatalog,
9541
+ resolutionTier,
9005
9542
  resolveAudioOptions,
9006
9543
  resolveImageOptions,
9007
9544
  resolveKeys,
@@ -9015,6 +9552,7 @@ var describe = (modelId) => createDefaultModelKit().describe(modelId);
9015
9552
  toGeneratedImage,
9016
9553
  validateInputSpec,
9017
9554
  videoLengthViolation,
9555
+ videoToolConstraints,
9018
9556
  withRetry,
9019
9557
  xaiVideoAdapter,
9020
9558
  ...require("ai")