@shop-os/modelkit 0.8.0 → 0.9.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 +20 -0
- package/README.md +7 -1
- package/dist/catalog.cjs +450 -13
- package/dist/catalog.cjs.map +1 -1
- package/dist/catalog.d.cts +110 -5
- package/dist/catalog.d.ts +110 -5
- package/dist/catalog.js +450 -13
- package/dist/catalog.js.map +1 -1
- package/dist/index.cjs +954 -182
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +110 -4
- package/dist/index.d.ts +110 -4
- package/dist/index.js +951 -182
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -70,6 +70,7 @@ __export(index_exports, {
|
|
|
70
70
|
falAdapter: () => falAdapter,
|
|
71
71
|
falWebhookBodySchema: () => falWebhookBodySchema,
|
|
72
72
|
fileCatalogCache: () => fileCatalogCache,
|
|
73
|
+
fishAdapter: () => fishAdapter,
|
|
73
74
|
generateAudio: () => generateAudio,
|
|
74
75
|
generateImage: () => generateImage,
|
|
75
76
|
generateObject: () => generateObject,
|
|
@@ -122,6 +123,8 @@ __export(index_exports, {
|
|
|
122
123
|
resolveTranscriptionOptions: () => resolveTranscriptionOptions,
|
|
123
124
|
resolveVideoOptions: () => resolveVideoOptions,
|
|
124
125
|
resolveVoiceChangeOptions: () => resolveVoiceChangeOptions,
|
|
126
|
+
resolveVoiceCloneOptions: () => resolveVoiceCloneOptions,
|
|
127
|
+
resolveVoiceDesignOptions: () => resolveVoiceDesignOptions,
|
|
125
128
|
shouldRetry: () => shouldRetry,
|
|
126
129
|
sleep: () => sleep,
|
|
127
130
|
sortCatalogRows: () => sortCatalogRows,
|
|
@@ -1368,6 +1371,303 @@ var VEED_SUBTITLES = {
|
|
|
1368
1371
|
}
|
|
1369
1372
|
};
|
|
1370
1373
|
|
|
1374
|
+
// src/catalog/voices-fish.ts
|
|
1375
|
+
var FISH_VOICES = [
|
|
1376
|
+
{
|
|
1377
|
+
id: "933563129e564b19a115bedd57b7406a",
|
|
1378
|
+
name: "Sarah",
|
|
1379
|
+
gender: "female",
|
|
1380
|
+
languages: ["en"],
|
|
1381
|
+
description: "An engaged speaker.",
|
|
1382
|
+
previewUrl: "https://platform.r2.fish.audio/task/4e204945670c460c86fdab57512cb308.mp3"
|
|
1383
|
+
},
|
|
1384
|
+
{
|
|
1385
|
+
id: "bf322df2096a46f18c579d0baa36f41d",
|
|
1386
|
+
name: "Adrian",
|
|
1387
|
+
gender: "male",
|
|
1388
|
+
languages: ["en"],
|
|
1389
|
+
description: "A steady and reliable narrator.",
|
|
1390
|
+
previewUrl: "https://platform.r2.fish.audio/task/d730b09f4a484316a77ecc86137e85fb.mp3"
|
|
1391
|
+
},
|
|
1392
|
+
{
|
|
1393
|
+
id: "536d3a5e000945adb7038665781a4aca",
|
|
1394
|
+
name: "Ethan",
|
|
1395
|
+
gender: "male",
|
|
1396
|
+
languages: ["en"],
|
|
1397
|
+
description: "A curious explainer.",
|
|
1398
|
+
previewUrl: "https://platform.r2.fish.audio/task/bdd677ed767744fc91f166468786264b.mp3"
|
|
1399
|
+
},
|
|
1400
|
+
{
|
|
1401
|
+
id: "b347db033a6549378b48d00acb0d06cd",
|
|
1402
|
+
name: "Selene",
|
|
1403
|
+
gender: "female",
|
|
1404
|
+
languages: ["en"],
|
|
1405
|
+
description: "A meditative female voice.",
|
|
1406
|
+
previewUrl: "https://platform.r2.fish.audio/task/fcf629b4a0b343558f461338ba1b9da4.mp3"
|
|
1407
|
+
},
|
|
1408
|
+
{
|
|
1409
|
+
id: "9a9cf47702da476aa4629e2506d4a857",
|
|
1410
|
+
name: "Hannah",
|
|
1411
|
+
gender: "female",
|
|
1412
|
+
languages: ["en"],
|
|
1413
|
+
description: "A conversation specialist.",
|
|
1414
|
+
previewUrl: "https://platform.r2.fish.audio/task/08d658835feb427db808e37060b78eb0.mp3"
|
|
1415
|
+
},
|
|
1416
|
+
{
|
|
1417
|
+
id: "79d0bd3e4e5444b18f7b6d89b5927bf1",
|
|
1418
|
+
name: "Jordan",
|
|
1419
|
+
gender: "male",
|
|
1420
|
+
languages: ["en"],
|
|
1421
|
+
description: "A motivational speaker.",
|
|
1422
|
+
previewUrl: "https://platform.r2.fish.audio/task/edecbc0bdd4c46c39eda8520a0f729ef.mp3"
|
|
1423
|
+
},
|
|
1424
|
+
{
|
|
1425
|
+
id: "e3cd384158934cc9a01029cd7d278634",
|
|
1426
|
+
name: "Laura",
|
|
1427
|
+
gender: "female",
|
|
1428
|
+
languages: ["en"],
|
|
1429
|
+
description: "A confident female narrator.",
|
|
1430
|
+
previewUrl: "https://platform.r2.fish.audio/task/e821bef995344d519caa1c93d808db23.mp3"
|
|
1431
|
+
},
|
|
1432
|
+
{
|
|
1433
|
+
id: "f3a2b90078d54a65af4b95f63bc7798e",
|
|
1434
|
+
name: "Sheila",
|
|
1435
|
+
gender: "female",
|
|
1436
|
+
accent: "american",
|
|
1437
|
+
languages: ["en"],
|
|
1438
|
+
description: "A young American English woman's voice.",
|
|
1439
|
+
previewUrl: "https://platform.r2.fish.audio/tasks/2026-08-24/9bb9e1a1cf3f47f38700da1c5c0a678a.mp3"
|
|
1440
|
+
},
|
|
1441
|
+
{
|
|
1442
|
+
id: "0db6e93af420470b9d9b9a886dbaa954",
|
|
1443
|
+
name: "Kai",
|
|
1444
|
+
gender: "male",
|
|
1445
|
+
languages: ["en"],
|
|
1446
|
+
description: "A friendly English man's voice for companion apps and everyday conversation.",
|
|
1447
|
+
previewUrl: "https://platform.r2.fish.audio/tasks/2026-08-24/13306f1172544c3ba3106d1e363feaa6.mp3"
|
|
1448
|
+
},
|
|
1449
|
+
{
|
|
1450
|
+
id: "8abfa9ebd4c24a3399b68c3cdac8c7b5",
|
|
1451
|
+
name: "Freya",
|
|
1452
|
+
gender: "female",
|
|
1453
|
+
accent: "british",
|
|
1454
|
+
languages: ["en"],
|
|
1455
|
+
description: "A natural, professional British English voice with a brisk, conversational pace. Clear and easy to follow, suited to voice assistants, customer support and everyday narration.",
|
|
1456
|
+
previewUrl: "https://platform.r2.fish.audio/tasks/2026-08-25/07918705a56b42daaab149f65392cea7.mp3"
|
|
1457
|
+
},
|
|
1458
|
+
{
|
|
1459
|
+
id: "2f64e528a4f2406691925ab1e0ed5b7f",
|
|
1460
|
+
name: "Ananya",
|
|
1461
|
+
gender: "female",
|
|
1462
|
+
languages: ["hi"],
|
|
1463
|
+
description: "\u0938\u093E\u092B\u093C \u0914\u0930 \u0906\u0924\u094D\u092E\u0935\u093F\u0936\u094D\u0935\u093E\u0938 \u092D\u0930\u0940 \u0906\u0935\u093E\u091C\u093C, \u091C\u094B \u0935\u0949\u0907\u0938 \u0905\u0938\u093F\u0938\u094D\u091F\u0947\u0902\u091F, \u0917\u094D\u0930\u093E\u0939\u0915 \u0938\u0947\u0935\u093E \u0914\u0930 \u092A\u094D\u0930\u0938\u094D\u0924\u0941\u0924\u093F\u092F\u094B\u0902 \u0915\u0947 \u0932\u093F\u090F \u0909\u092A\u092F\u0941\u0915\u094D\u0924 \u0939\u0948\u0964",
|
|
1464
|
+
previewUrl: "https://platform.r2.fish.audio/tasks/2026-08-25/a17a700668d8405f8316db120733145c.mp3"
|
|
1465
|
+
},
|
|
1466
|
+
{
|
|
1467
|
+
id: "cefd91a07b99468f9148e2580990082d",
|
|
1468
|
+
name: "Arjun",
|
|
1469
|
+
gender: "male",
|
|
1470
|
+
languages: ["hi"],
|
|
1471
|
+
description: "\u0938\u093E\u092B\u093C \u0914\u0930 \u0906\u0924\u094D\u092E\u0935\u093F\u0936\u094D\u0935\u093E\u0938 \u092D\u0930\u0940 \u0906\u0935\u093E\u091C\u093C, \u091C\u094B \u0935\u0949\u0907\u0938 \u0905\u0938\u093F\u0938\u094D\u091F\u0947\u0902\u091F, \u0917\u094D\u0930\u093E\u0939\u0915 \u0938\u0947\u0935\u093E \u0914\u0930 \u092A\u094D\u0930\u0938\u094D\u0924\u0941\u0924\u093F\u092F\u094B\u0902 \u0915\u0947 \u0932\u093F\u090F \u0909\u092A\u092F\u0941\u0915\u094D\u0924 \u0939\u0948\u0964",
|
|
1472
|
+
previewUrl: "https://platform.r2.fish.audio/tasks/2026-08-24/a0c4a8eadb7841cdae8e5e68031a2dfb.mp3"
|
|
1473
|
+
},
|
|
1474
|
+
{
|
|
1475
|
+
id: "3f065d660212478a9c697fa965b4d098",
|
|
1476
|
+
name: "Carmen",
|
|
1477
|
+
gender: "female",
|
|
1478
|
+
languages: ["es"],
|
|
1479
|
+
description: "Una voz clara y segura para asistentes de voz, atenci\xF3n al cliente y presentaciones.",
|
|
1480
|
+
previewUrl: "https://platform.r2.fish.audio/tasks/2026-08-25/3421be48b6cb4c28bf829c25188e7e74.mp3"
|
|
1481
|
+
},
|
|
1482
|
+
{
|
|
1483
|
+
id: "ec0718028a2445fb9be8e8bfb56a0150",
|
|
1484
|
+
name: "Rodrigo",
|
|
1485
|
+
gender: "male",
|
|
1486
|
+
languages: ["es"],
|
|
1487
|
+
description: "Una voz clara y segura para asistentes de voz, atenci\xF3n al cliente y presentaciones.",
|
|
1488
|
+
previewUrl: "https://platform.r2.fish.audio/tasks/2026-08-25/5a77c32365604800ad5b4eb13c5585df.mp3"
|
|
1489
|
+
},
|
|
1490
|
+
{
|
|
1491
|
+
id: "10a3a20742114a4ea6dd441e7591850f",
|
|
1492
|
+
name: "Manon",
|
|
1493
|
+
gender: "female",
|
|
1494
|
+
languages: ["fr"],
|
|
1495
|
+
description: "Une voix claire et vive, adapt\xE9e aux assistants vocaux et au support client.",
|
|
1496
|
+
previewUrl: "https://platform.r2.fish.audio/tasks/2026-08-25/f7b75ee1fa524e48a8cefb003cf72952.mp3"
|
|
1497
|
+
},
|
|
1498
|
+
{
|
|
1499
|
+
id: "f69bca092b674168a8d02d61ca20943c",
|
|
1500
|
+
name: "Lucas",
|
|
1501
|
+
gender: "male",
|
|
1502
|
+
languages: ["fr"],
|
|
1503
|
+
description: "Une voix claire et assur\xE9e, adapt\xE9e aux assistants vocaux et au service client.",
|
|
1504
|
+
previewUrl: "https://platform.r2.fish.audio/tasks/2026-08-25/86fca3e56a014a3d8a11450854bb8311.mp3"
|
|
1505
|
+
},
|
|
1506
|
+
{
|
|
1507
|
+
id: "3937b44b604249f18b94913daef94043",
|
|
1508
|
+
name: "Lena",
|
|
1509
|
+
gender: "female",
|
|
1510
|
+
languages: ["de"],
|
|
1511
|
+
description: "Eine klare, souver\xE4ne Stimme f\xFCr Sprachassistenten, Kundenservice und Pr\xE4sentationen.",
|
|
1512
|
+
previewUrl: "https://platform.r2.fish.audio/tasks/2026-08-25/8659fec80b74442dab68a7755716a401.mp3"
|
|
1513
|
+
},
|
|
1514
|
+
{
|
|
1515
|
+
id: "c1e7cc926aa5469aa966c353094d4b0b",
|
|
1516
|
+
name: "Lukas",
|
|
1517
|
+
gender: "male",
|
|
1518
|
+
languages: ["de"],
|
|
1519
|
+
description: "Eine klare, souver\xE4ne Stimme f\xFCr Sprachassistenten, Kundenservice und Pr\xE4sentationen.",
|
|
1520
|
+
previewUrl: "https://platform.r2.fish.audio/tasks/2026-08-25/fb1d538126bb4fe38f8366250f6a2136.mp3"
|
|
1521
|
+
},
|
|
1522
|
+
{
|
|
1523
|
+
id: "b3c060cc41544a7da94a2c487647c902",
|
|
1524
|
+
name: "Let\xEDcia",
|
|
1525
|
+
gender: "female",
|
|
1526
|
+
accent: "brazilian",
|
|
1527
|
+
languages: ["pt"],
|
|
1528
|
+
description: "A Brazilian-accented Portuguese woman's voice, in her late twenties. Soft, warm, intimate. A freelance designer from Belo Horizonte who enjoys long walks in the park. Best suited to companion apps and casual everyday conversation.",
|
|
1529
|
+
previewUrl: "https://platform.r2.fish.audio/tasks/2026-10-12/13c6c0d96b5c4069951f89868ee15360.mp3"
|
|
1530
|
+
},
|
|
1531
|
+
{
|
|
1532
|
+
id: "add7bcb8d3c8423bbfa152ca232aad6e",
|
|
1533
|
+
name: "Ricardo",
|
|
1534
|
+
gender: "male",
|
|
1535
|
+
accent: "brazilian",
|
|
1536
|
+
languages: ["pt"],
|
|
1537
|
+
description: "A Brazilian-accented Portuguese man's voice, in his late forties. Clear, professional, monotone. A high school history teacher from Curitiba who loves classical music. Best suited to lessons, tutoring and explainer content.",
|
|
1538
|
+
previewUrl: "https://platform.r2.fish.audio/tasks/2026-10-12/67475fc717ae45cbb38e647a2dd37fe1.mp3"
|
|
1539
|
+
},
|
|
1540
|
+
{
|
|
1541
|
+
id: "b2d9d8db057042688a5e318b8f405bc2",
|
|
1542
|
+
name: "Kyoko",
|
|
1543
|
+
gender: "female",
|
|
1544
|
+
languages: ["ja"],
|
|
1545
|
+
description: "\u4E01\u5BE7\u3067\u843D\u3061\u7740\u3044\u305F\u8A71\u3057\u65B9\u304C\u7279\u5FB4\u306E\u5973\u6027\u306E\u58F0\u3002\u304A\u5BA2\u69D8\u5BFE\u5FDC\u3084\u60C5\u5831\u63D0\u4F9B\u306B\u6700\u9069\u3002",
|
|
1546
|
+
previewUrl: "https://platform.r2.fish.audio/task/993b3ccb52124341aff79580f1ce5a5a.mp3"
|
|
1547
|
+
},
|
|
1548
|
+
{
|
|
1549
|
+
id: "297a6fd278df47c3b9da9bfdf55ac89a",
|
|
1550
|
+
name: "Satoru",
|
|
1551
|
+
gender: "male",
|
|
1552
|
+
languages: ["ja"],
|
|
1553
|
+
description: "\u82E5\u3005\u3057\u304F\u3082\u843D\u3061\u7740\u304D\u306E\u3042\u308B\u7537\u6027\u306E\u58F0\u3002\u65E5\u5E38\u306E\u8A9E\u308A\u3084\u30EA\u30E9\u30C3\u30AF\u30B9\u3057\u305F\u30CA\u30EC\u30FC\u30B7\u30E7\u30F3\u306B\u6700\u9069\u3002",
|
|
1554
|
+
previewUrl: "https://platform.r2.fish.audio/task/1b4712fb831f4c149eef6b0133157418.mp3"
|
|
1555
|
+
},
|
|
1556
|
+
{
|
|
1557
|
+
id: "0b14f34a13a94ed88fe6113193749bb0",
|
|
1558
|
+
name: "Fatima",
|
|
1559
|
+
gender: "female",
|
|
1560
|
+
languages: ["ar"],
|
|
1561
|
+
description: "\u0635\u0648\u062A \u0648\u0627\u0636\u062D \u0648\u0648\u0627\u062B\u0642 \u064A\u0646\u0627\u0633\u0628 \u0627\u0644\u0645\u0633\u0627\u0639\u062F\u0627\u062A \u0627\u0644\u0635\u0648\u062A\u064A\u0629 \u0648\u062E\u062F\u0645\u0629 \u0627\u0644\u0639\u0645\u0644\u0627\u0621 \u0648\u0627\u0644\u0639\u0631\u0648\u0636 \u0627\u0644\u062A\u0642\u062F\u064A\u0645\u064A\u0629.",
|
|
1562
|
+
previewUrl: "https://platform.r2.fish.audio/tasks/2026-08-24/93406e1b905a4c4994306e3421243390.mp3"
|
|
1563
|
+
},
|
|
1564
|
+
{
|
|
1565
|
+
id: "74c6aba5cbf94a15bbdc547ffce5cb38",
|
|
1566
|
+
name: "Yutong",
|
|
1567
|
+
gender: "female",
|
|
1568
|
+
languages: ["zh"],
|
|
1569
|
+
description: "\u58F0\u97F3\u6E05\u6670\u81EA\u7136\uFF0C\u8868\u8FBE\u5229\u843D\uFF0C\u9002\u5408\u8BED\u97F3\u52A9\u624B\u3001\u5BA2\u670D\u548C\u65E5\u5E38\u64AD\u62A5\u3002",
|
|
1570
|
+
previewUrl: "https://platform.r2.fish.audio/tasks/2026-08-25/a48320f37fe44c4699549a1afc3778e8.mp3"
|
|
1571
|
+
}
|
|
1572
|
+
];
|
|
1573
|
+
|
|
1574
|
+
// src/catalog/speech-fish.ts
|
|
1575
|
+
var FISH_LOGO = "https://cdn.jsdelivr.net/npm/@lobehub/icons-static-png@1.97.0/light/fishaudio.png";
|
|
1576
|
+
var PER_CALL = { unit: "images" };
|
|
1577
|
+
var PER_REQUEST = { unit: "requests" };
|
|
1578
|
+
var TTS_MAX_CHARS = 1e4;
|
|
1579
|
+
function fishTts(id, label, providerModelId, description) {
|
|
1580
|
+
return {
|
|
1581
|
+
id,
|
|
1582
|
+
aliases: [],
|
|
1583
|
+
label,
|
|
1584
|
+
type: "speech",
|
|
1585
|
+
adapter: "fish",
|
|
1586
|
+
providerModelId,
|
|
1587
|
+
lifecycle: "active",
|
|
1588
|
+
exposure: [],
|
|
1589
|
+
constraints: {
|
|
1590
|
+
voices: FISH_VOICES,
|
|
1591
|
+
outputFormats: ["mp3", "wav"],
|
|
1592
|
+
supports: [],
|
|
1593
|
+
prompt: { referenceSyntax: "numbered", maxChars: TTS_MAX_CHARS }
|
|
1594
|
+
},
|
|
1595
|
+
defaults: { voice: "9a9cf47702da476aa4629e2506d4a857", outputFormat: "mp3" },
|
|
1596
|
+
usage: PER_CALL,
|
|
1597
|
+
pricingKind: "flat",
|
|
1598
|
+
display: { provider: "fishaudio", logo: FISH_LOGO, description },
|
|
1599
|
+
capabilities: { customVoices: true }
|
|
1600
|
+
};
|
|
1601
|
+
}
|
|
1602
|
+
var FISH_MODELS = [
|
|
1603
|
+
fishTts(
|
|
1604
|
+
"fish-s2.1-pro",
|
|
1605
|
+
"Fish Audio S2.1 Pro",
|
|
1606
|
+
"s2.1-pro",
|
|
1607
|
+
"Fish Audio S2.1 Pro text to speech in 83 languages, with [bracket] directions and your own cloned voices."
|
|
1608
|
+
),
|
|
1609
|
+
fishTts(
|
|
1610
|
+
"fish-s2.1-pro-free",
|
|
1611
|
+
"Fish Audio S2.1 Pro Free",
|
|
1612
|
+
"s2.1-pro-free",
|
|
1613
|
+
"Fish Audio S2.1 Pro on the free developer tier: the same voices at no cost, without latency or data-processing guarantees."
|
|
1614
|
+
),
|
|
1615
|
+
fishTts(
|
|
1616
|
+
"fish-drama-3",
|
|
1617
|
+
"Fish Audio Drama 3",
|
|
1618
|
+
"drama-3",
|
|
1619
|
+
"Fish Audio Drama 3 text to speech you direct like an actor: [directions], sounds, pauses and per-word tags."
|
|
1620
|
+
),
|
|
1621
|
+
{
|
|
1622
|
+
id: "fish-voice-clone",
|
|
1623
|
+
aliases: [],
|
|
1624
|
+
label: "Fish Audio Voice Clone",
|
|
1625
|
+
type: "voice-clone",
|
|
1626
|
+
adapter: "fish",
|
|
1627
|
+
providerModelId: "voice-clone",
|
|
1628
|
+
lifecycle: "active",
|
|
1629
|
+
exposure: [],
|
|
1630
|
+
constraints: {
|
|
1631
|
+
// POST /model takes 1-20 voice files; Fish advises 10 s or more of clean speech each.
|
|
1632
|
+
references: { audios: 20, audioFormats: ["wav", "mp3", "m4a", "opus"] },
|
|
1633
|
+
supports: []
|
|
1634
|
+
},
|
|
1635
|
+
defaults: {},
|
|
1636
|
+
usage: PER_REQUEST,
|
|
1637
|
+
pricingKind: "flat",
|
|
1638
|
+
display: {
|
|
1639
|
+
provider: "fishaudio",
|
|
1640
|
+
logo: FISH_LOGO,
|
|
1641
|
+
description: "Clone a private, reusable voice from one or more clean recordings, then speak with it on the Fish Audio speech models."
|
|
1642
|
+
},
|
|
1643
|
+
capabilities: {}
|
|
1644
|
+
},
|
|
1645
|
+
{
|
|
1646
|
+
id: "fish-voice-design-1",
|
|
1647
|
+
aliases: [],
|
|
1648
|
+
label: "Fish Audio Voice Design",
|
|
1649
|
+
type: "voice-design",
|
|
1650
|
+
adapter: "fish",
|
|
1651
|
+
providerModelId: "voice-design-1",
|
|
1652
|
+
lifecycle: "active",
|
|
1653
|
+
exposure: [],
|
|
1654
|
+
constraints: {
|
|
1655
|
+
voiceDesign: { maxCandidates: 4, previewMaxChars: 150 },
|
|
1656
|
+
supports: [],
|
|
1657
|
+
prompt: { referenceSyntax: "numbered", maxChars: 2e3 }
|
|
1658
|
+
},
|
|
1659
|
+
defaults: {},
|
|
1660
|
+
usage: PER_REQUEST,
|
|
1661
|
+
pricingKind: "flat",
|
|
1662
|
+
display: {
|
|
1663
|
+
provider: "fishaudio",
|
|
1664
|
+
logo: FISH_LOGO,
|
|
1665
|
+
description: "Describe a voice and get up to four short candidates; keep one as a cloned voice."
|
|
1666
|
+
},
|
|
1667
|
+
capabilities: {}
|
|
1668
|
+
}
|
|
1669
|
+
];
|
|
1670
|
+
|
|
1371
1671
|
// src/catalog/languages-audio.ts
|
|
1372
1672
|
var ELEVENLABS_V4_LANGUAGES = [
|
|
1373
1673
|
{ code: "af", name: "Afrikaans" },
|
|
@@ -3449,7 +3749,7 @@ var ELEVENLABS_LOGO = "https://cdn.jsdelivr.net/npm/@lobehub/icons-static-png@1.
|
|
|
3449
3749
|
var GOOGLE_LOGO = "https://d31vvfpk2ppdyq.cloudfront.net/assets/image/192485d2-a76a-4657-9c06-930b2c70badd_compressed.png";
|
|
3450
3750
|
var MINIMAX_LOGO = "https://d31vvfpk2ppdyq.cloudfront.net/assets/image/f4c2e906-28b7-4a4a-b491-df8fef7808ed.png";
|
|
3451
3751
|
var SYNC_LOGO = "https://cdn.jsdelivr.net/npm/@lobehub/icons-static-png@1.97.0/light/sync.png";
|
|
3452
|
-
var
|
|
3752
|
+
var PER_CALL2 = { unit: "images" };
|
|
3453
3753
|
var EXPOSURE4 = ["cowork", "space_builder"];
|
|
3454
3754
|
var LIPSYNC_AUDIO = { audioSeconds: { max: 30 } };
|
|
3455
3755
|
function elevenLabsTts(tts) {
|
|
@@ -3470,7 +3770,7 @@ function elevenLabsTts(tts) {
|
|
|
3470
3770
|
prompt: { referenceSyntax: "numbered", maxChars: tts.maxChars }
|
|
3471
3771
|
},
|
|
3472
3772
|
defaults: { voice: "Rachel", ...tts.formats && { outputFormat: "mp3_44100_128" } },
|
|
3473
|
-
usage:
|
|
3773
|
+
usage: PER_CALL2,
|
|
3474
3774
|
pricingKind: "flat",
|
|
3475
3775
|
display: { provider: "elevenlabs", logo: ELEVENLABS_LOGO, description: tts.description },
|
|
3476
3776
|
capabilities: {}
|
|
@@ -3494,7 +3794,7 @@ function geminiTts(id, label, description) {
|
|
|
3494
3794
|
prompt: { referenceSyntax: "numbered", maxChars: 8192 }
|
|
3495
3795
|
},
|
|
3496
3796
|
defaults: { voice: "Kore" },
|
|
3497
|
-
usage:
|
|
3797
|
+
usage: PER_CALL2,
|
|
3498
3798
|
pricingKind: "flat",
|
|
3499
3799
|
display: { provider: "google", logo: GOOGLE_LOGO, description },
|
|
3500
3800
|
capabilities: {}
|
|
@@ -3517,7 +3817,7 @@ function syncLipsync(id, label, providerModelId, syncModel, description) {
|
|
|
3517
3817
|
},
|
|
3518
3818
|
defaults: {},
|
|
3519
3819
|
...syncModel !== void 0 && { providerOptions: { fal: { model: syncModel } } },
|
|
3520
|
-
usage:
|
|
3820
|
+
usage: PER_CALL2,
|
|
3521
3821
|
pricingKind: "flat",
|
|
3522
3822
|
display: { provider: "sync", logo: SYNC_LOGO, description },
|
|
3523
3823
|
capabilities: { acceptsSourceVideo: true }
|
|
@@ -3578,7 +3878,7 @@ var MEDIA_NODE_MODELS = [
|
|
|
3578
3878
|
prompt: { referenceSyntax: "numbered", maxChars: 1e4 }
|
|
3579
3879
|
},
|
|
3580
3880
|
defaults: { voice: "Wise_Woman" },
|
|
3581
|
-
usage:
|
|
3881
|
+
usage: PER_CALL2,
|
|
3582
3882
|
pricingKind: "flat",
|
|
3583
3883
|
display: {
|
|
3584
3884
|
provider: "minimax",
|
|
@@ -3605,7 +3905,7 @@ var MEDIA_NODE_MODELS = [
|
|
|
3605
3905
|
supports: []
|
|
3606
3906
|
},
|
|
3607
3907
|
defaults: { voice: "Rachel", outputFormat: "mp3_44100_128" },
|
|
3608
|
-
usage:
|
|
3908
|
+
usage: PER_CALL2,
|
|
3609
3909
|
pricingKind: "flat",
|
|
3610
3910
|
display: {
|
|
3611
3911
|
provider: "elevenlabs",
|
|
@@ -3632,7 +3932,7 @@ var MEDIA_NODE_MODELS = [
|
|
|
3632
3932
|
supports: []
|
|
3633
3933
|
},
|
|
3634
3934
|
defaults: {},
|
|
3635
|
-
usage:
|
|
3935
|
+
usage: PER_CALL2,
|
|
3636
3936
|
pricingKind: "flat",
|
|
3637
3937
|
display: {
|
|
3638
3938
|
provider: "elevenlabs",
|
|
@@ -3679,7 +3979,7 @@ var MEDIA_NODE_MODELS = [
|
|
|
3679
3979
|
supports: []
|
|
3680
3980
|
},
|
|
3681
3981
|
defaults: {},
|
|
3682
|
-
usage:
|
|
3982
|
+
usage: PER_CALL2,
|
|
3683
3983
|
pricingKind: "flat",
|
|
3684
3984
|
display: {
|
|
3685
3985
|
provider: "veed",
|
|
@@ -3731,7 +4031,7 @@ var MEDIA_NODE_MODELS = [
|
|
|
3731
4031
|
supports: []
|
|
3732
4032
|
},
|
|
3733
4033
|
defaults: {},
|
|
3734
|
-
usage:
|
|
4034
|
+
usage: PER_CALL2,
|
|
3735
4035
|
pricingKind: "flat",
|
|
3736
4036
|
display: {
|
|
3737
4037
|
provider: "elevenlabs",
|
|
@@ -3740,7 +4040,8 @@ var MEDIA_NODE_MODELS = [
|
|
|
3740
4040
|
},
|
|
3741
4041
|
capabilities: {}
|
|
3742
4042
|
},
|
|
3743
|
-
SAM_3_IMAGE
|
|
4043
|
+
SAM_3_IMAGE,
|
|
4044
|
+
...FISH_MODELS
|
|
3744
4045
|
];
|
|
3745
4046
|
|
|
3746
4047
|
// src/catalog/model3d.ts
|
|
@@ -7375,7 +7676,8 @@ var ADAPTER_IDS = [
|
|
|
7375
7676
|
"prodia",
|
|
7376
7677
|
"higgsfield",
|
|
7377
7678
|
"xai-video",
|
|
7378
|
-
"luma"
|
|
7679
|
+
"luma",
|
|
7680
|
+
"fish"
|
|
7379
7681
|
];
|
|
7380
7682
|
var ModelTypeSchema = import_zod3.z.enum([
|
|
7381
7683
|
"text",
|
|
@@ -7392,6 +7694,8 @@ var ModelTypeSchema = import_zod3.z.enum([
|
|
|
7392
7694
|
"dubbing",
|
|
7393
7695
|
"lipsync",
|
|
7394
7696
|
"transcription",
|
|
7697
|
+
"voice-clone",
|
|
7698
|
+
"voice-design",
|
|
7395
7699
|
"model3d"
|
|
7396
7700
|
]);
|
|
7397
7701
|
var LifecycleSchema = import_zod3.z.enum(["active", "deprecated", "retired"]);
|
|
@@ -7567,6 +7871,10 @@ var ModelConstraintsSchema = import_zod3.z.looseObject({
|
|
|
7567
7871
|
supports: import_zod3.z.array(SupportedOptionSchema).optional(),
|
|
7568
7872
|
ratioIgnoredWith: import_zod3.z.array(import_zod3.z.enum(["firstFrame", "sourceVideo"])).optional(),
|
|
7569
7873
|
voices: import_zod3.z.array(VoiceOptionSchema).optional(),
|
|
7874
|
+
voiceDesign: import_zod3.z.object({
|
|
7875
|
+
maxCandidates: import_zod3.z.number().int().positive(),
|
|
7876
|
+
previewMaxChars: import_zod3.z.number().int().positive()
|
|
7877
|
+
}).optional(),
|
|
7570
7878
|
languages: import_zod3.z.array(LanguageOptionSchema).optional(),
|
|
7571
7879
|
outputFormats: import_zod3.z.array(import_zod3.z.string().min(1)).min(1).optional(),
|
|
7572
7880
|
sourceVideoSeconds: VideoSecondsLimitsSchema.omit({ total: true }).extend({ inReferenceTotal: import_zod3.z.boolean().optional() }).optional(),
|
|
@@ -7665,6 +7973,7 @@ var CatalogDisplaySchema = import_zod3.z.looseObject({
|
|
|
7665
7973
|
});
|
|
7666
7974
|
var CatalogCapabilitiesSchema = import_zod3.z.looseObject({
|
|
7667
7975
|
acceptsSourceVideo: import_zod3.z.boolean().optional(),
|
|
7976
|
+
customVoices: import_zod3.z.boolean().optional(),
|
|
7668
7977
|
videoEdit: import_zod3.z.boolean().optional(),
|
|
7669
7978
|
framesExcludeReferences: import_zod3.z.boolean().optional(),
|
|
7670
7979
|
sourceVideoExcludesFrames: import_zod3.z.boolean().optional(),
|
|
@@ -8184,7 +8493,7 @@ var errorCodes = import_zod6.z.object({
|
|
|
8184
8493
|
type: import_zod6.z.string().optional(),
|
|
8185
8494
|
error: import_zod6.z.object({ code: import_zod6.z.string().optional(), type: import_zod6.z.string().optional() }).optional()
|
|
8186
8495
|
});
|
|
8187
|
-
var BILLING_TEXT = /insufficient_quota|payment[ _]required|exhausted balance|insufficient (?:credits?|balance|funds)|billing_hard_limit/i;
|
|
8496
|
+
var BILLING_TEXT = /insufficient_quota|payment[ _]required|exhausted balance|insufficient (?:credits?|balance|funds)|billing_hard_limit|top up (?:api )?credit/i;
|
|
8188
8497
|
var BILLING_TEXT_STATUSES = /* @__PURE__ */ new Set([403, 429]);
|
|
8189
8498
|
function billingCode(body) {
|
|
8190
8499
|
const parsed = errorCodes.safeParse(body);
|
|
@@ -8581,16 +8890,16 @@ async function generateSeedreamImage(req, ctx) {
|
|
|
8581
8890
|
} else {
|
|
8582
8891
|
throwArkError(void 0, "Seedream returned no image URL or base64 data", modelId);
|
|
8583
8892
|
}
|
|
8584
|
-
const
|
|
8893
|
+
const usage4 = {
|
|
8585
8894
|
model: modelId,
|
|
8586
8895
|
provider: "ark",
|
|
8587
8896
|
modality: "IMAGE",
|
|
8588
8897
|
unit: "images",
|
|
8589
8898
|
quantity: 1
|
|
8590
8899
|
};
|
|
8591
|
-
if (req.size !== void 0)
|
|
8592
|
-
if (req.quality !== void 0)
|
|
8593
|
-
return { images: [{ bytes, mime: sniffedImageMime(bytes) }], usage:
|
|
8900
|
+
if (req.size !== void 0) usage4.imageSize = req.size;
|
|
8901
|
+
if (req.quality !== void 0) usage4.imageQuality = req.quality;
|
|
8902
|
+
return { images: [{ bytes, mime: sniffedImageMime(bytes) }], usage: usage4, raw: data };
|
|
8594
8903
|
}
|
|
8595
8904
|
var SeedanceUsageSchema = import_zod7.z.object({
|
|
8596
8905
|
total_tokens: import_zod7.z.number().optional(),
|
|
@@ -8631,7 +8940,7 @@ function seedanceErrorMessage(error, status) {
|
|
|
8631
8940
|
if (asObject.success && asObject.data.message !== void 0) return asObject.data.message;
|
|
8632
8941
|
return `Seedance task ${status}`;
|
|
8633
8942
|
}
|
|
8634
|
-
function seedanceJob(ctx, key, jobId,
|
|
8943
|
+
function seedanceJob(ctx, key, jobId, usage4) {
|
|
8635
8944
|
const modelId = ctx.model.id;
|
|
8636
8945
|
const fetchStatus = async () => {
|
|
8637
8946
|
const res = await arkFetch(ctx, `${arkBaseUrl(ctx)}${SUBMIT_PATH}/${jobId}`, {
|
|
@@ -8681,21 +8990,21 @@ function seedanceJob(ctx, key, jobId, usage3) {
|
|
|
8681
8990
|
modelId
|
|
8682
8991
|
);
|
|
8683
8992
|
if (polled.duration !== void 0 && polled.duration > 0) {
|
|
8684
|
-
|
|
8685
|
-
|
|
8993
|
+
usage4.quantity = polled.duration;
|
|
8994
|
+
usage4.durationSeconds = polled.duration;
|
|
8686
8995
|
}
|
|
8687
8996
|
const rendered = VideoResolutionSchema.safeParse(
|
|
8688
8997
|
polled.resolution?.toLowerCase()
|
|
8689
8998
|
);
|
|
8690
|
-
if (rendered.success)
|
|
8999
|
+
if (rendered.success) usage4.resolution = rendered.data;
|
|
8691
9000
|
const tokens = polled.usage;
|
|
8692
9001
|
if (tokens?.total_tokens !== void 0 && tokens.completion_tokens !== void 0) {
|
|
8693
|
-
|
|
8694
|
-
|
|
9002
|
+
usage4.inputTokens = tokens.total_tokens - tokens.completion_tokens;
|
|
9003
|
+
usage4.outputTokens = tokens.completion_tokens;
|
|
8695
9004
|
}
|
|
8696
9005
|
return {
|
|
8697
9006
|
video: { url, expiresAt: new Date(Date.now() + VIDEO_URL_TTL_MS) },
|
|
8698
|
-
usage:
|
|
9007
|
+
usage: usage4,
|
|
8699
9008
|
raw: polled
|
|
8700
9009
|
};
|
|
8701
9010
|
}
|
|
@@ -8801,8 +9110,8 @@ async function generateSeedanceVideo(req, ctx) {
|
|
|
8801
9110
|
);
|
|
8802
9111
|
if (!submit.id) throwArkError(void 0, "Seedance task create returned no id", modelId);
|
|
8803
9112
|
const jobId = submit.id;
|
|
8804
|
-
const
|
|
8805
|
-
return seedanceJob(ctx, key, jobId,
|
|
9113
|
+
const usage4 = seedanceUsage(ctx, req, taskType === "edit" ? requestedDuration : duration);
|
|
9114
|
+
return seedanceJob(ctx, key, jobId, usage4);
|
|
8806
9115
|
}
|
|
8807
9116
|
|
|
8808
9117
|
// src/adapters/fal.ts
|
|
@@ -10290,7 +10599,7 @@ async function collectFalPlanImages(payload, plan4, ctx, req) {
|
|
|
10290
10599
|
return { bytes, mime: mime || "image/png" };
|
|
10291
10600
|
})
|
|
10292
10601
|
);
|
|
10293
|
-
const
|
|
10602
|
+
const usage4 = {
|
|
10294
10603
|
model: ctx.model.id,
|
|
10295
10604
|
provider: "fal",
|
|
10296
10605
|
modality: "IMAGE",
|
|
@@ -10298,9 +10607,9 @@ async function collectFalPlanImages(payload, plan4, ctx, req) {
|
|
|
10298
10607
|
quantity: images.length
|
|
10299
10608
|
};
|
|
10300
10609
|
const billedSize = plan4.imageSize ?? req.size;
|
|
10301
|
-
if (billedSize !== void 0 && ctx.model.type === "image")
|
|
10302
|
-
if (plan4.imageQuality !== void 0)
|
|
10303
|
-
const result = { images, usage:
|
|
10610
|
+
if (billedSize !== void 0 && ctx.model.type === "image") usage4.imageSize = billedSize;
|
|
10611
|
+
if (plan4.imageQuality !== void 0) usage4.imageQuality = plan4.imageQuality;
|
|
10612
|
+
const result = { images, usage: usage4, raw: payload };
|
|
10304
10613
|
const remote = files.find((f) => !f.url.startsWith("data:"));
|
|
10305
10614
|
if (remote !== void 0) result.outputUrl = remote.url;
|
|
10306
10615
|
return result;
|
|
@@ -12463,12 +12772,295 @@ function planUsage(ctx, plan4) {
|
|
|
12463
12772
|
};
|
|
12464
12773
|
}
|
|
12465
12774
|
|
|
12775
|
+
// src/adapters/fish.ts
|
|
12776
|
+
var import_zod21 = require("zod");
|
|
12777
|
+
var DEFAULT_BASE_URL = "https://api.fish.audio";
|
|
12778
|
+
var FISH_TTS_MODEL_IDS = /* @__PURE__ */ new Set([
|
|
12779
|
+
"s2.1-pro",
|
|
12780
|
+
"s2.1-pro-free",
|
|
12781
|
+
"drama-3"
|
|
12782
|
+
]);
|
|
12783
|
+
var FISH_VOICE_CLONE = "voice-clone";
|
|
12784
|
+
var FISH_VOICE_DESIGN = "voice-design-1";
|
|
12785
|
+
var VOICE_ID = /^[A-Za-z0-9_-]{1,64}$/;
|
|
12786
|
+
function fishRowRefusal(row2) {
|
|
12787
|
+
const id = row2.providerModelId;
|
|
12788
|
+
if (row2.type === "speech") {
|
|
12789
|
+
return FISH_TTS_MODEL_IDS.has(id) ? void 0 : `fish speech rows need providerModelId ${[...FISH_TTS_MODEL_IDS].join(", ")}`;
|
|
12790
|
+
}
|
|
12791
|
+
if (row2.type === "voice-clone") {
|
|
12792
|
+
return id === FISH_VOICE_CLONE ? void 0 : `fish voice-clone rows need providerModelId ${FISH_VOICE_CLONE}`;
|
|
12793
|
+
}
|
|
12794
|
+
if (row2.type === "voice-design") {
|
|
12795
|
+
return id === FISH_VOICE_DESIGN ? void 0 : `fish voice-design rows need providerModelId ${FISH_VOICE_DESIGN}`;
|
|
12796
|
+
}
|
|
12797
|
+
return `fish has no ${row2.type} rows`;
|
|
12798
|
+
}
|
|
12799
|
+
function fishError(ctx, code, message) {
|
|
12800
|
+
return new ModelKitError({
|
|
12801
|
+
code,
|
|
12802
|
+
message,
|
|
12803
|
+
provider: "fish",
|
|
12804
|
+
model: ctx.model.id,
|
|
12805
|
+
retryable: false
|
|
12806
|
+
});
|
|
12807
|
+
}
|
|
12808
|
+
function checkRow(ctx, type) {
|
|
12809
|
+
const refusal2 = ctx.model.type === type ? fishRowRefusal(ctx.model) : void 0;
|
|
12810
|
+
if (ctx.model.type !== type || refusal2 !== void 0) {
|
|
12811
|
+
throw fishError(
|
|
12812
|
+
ctx,
|
|
12813
|
+
"unsupported_option",
|
|
12814
|
+
refusal2 ?? `${ctx.model.id} is not a ${type} row`
|
|
12815
|
+
);
|
|
12816
|
+
}
|
|
12817
|
+
}
|
|
12818
|
+
function checkVoiceId(ctx, field, id) {
|
|
12819
|
+
if (!VOICE_ID.test(id))
|
|
12820
|
+
throw fishError(ctx, "unsupported_option", `${field} is not a voice id`);
|
|
12821
|
+
return id;
|
|
12822
|
+
}
|
|
12823
|
+
function fishKey(ctx) {
|
|
12824
|
+
const key = ctx.keys.fish;
|
|
12825
|
+
if (!key) throw fishError(ctx, "auth", "Missing API key for fish");
|
|
12826
|
+
return key;
|
|
12827
|
+
}
|
|
12828
|
+
function fishUrl(ctx, path) {
|
|
12829
|
+
return `${ctx.endpoints?.fish ?? DEFAULT_BASE_URL}${path}`;
|
|
12830
|
+
}
|
|
12831
|
+
async function fishFetch(ctx, path, init) {
|
|
12832
|
+
throwIfAborted(ctx.signal);
|
|
12833
|
+
const request = {
|
|
12834
|
+
method: init.method,
|
|
12835
|
+
headers: { Authorization: `Bearer ${fishKey(ctx)}`, ...init.headers }
|
|
12836
|
+
};
|
|
12837
|
+
if (init.body !== void 0) request.body = init.body;
|
|
12838
|
+
if (ctx.signal !== void 0) request.signal = ctx.signal;
|
|
12839
|
+
let res;
|
|
12840
|
+
try {
|
|
12841
|
+
res = await ctx.fetch(fishUrl(ctx, path), request);
|
|
12842
|
+
} catch (cause) {
|
|
12843
|
+
throw classifyThrown("fish", cause, ctx.model.id);
|
|
12844
|
+
}
|
|
12845
|
+
if (!res.ok) throw classifyHttpError(res.status, await readBody(res), "fish", ctx.model.id);
|
|
12846
|
+
return res;
|
|
12847
|
+
}
|
|
12848
|
+
function usage2(ctx) {
|
|
12849
|
+
return {
|
|
12850
|
+
model: ctx.model.id,
|
|
12851
|
+
provider: "fish",
|
|
12852
|
+
modality: "AUDIO",
|
|
12853
|
+
unit: ctx.model.usage.unit,
|
|
12854
|
+
quantity: 1
|
|
12855
|
+
};
|
|
12856
|
+
}
|
|
12857
|
+
function audioMime(res, format) {
|
|
12858
|
+
const header = res.headers.get("content-type")?.split(";")[0]?.trim().toLowerCase();
|
|
12859
|
+
if (header?.startsWith("audio/")) return header;
|
|
12860
|
+
return format === "wav" ? "audio/wav" : "audio/mpeg";
|
|
12861
|
+
}
|
|
12862
|
+
async function generateSpeech(req, ctx) {
|
|
12863
|
+
checkRow(ctx, "speech");
|
|
12864
|
+
const format = req.outputFormat ?? "mp3";
|
|
12865
|
+
const body = { text: req.text, format };
|
|
12866
|
+
const voice = req.customVoice ?? req.voice;
|
|
12867
|
+
if (voice !== void 0) {
|
|
12868
|
+
body.reference_id = checkVoiceId(ctx, req.customVoice ? "customVoice" : "voice", voice);
|
|
12869
|
+
}
|
|
12870
|
+
if (req.language !== void 0) body.language = req.language;
|
|
12871
|
+
const { bytes, mime } = await withRetry(
|
|
12872
|
+
async () => {
|
|
12873
|
+
const res = await fishFetch(ctx, "/v1/tts", {
|
|
12874
|
+
method: "POST",
|
|
12875
|
+
headers: { "Content-Type": "application/json", model: ctx.model.providerModelId },
|
|
12876
|
+
body: JSON.stringify(body)
|
|
12877
|
+
});
|
|
12878
|
+
let audio;
|
|
12879
|
+
try {
|
|
12880
|
+
audio = new Uint8Array(await res.arrayBuffer());
|
|
12881
|
+
} catch (cause) {
|
|
12882
|
+
throw classifyThrown("fish", cause, ctx.model.id);
|
|
12883
|
+
}
|
|
12884
|
+
return { bytes: audio, mime: audioMime(res, format) };
|
|
12885
|
+
},
|
|
12886
|
+
mediaRetryOptions(ctx.call, ctx.signal)
|
|
12887
|
+
);
|
|
12888
|
+
if (bytes.byteLength === 0)
|
|
12889
|
+
throw fishError(ctx, "provider_rejected", "Fish TTS returned no audio");
|
|
12890
|
+
return { audio: { bytes, mime }, usage: usage2(ctx) };
|
|
12891
|
+
}
|
|
12892
|
+
var createdModelSchema = import_zod21.z.object({
|
|
12893
|
+
_id: import_zod21.z.string().min(1),
|
|
12894
|
+
state: import_zod21.z.enum(["created", "training", "trained", "failed"]).optional().catch(void 0)
|
|
12895
|
+
});
|
|
12896
|
+
function fileName(index, mime) {
|
|
12897
|
+
const ext = mime.split("/")[1]?.replace("mpeg", "mp3").replace("x-", "") || "bin";
|
|
12898
|
+
return `sample-${index + 1}.${ext}`;
|
|
12899
|
+
}
|
|
12900
|
+
function allOrNone(ctx, field, values) {
|
|
12901
|
+
const set = values.filter((v) => v !== void 0 && v.trim() !== "");
|
|
12902
|
+
if (set.length === 0) return [];
|
|
12903
|
+
if (set.length !== values.length) {
|
|
12904
|
+
throw fishError(ctx, "missing_input", `set ${field} on every sample or on none`);
|
|
12905
|
+
}
|
|
12906
|
+
return set;
|
|
12907
|
+
}
|
|
12908
|
+
async function cloneForm(req, ctx) {
|
|
12909
|
+
if (req.samples.length === 0) throw fishError(ctx, "missing_input", "needs a voice sample");
|
|
12910
|
+
const transcripts = allOrNone(
|
|
12911
|
+
ctx,
|
|
12912
|
+
"transcript",
|
|
12913
|
+
req.samples.map((s) => s.transcript)
|
|
12914
|
+
);
|
|
12915
|
+
const signatures = allOrNone(
|
|
12916
|
+
ctx,
|
|
12917
|
+
"designSignature",
|
|
12918
|
+
req.samples.map((s) => s.designSignature)
|
|
12919
|
+
);
|
|
12920
|
+
const form = new FormData();
|
|
12921
|
+
form.append("type", "tts");
|
|
12922
|
+
form.append("train_mode", "fast");
|
|
12923
|
+
form.append("visibility", "private");
|
|
12924
|
+
form.append("title", req.title.trim());
|
|
12925
|
+
if (req.description?.trim()) form.append("description", req.description.trim());
|
|
12926
|
+
if (req.enhance !== void 0) form.append("enhance_audio_quality", String(req.enhance));
|
|
12927
|
+
for (const [index, sample] of req.samples.entries()) {
|
|
12928
|
+
const { bytes, mime } = await mediaRefToBytes(sample.audio, ctx.fetch, {
|
|
12929
|
+
signal: ctx.signal,
|
|
12930
|
+
provider: "fish",
|
|
12931
|
+
model: ctx.model.id
|
|
12932
|
+
});
|
|
12933
|
+
const audio = new Blob([new Uint8Array(bytes)], { type: mime });
|
|
12934
|
+
form.append("voices", audio, fileName(index, mime));
|
|
12935
|
+
}
|
|
12936
|
+
for (const text2 of transcripts) form.append("texts", text2.trim());
|
|
12937
|
+
for (const signature of signatures) form.append("voice_design_signatures", signature);
|
|
12938
|
+
return form;
|
|
12939
|
+
}
|
|
12940
|
+
async function onlyRateLimitRetries(fn) {
|
|
12941
|
+
try {
|
|
12942
|
+
return await fn();
|
|
12943
|
+
} catch (cause) {
|
|
12944
|
+
if (!isModelKitError(cause) || !cause.retryable || cause.code === "rate_limited")
|
|
12945
|
+
throw cause;
|
|
12946
|
+
throw new ModelKitError({
|
|
12947
|
+
code: cause.code,
|
|
12948
|
+
message: cause.message,
|
|
12949
|
+
...cause.provider !== void 0 && { provider: cause.provider },
|
|
12950
|
+
...cause.model !== void 0 && { model: cause.model },
|
|
12951
|
+
...cause.status !== void 0 && { status: cause.status },
|
|
12952
|
+
...cause.body !== void 0 && { body: cause.body },
|
|
12953
|
+
cause,
|
|
12954
|
+
retryable: false
|
|
12955
|
+
});
|
|
12956
|
+
}
|
|
12957
|
+
}
|
|
12958
|
+
async function createVoice(req, ctx) {
|
|
12959
|
+
checkRow(ctx, "voice-clone");
|
|
12960
|
+
const form = await cloneForm(req, ctx);
|
|
12961
|
+
const res = await withRetry(
|
|
12962
|
+
() => onlyRateLimitRetries(() => fishFetch(ctx, "/model", { method: "POST", body: form })),
|
|
12963
|
+
mediaRetryOptions(ctx.call, ctx.signal)
|
|
12964
|
+
);
|
|
12965
|
+
const raw = await readBody(res);
|
|
12966
|
+
const parsed = createdModelSchema.safeParse(raw);
|
|
12967
|
+
if (!parsed.success) {
|
|
12968
|
+
throw new ModelKitError({
|
|
12969
|
+
code: "provider_rejected",
|
|
12970
|
+
message: "Fish returned no voice id",
|
|
12971
|
+
provider: "fish",
|
|
12972
|
+
model: ctx.model.id,
|
|
12973
|
+
status: res.status,
|
|
12974
|
+
body: raw,
|
|
12975
|
+
retryable: false
|
|
12976
|
+
});
|
|
12977
|
+
}
|
|
12978
|
+
const result = { voiceId: parsed.data._id, usage: usage2(ctx), raw };
|
|
12979
|
+
if (parsed.data.state !== void 0) result.state = parsed.data.state;
|
|
12980
|
+
return result;
|
|
12981
|
+
}
|
|
12982
|
+
var designSchema = import_zod21.z.object({
|
|
12983
|
+
candidates: import_zod21.z.array(
|
|
12984
|
+
import_zod21.z.looseObject({
|
|
12985
|
+
id: import_zod21.z.string().min(1),
|
|
12986
|
+
index: import_zod21.z.number().int(),
|
|
12987
|
+
audio_base64: import_zod21.z.string().min(1),
|
|
12988
|
+
duration_ms: import_zod21.z.number().nonnegative(),
|
|
12989
|
+
signature: import_zod21.z.string().min(1).optional()
|
|
12990
|
+
})
|
|
12991
|
+
).min(1)
|
|
12992
|
+
});
|
|
12993
|
+
async function designVoice(req, ctx) {
|
|
12994
|
+
checkRow(ctx, "voice-design");
|
|
12995
|
+
const body = { instruction: req.prompt.trim() };
|
|
12996
|
+
if (req.previewText?.trim()) body.reference_text = req.previewText.trim();
|
|
12997
|
+
if (req.language !== void 0) body.language = req.language;
|
|
12998
|
+
if (req.count !== void 0) body.n = req.count;
|
|
12999
|
+
if (req.seed !== void 0) body.seed = req.seed;
|
|
13000
|
+
const raw = await withRetry(
|
|
13001
|
+
async () => {
|
|
13002
|
+
const res = await fishFetch(ctx, "/v1/voice-design", {
|
|
13003
|
+
method: "POST",
|
|
13004
|
+
headers: { "Content-Type": "application/json", model: ctx.model.providerModelId },
|
|
13005
|
+
body: JSON.stringify(body)
|
|
13006
|
+
});
|
|
13007
|
+
return readBody(res);
|
|
13008
|
+
},
|
|
13009
|
+
mediaRetryOptions(ctx.call, ctx.signal)
|
|
13010
|
+
);
|
|
13011
|
+
const parsed = designSchema.safeParse(raw);
|
|
13012
|
+
if (!parsed.success) {
|
|
13013
|
+
throw fishError(ctx, "provider_rejected", "Fish voice design returned no candidates");
|
|
13014
|
+
}
|
|
13015
|
+
const candidates = [...parsed.data.candidates].sort((a, b) => a.index - b.index).map((c) => ({
|
|
13016
|
+
audio: { bytes: base64ToBytes(c.audio_base64), mime: "audio/wav" },
|
|
13017
|
+
durationSeconds: c.duration_ms / 1e3,
|
|
13018
|
+
// The OpenAPI candidate has no signature field, so its stable id is the handle; Fish
|
|
13019
|
+
// rejects a clone whose signature does not verify, so a wrong one fails loudly.
|
|
13020
|
+
signature: c.signature ?? c.id
|
|
13021
|
+
}));
|
|
13022
|
+
return { candidates, usage: usage2(ctx) };
|
|
13023
|
+
}
|
|
13024
|
+
async function deleteVoice(req, ctx) {
|
|
13025
|
+
checkRow(ctx, "voice-clone");
|
|
13026
|
+
const id = encodeURIComponent(checkVoiceId(ctx, "voiceId", req.voiceId));
|
|
13027
|
+
let attempts = 0;
|
|
13028
|
+
await withRetry(
|
|
13029
|
+
async () => {
|
|
13030
|
+
attempts += 1;
|
|
13031
|
+
try {
|
|
13032
|
+
await fishFetch(ctx, `/model/${id}`, { method: "DELETE" });
|
|
13033
|
+
} catch (cause) {
|
|
13034
|
+
if (!isModelKitError(cause) || cause.status !== 404) throw cause;
|
|
13035
|
+
if (attempts > 1) return;
|
|
13036
|
+
throw new ModelKitError({
|
|
13037
|
+
code: "provider_rejected",
|
|
13038
|
+
message: `Fish has no voice ${req.voiceId} under this key set; delete with the tier that created it`,
|
|
13039
|
+
provider: "fish",
|
|
13040
|
+
model: ctx.model.id,
|
|
13041
|
+
status: 404,
|
|
13042
|
+
cause,
|
|
13043
|
+
retryable: false
|
|
13044
|
+
});
|
|
13045
|
+
}
|
|
13046
|
+
},
|
|
13047
|
+
mediaRetryOptions(ctx.call, ctx.signal)
|
|
13048
|
+
);
|
|
13049
|
+
}
|
|
13050
|
+
var fishAdapter = {
|
|
13051
|
+
id: "fish",
|
|
13052
|
+
generateSpeech,
|
|
13053
|
+
createVoice,
|
|
13054
|
+
designVoice,
|
|
13055
|
+
deleteVoice
|
|
13056
|
+
};
|
|
13057
|
+
|
|
12466
13058
|
// src/adapters/google-genai.ts
|
|
12467
|
-
var
|
|
13059
|
+
var import_zod23 = require("zod");
|
|
12468
13060
|
var import_genai = require("@google/genai");
|
|
12469
13061
|
|
|
12470
13062
|
// src/adapters/google-files.ts
|
|
12471
|
-
var
|
|
13063
|
+
var import_zod22 = require("zod");
|
|
12472
13064
|
var GOOGLE_FILES_BASE = "https://generativelanguage.googleapis.com";
|
|
12473
13065
|
var GOOGLE_FILES_POLL_INTERVAL_MS = 2e3;
|
|
12474
13066
|
var GOOGLE_FILES_POLL_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
@@ -12478,17 +13070,17 @@ var GENERIC_MEDIA_TYPES = /* @__PURE__ */ new Set([
|
|
|
12478
13070
|
"binary/octet-stream",
|
|
12479
13071
|
"application/binary"
|
|
12480
13072
|
]);
|
|
12481
|
-
var uploadedFileSchema =
|
|
12482
|
-
file:
|
|
12483
|
-
uri:
|
|
12484
|
-
name:
|
|
12485
|
-
state:
|
|
12486
|
-
mimeType:
|
|
13073
|
+
var uploadedFileSchema = import_zod22.z.object({
|
|
13074
|
+
file: import_zod22.z.object({
|
|
13075
|
+
uri: import_zod22.z.string().optional(),
|
|
13076
|
+
name: import_zod22.z.string().optional(),
|
|
13077
|
+
state: import_zod22.z.string().optional(),
|
|
13078
|
+
mimeType: import_zod22.z.string().optional()
|
|
12487
13079
|
}).optional()
|
|
12488
13080
|
});
|
|
12489
|
-
var fileStateSchema =
|
|
12490
|
-
state:
|
|
12491
|
-
error:
|
|
13081
|
+
var fileStateSchema = import_zod22.z.object({
|
|
13082
|
+
state: import_zod22.z.string().optional(),
|
|
13083
|
+
error: import_zod22.z.object({ message: import_zod22.z.string().optional() }).optional()
|
|
12492
13084
|
});
|
|
12493
13085
|
function resolveMime(declared, fallback) {
|
|
12494
13086
|
const clean = declared?.split(";")[0]?.trim().toLowerCase();
|
|
@@ -12595,7 +13187,7 @@ async function startAndUpload(bytes, mimeType, opts) {
|
|
|
12595
13187
|
if (uploaded.file?.state !== void 0) ref.state = uploaded.file.state;
|
|
12596
13188
|
return ref;
|
|
12597
13189
|
}
|
|
12598
|
-
async function waitForActive(
|
|
13190
|
+
async function waitForActive(fileName2, opts) {
|
|
12599
13191
|
const pollOptions2 = {
|
|
12600
13192
|
intervalMs: GOOGLE_FILES_POLL_INTERVAL_MS,
|
|
12601
13193
|
timeoutMs: GOOGLE_FILES_POLL_TIMEOUT_MS
|
|
@@ -12608,14 +13200,14 @@ async function waitForActive(fileName, opts) {
|
|
|
12608
13200
|
retryInit.signal = opts.signal;
|
|
12609
13201
|
}
|
|
12610
13202
|
await pollUntil(async () => {
|
|
12611
|
-
const res = await opts.fetchImpl(`${GOOGLE_FILES_BASE}/v1beta/${
|
|
13203
|
+
const res = await opts.fetchImpl(`${GOOGLE_FILES_BASE}/v1beta/${fileName2}`, retryInit);
|
|
12612
13204
|
if (res.ok) {
|
|
12613
13205
|
const json = fileStateSchema.parse(await res.json());
|
|
12614
13206
|
if (json.state === "ACTIVE") return true;
|
|
12615
13207
|
if (json.state === "FAILED") {
|
|
12616
13208
|
throw classifyHttpError(
|
|
12617
13209
|
void 0,
|
|
12618
|
-
`Files API processing failed for ${
|
|
13210
|
+
`Files API processing failed for ${fileName2}: ${json.error?.message ?? "unknown error"}`,
|
|
12619
13211
|
"google-genai",
|
|
12620
13212
|
opts.model
|
|
12621
13213
|
);
|
|
@@ -12627,9 +13219,9 @@ async function waitForActive(fileName, opts) {
|
|
|
12627
13219
|
throw classifyHttpError(res.status, text2, "google-genai", opts.model);
|
|
12628
13220
|
}, pollOptions2);
|
|
12629
13221
|
}
|
|
12630
|
-
async function deleteGoogleFile(
|
|
13222
|
+
async function deleteGoogleFile(fileName2, apiKey, fetchImpl) {
|
|
12631
13223
|
try {
|
|
12632
|
-
await fetchImpl(`${GOOGLE_FILES_BASE}/v1beta/${
|
|
13224
|
+
await fetchImpl(`${GOOGLE_FILES_BASE}/v1beta/${fileName2}`, {
|
|
12633
13225
|
method: "DELETE",
|
|
12634
13226
|
headers: { "x-goog-api-key": apiKey }
|
|
12635
13227
|
});
|
|
@@ -12709,7 +13301,7 @@ var OMNI_POLL_INTERVAL_MS = 1e4;
|
|
|
12709
13301
|
var RESULT_TIMEOUT_MS3 = 15 * 60 * 1e3;
|
|
12710
13302
|
var OMNI_INLINE_LIMIT_BYTES = 4 * 1024 * 1024;
|
|
12711
13303
|
var MEDIA_PART_INLINE_LIMIT_BYTES = 10 * 1024 * 1024;
|
|
12712
|
-
var errorTextSchema =
|
|
13304
|
+
var errorTextSchema = import_zod23.z.string();
|
|
12713
13305
|
function isGoogleGenaiVideoKnown(providerModelId) {
|
|
12714
13306
|
return providerModelId.startsWith("veo-") || providerModelId.startsWith("gemini-omni");
|
|
12715
13307
|
}
|
|
@@ -12904,7 +13496,7 @@ async function generateVeoVideo(req, ctx, createGenAIClient) {
|
|
|
12904
13496
|
}
|
|
12905
13497
|
};
|
|
12906
13498
|
const jobId = operation.name ?? crypto.randomUUID();
|
|
12907
|
-
const
|
|
13499
|
+
const usage4 = videoUsage2(ctx, duration, req.resolution ?? "720p");
|
|
12908
13500
|
return {
|
|
12909
13501
|
jobId,
|
|
12910
13502
|
async poll() {
|
|
@@ -12942,7 +13534,7 @@ async function generateVeoVideo(req, ctx, createGenAIClient) {
|
|
|
12942
13534
|
modelId
|
|
12943
13535
|
);
|
|
12944
13536
|
}
|
|
12945
|
-
return { video: await downloadVideo(ctx, uri, apiKey, signal), usage:
|
|
13537
|
+
return { video: await downloadVideo(ctx, uri, apiKey, signal), usage: usage4, raw: finished };
|
|
12946
13538
|
}
|
|
12947
13539
|
};
|
|
12948
13540
|
}
|
|
@@ -13053,7 +13645,7 @@ async function generateOmniVideo(req, ctx, createGenAIClient) {
|
|
|
13053
13645
|
return file.fileUri;
|
|
13054
13646
|
};
|
|
13055
13647
|
const cleanupUploads = async () => {
|
|
13056
|
-
for (const
|
|
13648
|
+
for (const fileName2 of uploadedNames) await deleteGoogleFile(fileName2, apiKey, ctx.fetch);
|
|
13057
13649
|
};
|
|
13058
13650
|
const callCreate = (input) => client2.interactions.create(
|
|
13059
13651
|
previousId !== void 0 ? {
|
|
@@ -13147,7 +13739,7 @@ async function generateOmniVideo(req, ctx, createGenAIClient) {
|
|
|
13147
13739
|
if (!(extend && !chained)) await cleanupUploads();
|
|
13148
13740
|
}
|
|
13149
13741
|
const jobId = interaction.id ?? crypto.randomUUID();
|
|
13150
|
-
const
|
|
13742
|
+
const usage4 = videoUsage2(ctx, duration, omniResolution ?? "720p");
|
|
13151
13743
|
const getInteraction = async () => {
|
|
13152
13744
|
try {
|
|
13153
13745
|
const getParams = { stream: false };
|
|
@@ -13195,7 +13787,7 @@ async function generateOmniVideo(req, ctx, createGenAIClient) {
|
|
|
13195
13787
|
bytes: Buffer.from(video.data, "base64"),
|
|
13196
13788
|
mime: video.mime_type ?? "video/mp4"
|
|
13197
13789
|
},
|
|
13198
|
-
usage:
|
|
13790
|
+
usage: usage4,
|
|
13199
13791
|
raw: done,
|
|
13200
13792
|
providerRef
|
|
13201
13793
|
};
|
|
@@ -13203,7 +13795,7 @@ async function generateOmniVideo(req, ctx, createGenAIClient) {
|
|
|
13203
13795
|
if (video.uri)
|
|
13204
13796
|
return {
|
|
13205
13797
|
video: await downloadVideo(ctx, video.uri, apiKey, signal),
|
|
13206
|
-
usage:
|
|
13798
|
+
usage: usage4,
|
|
13207
13799
|
raw: done,
|
|
13208
13800
|
providerRef
|
|
13209
13801
|
};
|
|
@@ -13373,15 +13965,15 @@ async function prepareGoogleMediaPart(ref, mediaType, ctx) {
|
|
|
13373
13965
|
// src/adapters/google-image.ts
|
|
13374
13966
|
var import_google2 = require("@ai-sdk/google");
|
|
13375
13967
|
var import_ai2 = require("ai");
|
|
13376
|
-
var
|
|
13968
|
+
var import_zod24 = require("zod");
|
|
13377
13969
|
var GEMINI_IMAGE_TIMEOUT_MS = 6e5;
|
|
13378
13970
|
var defaultGoogleImageDeps = {
|
|
13379
13971
|
createGoogleClient: (opts) => (0, import_google2.createGoogleGenerativeAI)(opts),
|
|
13380
13972
|
runTextGeneration: (opts) => (0, import_ai2.generateText)(opts)
|
|
13381
13973
|
};
|
|
13382
|
-
var causeChainNodeSchema =
|
|
13383
|
-
message:
|
|
13384
|
-
cause:
|
|
13974
|
+
var causeChainNodeSchema = import_zod24.z.object({
|
|
13975
|
+
message: import_zod24.z.string().optional(),
|
|
13976
|
+
cause: import_zod24.z.unknown().optional()
|
|
13385
13977
|
});
|
|
13386
13978
|
function extractBlockReason(cause) {
|
|
13387
13979
|
let current = cause;
|
|
@@ -13481,7 +14073,7 @@ function createGoogleImageAdapter(deps = defaultGoogleImageDeps) {
|
|
|
13481
14073
|
retryable: false
|
|
13482
14074
|
});
|
|
13483
14075
|
}
|
|
13484
|
-
const
|
|
14076
|
+
const usage4 = {
|
|
13485
14077
|
model: ctx.model.id,
|
|
13486
14078
|
provider: "google-image",
|
|
13487
14079
|
modality: "IMAGE",
|
|
@@ -13489,19 +14081,19 @@ function createGoogleImageAdapter(deps = defaultGoogleImageDeps) {
|
|
|
13489
14081
|
quantity: images.length,
|
|
13490
14082
|
imageQuality: "auto"
|
|
13491
14083
|
};
|
|
13492
|
-
if (req.size !== void 0)
|
|
14084
|
+
if (req.size !== void 0) usage4.imageSize = req.size;
|
|
13493
14085
|
if (result.usage?.inputTokens !== void 0)
|
|
13494
|
-
|
|
14086
|
+
usage4.inputTokens = result.usage.inputTokens;
|
|
13495
14087
|
if (result.usage?.outputTokens !== void 0)
|
|
13496
|
-
|
|
13497
|
-
return { images, usage:
|
|
14088
|
+
usage4.outputTokens = result.usage.outputTokens;
|
|
14089
|
+
return { images, usage: usage4, raw: result };
|
|
13498
14090
|
}
|
|
13499
14091
|
};
|
|
13500
14092
|
}
|
|
13501
14093
|
var googleImageAdapter = createGoogleImageAdapter();
|
|
13502
14094
|
|
|
13503
14095
|
// src/adapters/higgsfield.ts
|
|
13504
|
-
var
|
|
14096
|
+
var import_zod25 = require("zod");
|
|
13505
14097
|
|
|
13506
14098
|
// src/adapters/higgsfield-motions.ts
|
|
13507
14099
|
var MOTION_MAP = {
|
|
@@ -13720,14 +14312,14 @@ function klingEndpointFields(providerModelId) {
|
|
|
13720
14312
|
const path = (providerModelId.startsWith("/") ? providerModelId.slice(1) : providerModelId).toLowerCase();
|
|
13721
14313
|
return KLING_ENDPOINT_FIELDS.get(path) ?? UNLISTED_KLING_FIELDS;
|
|
13722
14314
|
}
|
|
13723
|
-
var klingCreateSchema =
|
|
13724
|
-
var klingStatusSchema =
|
|
13725
|
-
status:
|
|
13726
|
-
video:
|
|
14315
|
+
var klingCreateSchema = import_zod25.z.object({ status_url: import_zod25.z.string() });
|
|
14316
|
+
var klingStatusSchema = import_zod25.z.object({
|
|
14317
|
+
status: import_zod25.z.string().optional(),
|
|
14318
|
+
video: import_zod25.z.object({ url: import_zod25.z.string().optional() }).optional(),
|
|
13727
14319
|
error: JsonValueSchema.optional()
|
|
13728
14320
|
});
|
|
13729
|
-
var errorMessageSchema =
|
|
13730
|
-
var textValueSchema =
|
|
14321
|
+
var errorMessageSchema = import_zod25.z.object({ message: import_zod25.z.string().optional() });
|
|
14322
|
+
var textValueSchema = import_zod25.z.string();
|
|
13731
14323
|
function klingErrorDetail(error) {
|
|
13732
14324
|
if (error === void 0) return "unknown_error";
|
|
13733
14325
|
const asText = textValueSchema.safeParse(error);
|
|
@@ -13883,8 +14475,8 @@ async function generateKlingVideo(req, ctx) {
|
|
|
13883
14475
|
}
|
|
13884
14476
|
};
|
|
13885
14477
|
}
|
|
13886
|
-
var dopMotionOptionsSchema =
|
|
13887
|
-
modelkit:
|
|
14478
|
+
var dopMotionOptionsSchema = import_zod25.z.object({
|
|
14479
|
+
modelkit: import_zod25.z.object({ motion: import_zod25.z.string().optional() }).optional()
|
|
13888
14480
|
});
|
|
13889
14481
|
function dopMotionId(ctx) {
|
|
13890
14482
|
const parsed = dopMotionOptionsSchema.safeParse(ctx.model.providerOptions);
|
|
@@ -13900,7 +14492,7 @@ function dopMotionId(ctx) {
|
|
|
13900
14492
|
});
|
|
13901
14493
|
return id;
|
|
13902
14494
|
}
|
|
13903
|
-
var jsonRecordSchema =
|
|
14495
|
+
var jsonRecordSchema = import_zod25.z.record(import_zod25.z.string(), JsonValueSchema);
|
|
13904
14496
|
var DOP_URL_KEYS = ["url", "video_url", "output_url", "result_url", "download_url"];
|
|
13905
14497
|
var DOP_NESTED_KEYS = ["video", "result", "results"];
|
|
13906
14498
|
function dopUrl(body) {
|
|
@@ -13928,8 +14520,8 @@ function dopUrl(body) {
|
|
|
13928
14520
|
}
|
|
13929
14521
|
return void 0;
|
|
13930
14522
|
}
|
|
13931
|
-
var dopCreateSchema =
|
|
13932
|
-
var dopStatusSchema =
|
|
14523
|
+
var dopCreateSchema = import_zod25.z.object({ id: import_zod25.z.string() });
|
|
14524
|
+
var dopStatusSchema = import_zod25.z.object({ status: import_zod25.z.string().optional() });
|
|
13933
14525
|
async function generateDopVideo(req, ctx) {
|
|
13934
14526
|
const firstFrame = req.firstFrame ? refToUrl(req.firstFrame) : void 0;
|
|
13935
14527
|
if (!firstFrame) {
|
|
@@ -14056,7 +14648,7 @@ var higgsfieldAdapter = {
|
|
|
14056
14648
|
};
|
|
14057
14649
|
|
|
14058
14650
|
// src/adapters/luma.ts
|
|
14059
|
-
var
|
|
14651
|
+
var import_zod26 = require("zod");
|
|
14060
14652
|
|
|
14061
14653
|
// src/adapters/mp4-duration.ts
|
|
14062
14654
|
function mp4DurationSeconds(bytes) {
|
|
@@ -14112,7 +14704,7 @@ function findBox(bytes, from, to, type) {
|
|
|
14112
14704
|
}
|
|
14113
14705
|
|
|
14114
14706
|
// src/adapters/luma.ts
|
|
14115
|
-
var
|
|
14707
|
+
var DEFAULT_BASE_URL2 = "https://agents.lumalabs.ai";
|
|
14116
14708
|
var IMAGE_POLL_INTERVAL_MS = 3e3;
|
|
14117
14709
|
var IMAGE_TIMEOUT_MS = 5 * 6e4;
|
|
14118
14710
|
var VIDEO_POLL_INTERVAL_MS = 5e3;
|
|
@@ -14141,7 +14733,7 @@ function lumaModel(ctx) {
|
|
|
14141
14733
|
return ctx.model.providerModelId.toLowerCase();
|
|
14142
14734
|
}
|
|
14143
14735
|
function lumaBase(ctx) {
|
|
14144
|
-
return ctx.endpoints?.luma ??
|
|
14736
|
+
return ctx.endpoints?.luma ?? DEFAULT_BASE_URL2;
|
|
14145
14737
|
}
|
|
14146
14738
|
function lumaKey(ctx) {
|
|
14147
14739
|
const key = ctx.keys.luma;
|
|
@@ -14273,17 +14865,17 @@ function lumaReframeResolution(req, ctx) {
|
|
|
14273
14865
|
});
|
|
14274
14866
|
return "720p";
|
|
14275
14867
|
}
|
|
14276
|
-
var lumaGenerationSchema =
|
|
14277
|
-
id:
|
|
14278
|
-
state:
|
|
14279
|
-
output:
|
|
14280
|
-
|
|
14281
|
-
type:
|
|
14282
|
-
url:
|
|
14868
|
+
var lumaGenerationSchema = import_zod26.z.looseObject({
|
|
14869
|
+
id: import_zod26.z.string(),
|
|
14870
|
+
state: import_zod26.z.string().optional(),
|
|
14871
|
+
output: import_zod26.z.array(
|
|
14872
|
+
import_zod26.z.looseObject({
|
|
14873
|
+
type: import_zod26.z.string().optional(),
|
|
14874
|
+
url: import_zod26.z.string().optional()
|
|
14283
14875
|
})
|
|
14284
14876
|
).optional(),
|
|
14285
|
-
failure_reason:
|
|
14286
|
-
failure_code:
|
|
14877
|
+
failure_reason: import_zod26.z.string().optional().nullable(),
|
|
14878
|
+
failure_code: import_zod26.z.string().optional().nullable()
|
|
14287
14879
|
});
|
|
14288
14880
|
function lumaFailure(ctx, code, reason) {
|
|
14289
14881
|
const detail = reason ?? code ?? "unknown_error";
|
|
@@ -14715,7 +15307,7 @@ var lumaAdapter = {
|
|
|
14715
15307
|
|
|
14716
15308
|
// src/adapters/openai-image.ts
|
|
14717
15309
|
var import_openai2 = __toESM(require("openai"), 1);
|
|
14718
|
-
var
|
|
15310
|
+
var import_zod27 = require("zod");
|
|
14719
15311
|
var MAX_EDIT_REFERENCES = 16;
|
|
14720
15312
|
function aspectRatioToSize(ratio, tier) {
|
|
14721
15313
|
const TIER_LONG_EDGE = {
|
|
@@ -14798,9 +15390,9 @@ function toProviderError2(cause, ctx) {
|
|
|
14798
15390
|
ctx.model.id
|
|
14799
15391
|
);
|
|
14800
15392
|
}
|
|
14801
|
-
var openaiUsageSchema =
|
|
14802
|
-
input_tokens:
|
|
14803
|
-
output_tokens:
|
|
15393
|
+
var openaiUsageSchema = import_zod27.z.object({
|
|
15394
|
+
input_tokens: import_zod27.z.number().optional(),
|
|
15395
|
+
output_tokens: import_zod27.z.number().optional()
|
|
14804
15396
|
});
|
|
14805
15397
|
var openaiImageAdapter = {
|
|
14806
15398
|
id: "openai-image",
|
|
@@ -14925,7 +15517,7 @@ var openaiImageAdapter = {
|
|
|
14925
15517
|
const usageParsed = openaiUsageSchema.safeParse(response.usage);
|
|
14926
15518
|
const inputTokens = usageParsed.success ? usageParsed.data.input_tokens : void 0;
|
|
14927
15519
|
const outputTokens = usageParsed.success ? usageParsed.data.output_tokens : void 0;
|
|
14928
|
-
const
|
|
15520
|
+
const usage4 = {
|
|
14929
15521
|
model: ctx.model.id,
|
|
14930
15522
|
provider: "openai-image",
|
|
14931
15523
|
modality: "IMAGE",
|
|
@@ -14933,10 +15525,10 @@ var openaiImageAdapter = {
|
|
|
14933
15525
|
quantity: images.length,
|
|
14934
15526
|
imageQuality: quality
|
|
14935
15527
|
};
|
|
14936
|
-
if (inputTokens !== void 0)
|
|
14937
|
-
if (outputTokens !== void 0)
|
|
14938
|
-
if (req.size !== void 0)
|
|
14939
|
-
return { images, usage:
|
|
15528
|
+
if (inputTokens !== void 0) usage4.inputTokens = inputTokens;
|
|
15529
|
+
if (outputTokens !== void 0) usage4.outputTokens = outputTokens;
|
|
15530
|
+
if (req.size !== void 0) usage4.imageSize = req.size;
|
|
15531
|
+
return { images, usage: usage4, raw: response };
|
|
14940
15532
|
}
|
|
14941
15533
|
};
|
|
14942
15534
|
|
|
@@ -15192,16 +15784,16 @@ async function generateProdiaImage(req, ctx) {
|
|
|
15192
15784
|
new Uint8Array(await res.arrayBuffer()),
|
|
15193
15785
|
res.headers.get("content-type")
|
|
15194
15786
|
);
|
|
15195
|
-
const
|
|
15787
|
+
const usage4 = {
|
|
15196
15788
|
model: ctx.model.id,
|
|
15197
15789
|
provider: "prodia",
|
|
15198
15790
|
modality: "IMAGE",
|
|
15199
15791
|
unit: "images",
|
|
15200
15792
|
quantity: 1
|
|
15201
15793
|
};
|
|
15202
|
-
if (req.size !== void 0)
|
|
15203
|
-
if (req.quality !== void 0)
|
|
15204
|
-
return { images: [{ bytes, mime }], usage:
|
|
15794
|
+
if (req.size !== void 0) usage4.imageSize = req.size;
|
|
15795
|
+
if (req.quality !== void 0) usage4.imageQuality = req.quality;
|
|
15796
|
+
return { images: [{ bytes, mime }], usage: usage4, raw: void 0 };
|
|
15205
15797
|
}
|
|
15206
15798
|
var prodiaAdapter = {
|
|
15207
15799
|
id: "prodia",
|
|
@@ -15212,13 +15804,13 @@ var prodiaAdapter = {
|
|
|
15212
15804
|
var import_replicate = __toESM(require("replicate"), 1);
|
|
15213
15805
|
|
|
15214
15806
|
// src/adapters/replicate-http.ts
|
|
15215
|
-
var
|
|
15216
|
-
var predictionSchema =
|
|
15217
|
-
id:
|
|
15218
|
-
status:
|
|
15807
|
+
var import_zod28 = require("zod");
|
|
15808
|
+
var predictionSchema = import_zod28.z.object({
|
|
15809
|
+
id: import_zod28.z.string(),
|
|
15810
|
+
status: import_zod28.z.string(),
|
|
15219
15811
|
output: JsonValueSchema.optional(),
|
|
15220
15812
|
error: JsonValueSchema.optional(),
|
|
15221
|
-
metrics:
|
|
15813
|
+
metrics: import_zod28.z.object({ predict_time: import_zod28.z.number().optional() }).optional()
|
|
15222
15814
|
});
|
|
15223
15815
|
function createReplicateHttpClient(opts) {
|
|
15224
15816
|
async function request(path, body, signal) {
|
|
@@ -15269,7 +15861,7 @@ function createReplicateHttpClient(opts) {
|
|
|
15269
15861
|
}
|
|
15270
15862
|
|
|
15271
15863
|
// src/adapters/replicate.ts
|
|
15272
|
-
var
|
|
15864
|
+
var import_zod29 = require("zod");
|
|
15273
15865
|
var POLL_INTERVAL_MS = 1e3;
|
|
15274
15866
|
var POLL_TIMEOUT_MS = 15 * 6e4;
|
|
15275
15867
|
var defaultReplicateDeps = {
|
|
@@ -15309,8 +15901,8 @@ function route(providerModelId) {
|
|
|
15309
15901
|
if (!providerModelId.includes("/")) return { version: providerModelId };
|
|
15310
15902
|
return { model: providerModelId };
|
|
15311
15903
|
}
|
|
15312
|
-
var replicateResponseStatusSchema =
|
|
15313
|
-
response:
|
|
15904
|
+
var replicateResponseStatusSchema = import_zod29.z.object({
|
|
15905
|
+
response: import_zod29.z.object({ status: import_zod29.z.number() }).partial()
|
|
15314
15906
|
});
|
|
15315
15907
|
function replicateError(cause, ctx) {
|
|
15316
15908
|
if (isModelKitError(cause)) return cause;
|
|
@@ -15333,7 +15925,7 @@ function isUrlFn(value) {
|
|
|
15333
15925
|
function extractOutputUrl(output) {
|
|
15334
15926
|
const root = Array.isArray(output) ? output[0] : output;
|
|
15335
15927
|
if (root === void 0) throw noOutput();
|
|
15336
|
-
const asString =
|
|
15928
|
+
const asString = import_zod29.z.string().safeParse(root);
|
|
15337
15929
|
if (asString.success && asString.data) return asString.data;
|
|
15338
15930
|
if (root instanceof URL) return root.href;
|
|
15339
15931
|
if (isObjectOutput(root)) {
|
|
@@ -15342,15 +15934,15 @@ function extractOutputUrl(output) {
|
|
|
15342
15934
|
if (urlValue !== void 0 && isUrlFn(urlValue)) {
|
|
15343
15935
|
const called = urlValue();
|
|
15344
15936
|
if (called instanceof URL) return called.href;
|
|
15345
|
-
const calledString =
|
|
15937
|
+
const calledString = import_zod29.z.string().safeParse(called);
|
|
15346
15938
|
if (calledString.success && calledString.data) return calledString.data;
|
|
15347
15939
|
} else {
|
|
15348
|
-
const direct =
|
|
15940
|
+
const direct = import_zod29.z.string().safeParse(urlValue);
|
|
15349
15941
|
if (direct.success && direct.data) return direct.data;
|
|
15350
15942
|
}
|
|
15351
15943
|
}
|
|
15352
15944
|
if ("default" in root) {
|
|
15353
|
-
const fallback =
|
|
15945
|
+
const fallback = import_zod29.z.string().safeParse(root.default);
|
|
15354
15946
|
if (fallback.success && fallback.data) return fallback.data;
|
|
15355
15947
|
}
|
|
15356
15948
|
}
|
|
@@ -15411,7 +16003,7 @@ async function runPrediction(ctx, input, deps) {
|
|
|
15411
16003
|
}
|
|
15412
16004
|
return void 0;
|
|
15413
16005
|
}, pollOpts);
|
|
15414
|
-
const predictTime =
|
|
16006
|
+
const predictTime = import_zod29.z.number().safeParse(done.metrics?.predict_time);
|
|
15415
16007
|
if (done.output === void 0) throw noOutput();
|
|
15416
16008
|
return {
|
|
15417
16009
|
url: extractOutputUrl(done.output),
|
|
@@ -15657,9 +16249,9 @@ async function generateReplicateImage(req, ctx, deps) {
|
|
|
15657
16249
|
}
|
|
15658
16250
|
const { url, predictTime, raw } = await runPrediction(ctx, input, deps);
|
|
15659
16251
|
const file = await download(ctx, url);
|
|
15660
|
-
const
|
|
15661
|
-
|
|
15662
|
-
return { images: [{ bytes: file.bytes, mime: file.mime }], usage:
|
|
16252
|
+
const usage4 = imageUsage3(ctx, req);
|
|
16253
|
+
usage4.quantity = predictTime;
|
|
16254
|
+
return { images: [{ bytes: file.bytes, mime: file.mime }], usage: usage4, raw, outputUrl: url };
|
|
15663
16255
|
}
|
|
15664
16256
|
function klingInput(req) {
|
|
15665
16257
|
const images = (req.firstFrame ? [req.firstFrame] : []).map(refToUrl);
|
|
@@ -15764,7 +16356,7 @@ async function generateReplicateVideo(req, ctx, deps) {
|
|
|
15764
16356
|
throw replicateError(cause, ctx);
|
|
15765
16357
|
}
|
|
15766
16358
|
if (current.status === "succeeded") {
|
|
15767
|
-
const predictTime =
|
|
16359
|
+
const predictTime = import_zod29.z.number().safeParse(current.metrics?.predict_time);
|
|
15768
16360
|
if (current.output === void 0) throw noOutput();
|
|
15769
16361
|
return {
|
|
15770
16362
|
url: extractOutputUrl(current.output),
|
|
@@ -15783,9 +16375,9 @@ async function generateReplicateVideo(req, ctx, deps) {
|
|
|
15783
16375
|
return void 0;
|
|
15784
16376
|
};
|
|
15785
16377
|
const toResult = (done) => {
|
|
15786
|
-
const
|
|
15787
|
-
|
|
15788
|
-
return { video: { url: done.url }, usage:
|
|
16378
|
+
const usage4 = videoUsage5(ctx, req);
|
|
16379
|
+
usage4.quantity = done.predictTime;
|
|
16380
|
+
return { video: { url: done.url }, usage: usage4, raw: done.raw };
|
|
15789
16381
|
};
|
|
15790
16382
|
return {
|
|
15791
16383
|
jobId,
|
|
@@ -15892,21 +16484,21 @@ async function generateReplicateAudio(req, ctx, deps) {
|
|
|
15892
16484
|
input = specResult.input;
|
|
15893
16485
|
}
|
|
15894
16486
|
const { url, predictTime, raw } = await runPrediction(ctx, input, deps);
|
|
15895
|
-
const
|
|
16487
|
+
const usage4 = audioUsage(ctx, req);
|
|
15896
16488
|
if (ctx.model.usage.unit === "seconds") {
|
|
15897
16489
|
const seconds3 = elevenLabsMusicDuration(req.durationSeconds);
|
|
15898
|
-
|
|
15899
|
-
|
|
16490
|
+
usage4.quantity = seconds3;
|
|
16491
|
+
usage4.durationSeconds = seconds3;
|
|
15900
16492
|
} else {
|
|
15901
|
-
|
|
16493
|
+
usage4.quantity = predictTime;
|
|
15902
16494
|
}
|
|
15903
|
-
return { audio: { url }, usage:
|
|
16495
|
+
return { audio: { url }, usage: usage4, raw: predictionRaw(raw) };
|
|
15904
16496
|
}
|
|
15905
16497
|
|
|
15906
16498
|
// src/adapters/xai-video.ts
|
|
15907
16499
|
var import_ai3 = require("ai");
|
|
15908
16500
|
var import_xai2 = require("@ai-sdk/xai");
|
|
15909
|
-
var
|
|
16501
|
+
var import_zod30 = require("zod");
|
|
15910
16502
|
var POLL_INTERVAL_MS2 = 1e4;
|
|
15911
16503
|
var POLL_TIMEOUT_MS2 = 15 * 6e4;
|
|
15912
16504
|
var defaultXaiDeps = {
|
|
@@ -15919,8 +16511,8 @@ function createXaiVideoAdapter(deps = defaultXaiDeps) {
|
|
|
15919
16511
|
};
|
|
15920
16512
|
}
|
|
15921
16513
|
var xaiVideoAdapter = createXaiVideoAdapter();
|
|
15922
|
-
var xaiResponseStatusSchema =
|
|
15923
|
-
response:
|
|
16514
|
+
var xaiResponseStatusSchema = import_zod30.z.object({
|
|
16515
|
+
response: import_zod30.z.object({ status: import_zod30.z.number() }).partial()
|
|
15924
16516
|
});
|
|
15925
16517
|
function xaiError(cause, ctx) {
|
|
15926
16518
|
const info = describeThrown(cause);
|
|
@@ -15928,12 +16520,12 @@ function xaiError(cause, ctx) {
|
|
|
15928
16520
|
const status = info.status ?? (nested.success ? nested.data.response?.status : void 0);
|
|
15929
16521
|
return classifyThrown("xai-video", cause, ctx.model.id, { status, body: info.body });
|
|
15930
16522
|
}
|
|
15931
|
-
var xaiMetaSchema =
|
|
16523
|
+
var xaiMetaSchema = import_zod30.z.object({
|
|
15932
16524
|
videoUrl: JsonValueSchema.optional(),
|
|
15933
16525
|
costInUsdTicks: JsonValueSchema.optional(),
|
|
15934
16526
|
duration: JsonValueSchema.optional()
|
|
15935
16527
|
});
|
|
15936
|
-
var xaiProviderMetadataSchema =
|
|
16528
|
+
var xaiProviderMetadataSchema = import_zod30.z.object({ xai: xaiMetaSchema });
|
|
15937
16529
|
function metaOf(result) {
|
|
15938
16530
|
const parsed = xaiProviderMetadataSchema.partial().safeParse(result.providerMetadata);
|
|
15939
16531
|
if (!parsed.success) return {};
|
|
@@ -16045,12 +16637,12 @@ async function mapResult(ctx, req, result) {
|
|
|
16045
16637
|
if (first) {
|
|
16046
16638
|
return {
|
|
16047
16639
|
video: { bytes: Uint8Array.from(first.uint8Array), mime: first.mediaType },
|
|
16048
|
-
usage:
|
|
16640
|
+
usage: usage3(ctx, req, metaOf(result)),
|
|
16049
16641
|
raw: result.providerMetadata
|
|
16050
16642
|
};
|
|
16051
16643
|
}
|
|
16052
16644
|
const meta = metaOf(result);
|
|
16053
|
-
const videoUrl =
|
|
16645
|
+
const videoUrl = import_zod30.z.string().safeParse(meta.videoUrl);
|
|
16054
16646
|
if (videoUrl.success && videoUrl.data) {
|
|
16055
16647
|
const res = await ctx.fetch(videoUrl.data);
|
|
16056
16648
|
if (!res.ok) {
|
|
@@ -16060,7 +16652,7 @@ async function mapResult(ctx, req, result) {
|
|
|
16060
16652
|
const mime = res.headers.get("content-type") ?? "video/mp4";
|
|
16061
16653
|
return {
|
|
16062
16654
|
video: { bytes: new Uint8Array(await res.arrayBuffer()), mime },
|
|
16063
|
-
usage:
|
|
16655
|
+
usage: usage3(ctx, req, meta),
|
|
16064
16656
|
raw: result.providerMetadata
|
|
16065
16657
|
};
|
|
16066
16658
|
}
|
|
@@ -16072,8 +16664,8 @@ async function mapResult(ctx, req, result) {
|
|
|
16072
16664
|
retryable: false
|
|
16073
16665
|
});
|
|
16074
16666
|
}
|
|
16075
|
-
function
|
|
16076
|
-
const costTicks =
|
|
16667
|
+
function usage3(ctx, req, meta) {
|
|
16668
|
+
const costTicks = import_zod30.z.number().safeParse(meta.costInUsdTicks);
|
|
16077
16669
|
const cost = costTicks.success ? costTicks.data / 1e10 : void 0;
|
|
16078
16670
|
const event = {
|
|
16079
16671
|
model: ctx.model.id,
|
|
@@ -16112,7 +16704,8 @@ var DEFAULT_ADAPTERS = {
|
|
|
16112
16704
|
prodia: prodiaAdapter,
|
|
16113
16705
|
higgsfield: higgsfieldAdapter,
|
|
16114
16706
|
"xai-video": xaiVideoAdapter,
|
|
16115
|
-
luma: lumaAdapter
|
|
16707
|
+
luma: lumaAdapter,
|
|
16708
|
+
fish: fishAdapter
|
|
16116
16709
|
};
|
|
16117
16710
|
|
|
16118
16711
|
// src/catalog/data-only.ts
|
|
@@ -16136,6 +16729,8 @@ function adapterServesType(adapter, type) {
|
|
|
16136
16729
|
if (type === "dubbing") return adapter.dub !== void 0;
|
|
16137
16730
|
if (type === "lipsync") return adapter.lipsync !== void 0;
|
|
16138
16731
|
if (type === "transcription") return adapter.transcribe !== void 0;
|
|
16732
|
+
if (type === "voice-clone") return adapter.createVoice !== void 0;
|
|
16733
|
+
if (type === "voice-design") return adapter.designVoice !== void 0;
|
|
16139
16734
|
if (type === "video-tool") return adapter.submitVideoTool !== void 0;
|
|
16140
16735
|
if (type === "model3d") return adapter.submitModel3d !== void 0;
|
|
16141
16736
|
return adapter.languageModel !== void 0;
|
|
@@ -16149,12 +16744,15 @@ var FAL_NODE_TYPES = /* @__PURE__ */ new Set([
|
|
|
16149
16744
|
"transcription",
|
|
16150
16745
|
"mask"
|
|
16151
16746
|
]);
|
|
16747
|
+
function fishSpeech(row2) {
|
|
16748
|
+
return row2.adapter === "fish" && row2.type === "speech";
|
|
16749
|
+
}
|
|
16152
16750
|
function dataOnlyCapable(row2) {
|
|
16153
16751
|
const adapter = DEFAULT_ADAPTERS[row2.adapter];
|
|
16154
16752
|
if (!adapterServesType(adapter, row2.type)) {
|
|
16155
16753
|
return { ok: false, reason: `${row2.adapter} cannot serve ${row2.type} rows` };
|
|
16156
16754
|
}
|
|
16157
|
-
if (FAL_NODE_TYPES.has(row2.type) && row2.adapter !== "fal") {
|
|
16755
|
+
if (FAL_NODE_TYPES.has(row2.type) && row2.adapter !== "fal" && !fishSpeech(row2)) {
|
|
16158
16756
|
return { ok: false, reason: `only fal serves ${row2.type} rows` };
|
|
16159
16757
|
}
|
|
16160
16758
|
switch (row2.adapter) {
|
|
@@ -16232,6 +16830,10 @@ function dataOnlyCapable(row2) {
|
|
|
16232
16830
|
const reason = lumaRowRefusal(row2);
|
|
16233
16831
|
return reason === void 0 ? { ok: true } : { ok: false, reason };
|
|
16234
16832
|
}
|
|
16833
|
+
case "fish": {
|
|
16834
|
+
const reason = fishRowRefusal(row2);
|
|
16835
|
+
return reason === void 0 ? { ok: true } : { ok: false, reason };
|
|
16836
|
+
}
|
|
16235
16837
|
default: {
|
|
16236
16838
|
return assertNever(row2.adapter);
|
|
16237
16839
|
}
|
|
@@ -16251,22 +16853,22 @@ var liveState = store[KEY] ??= {
|
|
|
16251
16853
|
var liveCatalog = liveState.catalog;
|
|
16252
16854
|
|
|
16253
16855
|
// src/catalog/load.ts
|
|
16254
|
-
var
|
|
16856
|
+
var import_zod31 = require("zod");
|
|
16255
16857
|
function rowCount() {
|
|
16256
16858
|
return liveCatalog.list({ lifecycle: ["active", "deprecated", "retired"] }).length;
|
|
16257
16859
|
}
|
|
16258
16860
|
function authHeaders(auth) {
|
|
16259
16861
|
return "bearer" in auth ? { Authorization: `Bearer ${auth.bearer}` } : { "x-api-key": auth.apiKey };
|
|
16260
16862
|
}
|
|
16261
|
-
var EnvelopeSchema =
|
|
16262
|
-
rows:
|
|
16263
|
-
revision:
|
|
16863
|
+
var EnvelopeSchema = import_zod31.z.object({
|
|
16864
|
+
rows: import_zod31.z.array(JsonValueSchema),
|
|
16865
|
+
revision: import_zod31.z.string().optional()
|
|
16264
16866
|
});
|
|
16265
16867
|
function dropReason(path, message) {
|
|
16266
16868
|
return path.length === 0 ? message : `${path.map((part) => String(part)).join(".")} ${message}`;
|
|
16267
16869
|
}
|
|
16268
16870
|
function rowId(raw) {
|
|
16269
|
-
const parsed =
|
|
16871
|
+
const parsed = import_zod31.z.object({ id: import_zod31.z.string().min(1) }).loose().safeParse(raw);
|
|
16270
16872
|
if (!parsed.success) return "?";
|
|
16271
16873
|
return parsed.data.id;
|
|
16272
16874
|
}
|
|
@@ -17182,8 +17784,17 @@ function resolveSpeechOptions(model, request, onUnsupported = "error") {
|
|
|
17182
17784
|
const warnings = [];
|
|
17183
17785
|
checkScript(model, request.text);
|
|
17184
17786
|
const resolved = { model: model.id, text: request.text };
|
|
17185
|
-
const
|
|
17186
|
-
if (
|
|
17787
|
+
const customVoice = request.customVoice?.trim();
|
|
17788
|
+
if (customVoice) {
|
|
17789
|
+
if (model.capabilities?.customVoices !== true) {
|
|
17790
|
+
throw unsupported3(model, "does not take a custom voice");
|
|
17791
|
+
}
|
|
17792
|
+
if (request.voice?.trim()) throw unsupported3(model, "takes voice or customVoice, not both");
|
|
17793
|
+
resolved.customVoice = customVoice;
|
|
17794
|
+
} else {
|
|
17795
|
+
const voice = resolveVoice(model, request.voice, onUnsupported, warnings);
|
|
17796
|
+
if (voice !== void 0) resolved.voice = voice;
|
|
17797
|
+
}
|
|
17187
17798
|
const language = resolveListed(
|
|
17188
17799
|
model,
|
|
17189
17800
|
{
|
|
@@ -17305,6 +17916,106 @@ function resolveTranscriptionOptions(model, request, onUnsupported = "error") {
|
|
|
17305
17916
|
return { request: resolved, warnings };
|
|
17306
17917
|
}
|
|
17307
17918
|
|
|
17919
|
+
// src/resolve-voice.ts
|
|
17920
|
+
function refuse(model, code, message) {
|
|
17921
|
+
return new ModelKitError({ code, message: `${model.label} ${message}`, model: model.id });
|
|
17922
|
+
}
|
|
17923
|
+
function checkSample(model, sample, index) {
|
|
17924
|
+
const limits = model.constraints.references?.audioSeconds;
|
|
17925
|
+
const length = sample.audio.durationSeconds;
|
|
17926
|
+
if (limits === void 0 || length === void 0) return;
|
|
17927
|
+
if (limits.min !== void 0 && length < limits.min || limits.max !== void 0 && length > limits.max) {
|
|
17928
|
+
const range2 = `${limits.min ?? 0}-${limits.max ?? "any"} s`;
|
|
17929
|
+
throw refuse(
|
|
17930
|
+
model,
|
|
17931
|
+
"unsupported_option",
|
|
17932
|
+
`takes samples of ${range2}; sample ${index + 1} is ${length} s`
|
|
17933
|
+
);
|
|
17934
|
+
}
|
|
17935
|
+
}
|
|
17936
|
+
function resolveVoiceCloneOptions(model, request) {
|
|
17937
|
+
const title = request.title.trim();
|
|
17938
|
+
if (!title) throw refuse(model, "missing_input", "needs a title");
|
|
17939
|
+
if (request.samples.length === 0) throw refuse(model, "missing_input", "needs a voice sample");
|
|
17940
|
+
const max = model.constraints.references?.audios;
|
|
17941
|
+
if (max !== void 0 && request.samples.length > max) {
|
|
17942
|
+
throw refuse(
|
|
17943
|
+
model,
|
|
17944
|
+
"unsupported_option",
|
|
17945
|
+
`takes up to ${max} samples; got ${request.samples.length}`
|
|
17946
|
+
);
|
|
17947
|
+
}
|
|
17948
|
+
request.samples.forEach((sample, index) => checkSample(model, sample, index));
|
|
17949
|
+
const total = model.constraints.references?.audioSeconds?.total;
|
|
17950
|
+
const seconds3 = request.samples.reduce((sum, s) => sum + (s.audio.durationSeconds ?? 0), 0);
|
|
17951
|
+
if (total !== void 0 && seconds3 > total) {
|
|
17952
|
+
throw refuse(
|
|
17953
|
+
model,
|
|
17954
|
+
"unsupported_option",
|
|
17955
|
+
`takes up to ${total} s of samples; got ${seconds3} s`
|
|
17956
|
+
);
|
|
17957
|
+
}
|
|
17958
|
+
for (const field of ["transcript", "designSignature"]) {
|
|
17959
|
+
const set = request.samples.filter((s) => s[field]?.trim()).length;
|
|
17960
|
+
if (set !== 0 && set !== request.samples.length) {
|
|
17961
|
+
throw refuse(model, "missing_input", `needs ${field} on every sample or on none`);
|
|
17962
|
+
}
|
|
17963
|
+
}
|
|
17964
|
+
return { request: { ...request, model: model.id, title }, warnings: [] };
|
|
17965
|
+
}
|
|
17966
|
+
function resolveVoiceDesignOptions(model, request, onUnsupported = "error") {
|
|
17967
|
+
const warnings = [];
|
|
17968
|
+
const prompt = request.prompt.trim();
|
|
17969
|
+
if (!prompt) throw refuse(model, "missing_input", "needs a voice description");
|
|
17970
|
+
const maxChars = promptConventions(model).maxChars;
|
|
17971
|
+
if (maxChars !== void 0 && prompt.length > maxChars) {
|
|
17972
|
+
throw refuse(
|
|
17973
|
+
model,
|
|
17974
|
+
"unsupported_option",
|
|
17975
|
+
`takes up to ${maxChars} characters; got ${prompt.length}`
|
|
17976
|
+
);
|
|
17977
|
+
}
|
|
17978
|
+
const limits = model.constraints.voiceDesign;
|
|
17979
|
+
const resolved = { model: model.id, prompt };
|
|
17980
|
+
const preview2 = request.previewText?.trim();
|
|
17981
|
+
if (preview2) {
|
|
17982
|
+
if (limits !== void 0 && preview2.length > limits.previewMaxChars) {
|
|
17983
|
+
throw refuse(
|
|
17984
|
+
model,
|
|
17985
|
+
"unsupported_option",
|
|
17986
|
+
`takes a preview line of up to ${limits.previewMaxChars} characters; got ${preview2.length}`
|
|
17987
|
+
);
|
|
17988
|
+
}
|
|
17989
|
+
resolved.previewText = preview2;
|
|
17990
|
+
}
|
|
17991
|
+
const language = request.language?.trim();
|
|
17992
|
+
if (language) resolved.language = language;
|
|
17993
|
+
if (request.seed !== void 0) resolved.seed = request.seed;
|
|
17994
|
+
const count2 = request.count ?? model.defaults.count;
|
|
17995
|
+
if (count2 !== void 0) {
|
|
17996
|
+
const cap = limits?.maxCandidates ?? count2;
|
|
17997
|
+
if (!Number.isInteger(count2) || count2 < 1 || count2 > cap) {
|
|
17998
|
+
if (onUnsupported === "error" || !Number.isInteger(count2)) {
|
|
17999
|
+
throw refuse(
|
|
18000
|
+
model,
|
|
18001
|
+
"unsupported_option",
|
|
18002
|
+
`returns 1-${cap} candidates; got ${count2}`
|
|
18003
|
+
);
|
|
18004
|
+
}
|
|
18005
|
+
const to = Math.min(Math.max(count2, 1), cap);
|
|
18006
|
+
warnings.push({
|
|
18007
|
+
code: "option_ignored",
|
|
18008
|
+
field: "count",
|
|
18009
|
+
from: String(count2),
|
|
18010
|
+
to: String(to),
|
|
18011
|
+
message: `count ${count2} replaced by ${to} for ${model.id}`
|
|
18012
|
+
});
|
|
18013
|
+
resolved.count = to;
|
|
18014
|
+
} else resolved.count = count2;
|
|
18015
|
+
}
|
|
18016
|
+
return { request: resolved, warnings };
|
|
18017
|
+
}
|
|
18018
|
+
|
|
17308
18019
|
// src/keys.ts
|
|
17309
18020
|
var ADAPTER_KEYS = {
|
|
17310
18021
|
"ai-sdk-text": [],
|
|
@@ -17317,7 +18028,8 @@ var ADAPTER_KEYS = {
|
|
|
17317
18028
|
prodia: ["prodia"],
|
|
17318
18029
|
higgsfield: ["higgsfield"],
|
|
17319
18030
|
"xai-video": ["xai"],
|
|
17320
|
-
luma: ["luma"]
|
|
18031
|
+
luma: ["luma"],
|
|
18032
|
+
fish: ["fish"]
|
|
17321
18033
|
};
|
|
17322
18034
|
function hasAll(keys, names) {
|
|
17323
18035
|
if (!keys) return false;
|
|
@@ -17376,6 +18088,7 @@ function keysFromEnv(env, prefix = "") {
|
|
|
17376
18088
|
set("higgsfield", pick2("HIGGSFIELD_API_KEY"));
|
|
17377
18089
|
set("higgsfieldSecret", pick2("HIGGSFIELD_API_SECRET"));
|
|
17378
18090
|
set("luma", pick2("LUMA_API_KEY", "LUMA_AGENTS_API_KEY"));
|
|
18091
|
+
set("fish", pick2("FISH_AUDIO_API_KEY"));
|
|
17379
18092
|
set("cloudflare", pick2("CLOUDFLARE_AI_GATEWAY_TOKEN", "CF_AIG_TOKEN"));
|
|
17380
18093
|
const bearer = pick2("AWS_BEARER_TOKEN_BEDROCK");
|
|
17381
18094
|
const accessKeyId = pick2("AWS_ACCESS_KEY_ID");
|
|
@@ -17398,7 +18111,7 @@ function keysFromEnv(env, prefix = "") {
|
|
|
17398
18111
|
|
|
17399
18112
|
// src/text.ts
|
|
17400
18113
|
var import_ai4 = require("ai");
|
|
17401
|
-
var
|
|
18114
|
+
var import_zod32 = require("zod");
|
|
17402
18115
|
function mergeTextProviderOptions(catalog, caller) {
|
|
17403
18116
|
const merged = {};
|
|
17404
18117
|
const catalogOptions = catalog.providerOptions ?? {};
|
|
@@ -17437,17 +18150,17 @@ function passthroughTextModel(model) {
|
|
|
17437
18150
|
pricingKind: "token"
|
|
17438
18151
|
};
|
|
17439
18152
|
}
|
|
17440
|
-
var perplexityCostSchema =
|
|
17441
|
-
perplexity:
|
|
18153
|
+
var perplexityCostSchema = import_zod32.z.object({
|
|
18154
|
+
perplexity: import_zod32.z.object({ cost: import_zod32.z.object({ totalCost: import_zod32.z.number().finite().nonnegative() }) })
|
|
17442
18155
|
});
|
|
17443
18156
|
function reportedCostUsd(metadata) {
|
|
17444
18157
|
const parsed = perplexityCostSchema.safeParse(metadata);
|
|
17445
18158
|
return parsed.success ? parsed.data.perplexity.cost.totalCost : void 0;
|
|
17446
18159
|
}
|
|
17447
|
-
function textUsageEvent(model, provider,
|
|
17448
|
-
const inputTokens =
|
|
17449
|
-
const outputTokens =
|
|
17450
|
-
const total =
|
|
18160
|
+
function textUsageEvent(model, provider, usage4, providerMetadata) {
|
|
18161
|
+
const inputTokens = usage4.inputTokens ?? 0;
|
|
18162
|
+
const outputTokens = usage4.outputTokens ?? 0;
|
|
18163
|
+
const total = usage4.totalTokens ?? inputTokens + outputTokens;
|
|
17451
18164
|
const event = {
|
|
17452
18165
|
model: model.id,
|
|
17453
18166
|
provider,
|
|
@@ -17482,7 +18195,7 @@ function createTextSteps(initial, resolve, callerProviderOptions) {
|
|
|
17482
18195
|
return { ...prepared, providerOptions };
|
|
17483
18196
|
};
|
|
17484
18197
|
}
|
|
17485
|
-
function
|
|
18198
|
+
function usage4(results) {
|
|
17486
18199
|
const grouped = /* @__PURE__ */ new Map();
|
|
17487
18200
|
for (const [index, step] of results.entries()) {
|
|
17488
18201
|
const target = steps.get(index) ?? initial;
|
|
@@ -17506,12 +18219,12 @@ function createTextSteps(initial, resolve, callerProviderOptions) {
|
|
|
17506
18219
|
}
|
|
17507
18220
|
return [...grouped.values()];
|
|
17508
18221
|
}
|
|
17509
|
-
return { wrap, usage:
|
|
18222
|
+
return { wrap, usage: usage4 };
|
|
17510
18223
|
}
|
|
17511
18224
|
|
|
17512
18225
|
// src/client.ts
|
|
17513
18226
|
var import_ai5 = require("ai");
|
|
17514
|
-
var
|
|
18227
|
+
var import_zod33 = require("zod");
|
|
17515
18228
|
|
|
17516
18229
|
// src/generated-image.ts
|
|
17517
18230
|
function toGeneratedImage(image) {
|
|
@@ -17633,9 +18346,9 @@ function providerJobMethods(kind, deps) {
|
|
|
17633
18346
|
if (!methods.result) throw missing3(adapter, ctx.model);
|
|
17634
18347
|
const result = await methods.result(sub, ctx, webhook);
|
|
17635
18348
|
const base = { ...result.usage, model: ctx.model.id, unit: ctx.model.usage.unit };
|
|
17636
|
-
const
|
|
17637
|
-
await deps.emit(
|
|
17638
|
-
return { ...result, usage:
|
|
18349
|
+
const usage4 = sub.submittedAt === void 0 ? base : deps.timed(base, sub.submittedAt);
|
|
18350
|
+
await deps.emit(usage4);
|
|
18351
|
+
return { ...result, usage: usage4 };
|
|
17639
18352
|
},
|
|
17640
18353
|
async cancel(sub, call = {}) {
|
|
17641
18354
|
const { methods, adapter, ctx } = target(sub.model, call);
|
|
@@ -17660,6 +18373,9 @@ var MEDIA_METHODS = {
|
|
|
17660
18373
|
lipsync: ["lipsync"],
|
|
17661
18374
|
dubbing: ["dub"],
|
|
17662
18375
|
transcription: ["transcribe"],
|
|
18376
|
+
// deleteVoice runs on the voice-clone row too; it checks with assertMethod("createVoice").
|
|
18377
|
+
"voice-clone": ["createVoice"],
|
|
18378
|
+
"voice-design": ["designVoice"],
|
|
17663
18379
|
"video-tool": ["submitVideoTool"],
|
|
17664
18380
|
// 3D jobs run through submitModel3d, which checks the row type itself; their preflight
|
|
17665
18381
|
// is model3dInputRefusal, not resolveOptions.
|
|
@@ -17674,6 +18390,8 @@ var METHOD_NOUN = {
|
|
|
17674
18390
|
lipsync: "a lipsync model",
|
|
17675
18391
|
dub: "a dubbing model",
|
|
17676
18392
|
transcribe: "a transcription model",
|
|
18393
|
+
createVoice: "a voice cloning model",
|
|
18394
|
+
designVoice: "a voice design model",
|
|
17677
18395
|
submitVideoTool: "a video tool"
|
|
17678
18396
|
};
|
|
17679
18397
|
function assertMethod(model, method) {
|
|
@@ -17716,6 +18434,14 @@ function resolveTranscriptionCall(model, request, onUnsupported = "error") {
|
|
|
17716
18434
|
assertMethod(model, "transcribe");
|
|
17717
18435
|
return resolveTranscriptionOptions(model, request, onUnsupported);
|
|
17718
18436
|
}
|
|
18437
|
+
function resolveVoiceCloneCall(model, request) {
|
|
18438
|
+
assertMethod(model, "createVoice");
|
|
18439
|
+
return resolveVoiceCloneOptions(model, request);
|
|
18440
|
+
}
|
|
18441
|
+
function resolveVoiceDesignCall(model, request, onUnsupported = "error") {
|
|
18442
|
+
assertMethod(model, "designVoice");
|
|
18443
|
+
return resolveVoiceDesignOptions(model, request, onUnsupported);
|
|
18444
|
+
}
|
|
17719
18445
|
|
|
17720
18446
|
// src/client-audio.ts
|
|
17721
18447
|
function noMethod(adapter, model, what) {
|
|
@@ -17805,6 +18531,49 @@ function audioNodeMethods(deps) {
|
|
|
17805
18531
|
const result = await adapter.transcribe(resolved, ctx);
|
|
17806
18532
|
return { ...result, usage: await deps.settle(model, result.usage, startedAt) };
|
|
17807
18533
|
},
|
|
18534
|
+
async createVoice(req, call = {}) {
|
|
18535
|
+
mediaRetryOptions(call);
|
|
18536
|
+
const { abortSignal, ...request } = req;
|
|
18537
|
+
const model = catalog.require(req.model);
|
|
18538
|
+
const { request: resolved, warnings } = resolveVoiceCloneCall(model, request);
|
|
18539
|
+
const { adapter, ctx } = prepare(model, call, abortSignal, warnings);
|
|
18540
|
+
if (!adapter.createVoice) throw noMethod(adapter, model, "clone a voice");
|
|
18541
|
+
const startedAt = Date.now();
|
|
18542
|
+
const result = await adapter.createVoice(resolved, ctx);
|
|
18543
|
+
return { ...result, usage: await deps.settle(model, result.usage, startedAt) };
|
|
18544
|
+
},
|
|
18545
|
+
async designVoice(req, call = {}) {
|
|
18546
|
+
mediaRetryOptions(call);
|
|
18547
|
+
const { abortSignal, ...request } = req;
|
|
18548
|
+
const model = catalog.require(req.model);
|
|
18549
|
+
const { request: resolved, warnings } = resolveVoiceDesignCall(
|
|
18550
|
+
model,
|
|
18551
|
+
request,
|
|
18552
|
+
call.onUnsupported ?? "error"
|
|
18553
|
+
);
|
|
18554
|
+
const { adapter, ctx } = prepare(model, call, abortSignal, warnings);
|
|
18555
|
+
if (!adapter.designVoice) throw noMethod(adapter, model, "design a voice");
|
|
18556
|
+
const startedAt = Date.now();
|
|
18557
|
+
const result = await adapter.designVoice(resolved, ctx);
|
|
18558
|
+
return { ...result, usage: await deps.settle(model, result.usage, startedAt) };
|
|
18559
|
+
},
|
|
18560
|
+
async deleteVoice(req, call = {}) {
|
|
18561
|
+
mediaRetryOptions(call);
|
|
18562
|
+
const { abortSignal, ...request } = req;
|
|
18563
|
+
const model = catalog.require(req.model);
|
|
18564
|
+
assertMethod(model, "createVoice");
|
|
18565
|
+
const voiceId = request.voiceId.trim();
|
|
18566
|
+
if (!voiceId) {
|
|
18567
|
+
throw new ModelKitError({
|
|
18568
|
+
code: "missing_input",
|
|
18569
|
+
message: `${model.id} requires voiceId`,
|
|
18570
|
+
model: model.id
|
|
18571
|
+
});
|
|
18572
|
+
}
|
|
18573
|
+
const { adapter, ctx } = prepare(model, call, abortSignal, []);
|
|
18574
|
+
if (!adapter.deleteVoice) throw noMethod(adapter, model, "delete a voice");
|
|
18575
|
+
await adapter.deleteVoice({ model: model.id, voiceId }, ctx);
|
|
18576
|
+
},
|
|
17808
18577
|
async dub(req, call = {}) {
|
|
17809
18578
|
mediaRetryOptions(call);
|
|
17810
18579
|
const { abortSignal, ...request } = req;
|
|
@@ -17819,10 +18588,10 @@ function audioNodeMethods(deps) {
|
|
|
17819
18588
|
const startedAt = Date.now();
|
|
17820
18589
|
const outcome = await adapter.dub(resolved, ctx);
|
|
17821
18590
|
if (outcome.kind === "audio") {
|
|
17822
|
-
const { audio, usage:
|
|
18591
|
+
const { audio, usage: usage4, raw } = outcome.result;
|
|
17823
18592
|
return {
|
|
17824
18593
|
audio,
|
|
17825
|
-
usage: await deps.settle(model,
|
|
18594
|
+
usage: await deps.settle(model, usage4, startedAt),
|
|
17826
18595
|
...raw !== void 0 && { raw }
|
|
17827
18596
|
};
|
|
17828
18597
|
}
|
|
@@ -17860,10 +18629,10 @@ function textAbortOptions(sdk, context) {
|
|
|
17860
18629
|
if (abortSignal) return { abortSignal };
|
|
17861
18630
|
return {};
|
|
17862
18631
|
}
|
|
17863
|
-
var catalogId =
|
|
17864
|
-
var exactSize =
|
|
17865
|
-
var sdkRatio =
|
|
17866
|
-
var sizeTier =
|
|
18632
|
+
var catalogId = import_zod33.z.string();
|
|
18633
|
+
var exactSize = import_zod33.z.templateLiteral([import_zod33.z.number(), "x", import_zod33.z.number()]);
|
|
18634
|
+
var sdkRatio = import_zod33.z.templateLiteral([import_zod33.z.number(), ":", import_zod33.z.number()]);
|
|
18635
|
+
var sizeTier = import_zod33.z.enum(["512", "1K", "2K", "4K"]);
|
|
17867
18636
|
function isCatalogId(model) {
|
|
17868
18637
|
return catalogId.safeParse(model).success;
|
|
17869
18638
|
}
|
|
@@ -18076,7 +18845,7 @@ function createModelKit(config, adapters) {
|
|
|
18076
18845
|
const images = result.images.map(
|
|
18077
18846
|
(file) => toGeneratedImage({ bytes: file.uint8Array, mime: file.mediaType })
|
|
18078
18847
|
);
|
|
18079
|
-
const
|
|
18848
|
+
const usage4 = timed(
|
|
18080
18849
|
{
|
|
18081
18850
|
model: model.modelId,
|
|
18082
18851
|
provider: model.provider,
|
|
@@ -18086,8 +18855,8 @@ function createModelKit(config, adapters) {
|
|
|
18086
18855
|
},
|
|
18087
18856
|
startedAt
|
|
18088
18857
|
);
|
|
18089
|
-
await emit(
|
|
18090
|
-
return { image: images[0], images, usage:
|
|
18858
|
+
await emit(usage4);
|
|
18859
|
+
return { image: images[0], images, usage: usage4, raw: result, warnings };
|
|
18091
18860
|
}
|
|
18092
18861
|
function passthroughVideo(req, call) {
|
|
18093
18862
|
const {
|
|
@@ -18163,7 +18932,7 @@ function createModelKit(config, adapters) {
|
|
|
18163
18932
|
let settled;
|
|
18164
18933
|
let failed = false;
|
|
18165
18934
|
const done = pending.then(async (result) => {
|
|
18166
|
-
const
|
|
18935
|
+
const usage4 = timed(
|
|
18167
18936
|
{
|
|
18168
18937
|
model: model.modelId,
|
|
18169
18938
|
provider: model.provider,
|
|
@@ -18176,10 +18945,10 @@ function createModelKit(config, adapters) {
|
|
|
18176
18945
|
);
|
|
18177
18946
|
settled = {
|
|
18178
18947
|
video: { bytes: result.video.uint8Array, mime: result.video.mediaType },
|
|
18179
|
-
usage:
|
|
18948
|
+
usage: usage4,
|
|
18180
18949
|
raw: result
|
|
18181
18950
|
};
|
|
18182
|
-
await emit(
|
|
18951
|
+
await emit(usage4);
|
|
18183
18952
|
return settled;
|
|
18184
18953
|
});
|
|
18185
18954
|
done.catch(() => {
|
|
@@ -18206,12 +18975,12 @@ function createModelKit(config, adapters) {
|
|
|
18206
18975
|
if (settled) return settled;
|
|
18207
18976
|
const pending = result(opts).then(
|
|
18208
18977
|
async (out) => {
|
|
18209
|
-
const
|
|
18978
|
+
const usage4 = timed(
|
|
18210
18979
|
{ ...out.usage, model: model.id, unit: model.usage.unit },
|
|
18211
18980
|
startedAt
|
|
18212
18981
|
);
|
|
18213
|
-
await emit(
|
|
18214
|
-
return { ...out, usage:
|
|
18982
|
+
await emit(usage4);
|
|
18983
|
+
return { ...out, usage: usage4 };
|
|
18215
18984
|
},
|
|
18216
18985
|
(cause) => {
|
|
18217
18986
|
settled = void 0;
|
|
@@ -18231,9 +19000,9 @@ function createModelKit(config, adapters) {
|
|
|
18231
19000
|
return context(model, signal ? { ...call, signal } : call, warnings);
|
|
18232
19001
|
},
|
|
18233
19002
|
async settle(model, event, startedAt) {
|
|
18234
|
-
const
|
|
18235
|
-
await emit(
|
|
18236
|
-
return
|
|
19003
|
+
const usage4 = timed({ ...event, model: model.id, unit: model.usage.unit }, startedAt);
|
|
19004
|
+
await emit(usage4);
|
|
19005
|
+
return usage4;
|
|
18237
19006
|
},
|
|
18238
19007
|
wrapVideoJob
|
|
18239
19008
|
});
|
|
@@ -18269,11 +19038,11 @@ function createModelKit(config, adapters) {
|
|
|
18269
19038
|
});
|
|
18270
19039
|
const startedAt = Date.now();
|
|
18271
19040
|
const result = await adapter.generateImage(request, ctx);
|
|
18272
|
-
const
|
|
19041
|
+
const usage4 = timed(
|
|
18273
19042
|
{ ...result.usage, model: model.id, unit: model.usage.unit },
|
|
18274
19043
|
startedAt
|
|
18275
19044
|
);
|
|
18276
|
-
await emit(
|
|
19045
|
+
await emit(usage4);
|
|
18277
19046
|
const images = result.images.map(toGeneratedImage);
|
|
18278
19047
|
const first = images[0];
|
|
18279
19048
|
if (!first)
|
|
@@ -18282,7 +19051,7 @@ function createModelKit(config, adapters) {
|
|
|
18282
19051
|
message: `${model.id} returned no image`,
|
|
18283
19052
|
model: model.id
|
|
18284
19053
|
});
|
|
18285
|
-
return { ...result, usage:
|
|
19054
|
+
return { ...result, usage: usage4, image: first, images, warnings };
|
|
18286
19055
|
},
|
|
18287
19056
|
async generateVideo(req, call = {}) {
|
|
18288
19057
|
mediaRetryOptions(call);
|
|
@@ -18381,12 +19150,12 @@ function createModelKit(config, adapters) {
|
|
|
18381
19150
|
}
|
|
18382
19151
|
const startedAt = Date.now();
|
|
18383
19152
|
const result = await adapter.generateAudio(resolved, ctx);
|
|
18384
|
-
const
|
|
19153
|
+
const usage4 = timed(
|
|
18385
19154
|
{ ...result.usage, model: model.id, unit: model.usage.unit },
|
|
18386
19155
|
startedAt
|
|
18387
19156
|
);
|
|
18388
|
-
await emit(
|
|
18389
|
-
return { ...result, usage:
|
|
19157
|
+
await emit(usage4);
|
|
19158
|
+
return { ...result, usage: usage4 };
|
|
18390
19159
|
},
|
|
18391
19160
|
async prepareMediaPart(modelId, ref, mediaType, call = {}) {
|
|
18392
19161
|
mediaRetryOptions(call);
|
|
@@ -18466,8 +19235,8 @@ function createModelKit(config, adapters) {
|
|
|
18466
19235
|
options.prepareStep ?? options.experimental_prepareStep
|
|
18467
19236
|
),
|
|
18468
19237
|
onFinish: async (event) => {
|
|
18469
|
-
for (const
|
|
18470
|
-
await emit(textTimed(withRowUnit(
|
|
19238
|
+
for (const usage4 of steps.usage(event.steps))
|
|
19239
|
+
await emit(textTimed(withRowUnit(usage4), event.steps.length, startedAt));
|
|
18471
19240
|
await callerOnFinish?.(event);
|
|
18472
19241
|
}
|
|
18473
19242
|
});
|
|
@@ -18590,6 +19359,7 @@ var describe = (modelId) => createDefaultModelKit().describe(modelId);
|
|
|
18590
19359
|
falAdapter,
|
|
18591
19360
|
falWebhookBodySchema,
|
|
18592
19361
|
fileCatalogCache,
|
|
19362
|
+
fishAdapter,
|
|
18593
19363
|
generateAudio,
|
|
18594
19364
|
generateImage,
|
|
18595
19365
|
generateObject,
|
|
@@ -18642,6 +19412,8 @@ var describe = (modelId) => createDefaultModelKit().describe(modelId);
|
|
|
18642
19412
|
resolveTranscriptionOptions,
|
|
18643
19413
|
resolveVideoOptions,
|
|
18644
19414
|
resolveVoiceChangeOptions,
|
|
19415
|
+
resolveVoiceCloneOptions,
|
|
19416
|
+
resolveVoiceDesignOptions,
|
|
18645
19417
|
shouldRetry,
|
|
18646
19418
|
sleep,
|
|
18647
19419
|
sortCatalogRows,
|