@shop-os/modelkit 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -0
- package/dist/index.cjs +160 -110
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +160 -110
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -101,6 +101,11 @@ fetch, logging, and the `onUsage` sink.
|
|
|
101
101
|
pass-through instances; catalog rows carry their own and the caller's are dropped
|
|
102
102
|
with an `option_ignored` warning.
|
|
103
103
|
|
|
104
|
+
Text catalog rows carry no reasoning defaults. A catalog id behaves like the
|
|
105
|
+
provider's own default, so `temperature` and friends work as they do in `ai`.
|
|
106
|
+
Opt into thinking per call, for example
|
|
107
|
+
`providerOptions: { anthropic: { thinking: { type: "enabled", budgetTokens: 4000 } } }`.
|
|
108
|
+
|
|
104
109
|
The kit keeps its `Warning` type for coercions; the SDK's warning type is `AiWarning`.
|
|
105
110
|
`languageModel()` remains the low-level handle for Mastra and custom middleware.
|
|
106
111
|
|
package/dist/index.cjs
CHANGED
|
@@ -212,6 +212,44 @@ var IMAGE_MODELS = [
|
|
|
212
212
|
usage: { ...IMAGE_USAGE },
|
|
213
213
|
pricingKind: "image_size"
|
|
214
214
|
},
|
|
215
|
+
{
|
|
216
|
+
// Same Images API surface as gpt-image-2 plus the "xhigh" and "max" quality tiers.
|
|
217
|
+
id: "gpt-image-2.5-sunburst",
|
|
218
|
+
aliases: [],
|
|
219
|
+
label: "GPT Image 2.5 Sunburst",
|
|
220
|
+
type: "image",
|
|
221
|
+
adapter: "openai-image",
|
|
222
|
+
providerModelId: "gpt-image-2.5-sunburst",
|
|
223
|
+
lifecycle: "active",
|
|
224
|
+
constraints: {
|
|
225
|
+
aspectRatios: ["1:1", "3:2", "2:3", "16:9", "9:16", "4:5", "5:4", "adaptive"],
|
|
226
|
+
sizes: ["1K", "2K", "4K"],
|
|
227
|
+
references: { images: 16 },
|
|
228
|
+
supports: ["quality", "count"]
|
|
229
|
+
},
|
|
230
|
+
defaults: { size: "1K", aspectRatio: "adaptive", quality: "auto" },
|
|
231
|
+
usage: { ...IMAGE_USAGE },
|
|
232
|
+
pricingKind: "image_size"
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
// Same Images API surface as gpt-image-2 plus the "xhigh" and "max" quality tiers.
|
|
236
|
+
id: "gpt-image-2.5-flare",
|
|
237
|
+
aliases: [],
|
|
238
|
+
label: "GPT Image 2.5 Flare",
|
|
239
|
+
type: "image",
|
|
240
|
+
adapter: "openai-image",
|
|
241
|
+
providerModelId: "gpt-image-2.5-flare",
|
|
242
|
+
lifecycle: "active",
|
|
243
|
+
constraints: {
|
|
244
|
+
aspectRatios: ["1:1", "3:2", "2:3", "16:9", "9:16", "4:5", "5:4", "adaptive"],
|
|
245
|
+
sizes: ["1K", "2K", "4K"],
|
|
246
|
+
references: { images: 16 },
|
|
247
|
+
supports: ["quality", "count"]
|
|
248
|
+
},
|
|
249
|
+
defaults: { size: "1K", aspectRatio: "adaptive", quality: "auto" },
|
|
250
|
+
usage: { ...IMAGE_USAGE },
|
|
251
|
+
pricingKind: "image_size"
|
|
252
|
+
},
|
|
215
253
|
{
|
|
216
254
|
// Cowork allows 7 ratios; trigger-workflows allows 9 (adds 3:2, 9:21, drops 4:5/5:4).
|
|
217
255
|
id: "muse-image-1.0",
|
|
@@ -588,77 +626,42 @@ function text(id, label, providerModelId, extra) {
|
|
|
588
626
|
...extra
|
|
589
627
|
};
|
|
590
628
|
}
|
|
591
|
-
var ANTHROPIC_THINKING = {
|
|
592
|
-
anthropic: {
|
|
593
|
-
thinking: { type: "enabled", budgetTokens: 4e3 },
|
|
594
|
-
sendReasoning: true
|
|
595
|
-
}
|
|
596
|
-
};
|
|
597
|
-
var ANTHROPIC_ADAPTIVE = {
|
|
598
|
-
anthropic: {
|
|
599
|
-
thinking: { type: "adaptive", display: "summarized" },
|
|
600
|
-
sendReasoning: true
|
|
601
|
-
}
|
|
602
|
-
};
|
|
603
|
-
var OPENAI_REASONING = {
|
|
604
|
-
openai: {
|
|
605
|
-
reasoningEffort: "medium",
|
|
606
|
-
reasoningSummary: "auto"
|
|
607
|
-
}
|
|
608
|
-
};
|
|
609
|
-
var DEEPSEEK_THINKING = {
|
|
610
|
-
deepseek: {
|
|
611
|
-
thinking: { type: "enabled" }
|
|
612
|
-
}
|
|
613
|
-
};
|
|
614
629
|
var TEXT_MODELS = [
|
|
615
630
|
text("gpt-4o", "GPT-4o", "gpt-4o"),
|
|
616
631
|
text("gpt-4o-mini", "GPT-4o mini", "gpt-4o-mini"),
|
|
617
632
|
text("gpt-5.1", "GPT-5.1", "gpt-5.1"),
|
|
618
|
-
text("gpt-5.1-mini", "GPT-5.1 mini", "gpt-5.1-mini"),
|
|
619
633
|
text("gpt-5.2", "GPT-5.2", "gpt-5.2"),
|
|
620
|
-
text("gpt-5.2-mini", "GPT-5.2 mini", "gpt-5.2-mini"),
|
|
621
634
|
text("gpt-5.4", "GPT-5.4", "gpt-5.4"),
|
|
622
|
-
|
|
623
|
-
text("gpt-5.
|
|
624
|
-
|
|
625
|
-
providerOptions: { ...OPENAI_REASONING }
|
|
626
|
-
}),
|
|
627
|
-
text("gpt-5.6-terra", "GPT-5.6 Terra", "gpt-5.6-terra", {
|
|
628
|
-
providerOptions: { ...OPENAI_REASONING }
|
|
629
|
-
}),
|
|
630
|
-
text("gpt-5.6-sol", "GPT-5.6 Sol", "gpt-5.6-sol", {
|
|
631
|
-
providerOptions: { ...OPENAI_REASONING }
|
|
632
|
-
}),
|
|
633
|
-
// Dated 4.0 ids are what vibe-api, pro-admin and the TW geo agents still send.
|
|
634
|
-
text("claude-sonnet-4", "Claude Sonnet 4", "claude-sonnet-4-20250514", {
|
|
635
|
-
aliases: ["claude-sonnet-4.0", "claude-sonnet-4-20250514"]
|
|
636
|
-
}),
|
|
637
|
-
text("claude-opus-4", "Claude Opus 4", "claude-opus-4-20250514", {
|
|
638
|
-
aliases: ["claude-opus-4.0", "claude-opus-4-20250514"]
|
|
635
|
+
// OpenAI never shipped gpt-5.1-mini or gpt-5.2-mini; callers that still send them get 5.4 mini.
|
|
636
|
+
text("gpt-5.4-mini", "GPT-5.4 mini", "gpt-5.4-mini", {
|
|
637
|
+
aliases: ["gpt-5.1-mini", "gpt-5.2-mini"]
|
|
639
638
|
}),
|
|
639
|
+
text("gpt-5.5", "GPT-5.5", "gpt-5.5"),
|
|
640
|
+
text("gpt-5.6-luna", "GPT-5.6 Luna", "gpt-5.6-luna"),
|
|
641
|
+
text("gpt-5.6-terra", "GPT-5.6 Terra", "gpt-5.6-terra"),
|
|
642
|
+
text("gpt-5.6-sol", "GPT-5.6 Sol", "gpt-5.6-sol"),
|
|
640
643
|
// Library key "claude-sonnet-4.5" maps to the SDK id "claude-sonnet-4-5".
|
|
641
644
|
text("claude-sonnet-4-5", "Claude Sonnet 4.5", "claude-sonnet-4-5", {
|
|
642
645
|
aliases: ["claude-sonnet-4.5"]
|
|
643
646
|
}),
|
|
647
|
+
// Anthropic retired the dated 4.0 ids; callers that still send them get 4.6.
|
|
644
648
|
text("claude-sonnet-4-6", "Claude Sonnet 4.6", "claude-sonnet-4-6", {
|
|
645
|
-
aliases: [
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
649
|
+
aliases: [
|
|
650
|
+
"claude-sonnet-4.6",
|
|
651
|
+
"claude-sonnet-4",
|
|
652
|
+
"claude-sonnet-4.0",
|
|
653
|
+
"claude-sonnet-4-20250514"
|
|
654
|
+
]
|
|
650
655
|
}),
|
|
656
|
+
text("claude-sonnet-5", "Claude Sonnet 5", "claude-sonnet-5"),
|
|
651
657
|
text("claude-opus-4-8", "Claude Opus 4.8", "claude-opus-4-8", {
|
|
652
|
-
aliases: ["claude-opus-4.8"]
|
|
653
|
-
providerOptions: { ...ANTHROPIC_ADAPTIVE }
|
|
658
|
+
aliases: ["claude-opus-4.8", "claude-opus-4", "claude-opus-4.0", "claude-opus-4-20250514"]
|
|
654
659
|
}),
|
|
655
660
|
text("claude-haiku-4-5", "Claude Haiku 4.5", "claude-haiku-4-5", {
|
|
656
|
-
aliases: ["claude-haiku-4.5", "claude-haiku-4-5-20251001"]
|
|
657
|
-
providerOptions: { ...ANTHROPIC_THINKING }
|
|
661
|
+
aliases: ["claude-haiku-4.5", "claude-haiku-4-5-20251001"]
|
|
658
662
|
}),
|
|
659
663
|
text("claude-opus-5", "Claude Opus 5", "claude-opus-5", {
|
|
660
|
-
aliases: ["claude-opus-5.0"]
|
|
661
|
-
providerOptions: { ...ANTHROPIC_ADAPTIVE }
|
|
664
|
+
aliases: ["claude-opus-5.0"]
|
|
662
665
|
}),
|
|
663
666
|
text("claude-fable-5", "Claude Fable 5", "claude-fable-5"),
|
|
664
667
|
text("gemini-2.5-flash", "Gemini 2.5 Flash", "gemini-2.5-flash"),
|
|
@@ -677,12 +680,8 @@ var TEXT_MODELS = [
|
|
|
677
680
|
text("sonar", "Sonar", "sonar"),
|
|
678
681
|
text("sonar-pro", "Sonar Pro", "sonar-pro"),
|
|
679
682
|
text("sonar-reasoning-pro", "Sonar Reasoning Pro", "sonar-reasoning-pro"),
|
|
680
|
-
text("deepseek-v4-flash", "DeepSeek V4 Flash", "deepseek-v4-flash",
|
|
681
|
-
|
|
682
|
-
}),
|
|
683
|
-
text("deepseek-v4-pro", "DeepSeek V4 Pro", "deepseek-v4-pro", {
|
|
684
|
-
providerOptions: { ...DEEPSEEK_THINKING }
|
|
685
|
-
}),
|
|
683
|
+
text("deepseek-v4-flash", "DeepSeek V4 Flash", "deepseek-v4-flash"),
|
|
684
|
+
text("deepseek-v4-pro", "DeepSeek V4 Pro", "deepseek-v4-pro"),
|
|
686
685
|
text("grok-4.3", "Grok 4.3", "grok-4.3"),
|
|
687
686
|
text("kimi-k2.5", "Kimi K2.5", "kimi-k2.5"),
|
|
688
687
|
text("kimi-k3", "Kimi K3", "kimi-k3"),
|
|
@@ -1513,23 +1512,46 @@ async function withRetry(fn, opts = {}) {
|
|
|
1513
1512
|
}
|
|
1514
1513
|
function sleep(ms, signal) {
|
|
1515
1514
|
return new Promise((resolve, reject) => {
|
|
1516
|
-
const
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1515
|
+
const rejectAborted = () => {
|
|
1516
|
+
reject(new ModelKitError({ code: "timeout", message: "aborted", retryable: false }));
|
|
1517
|
+
};
|
|
1518
|
+
if (signal?.aborted) {
|
|
1519
|
+
rejectAborted();
|
|
1520
|
+
return;
|
|
1521
|
+
}
|
|
1522
|
+
let timer;
|
|
1523
|
+
const onAbort = () => {
|
|
1524
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
1525
|
+
rejectAborted();
|
|
1526
|
+
};
|
|
1527
|
+
timer = setTimeout(() => {
|
|
1528
|
+
signal?.removeEventListener("abort", onAbort);
|
|
1529
|
+
resolve();
|
|
1530
|
+
}, ms);
|
|
1531
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
1527
1532
|
});
|
|
1528
1533
|
}
|
|
1534
|
+
function throwAborted() {
|
|
1535
|
+
return new ModelKitError({ code: "timeout", message: "aborted", retryable: false });
|
|
1536
|
+
}
|
|
1537
|
+
function transportError(provider, cause, model) {
|
|
1538
|
+
const message = cause instanceof Error ? cause.message : String(cause);
|
|
1539
|
+
const aborted = cause instanceof Error && cause.name === "AbortError";
|
|
1540
|
+
const init = {
|
|
1541
|
+
code: aborted ? "timeout" : "network",
|
|
1542
|
+
message: `${provider} request failed before a response: ${message}`,
|
|
1543
|
+
provider,
|
|
1544
|
+
retryable: !aborted,
|
|
1545
|
+
cause
|
|
1546
|
+
};
|
|
1547
|
+
if (model !== void 0) init.model = model;
|
|
1548
|
+
return new ModelKitError(init);
|
|
1549
|
+
}
|
|
1529
1550
|
async function pollUntil(check, opts) {
|
|
1530
1551
|
const start = Date.now();
|
|
1531
1552
|
let interval = opts.intervalMs;
|
|
1532
1553
|
for (; ; ) {
|
|
1554
|
+
if (opts.signal?.aborted) throw throwAborted();
|
|
1533
1555
|
const value = await check();
|
|
1534
1556
|
if (value !== void 0) return value;
|
|
1535
1557
|
if (Date.now() - start > opts.timeoutMs)
|
|
@@ -1538,6 +1560,7 @@ async function pollUntil(check, opts) {
|
|
|
1538
1560
|
message: `poll timed out after ${opts.timeoutMs}ms`,
|
|
1539
1561
|
retryable: false
|
|
1540
1562
|
});
|
|
1563
|
+
if (opts.signal?.aborted) throw throwAborted();
|
|
1541
1564
|
await sleep(interval, opts.signal);
|
|
1542
1565
|
if (opts.backoff)
|
|
1543
1566
|
interval = Math.min(opts.maxIntervalMs ?? interval * 4, interval * opts.backoff);
|
|
@@ -1715,7 +1738,7 @@ var OPENAI_COMPATIBLE_BASE_URLS = {
|
|
|
1715
1738
|
var GATEWAY_SLUGS = {
|
|
1716
1739
|
openai: "openai",
|
|
1717
1740
|
anthropic: "anthropic",
|
|
1718
|
-
google: "google-ai-studio",
|
|
1741
|
+
google: "google-ai-studio/v1beta",
|
|
1719
1742
|
xai: "grok",
|
|
1720
1743
|
perplexity: "perplexity-ai",
|
|
1721
1744
|
deepseek: "deepseek"
|
|
@@ -2141,13 +2164,21 @@ function createModelKit(config, adapters) {
|
|
|
2141
2164
|
});
|
|
2142
2165
|
const job = await adapter.generateVideo(request, ctx);
|
|
2143
2166
|
const result = job.result.bind(job);
|
|
2167
|
+
let settled;
|
|
2144
2168
|
return {
|
|
2145
2169
|
...job,
|
|
2146
2170
|
warnings,
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2171
|
+
result(opts) {
|
|
2172
|
+
if (settled) return settled;
|
|
2173
|
+
const pending = result(opts).then(
|
|
2174
|
+
(out) => emit({ ...out.usage, model: model.id }).then(() => out),
|
|
2175
|
+
(cause) => {
|
|
2176
|
+
settled = void 0;
|
|
2177
|
+
throw cause;
|
|
2178
|
+
}
|
|
2179
|
+
);
|
|
2180
|
+
settled = pending;
|
|
2181
|
+
return pending;
|
|
2151
2182
|
}
|
|
2152
2183
|
};
|
|
2153
2184
|
},
|
|
@@ -2961,7 +2992,7 @@ async function generateFalVideo(req, ctx, deps) {
|
|
|
2961
2992
|
if (isKling(providerModelId)) {
|
|
2962
2993
|
const input = klingO1Input(req);
|
|
2963
2994
|
if (ctx.routing.fal === "cloudflare-passthrough") {
|
|
2964
|
-
return passthroughVideoJob(ctx, req, KLING_O1_ENDPOINT, input);
|
|
2995
|
+
return await passthroughVideoJob(ctx, req, KLING_O1_ENDPOINT, input);
|
|
2965
2996
|
}
|
|
2966
2997
|
const result2 = await runJob(ctx, deps, KLING_O1_ENDPOINT, input);
|
|
2967
2998
|
return completedVideoJob(
|
|
@@ -2996,7 +3027,7 @@ async function generateFalVideo(req, ctx, deps) {
|
|
|
2996
3027
|
base.aspect_ratio = req.aspectRatio ?? "adaptive";
|
|
2997
3028
|
}
|
|
2998
3029
|
if (ctx.routing.fal === "cloudflare-passthrough") {
|
|
2999
|
-
return passthroughVideoJob(ctx, req, endpoint, base);
|
|
3030
|
+
return await passthroughVideoJob(ctx, req, endpoint, base);
|
|
3000
3031
|
}
|
|
3001
3032
|
const result = await runJob(ctx, deps, endpoint, base);
|
|
3002
3033
|
return completedVideoJob(ctx, req, extractVideoUrl(result, endpoint, ctx.model.id), result);
|
|
@@ -3014,31 +3045,26 @@ function completedVideoJob(ctx, req, url, raw) {
|
|
|
3014
3045
|
}
|
|
3015
3046
|
};
|
|
3016
3047
|
}
|
|
3017
|
-
function passthroughVideoJob(ctx, req, endpoint, input) {
|
|
3048
|
+
async function passthroughVideoJob(ctx, req, endpoint, input) {
|
|
3018
3049
|
const cfg = gatewayConfig(ctx);
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3050
|
+
const res = await gatewayFetch(cfg, ctx.fetch, `${FAL_QUEUE_HOST}/${endpoint}`, {
|
|
3051
|
+
method: "POST",
|
|
3052
|
+
body: JSON.stringify({ ...input, sync_mode: true })
|
|
3053
|
+
});
|
|
3054
|
+
if (!res.ok) throw falError(res.status, await readBody(res), ctx.model.id);
|
|
3055
|
+
const parsed = falQueueSubmitSchema.safeParse(await res.json());
|
|
3056
|
+
if (!parsed.success) {
|
|
3057
|
+
throw new ModelKitError({
|
|
3058
|
+
code: "provider_rejected",
|
|
3059
|
+
message: `fal ${endpoint} submit returned no status URL`,
|
|
3060
|
+
provider: "fal",
|
|
3061
|
+
model: ctx.model.id,
|
|
3062
|
+
retryable: false
|
|
3024
3063
|
});
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
if (!parsed.success) {
|
|
3028
|
-
throw new ModelKitError({
|
|
3029
|
-
code: "provider_rejected",
|
|
3030
|
-
message: `fal ${endpoint} submit returned no status URL`,
|
|
3031
|
-
provider: "fal",
|
|
3032
|
-
model: ctx.model.id,
|
|
3033
|
-
retryable: false
|
|
3034
|
-
});
|
|
3035
|
-
}
|
|
3036
|
-
statusUrl = parsed.data.status_url;
|
|
3037
|
-
return parsed.data;
|
|
3038
|
-
})();
|
|
3064
|
+
}
|
|
3065
|
+
const { request_id: jobId, status_url, response_url } = parsed.data;
|
|
3039
3066
|
const checkStatus = async () => {
|
|
3040
|
-
const
|
|
3041
|
-
const statusRes = await gatewayFetch(cfg, ctx.fetch, statusUrl ?? "", { method: "GET" });
|
|
3067
|
+
const statusRes = await gatewayFetch(cfg, ctx.fetch, status_url, { method: "GET" });
|
|
3042
3068
|
if (!statusRes.ok)
|
|
3043
3069
|
throw falError(statusRes.status, await readBody(statusRes), ctx.model.id);
|
|
3044
3070
|
const statusParsed = falQueueStatusSchema.safeParse(await statusRes.json());
|
|
@@ -3052,7 +3078,7 @@ function passthroughVideoJob(ctx, req, endpoint, input) {
|
|
|
3052
3078
|
};
|
|
3053
3079
|
const duration = req.durationSeconds ?? 5;
|
|
3054
3080
|
return {
|
|
3055
|
-
jobId
|
|
3081
|
+
jobId,
|
|
3056
3082
|
async poll() {
|
|
3057
3083
|
try {
|
|
3058
3084
|
const url = await checkStatus();
|
|
@@ -4618,6 +4644,7 @@ var openaiImageAdapter = {
|
|
|
4618
4644
|
const refs = req.references ?? [];
|
|
4619
4645
|
const isEdit = refs.length > 0;
|
|
4620
4646
|
const quality = req.quality ?? (isEdit ? "medium" : "auto");
|
|
4647
|
+
const sdkQuality = quality;
|
|
4621
4648
|
const count = req.count !== void 0 && req.count > 1 ? { n: req.count } : {};
|
|
4622
4649
|
const retryOptions = {};
|
|
4623
4650
|
if (ctx.signal !== void 0) retryOptions.signal = ctx.signal;
|
|
@@ -4629,14 +4656,14 @@ var openaiImageAdapter = {
|
|
|
4629
4656
|
model: ctx.model.providerModelId,
|
|
4630
4657
|
prompt: req.prompt,
|
|
4631
4658
|
size,
|
|
4632
|
-
quality,
|
|
4659
|
+
quality: sdkQuality,
|
|
4633
4660
|
...count
|
|
4634
4661
|
});
|
|
4635
4662
|
}
|
|
4636
4663
|
return await client2.images.generate({
|
|
4637
4664
|
model: ctx.model.providerModelId,
|
|
4638
4665
|
prompt: req.prompt,
|
|
4639
|
-
quality,
|
|
4666
|
+
quality: sdkQuality,
|
|
4640
4667
|
...count
|
|
4641
4668
|
});
|
|
4642
4669
|
}
|
|
@@ -4655,7 +4682,7 @@ var openaiImageAdapter = {
|
|
|
4655
4682
|
image: imageInput,
|
|
4656
4683
|
prompt: req.prompt,
|
|
4657
4684
|
size,
|
|
4658
|
-
quality,
|
|
4685
|
+
quality: sdkQuality,
|
|
4659
4686
|
...count
|
|
4660
4687
|
});
|
|
4661
4688
|
}
|
|
@@ -4663,7 +4690,7 @@ var openaiImageAdapter = {
|
|
|
4663
4690
|
model: ctx.model.providerModelId,
|
|
4664
4691
|
image: imageInput,
|
|
4665
4692
|
prompt: req.prompt,
|
|
4666
|
-
quality,
|
|
4693
|
+
quality: sdkQuality,
|
|
4667
4694
|
...count
|
|
4668
4695
|
});
|
|
4669
4696
|
} catch (cause) {
|
|
@@ -4884,7 +4911,7 @@ async function generateProdiaImage(req, ctx) {
|
|
|
4884
4911
|
});
|
|
4885
4912
|
} catch (err) {
|
|
4886
4913
|
if (isModelKitError(err)) throw err;
|
|
4887
|
-
throw
|
|
4914
|
+
throw transportError("prodia", err, ctx.model.id);
|
|
4888
4915
|
}
|
|
4889
4916
|
if (!attemptRes.ok) {
|
|
4890
4917
|
const text2 = await attemptRes.text().catch(() => "");
|
|
@@ -4894,7 +4921,7 @@ async function generateProdiaImage(req, ctx) {
|
|
|
4894
4921
|
}, retryOpts);
|
|
4895
4922
|
} catch (err) {
|
|
4896
4923
|
if (isModelKitError(err)) throw err;
|
|
4897
|
-
throw
|
|
4924
|
+
throw transportError("prodia", err, ctx.model.id);
|
|
4898
4925
|
}
|
|
4899
4926
|
const bytes = parseImageResponse(
|
|
4900
4927
|
new Uint8Array(await res.arrayBuffer()),
|
|
@@ -5182,6 +5209,27 @@ function klingInput(req) {
|
|
|
5182
5209
|
if (req.negativePrompt !== void 0) input.negative_prompt = req.negativePrompt;
|
|
5183
5210
|
return input;
|
|
5184
5211
|
}
|
|
5212
|
+
function klingOmniInput(req) {
|
|
5213
|
+
const images = (req.firstFrame ? [req.firstFrame] : []).map(refToUrl3);
|
|
5214
|
+
if (req.lastFrame) images.push(refToUrl3(req.lastFrame));
|
|
5215
|
+
const input = {
|
|
5216
|
+
prompt: req.prompt,
|
|
5217
|
+
duration: req.durationSeconds ?? 10,
|
|
5218
|
+
mode: req.mode ?? "standard",
|
|
5219
|
+
generate_audio: req.generateAudio ?? false
|
|
5220
|
+
};
|
|
5221
|
+
const startImage = images[0];
|
|
5222
|
+
if (startImage !== void 0) {
|
|
5223
|
+
input.start_image = startImage;
|
|
5224
|
+
const endImage = images[1];
|
|
5225
|
+
if (endImage !== void 0) input.end_image = endImage;
|
|
5226
|
+
} else {
|
|
5227
|
+
input.aspect_ratio = req.aspectRatio ?? "16:9";
|
|
5228
|
+
}
|
|
5229
|
+
const refs = (req.referenceImages ?? []).map(refToUrl3);
|
|
5230
|
+
if (refs.length > 0) input.reference_images = refs;
|
|
5231
|
+
return input;
|
|
5232
|
+
}
|
|
5185
5233
|
function hailuoInput(req) {
|
|
5186
5234
|
const input = {
|
|
5187
5235
|
prompt: req.prompt,
|
|
@@ -5204,7 +5252,7 @@ function wanInput(req) {
|
|
|
5204
5252
|
}
|
|
5205
5253
|
async function generateReplicateVideo(req, ctx, deps) {
|
|
5206
5254
|
const id = isLower(ctx.model.providerModelId);
|
|
5207
|
-
const input = id.includes("kling") ? klingInput(req) : id.includes("hailuo") ? hailuoInput(req) : wanInput(req);
|
|
5255
|
+
const input = id.includes("kling") ? id.includes("omni") ? klingOmniInput(req) : klingInput(req) : id.includes("hailuo") ? hailuoInput(req) : wanInput(req);
|
|
5208
5256
|
const api = client(ctx, deps);
|
|
5209
5257
|
const createOptions = { ...route(ctx.model.providerModelId), input };
|
|
5210
5258
|
let prediction;
|
|
@@ -5294,6 +5342,9 @@ function lyriaAudioInput(req, ctx) {
|
|
|
5294
5342
|
if (negative) input.negative_prompt = negative;
|
|
5295
5343
|
return input;
|
|
5296
5344
|
}
|
|
5345
|
+
function elevenLabsMusicDuration(seconds) {
|
|
5346
|
+
return Math.min(300, Math.max(5, seconds ?? 15));
|
|
5347
|
+
}
|
|
5297
5348
|
function elevenLabsMusicInput(req, ctx) {
|
|
5298
5349
|
const prompt = req.prompt.trim();
|
|
5299
5350
|
if (!prompt) {
|
|
@@ -5305,10 +5356,9 @@ function elevenLabsMusicInput(req, ctx) {
|
|
|
5305
5356
|
retryable: false
|
|
5306
5357
|
});
|
|
5307
5358
|
}
|
|
5308
|
-
const seconds = Math.min(300, Math.max(5, req.durationSeconds ?? 15));
|
|
5309
5359
|
return {
|
|
5310
5360
|
prompt,
|
|
5311
|
-
music_length_ms:
|
|
5361
|
+
music_length_ms: elevenLabsMusicDuration(req.durationSeconds) * 1e3,
|
|
5312
5362
|
force_instrumental: req.instrumental ?? true,
|
|
5313
5363
|
output_format: "wav_cd_quality"
|
|
5314
5364
|
};
|
|
@@ -5348,7 +5398,7 @@ async function generateReplicateAudio(req, ctx, deps) {
|
|
|
5348
5398
|
const input = id.includes("mmaudio") ? mmaudioInput(req, ctx) : id.includes("elevenlabs") ? elevenLabsMusicInput(req, ctx) : lyriaAudioInput(req, ctx);
|
|
5349
5399
|
const { url, predictTime, raw } = await runPrediction(ctx, input, deps);
|
|
5350
5400
|
const usage2 = audioUsage(ctx, req);
|
|
5351
|
-
usage2.quantity = ctx.model.usage.unit === "seconds" ? req.durationSeconds
|
|
5401
|
+
usage2.quantity = ctx.model.usage.unit === "seconds" ? elevenLabsMusicDuration(req.durationSeconds) : predictTime;
|
|
5352
5402
|
return { audio: { url }, usage: usage2, raw: predictionRaw(raw) };
|
|
5353
5403
|
}
|
|
5354
5404
|
|