@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.js
CHANGED
|
@@ -1230,6 +1230,303 @@ var VEED_SUBTITLES = {
|
|
|
1230
1230
|
}
|
|
1231
1231
|
};
|
|
1232
1232
|
|
|
1233
|
+
// src/catalog/voices-fish.ts
|
|
1234
|
+
var FISH_VOICES = [
|
|
1235
|
+
{
|
|
1236
|
+
id: "933563129e564b19a115bedd57b7406a",
|
|
1237
|
+
name: "Sarah",
|
|
1238
|
+
gender: "female",
|
|
1239
|
+
languages: ["en"],
|
|
1240
|
+
description: "An engaged speaker.",
|
|
1241
|
+
previewUrl: "https://platform.r2.fish.audio/task/4e204945670c460c86fdab57512cb308.mp3"
|
|
1242
|
+
},
|
|
1243
|
+
{
|
|
1244
|
+
id: "bf322df2096a46f18c579d0baa36f41d",
|
|
1245
|
+
name: "Adrian",
|
|
1246
|
+
gender: "male",
|
|
1247
|
+
languages: ["en"],
|
|
1248
|
+
description: "A steady and reliable narrator.",
|
|
1249
|
+
previewUrl: "https://platform.r2.fish.audio/task/d730b09f4a484316a77ecc86137e85fb.mp3"
|
|
1250
|
+
},
|
|
1251
|
+
{
|
|
1252
|
+
id: "536d3a5e000945adb7038665781a4aca",
|
|
1253
|
+
name: "Ethan",
|
|
1254
|
+
gender: "male",
|
|
1255
|
+
languages: ["en"],
|
|
1256
|
+
description: "A curious explainer.",
|
|
1257
|
+
previewUrl: "https://platform.r2.fish.audio/task/bdd677ed767744fc91f166468786264b.mp3"
|
|
1258
|
+
},
|
|
1259
|
+
{
|
|
1260
|
+
id: "b347db033a6549378b48d00acb0d06cd",
|
|
1261
|
+
name: "Selene",
|
|
1262
|
+
gender: "female",
|
|
1263
|
+
languages: ["en"],
|
|
1264
|
+
description: "A meditative female voice.",
|
|
1265
|
+
previewUrl: "https://platform.r2.fish.audio/task/fcf629b4a0b343558f461338ba1b9da4.mp3"
|
|
1266
|
+
},
|
|
1267
|
+
{
|
|
1268
|
+
id: "9a9cf47702da476aa4629e2506d4a857",
|
|
1269
|
+
name: "Hannah",
|
|
1270
|
+
gender: "female",
|
|
1271
|
+
languages: ["en"],
|
|
1272
|
+
description: "A conversation specialist.",
|
|
1273
|
+
previewUrl: "https://platform.r2.fish.audio/task/08d658835feb427db808e37060b78eb0.mp3"
|
|
1274
|
+
},
|
|
1275
|
+
{
|
|
1276
|
+
id: "79d0bd3e4e5444b18f7b6d89b5927bf1",
|
|
1277
|
+
name: "Jordan",
|
|
1278
|
+
gender: "male",
|
|
1279
|
+
languages: ["en"],
|
|
1280
|
+
description: "A motivational speaker.",
|
|
1281
|
+
previewUrl: "https://platform.r2.fish.audio/task/edecbc0bdd4c46c39eda8520a0f729ef.mp3"
|
|
1282
|
+
},
|
|
1283
|
+
{
|
|
1284
|
+
id: "e3cd384158934cc9a01029cd7d278634",
|
|
1285
|
+
name: "Laura",
|
|
1286
|
+
gender: "female",
|
|
1287
|
+
languages: ["en"],
|
|
1288
|
+
description: "A confident female narrator.",
|
|
1289
|
+
previewUrl: "https://platform.r2.fish.audio/task/e821bef995344d519caa1c93d808db23.mp3"
|
|
1290
|
+
},
|
|
1291
|
+
{
|
|
1292
|
+
id: "f3a2b90078d54a65af4b95f63bc7798e",
|
|
1293
|
+
name: "Sheila",
|
|
1294
|
+
gender: "female",
|
|
1295
|
+
accent: "american",
|
|
1296
|
+
languages: ["en"],
|
|
1297
|
+
description: "A young American English woman's voice.",
|
|
1298
|
+
previewUrl: "https://platform.r2.fish.audio/tasks/2026-08-24/9bb9e1a1cf3f47f38700da1c5c0a678a.mp3"
|
|
1299
|
+
},
|
|
1300
|
+
{
|
|
1301
|
+
id: "0db6e93af420470b9d9b9a886dbaa954",
|
|
1302
|
+
name: "Kai",
|
|
1303
|
+
gender: "male",
|
|
1304
|
+
languages: ["en"],
|
|
1305
|
+
description: "A friendly English man's voice for companion apps and everyday conversation.",
|
|
1306
|
+
previewUrl: "https://platform.r2.fish.audio/tasks/2026-08-24/13306f1172544c3ba3106d1e363feaa6.mp3"
|
|
1307
|
+
},
|
|
1308
|
+
{
|
|
1309
|
+
id: "8abfa9ebd4c24a3399b68c3cdac8c7b5",
|
|
1310
|
+
name: "Freya",
|
|
1311
|
+
gender: "female",
|
|
1312
|
+
accent: "british",
|
|
1313
|
+
languages: ["en"],
|
|
1314
|
+
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.",
|
|
1315
|
+
previewUrl: "https://platform.r2.fish.audio/tasks/2026-08-25/07918705a56b42daaab149f65392cea7.mp3"
|
|
1316
|
+
},
|
|
1317
|
+
{
|
|
1318
|
+
id: "2f64e528a4f2406691925ab1e0ed5b7f",
|
|
1319
|
+
name: "Ananya",
|
|
1320
|
+
gender: "female",
|
|
1321
|
+
languages: ["hi"],
|
|
1322
|
+
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",
|
|
1323
|
+
previewUrl: "https://platform.r2.fish.audio/tasks/2026-08-25/a17a700668d8405f8316db120733145c.mp3"
|
|
1324
|
+
},
|
|
1325
|
+
{
|
|
1326
|
+
id: "cefd91a07b99468f9148e2580990082d",
|
|
1327
|
+
name: "Arjun",
|
|
1328
|
+
gender: "male",
|
|
1329
|
+
languages: ["hi"],
|
|
1330
|
+
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",
|
|
1331
|
+
previewUrl: "https://platform.r2.fish.audio/tasks/2026-08-24/a0c4a8eadb7841cdae8e5e68031a2dfb.mp3"
|
|
1332
|
+
},
|
|
1333
|
+
{
|
|
1334
|
+
id: "3f065d660212478a9c697fa965b4d098",
|
|
1335
|
+
name: "Carmen",
|
|
1336
|
+
gender: "female",
|
|
1337
|
+
languages: ["es"],
|
|
1338
|
+
description: "Una voz clara y segura para asistentes de voz, atenci\xF3n al cliente y presentaciones.",
|
|
1339
|
+
previewUrl: "https://platform.r2.fish.audio/tasks/2026-08-25/3421be48b6cb4c28bf829c25188e7e74.mp3"
|
|
1340
|
+
},
|
|
1341
|
+
{
|
|
1342
|
+
id: "ec0718028a2445fb9be8e8bfb56a0150",
|
|
1343
|
+
name: "Rodrigo",
|
|
1344
|
+
gender: "male",
|
|
1345
|
+
languages: ["es"],
|
|
1346
|
+
description: "Una voz clara y segura para asistentes de voz, atenci\xF3n al cliente y presentaciones.",
|
|
1347
|
+
previewUrl: "https://platform.r2.fish.audio/tasks/2026-08-25/5a77c32365604800ad5b4eb13c5585df.mp3"
|
|
1348
|
+
},
|
|
1349
|
+
{
|
|
1350
|
+
id: "10a3a20742114a4ea6dd441e7591850f",
|
|
1351
|
+
name: "Manon",
|
|
1352
|
+
gender: "female",
|
|
1353
|
+
languages: ["fr"],
|
|
1354
|
+
description: "Une voix claire et vive, adapt\xE9e aux assistants vocaux et au support client.",
|
|
1355
|
+
previewUrl: "https://platform.r2.fish.audio/tasks/2026-08-25/f7b75ee1fa524e48a8cefb003cf72952.mp3"
|
|
1356
|
+
},
|
|
1357
|
+
{
|
|
1358
|
+
id: "f69bca092b674168a8d02d61ca20943c",
|
|
1359
|
+
name: "Lucas",
|
|
1360
|
+
gender: "male",
|
|
1361
|
+
languages: ["fr"],
|
|
1362
|
+
description: "Une voix claire et assur\xE9e, adapt\xE9e aux assistants vocaux et au service client.",
|
|
1363
|
+
previewUrl: "https://platform.r2.fish.audio/tasks/2026-08-25/86fca3e56a014a3d8a11450854bb8311.mp3"
|
|
1364
|
+
},
|
|
1365
|
+
{
|
|
1366
|
+
id: "3937b44b604249f18b94913daef94043",
|
|
1367
|
+
name: "Lena",
|
|
1368
|
+
gender: "female",
|
|
1369
|
+
languages: ["de"],
|
|
1370
|
+
description: "Eine klare, souver\xE4ne Stimme f\xFCr Sprachassistenten, Kundenservice und Pr\xE4sentationen.",
|
|
1371
|
+
previewUrl: "https://platform.r2.fish.audio/tasks/2026-08-25/8659fec80b74442dab68a7755716a401.mp3"
|
|
1372
|
+
},
|
|
1373
|
+
{
|
|
1374
|
+
id: "c1e7cc926aa5469aa966c353094d4b0b",
|
|
1375
|
+
name: "Lukas",
|
|
1376
|
+
gender: "male",
|
|
1377
|
+
languages: ["de"],
|
|
1378
|
+
description: "Eine klare, souver\xE4ne Stimme f\xFCr Sprachassistenten, Kundenservice und Pr\xE4sentationen.",
|
|
1379
|
+
previewUrl: "https://platform.r2.fish.audio/tasks/2026-08-25/fb1d538126bb4fe38f8366250f6a2136.mp3"
|
|
1380
|
+
},
|
|
1381
|
+
{
|
|
1382
|
+
id: "b3c060cc41544a7da94a2c487647c902",
|
|
1383
|
+
name: "Let\xEDcia",
|
|
1384
|
+
gender: "female",
|
|
1385
|
+
accent: "brazilian",
|
|
1386
|
+
languages: ["pt"],
|
|
1387
|
+
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.",
|
|
1388
|
+
previewUrl: "https://platform.r2.fish.audio/tasks/2026-10-12/13c6c0d96b5c4069951f89868ee15360.mp3"
|
|
1389
|
+
},
|
|
1390
|
+
{
|
|
1391
|
+
id: "add7bcb8d3c8423bbfa152ca232aad6e",
|
|
1392
|
+
name: "Ricardo",
|
|
1393
|
+
gender: "male",
|
|
1394
|
+
accent: "brazilian",
|
|
1395
|
+
languages: ["pt"],
|
|
1396
|
+
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.",
|
|
1397
|
+
previewUrl: "https://platform.r2.fish.audio/tasks/2026-10-12/67475fc717ae45cbb38e647a2dd37fe1.mp3"
|
|
1398
|
+
},
|
|
1399
|
+
{
|
|
1400
|
+
id: "b2d9d8db057042688a5e318b8f405bc2",
|
|
1401
|
+
name: "Kyoko",
|
|
1402
|
+
gender: "female",
|
|
1403
|
+
languages: ["ja"],
|
|
1404
|
+
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",
|
|
1405
|
+
previewUrl: "https://platform.r2.fish.audio/task/993b3ccb52124341aff79580f1ce5a5a.mp3"
|
|
1406
|
+
},
|
|
1407
|
+
{
|
|
1408
|
+
id: "297a6fd278df47c3b9da9bfdf55ac89a",
|
|
1409
|
+
name: "Satoru",
|
|
1410
|
+
gender: "male",
|
|
1411
|
+
languages: ["ja"],
|
|
1412
|
+
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",
|
|
1413
|
+
previewUrl: "https://platform.r2.fish.audio/task/1b4712fb831f4c149eef6b0133157418.mp3"
|
|
1414
|
+
},
|
|
1415
|
+
{
|
|
1416
|
+
id: "0b14f34a13a94ed88fe6113193749bb0",
|
|
1417
|
+
name: "Fatima",
|
|
1418
|
+
gender: "female",
|
|
1419
|
+
languages: ["ar"],
|
|
1420
|
+
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.",
|
|
1421
|
+
previewUrl: "https://platform.r2.fish.audio/tasks/2026-08-24/93406e1b905a4c4994306e3421243390.mp3"
|
|
1422
|
+
},
|
|
1423
|
+
{
|
|
1424
|
+
id: "74c6aba5cbf94a15bbdc547ffce5cb38",
|
|
1425
|
+
name: "Yutong",
|
|
1426
|
+
gender: "female",
|
|
1427
|
+
languages: ["zh"],
|
|
1428
|
+
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",
|
|
1429
|
+
previewUrl: "https://platform.r2.fish.audio/tasks/2026-08-25/a48320f37fe44c4699549a1afc3778e8.mp3"
|
|
1430
|
+
}
|
|
1431
|
+
];
|
|
1432
|
+
|
|
1433
|
+
// src/catalog/speech-fish.ts
|
|
1434
|
+
var FISH_LOGO = "https://cdn.jsdelivr.net/npm/@lobehub/icons-static-png@1.97.0/light/fishaudio.png";
|
|
1435
|
+
var PER_CALL = { unit: "images" };
|
|
1436
|
+
var PER_REQUEST = { unit: "requests" };
|
|
1437
|
+
var TTS_MAX_CHARS = 1e4;
|
|
1438
|
+
function fishTts(id, label, providerModelId, description) {
|
|
1439
|
+
return {
|
|
1440
|
+
id,
|
|
1441
|
+
aliases: [],
|
|
1442
|
+
label,
|
|
1443
|
+
type: "speech",
|
|
1444
|
+
adapter: "fish",
|
|
1445
|
+
providerModelId,
|
|
1446
|
+
lifecycle: "active",
|
|
1447
|
+
exposure: [],
|
|
1448
|
+
constraints: {
|
|
1449
|
+
voices: FISH_VOICES,
|
|
1450
|
+
outputFormats: ["mp3", "wav"],
|
|
1451
|
+
supports: [],
|
|
1452
|
+
prompt: { referenceSyntax: "numbered", maxChars: TTS_MAX_CHARS }
|
|
1453
|
+
},
|
|
1454
|
+
defaults: { voice: "9a9cf47702da476aa4629e2506d4a857", outputFormat: "mp3" },
|
|
1455
|
+
usage: PER_CALL,
|
|
1456
|
+
pricingKind: "flat",
|
|
1457
|
+
display: { provider: "fishaudio", logo: FISH_LOGO, description },
|
|
1458
|
+
capabilities: { customVoices: true }
|
|
1459
|
+
};
|
|
1460
|
+
}
|
|
1461
|
+
var FISH_MODELS = [
|
|
1462
|
+
fishTts(
|
|
1463
|
+
"fish-s2.1-pro",
|
|
1464
|
+
"Fish Audio S2.1 Pro",
|
|
1465
|
+
"s2.1-pro",
|
|
1466
|
+
"Fish Audio S2.1 Pro text to speech in 83 languages, with [bracket] directions and your own cloned voices."
|
|
1467
|
+
),
|
|
1468
|
+
fishTts(
|
|
1469
|
+
"fish-s2.1-pro-free",
|
|
1470
|
+
"Fish Audio S2.1 Pro Free",
|
|
1471
|
+
"s2.1-pro-free",
|
|
1472
|
+
"Fish Audio S2.1 Pro on the free developer tier: the same voices at no cost, without latency or data-processing guarantees."
|
|
1473
|
+
),
|
|
1474
|
+
fishTts(
|
|
1475
|
+
"fish-drama-3",
|
|
1476
|
+
"Fish Audio Drama 3",
|
|
1477
|
+
"drama-3",
|
|
1478
|
+
"Fish Audio Drama 3 text to speech you direct like an actor: [directions], sounds, pauses and per-word tags."
|
|
1479
|
+
),
|
|
1480
|
+
{
|
|
1481
|
+
id: "fish-voice-clone",
|
|
1482
|
+
aliases: [],
|
|
1483
|
+
label: "Fish Audio Voice Clone",
|
|
1484
|
+
type: "voice-clone",
|
|
1485
|
+
adapter: "fish",
|
|
1486
|
+
providerModelId: "voice-clone",
|
|
1487
|
+
lifecycle: "active",
|
|
1488
|
+
exposure: [],
|
|
1489
|
+
constraints: {
|
|
1490
|
+
// POST /model takes 1-20 voice files; Fish advises 10 s or more of clean speech each.
|
|
1491
|
+
references: { audios: 20, audioFormats: ["wav", "mp3", "m4a", "opus"] },
|
|
1492
|
+
supports: []
|
|
1493
|
+
},
|
|
1494
|
+
defaults: {},
|
|
1495
|
+
usage: PER_REQUEST,
|
|
1496
|
+
pricingKind: "flat",
|
|
1497
|
+
display: {
|
|
1498
|
+
provider: "fishaudio",
|
|
1499
|
+
logo: FISH_LOGO,
|
|
1500
|
+
description: "Clone a private, reusable voice from one or more clean recordings, then speak with it on the Fish Audio speech models."
|
|
1501
|
+
},
|
|
1502
|
+
capabilities: {}
|
|
1503
|
+
},
|
|
1504
|
+
{
|
|
1505
|
+
id: "fish-voice-design-1",
|
|
1506
|
+
aliases: [],
|
|
1507
|
+
label: "Fish Audio Voice Design",
|
|
1508
|
+
type: "voice-design",
|
|
1509
|
+
adapter: "fish",
|
|
1510
|
+
providerModelId: "voice-design-1",
|
|
1511
|
+
lifecycle: "active",
|
|
1512
|
+
exposure: [],
|
|
1513
|
+
constraints: {
|
|
1514
|
+
voiceDesign: { maxCandidates: 4, previewMaxChars: 150 },
|
|
1515
|
+
supports: [],
|
|
1516
|
+
prompt: { referenceSyntax: "numbered", maxChars: 2e3 }
|
|
1517
|
+
},
|
|
1518
|
+
defaults: {},
|
|
1519
|
+
usage: PER_REQUEST,
|
|
1520
|
+
pricingKind: "flat",
|
|
1521
|
+
display: {
|
|
1522
|
+
provider: "fishaudio",
|
|
1523
|
+
logo: FISH_LOGO,
|
|
1524
|
+
description: "Describe a voice and get up to four short candidates; keep one as a cloned voice."
|
|
1525
|
+
},
|
|
1526
|
+
capabilities: {}
|
|
1527
|
+
}
|
|
1528
|
+
];
|
|
1529
|
+
|
|
1233
1530
|
// src/catalog/languages-audio.ts
|
|
1234
1531
|
var ELEVENLABS_V4_LANGUAGES = [
|
|
1235
1532
|
{ code: "af", name: "Afrikaans" },
|
|
@@ -3311,7 +3608,7 @@ var ELEVENLABS_LOGO = "https://cdn.jsdelivr.net/npm/@lobehub/icons-static-png@1.
|
|
|
3311
3608
|
var GOOGLE_LOGO = "https://d31vvfpk2ppdyq.cloudfront.net/assets/image/192485d2-a76a-4657-9c06-930b2c70badd_compressed.png";
|
|
3312
3609
|
var MINIMAX_LOGO = "https://d31vvfpk2ppdyq.cloudfront.net/assets/image/f4c2e906-28b7-4a4a-b491-df8fef7808ed.png";
|
|
3313
3610
|
var SYNC_LOGO = "https://cdn.jsdelivr.net/npm/@lobehub/icons-static-png@1.97.0/light/sync.png";
|
|
3314
|
-
var
|
|
3611
|
+
var PER_CALL2 = { unit: "images" };
|
|
3315
3612
|
var EXPOSURE4 = ["cowork", "space_builder"];
|
|
3316
3613
|
var LIPSYNC_AUDIO = { audioSeconds: { max: 30 } };
|
|
3317
3614
|
function elevenLabsTts(tts) {
|
|
@@ -3332,7 +3629,7 @@ function elevenLabsTts(tts) {
|
|
|
3332
3629
|
prompt: { referenceSyntax: "numbered", maxChars: tts.maxChars }
|
|
3333
3630
|
},
|
|
3334
3631
|
defaults: { voice: "Rachel", ...tts.formats && { outputFormat: "mp3_44100_128" } },
|
|
3335
|
-
usage:
|
|
3632
|
+
usage: PER_CALL2,
|
|
3336
3633
|
pricingKind: "flat",
|
|
3337
3634
|
display: { provider: "elevenlabs", logo: ELEVENLABS_LOGO, description: tts.description },
|
|
3338
3635
|
capabilities: {}
|
|
@@ -3356,7 +3653,7 @@ function geminiTts(id, label, description) {
|
|
|
3356
3653
|
prompt: { referenceSyntax: "numbered", maxChars: 8192 }
|
|
3357
3654
|
},
|
|
3358
3655
|
defaults: { voice: "Kore" },
|
|
3359
|
-
usage:
|
|
3656
|
+
usage: PER_CALL2,
|
|
3360
3657
|
pricingKind: "flat",
|
|
3361
3658
|
display: { provider: "google", logo: GOOGLE_LOGO, description },
|
|
3362
3659
|
capabilities: {}
|
|
@@ -3379,7 +3676,7 @@ function syncLipsync(id, label, providerModelId, syncModel, description) {
|
|
|
3379
3676
|
},
|
|
3380
3677
|
defaults: {},
|
|
3381
3678
|
...syncModel !== void 0 && { providerOptions: { fal: { model: syncModel } } },
|
|
3382
|
-
usage:
|
|
3679
|
+
usage: PER_CALL2,
|
|
3383
3680
|
pricingKind: "flat",
|
|
3384
3681
|
display: { provider: "sync", logo: SYNC_LOGO, description },
|
|
3385
3682
|
capabilities: { acceptsSourceVideo: true }
|
|
@@ -3440,7 +3737,7 @@ var MEDIA_NODE_MODELS = [
|
|
|
3440
3737
|
prompt: { referenceSyntax: "numbered", maxChars: 1e4 }
|
|
3441
3738
|
},
|
|
3442
3739
|
defaults: { voice: "Wise_Woman" },
|
|
3443
|
-
usage:
|
|
3740
|
+
usage: PER_CALL2,
|
|
3444
3741
|
pricingKind: "flat",
|
|
3445
3742
|
display: {
|
|
3446
3743
|
provider: "minimax",
|
|
@@ -3467,7 +3764,7 @@ var MEDIA_NODE_MODELS = [
|
|
|
3467
3764
|
supports: []
|
|
3468
3765
|
},
|
|
3469
3766
|
defaults: { voice: "Rachel", outputFormat: "mp3_44100_128" },
|
|
3470
|
-
usage:
|
|
3767
|
+
usage: PER_CALL2,
|
|
3471
3768
|
pricingKind: "flat",
|
|
3472
3769
|
display: {
|
|
3473
3770
|
provider: "elevenlabs",
|
|
@@ -3494,7 +3791,7 @@ var MEDIA_NODE_MODELS = [
|
|
|
3494
3791
|
supports: []
|
|
3495
3792
|
},
|
|
3496
3793
|
defaults: {},
|
|
3497
|
-
usage:
|
|
3794
|
+
usage: PER_CALL2,
|
|
3498
3795
|
pricingKind: "flat",
|
|
3499
3796
|
display: {
|
|
3500
3797
|
provider: "elevenlabs",
|
|
@@ -3541,7 +3838,7 @@ var MEDIA_NODE_MODELS = [
|
|
|
3541
3838
|
supports: []
|
|
3542
3839
|
},
|
|
3543
3840
|
defaults: {},
|
|
3544
|
-
usage:
|
|
3841
|
+
usage: PER_CALL2,
|
|
3545
3842
|
pricingKind: "flat",
|
|
3546
3843
|
display: {
|
|
3547
3844
|
provider: "veed",
|
|
@@ -3593,7 +3890,7 @@ var MEDIA_NODE_MODELS = [
|
|
|
3593
3890
|
supports: []
|
|
3594
3891
|
},
|
|
3595
3892
|
defaults: {},
|
|
3596
|
-
usage:
|
|
3893
|
+
usage: PER_CALL2,
|
|
3597
3894
|
pricingKind: "flat",
|
|
3598
3895
|
display: {
|
|
3599
3896
|
provider: "elevenlabs",
|
|
@@ -3602,7 +3899,8 @@ var MEDIA_NODE_MODELS = [
|
|
|
3602
3899
|
},
|
|
3603
3900
|
capabilities: {}
|
|
3604
3901
|
},
|
|
3605
|
-
SAM_3_IMAGE
|
|
3902
|
+
SAM_3_IMAGE,
|
|
3903
|
+
...FISH_MODELS
|
|
3606
3904
|
];
|
|
3607
3905
|
|
|
3608
3906
|
// src/catalog/model3d.ts
|
|
@@ -7237,7 +7535,8 @@ var ADAPTER_IDS = [
|
|
|
7237
7535
|
"prodia",
|
|
7238
7536
|
"higgsfield",
|
|
7239
7537
|
"xai-video",
|
|
7240
|
-
"luma"
|
|
7538
|
+
"luma",
|
|
7539
|
+
"fish"
|
|
7241
7540
|
];
|
|
7242
7541
|
var ModelTypeSchema = z3.enum([
|
|
7243
7542
|
"text",
|
|
@@ -7254,6 +7553,8 @@ var ModelTypeSchema = z3.enum([
|
|
|
7254
7553
|
"dubbing",
|
|
7255
7554
|
"lipsync",
|
|
7256
7555
|
"transcription",
|
|
7556
|
+
"voice-clone",
|
|
7557
|
+
"voice-design",
|
|
7257
7558
|
"model3d"
|
|
7258
7559
|
]);
|
|
7259
7560
|
var LifecycleSchema = z3.enum(["active", "deprecated", "retired"]);
|
|
@@ -7429,6 +7730,10 @@ var ModelConstraintsSchema = z3.looseObject({
|
|
|
7429
7730
|
supports: z3.array(SupportedOptionSchema).optional(),
|
|
7430
7731
|
ratioIgnoredWith: z3.array(z3.enum(["firstFrame", "sourceVideo"])).optional(),
|
|
7431
7732
|
voices: z3.array(VoiceOptionSchema).optional(),
|
|
7733
|
+
voiceDesign: z3.object({
|
|
7734
|
+
maxCandidates: z3.number().int().positive(),
|
|
7735
|
+
previewMaxChars: z3.number().int().positive()
|
|
7736
|
+
}).optional(),
|
|
7432
7737
|
languages: z3.array(LanguageOptionSchema).optional(),
|
|
7433
7738
|
outputFormats: z3.array(z3.string().min(1)).min(1).optional(),
|
|
7434
7739
|
sourceVideoSeconds: VideoSecondsLimitsSchema.omit({ total: true }).extend({ inReferenceTotal: z3.boolean().optional() }).optional(),
|
|
@@ -7527,6 +7832,7 @@ var CatalogDisplaySchema = z3.looseObject({
|
|
|
7527
7832
|
});
|
|
7528
7833
|
var CatalogCapabilitiesSchema = z3.looseObject({
|
|
7529
7834
|
acceptsSourceVideo: z3.boolean().optional(),
|
|
7835
|
+
customVoices: z3.boolean().optional(),
|
|
7530
7836
|
videoEdit: z3.boolean().optional(),
|
|
7531
7837
|
framesExcludeReferences: z3.boolean().optional(),
|
|
7532
7838
|
sourceVideoExcludesFrames: z3.boolean().optional(),
|
|
@@ -8046,7 +8352,7 @@ var errorCodes = z6.object({
|
|
|
8046
8352
|
type: z6.string().optional(),
|
|
8047
8353
|
error: z6.object({ code: z6.string().optional(), type: z6.string().optional() }).optional()
|
|
8048
8354
|
});
|
|
8049
|
-
var BILLING_TEXT = /insufficient_quota|payment[ _]required|exhausted balance|insufficient (?:credits?|balance|funds)|billing_hard_limit/i;
|
|
8355
|
+
var BILLING_TEXT = /insufficient_quota|payment[ _]required|exhausted balance|insufficient (?:credits?|balance|funds)|billing_hard_limit|top up (?:api )?credit/i;
|
|
8050
8356
|
var BILLING_TEXT_STATUSES = /* @__PURE__ */ new Set([403, 429]);
|
|
8051
8357
|
function billingCode(body) {
|
|
8052
8358
|
const parsed = errorCodes.safeParse(body);
|
|
@@ -8443,16 +8749,16 @@ async function generateSeedreamImage(req, ctx) {
|
|
|
8443
8749
|
} else {
|
|
8444
8750
|
throwArkError(void 0, "Seedream returned no image URL or base64 data", modelId);
|
|
8445
8751
|
}
|
|
8446
|
-
const
|
|
8752
|
+
const usage4 = {
|
|
8447
8753
|
model: modelId,
|
|
8448
8754
|
provider: "ark",
|
|
8449
8755
|
modality: "IMAGE",
|
|
8450
8756
|
unit: "images",
|
|
8451
8757
|
quantity: 1
|
|
8452
8758
|
};
|
|
8453
|
-
if (req.size !== void 0)
|
|
8454
|
-
if (req.quality !== void 0)
|
|
8455
|
-
return { images: [{ bytes, mime: sniffedImageMime(bytes) }], usage:
|
|
8759
|
+
if (req.size !== void 0) usage4.imageSize = req.size;
|
|
8760
|
+
if (req.quality !== void 0) usage4.imageQuality = req.quality;
|
|
8761
|
+
return { images: [{ bytes, mime: sniffedImageMime(bytes) }], usage: usage4, raw: data };
|
|
8456
8762
|
}
|
|
8457
8763
|
var SeedanceUsageSchema = z7.object({
|
|
8458
8764
|
total_tokens: z7.number().optional(),
|
|
@@ -8493,7 +8799,7 @@ function seedanceErrorMessage(error, status) {
|
|
|
8493
8799
|
if (asObject.success && asObject.data.message !== void 0) return asObject.data.message;
|
|
8494
8800
|
return `Seedance task ${status}`;
|
|
8495
8801
|
}
|
|
8496
|
-
function seedanceJob(ctx, key, jobId,
|
|
8802
|
+
function seedanceJob(ctx, key, jobId, usage4) {
|
|
8497
8803
|
const modelId = ctx.model.id;
|
|
8498
8804
|
const fetchStatus = async () => {
|
|
8499
8805
|
const res = await arkFetch(ctx, `${arkBaseUrl(ctx)}${SUBMIT_PATH}/${jobId}`, {
|
|
@@ -8543,21 +8849,21 @@ function seedanceJob(ctx, key, jobId, usage3) {
|
|
|
8543
8849
|
modelId
|
|
8544
8850
|
);
|
|
8545
8851
|
if (polled.duration !== void 0 && polled.duration > 0) {
|
|
8546
|
-
|
|
8547
|
-
|
|
8852
|
+
usage4.quantity = polled.duration;
|
|
8853
|
+
usage4.durationSeconds = polled.duration;
|
|
8548
8854
|
}
|
|
8549
8855
|
const rendered = VideoResolutionSchema.safeParse(
|
|
8550
8856
|
polled.resolution?.toLowerCase()
|
|
8551
8857
|
);
|
|
8552
|
-
if (rendered.success)
|
|
8858
|
+
if (rendered.success) usage4.resolution = rendered.data;
|
|
8553
8859
|
const tokens = polled.usage;
|
|
8554
8860
|
if (tokens?.total_tokens !== void 0 && tokens.completion_tokens !== void 0) {
|
|
8555
|
-
|
|
8556
|
-
|
|
8861
|
+
usage4.inputTokens = tokens.total_tokens - tokens.completion_tokens;
|
|
8862
|
+
usage4.outputTokens = tokens.completion_tokens;
|
|
8557
8863
|
}
|
|
8558
8864
|
return {
|
|
8559
8865
|
video: { url, expiresAt: new Date(Date.now() + VIDEO_URL_TTL_MS) },
|
|
8560
|
-
usage:
|
|
8866
|
+
usage: usage4,
|
|
8561
8867
|
raw: polled
|
|
8562
8868
|
};
|
|
8563
8869
|
}
|
|
@@ -8663,8 +8969,8 @@ async function generateSeedanceVideo(req, ctx) {
|
|
|
8663
8969
|
);
|
|
8664
8970
|
if (!submit.id) throwArkError(void 0, "Seedance task create returned no id", modelId);
|
|
8665
8971
|
const jobId = submit.id;
|
|
8666
|
-
const
|
|
8667
|
-
return seedanceJob(ctx, key, jobId,
|
|
8972
|
+
const usage4 = seedanceUsage(ctx, req, taskType === "edit" ? requestedDuration : duration);
|
|
8973
|
+
return seedanceJob(ctx, key, jobId, usage4);
|
|
8668
8974
|
}
|
|
8669
8975
|
|
|
8670
8976
|
// src/adapters/fal.ts
|
|
@@ -10152,7 +10458,7 @@ async function collectFalPlanImages(payload, plan4, ctx, req) {
|
|
|
10152
10458
|
return { bytes, mime: mime || "image/png" };
|
|
10153
10459
|
})
|
|
10154
10460
|
);
|
|
10155
|
-
const
|
|
10461
|
+
const usage4 = {
|
|
10156
10462
|
model: ctx.model.id,
|
|
10157
10463
|
provider: "fal",
|
|
10158
10464
|
modality: "IMAGE",
|
|
@@ -10160,9 +10466,9 @@ async function collectFalPlanImages(payload, plan4, ctx, req) {
|
|
|
10160
10466
|
quantity: images.length
|
|
10161
10467
|
};
|
|
10162
10468
|
const billedSize = plan4.imageSize ?? req.size;
|
|
10163
|
-
if (billedSize !== void 0 && ctx.model.type === "image")
|
|
10164
|
-
if (plan4.imageQuality !== void 0)
|
|
10165
|
-
const result = { images, usage:
|
|
10469
|
+
if (billedSize !== void 0 && ctx.model.type === "image") usage4.imageSize = billedSize;
|
|
10470
|
+
if (plan4.imageQuality !== void 0) usage4.imageQuality = plan4.imageQuality;
|
|
10471
|
+
const result = { images, usage: usage4, raw: payload };
|
|
10166
10472
|
const remote = files.find((f) => !f.url.startsWith("data:"));
|
|
10167
10473
|
if (remote !== void 0) result.outputUrl = remote.url;
|
|
10168
10474
|
return result;
|
|
@@ -12325,14 +12631,297 @@ function planUsage(ctx, plan4) {
|
|
|
12325
12631
|
};
|
|
12326
12632
|
}
|
|
12327
12633
|
|
|
12634
|
+
// src/adapters/fish.ts
|
|
12635
|
+
import { z as z21 } from "zod";
|
|
12636
|
+
var DEFAULT_BASE_URL = "https://api.fish.audio";
|
|
12637
|
+
var FISH_TTS_MODEL_IDS = /* @__PURE__ */ new Set([
|
|
12638
|
+
"s2.1-pro",
|
|
12639
|
+
"s2.1-pro-free",
|
|
12640
|
+
"drama-3"
|
|
12641
|
+
]);
|
|
12642
|
+
var FISH_VOICE_CLONE = "voice-clone";
|
|
12643
|
+
var FISH_VOICE_DESIGN = "voice-design-1";
|
|
12644
|
+
var VOICE_ID = /^[A-Za-z0-9_-]{1,64}$/;
|
|
12645
|
+
function fishRowRefusal(row2) {
|
|
12646
|
+
const id = row2.providerModelId;
|
|
12647
|
+
if (row2.type === "speech") {
|
|
12648
|
+
return FISH_TTS_MODEL_IDS.has(id) ? void 0 : `fish speech rows need providerModelId ${[...FISH_TTS_MODEL_IDS].join(", ")}`;
|
|
12649
|
+
}
|
|
12650
|
+
if (row2.type === "voice-clone") {
|
|
12651
|
+
return id === FISH_VOICE_CLONE ? void 0 : `fish voice-clone rows need providerModelId ${FISH_VOICE_CLONE}`;
|
|
12652
|
+
}
|
|
12653
|
+
if (row2.type === "voice-design") {
|
|
12654
|
+
return id === FISH_VOICE_DESIGN ? void 0 : `fish voice-design rows need providerModelId ${FISH_VOICE_DESIGN}`;
|
|
12655
|
+
}
|
|
12656
|
+
return `fish has no ${row2.type} rows`;
|
|
12657
|
+
}
|
|
12658
|
+
function fishError(ctx, code, message) {
|
|
12659
|
+
return new ModelKitError({
|
|
12660
|
+
code,
|
|
12661
|
+
message,
|
|
12662
|
+
provider: "fish",
|
|
12663
|
+
model: ctx.model.id,
|
|
12664
|
+
retryable: false
|
|
12665
|
+
});
|
|
12666
|
+
}
|
|
12667
|
+
function checkRow(ctx, type) {
|
|
12668
|
+
const refusal2 = ctx.model.type === type ? fishRowRefusal(ctx.model) : void 0;
|
|
12669
|
+
if (ctx.model.type !== type || refusal2 !== void 0) {
|
|
12670
|
+
throw fishError(
|
|
12671
|
+
ctx,
|
|
12672
|
+
"unsupported_option",
|
|
12673
|
+
refusal2 ?? `${ctx.model.id} is not a ${type} row`
|
|
12674
|
+
);
|
|
12675
|
+
}
|
|
12676
|
+
}
|
|
12677
|
+
function checkVoiceId(ctx, field, id) {
|
|
12678
|
+
if (!VOICE_ID.test(id))
|
|
12679
|
+
throw fishError(ctx, "unsupported_option", `${field} is not a voice id`);
|
|
12680
|
+
return id;
|
|
12681
|
+
}
|
|
12682
|
+
function fishKey(ctx) {
|
|
12683
|
+
const key = ctx.keys.fish;
|
|
12684
|
+
if (!key) throw fishError(ctx, "auth", "Missing API key for fish");
|
|
12685
|
+
return key;
|
|
12686
|
+
}
|
|
12687
|
+
function fishUrl(ctx, path) {
|
|
12688
|
+
return `${ctx.endpoints?.fish ?? DEFAULT_BASE_URL}${path}`;
|
|
12689
|
+
}
|
|
12690
|
+
async function fishFetch(ctx, path, init) {
|
|
12691
|
+
throwIfAborted(ctx.signal);
|
|
12692
|
+
const request = {
|
|
12693
|
+
method: init.method,
|
|
12694
|
+
headers: { Authorization: `Bearer ${fishKey(ctx)}`, ...init.headers }
|
|
12695
|
+
};
|
|
12696
|
+
if (init.body !== void 0) request.body = init.body;
|
|
12697
|
+
if (ctx.signal !== void 0) request.signal = ctx.signal;
|
|
12698
|
+
let res;
|
|
12699
|
+
try {
|
|
12700
|
+
res = await ctx.fetch(fishUrl(ctx, path), request);
|
|
12701
|
+
} catch (cause) {
|
|
12702
|
+
throw classifyThrown("fish", cause, ctx.model.id);
|
|
12703
|
+
}
|
|
12704
|
+
if (!res.ok) throw classifyHttpError(res.status, await readBody(res), "fish", ctx.model.id);
|
|
12705
|
+
return res;
|
|
12706
|
+
}
|
|
12707
|
+
function usage2(ctx) {
|
|
12708
|
+
return {
|
|
12709
|
+
model: ctx.model.id,
|
|
12710
|
+
provider: "fish",
|
|
12711
|
+
modality: "AUDIO",
|
|
12712
|
+
unit: ctx.model.usage.unit,
|
|
12713
|
+
quantity: 1
|
|
12714
|
+
};
|
|
12715
|
+
}
|
|
12716
|
+
function audioMime(res, format) {
|
|
12717
|
+
const header = res.headers.get("content-type")?.split(";")[0]?.trim().toLowerCase();
|
|
12718
|
+
if (header?.startsWith("audio/")) return header;
|
|
12719
|
+
return format === "wav" ? "audio/wav" : "audio/mpeg";
|
|
12720
|
+
}
|
|
12721
|
+
async function generateSpeech(req, ctx) {
|
|
12722
|
+
checkRow(ctx, "speech");
|
|
12723
|
+
const format = req.outputFormat ?? "mp3";
|
|
12724
|
+
const body = { text: req.text, format };
|
|
12725
|
+
const voice = req.customVoice ?? req.voice;
|
|
12726
|
+
if (voice !== void 0) {
|
|
12727
|
+
body.reference_id = checkVoiceId(ctx, req.customVoice ? "customVoice" : "voice", voice);
|
|
12728
|
+
}
|
|
12729
|
+
if (req.language !== void 0) body.language = req.language;
|
|
12730
|
+
const { bytes, mime } = await withRetry(
|
|
12731
|
+
async () => {
|
|
12732
|
+
const res = await fishFetch(ctx, "/v1/tts", {
|
|
12733
|
+
method: "POST",
|
|
12734
|
+
headers: { "Content-Type": "application/json", model: ctx.model.providerModelId },
|
|
12735
|
+
body: JSON.stringify(body)
|
|
12736
|
+
});
|
|
12737
|
+
let audio;
|
|
12738
|
+
try {
|
|
12739
|
+
audio = new Uint8Array(await res.arrayBuffer());
|
|
12740
|
+
} catch (cause) {
|
|
12741
|
+
throw classifyThrown("fish", cause, ctx.model.id);
|
|
12742
|
+
}
|
|
12743
|
+
return { bytes: audio, mime: audioMime(res, format) };
|
|
12744
|
+
},
|
|
12745
|
+
mediaRetryOptions(ctx.call, ctx.signal)
|
|
12746
|
+
);
|
|
12747
|
+
if (bytes.byteLength === 0)
|
|
12748
|
+
throw fishError(ctx, "provider_rejected", "Fish TTS returned no audio");
|
|
12749
|
+
return { audio: { bytes, mime }, usage: usage2(ctx) };
|
|
12750
|
+
}
|
|
12751
|
+
var createdModelSchema = z21.object({
|
|
12752
|
+
_id: z21.string().min(1),
|
|
12753
|
+
state: z21.enum(["created", "training", "trained", "failed"]).optional().catch(void 0)
|
|
12754
|
+
});
|
|
12755
|
+
function fileName(index, mime) {
|
|
12756
|
+
const ext = mime.split("/")[1]?.replace("mpeg", "mp3").replace("x-", "") || "bin";
|
|
12757
|
+
return `sample-${index + 1}.${ext}`;
|
|
12758
|
+
}
|
|
12759
|
+
function allOrNone(ctx, field, values) {
|
|
12760
|
+
const set = values.filter((v) => v !== void 0 && v.trim() !== "");
|
|
12761
|
+
if (set.length === 0) return [];
|
|
12762
|
+
if (set.length !== values.length) {
|
|
12763
|
+
throw fishError(ctx, "missing_input", `set ${field} on every sample or on none`);
|
|
12764
|
+
}
|
|
12765
|
+
return set;
|
|
12766
|
+
}
|
|
12767
|
+
async function cloneForm(req, ctx) {
|
|
12768
|
+
if (req.samples.length === 0) throw fishError(ctx, "missing_input", "needs a voice sample");
|
|
12769
|
+
const transcripts = allOrNone(
|
|
12770
|
+
ctx,
|
|
12771
|
+
"transcript",
|
|
12772
|
+
req.samples.map((s) => s.transcript)
|
|
12773
|
+
);
|
|
12774
|
+
const signatures = allOrNone(
|
|
12775
|
+
ctx,
|
|
12776
|
+
"designSignature",
|
|
12777
|
+
req.samples.map((s) => s.designSignature)
|
|
12778
|
+
);
|
|
12779
|
+
const form = new FormData();
|
|
12780
|
+
form.append("type", "tts");
|
|
12781
|
+
form.append("train_mode", "fast");
|
|
12782
|
+
form.append("visibility", "private");
|
|
12783
|
+
form.append("title", req.title.trim());
|
|
12784
|
+
if (req.description?.trim()) form.append("description", req.description.trim());
|
|
12785
|
+
if (req.enhance !== void 0) form.append("enhance_audio_quality", String(req.enhance));
|
|
12786
|
+
for (const [index, sample] of req.samples.entries()) {
|
|
12787
|
+
const { bytes, mime } = await mediaRefToBytes(sample.audio, ctx.fetch, {
|
|
12788
|
+
signal: ctx.signal,
|
|
12789
|
+
provider: "fish",
|
|
12790
|
+
model: ctx.model.id
|
|
12791
|
+
});
|
|
12792
|
+
const audio = new Blob([new Uint8Array(bytes)], { type: mime });
|
|
12793
|
+
form.append("voices", audio, fileName(index, mime));
|
|
12794
|
+
}
|
|
12795
|
+
for (const text2 of transcripts) form.append("texts", text2.trim());
|
|
12796
|
+
for (const signature of signatures) form.append("voice_design_signatures", signature);
|
|
12797
|
+
return form;
|
|
12798
|
+
}
|
|
12799
|
+
async function onlyRateLimitRetries(fn) {
|
|
12800
|
+
try {
|
|
12801
|
+
return await fn();
|
|
12802
|
+
} catch (cause) {
|
|
12803
|
+
if (!isModelKitError(cause) || !cause.retryable || cause.code === "rate_limited")
|
|
12804
|
+
throw cause;
|
|
12805
|
+
throw new ModelKitError({
|
|
12806
|
+
code: cause.code,
|
|
12807
|
+
message: cause.message,
|
|
12808
|
+
...cause.provider !== void 0 && { provider: cause.provider },
|
|
12809
|
+
...cause.model !== void 0 && { model: cause.model },
|
|
12810
|
+
...cause.status !== void 0 && { status: cause.status },
|
|
12811
|
+
...cause.body !== void 0 && { body: cause.body },
|
|
12812
|
+
cause,
|
|
12813
|
+
retryable: false
|
|
12814
|
+
});
|
|
12815
|
+
}
|
|
12816
|
+
}
|
|
12817
|
+
async function createVoice(req, ctx) {
|
|
12818
|
+
checkRow(ctx, "voice-clone");
|
|
12819
|
+
const form = await cloneForm(req, ctx);
|
|
12820
|
+
const res = await withRetry(
|
|
12821
|
+
() => onlyRateLimitRetries(() => fishFetch(ctx, "/model", { method: "POST", body: form })),
|
|
12822
|
+
mediaRetryOptions(ctx.call, ctx.signal)
|
|
12823
|
+
);
|
|
12824
|
+
const raw = await readBody(res);
|
|
12825
|
+
const parsed = createdModelSchema.safeParse(raw);
|
|
12826
|
+
if (!parsed.success) {
|
|
12827
|
+
throw new ModelKitError({
|
|
12828
|
+
code: "provider_rejected",
|
|
12829
|
+
message: "Fish returned no voice id",
|
|
12830
|
+
provider: "fish",
|
|
12831
|
+
model: ctx.model.id,
|
|
12832
|
+
status: res.status,
|
|
12833
|
+
body: raw,
|
|
12834
|
+
retryable: false
|
|
12835
|
+
});
|
|
12836
|
+
}
|
|
12837
|
+
const result = { voiceId: parsed.data._id, usage: usage2(ctx), raw };
|
|
12838
|
+
if (parsed.data.state !== void 0) result.state = parsed.data.state;
|
|
12839
|
+
return result;
|
|
12840
|
+
}
|
|
12841
|
+
var designSchema = z21.object({
|
|
12842
|
+
candidates: z21.array(
|
|
12843
|
+
z21.looseObject({
|
|
12844
|
+
id: z21.string().min(1),
|
|
12845
|
+
index: z21.number().int(),
|
|
12846
|
+
audio_base64: z21.string().min(1),
|
|
12847
|
+
duration_ms: z21.number().nonnegative(),
|
|
12848
|
+
signature: z21.string().min(1).optional()
|
|
12849
|
+
})
|
|
12850
|
+
).min(1)
|
|
12851
|
+
});
|
|
12852
|
+
async function designVoice(req, ctx) {
|
|
12853
|
+
checkRow(ctx, "voice-design");
|
|
12854
|
+
const body = { instruction: req.prompt.trim() };
|
|
12855
|
+
if (req.previewText?.trim()) body.reference_text = req.previewText.trim();
|
|
12856
|
+
if (req.language !== void 0) body.language = req.language;
|
|
12857
|
+
if (req.count !== void 0) body.n = req.count;
|
|
12858
|
+
if (req.seed !== void 0) body.seed = req.seed;
|
|
12859
|
+
const raw = await withRetry(
|
|
12860
|
+
async () => {
|
|
12861
|
+
const res = await fishFetch(ctx, "/v1/voice-design", {
|
|
12862
|
+
method: "POST",
|
|
12863
|
+
headers: { "Content-Type": "application/json", model: ctx.model.providerModelId },
|
|
12864
|
+
body: JSON.stringify(body)
|
|
12865
|
+
});
|
|
12866
|
+
return readBody(res);
|
|
12867
|
+
},
|
|
12868
|
+
mediaRetryOptions(ctx.call, ctx.signal)
|
|
12869
|
+
);
|
|
12870
|
+
const parsed = designSchema.safeParse(raw);
|
|
12871
|
+
if (!parsed.success) {
|
|
12872
|
+
throw fishError(ctx, "provider_rejected", "Fish voice design returned no candidates");
|
|
12873
|
+
}
|
|
12874
|
+
const candidates = [...parsed.data.candidates].sort((a, b) => a.index - b.index).map((c) => ({
|
|
12875
|
+
audio: { bytes: base64ToBytes(c.audio_base64), mime: "audio/wav" },
|
|
12876
|
+
durationSeconds: c.duration_ms / 1e3,
|
|
12877
|
+
// The OpenAPI candidate has no signature field, so its stable id is the handle; Fish
|
|
12878
|
+
// rejects a clone whose signature does not verify, so a wrong one fails loudly.
|
|
12879
|
+
signature: c.signature ?? c.id
|
|
12880
|
+
}));
|
|
12881
|
+
return { candidates, usage: usage2(ctx) };
|
|
12882
|
+
}
|
|
12883
|
+
async function deleteVoice(req, ctx) {
|
|
12884
|
+
checkRow(ctx, "voice-clone");
|
|
12885
|
+
const id = encodeURIComponent(checkVoiceId(ctx, "voiceId", req.voiceId));
|
|
12886
|
+
let attempts = 0;
|
|
12887
|
+
await withRetry(
|
|
12888
|
+
async () => {
|
|
12889
|
+
attempts += 1;
|
|
12890
|
+
try {
|
|
12891
|
+
await fishFetch(ctx, `/model/${id}`, { method: "DELETE" });
|
|
12892
|
+
} catch (cause) {
|
|
12893
|
+
if (!isModelKitError(cause) || cause.status !== 404) throw cause;
|
|
12894
|
+
if (attempts > 1) return;
|
|
12895
|
+
throw new ModelKitError({
|
|
12896
|
+
code: "provider_rejected",
|
|
12897
|
+
message: `Fish has no voice ${req.voiceId} under this key set; delete with the tier that created it`,
|
|
12898
|
+
provider: "fish",
|
|
12899
|
+
model: ctx.model.id,
|
|
12900
|
+
status: 404,
|
|
12901
|
+
cause,
|
|
12902
|
+
retryable: false
|
|
12903
|
+
});
|
|
12904
|
+
}
|
|
12905
|
+
},
|
|
12906
|
+
mediaRetryOptions(ctx.call, ctx.signal)
|
|
12907
|
+
);
|
|
12908
|
+
}
|
|
12909
|
+
var fishAdapter = {
|
|
12910
|
+
id: "fish",
|
|
12911
|
+
generateSpeech,
|
|
12912
|
+
createVoice,
|
|
12913
|
+
designVoice,
|
|
12914
|
+
deleteVoice
|
|
12915
|
+
};
|
|
12916
|
+
|
|
12328
12917
|
// src/adapters/google-genai.ts
|
|
12329
|
-
import { z as
|
|
12918
|
+
import { z as z23 } from "zod";
|
|
12330
12919
|
import {
|
|
12331
12920
|
GoogleGenAI
|
|
12332
12921
|
} from "@google/genai";
|
|
12333
12922
|
|
|
12334
12923
|
// src/adapters/google-files.ts
|
|
12335
|
-
import { z as
|
|
12924
|
+
import { z as z22 } from "zod";
|
|
12336
12925
|
var GOOGLE_FILES_BASE = "https://generativelanguage.googleapis.com";
|
|
12337
12926
|
var GOOGLE_FILES_POLL_INTERVAL_MS = 2e3;
|
|
12338
12927
|
var GOOGLE_FILES_POLL_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
@@ -12342,17 +12931,17 @@ var GENERIC_MEDIA_TYPES = /* @__PURE__ */ new Set([
|
|
|
12342
12931
|
"binary/octet-stream",
|
|
12343
12932
|
"application/binary"
|
|
12344
12933
|
]);
|
|
12345
|
-
var uploadedFileSchema =
|
|
12346
|
-
file:
|
|
12347
|
-
uri:
|
|
12348
|
-
name:
|
|
12349
|
-
state:
|
|
12350
|
-
mimeType:
|
|
12934
|
+
var uploadedFileSchema = z22.object({
|
|
12935
|
+
file: z22.object({
|
|
12936
|
+
uri: z22.string().optional(),
|
|
12937
|
+
name: z22.string().optional(),
|
|
12938
|
+
state: z22.string().optional(),
|
|
12939
|
+
mimeType: z22.string().optional()
|
|
12351
12940
|
}).optional()
|
|
12352
12941
|
});
|
|
12353
|
-
var fileStateSchema =
|
|
12354
|
-
state:
|
|
12355
|
-
error:
|
|
12942
|
+
var fileStateSchema = z22.object({
|
|
12943
|
+
state: z22.string().optional(),
|
|
12944
|
+
error: z22.object({ message: z22.string().optional() }).optional()
|
|
12356
12945
|
});
|
|
12357
12946
|
function resolveMime(declared, fallback) {
|
|
12358
12947
|
const clean = declared?.split(";")[0]?.trim().toLowerCase();
|
|
@@ -12459,7 +13048,7 @@ async function startAndUpload(bytes, mimeType, opts) {
|
|
|
12459
13048
|
if (uploaded.file?.state !== void 0) ref.state = uploaded.file.state;
|
|
12460
13049
|
return ref;
|
|
12461
13050
|
}
|
|
12462
|
-
async function waitForActive(
|
|
13051
|
+
async function waitForActive(fileName2, opts) {
|
|
12463
13052
|
const pollOptions2 = {
|
|
12464
13053
|
intervalMs: GOOGLE_FILES_POLL_INTERVAL_MS,
|
|
12465
13054
|
timeoutMs: GOOGLE_FILES_POLL_TIMEOUT_MS
|
|
@@ -12472,14 +13061,14 @@ async function waitForActive(fileName, opts) {
|
|
|
12472
13061
|
retryInit.signal = opts.signal;
|
|
12473
13062
|
}
|
|
12474
13063
|
await pollUntil(async () => {
|
|
12475
|
-
const res = await opts.fetchImpl(`${GOOGLE_FILES_BASE}/v1beta/${
|
|
13064
|
+
const res = await opts.fetchImpl(`${GOOGLE_FILES_BASE}/v1beta/${fileName2}`, retryInit);
|
|
12476
13065
|
if (res.ok) {
|
|
12477
13066
|
const json = fileStateSchema.parse(await res.json());
|
|
12478
13067
|
if (json.state === "ACTIVE") return true;
|
|
12479
13068
|
if (json.state === "FAILED") {
|
|
12480
13069
|
throw classifyHttpError(
|
|
12481
13070
|
void 0,
|
|
12482
|
-
`Files API processing failed for ${
|
|
13071
|
+
`Files API processing failed for ${fileName2}: ${json.error?.message ?? "unknown error"}`,
|
|
12483
13072
|
"google-genai",
|
|
12484
13073
|
opts.model
|
|
12485
13074
|
);
|
|
@@ -12491,9 +13080,9 @@ async function waitForActive(fileName, opts) {
|
|
|
12491
13080
|
throw classifyHttpError(res.status, text2, "google-genai", opts.model);
|
|
12492
13081
|
}, pollOptions2);
|
|
12493
13082
|
}
|
|
12494
|
-
async function deleteGoogleFile(
|
|
13083
|
+
async function deleteGoogleFile(fileName2, apiKey, fetchImpl) {
|
|
12495
13084
|
try {
|
|
12496
|
-
await fetchImpl(`${GOOGLE_FILES_BASE}/v1beta/${
|
|
13085
|
+
await fetchImpl(`${GOOGLE_FILES_BASE}/v1beta/${fileName2}`, {
|
|
12497
13086
|
method: "DELETE",
|
|
12498
13087
|
headers: { "x-goog-api-key": apiKey }
|
|
12499
13088
|
});
|
|
@@ -12573,7 +13162,7 @@ var OMNI_POLL_INTERVAL_MS = 1e4;
|
|
|
12573
13162
|
var RESULT_TIMEOUT_MS3 = 15 * 60 * 1e3;
|
|
12574
13163
|
var OMNI_INLINE_LIMIT_BYTES = 4 * 1024 * 1024;
|
|
12575
13164
|
var MEDIA_PART_INLINE_LIMIT_BYTES = 10 * 1024 * 1024;
|
|
12576
|
-
var errorTextSchema =
|
|
13165
|
+
var errorTextSchema = z23.string();
|
|
12577
13166
|
function isGoogleGenaiVideoKnown(providerModelId) {
|
|
12578
13167
|
return providerModelId.startsWith("veo-") || providerModelId.startsWith("gemini-omni");
|
|
12579
13168
|
}
|
|
@@ -12768,7 +13357,7 @@ async function generateVeoVideo(req, ctx, createGenAIClient) {
|
|
|
12768
13357
|
}
|
|
12769
13358
|
};
|
|
12770
13359
|
const jobId = operation.name ?? crypto.randomUUID();
|
|
12771
|
-
const
|
|
13360
|
+
const usage4 = videoUsage2(ctx, duration, req.resolution ?? "720p");
|
|
12772
13361
|
return {
|
|
12773
13362
|
jobId,
|
|
12774
13363
|
async poll() {
|
|
@@ -12806,7 +13395,7 @@ async function generateVeoVideo(req, ctx, createGenAIClient) {
|
|
|
12806
13395
|
modelId
|
|
12807
13396
|
);
|
|
12808
13397
|
}
|
|
12809
|
-
return { video: await downloadVideo(ctx, uri, apiKey, signal), usage:
|
|
13398
|
+
return { video: await downloadVideo(ctx, uri, apiKey, signal), usage: usage4, raw: finished };
|
|
12810
13399
|
}
|
|
12811
13400
|
};
|
|
12812
13401
|
}
|
|
@@ -12917,7 +13506,7 @@ async function generateOmniVideo(req, ctx, createGenAIClient) {
|
|
|
12917
13506
|
return file.fileUri;
|
|
12918
13507
|
};
|
|
12919
13508
|
const cleanupUploads = async () => {
|
|
12920
|
-
for (const
|
|
13509
|
+
for (const fileName2 of uploadedNames) await deleteGoogleFile(fileName2, apiKey, ctx.fetch);
|
|
12921
13510
|
};
|
|
12922
13511
|
const callCreate = (input) => client2.interactions.create(
|
|
12923
13512
|
previousId !== void 0 ? {
|
|
@@ -13011,7 +13600,7 @@ async function generateOmniVideo(req, ctx, createGenAIClient) {
|
|
|
13011
13600
|
if (!(extend && !chained)) await cleanupUploads();
|
|
13012
13601
|
}
|
|
13013
13602
|
const jobId = interaction.id ?? crypto.randomUUID();
|
|
13014
|
-
const
|
|
13603
|
+
const usage4 = videoUsage2(ctx, duration, omniResolution ?? "720p");
|
|
13015
13604
|
const getInteraction = async () => {
|
|
13016
13605
|
try {
|
|
13017
13606
|
const getParams = { stream: false };
|
|
@@ -13059,7 +13648,7 @@ async function generateOmniVideo(req, ctx, createGenAIClient) {
|
|
|
13059
13648
|
bytes: Buffer.from(video.data, "base64"),
|
|
13060
13649
|
mime: video.mime_type ?? "video/mp4"
|
|
13061
13650
|
},
|
|
13062
|
-
usage:
|
|
13651
|
+
usage: usage4,
|
|
13063
13652
|
raw: done,
|
|
13064
13653
|
providerRef
|
|
13065
13654
|
};
|
|
@@ -13067,7 +13656,7 @@ async function generateOmniVideo(req, ctx, createGenAIClient) {
|
|
|
13067
13656
|
if (video.uri)
|
|
13068
13657
|
return {
|
|
13069
13658
|
video: await downloadVideo(ctx, video.uri, apiKey, signal),
|
|
13070
|
-
usage:
|
|
13659
|
+
usage: usage4,
|
|
13071
13660
|
raw: done,
|
|
13072
13661
|
providerRef
|
|
13073
13662
|
};
|
|
@@ -13237,15 +13826,15 @@ async function prepareGoogleMediaPart(ref, mediaType, ctx) {
|
|
|
13237
13826
|
// src/adapters/google-image.ts
|
|
13238
13827
|
import { createGoogleGenerativeAI as createGoogleGenerativeAI2 } from "@ai-sdk/google";
|
|
13239
13828
|
import { generateText } from "ai";
|
|
13240
|
-
import { z as
|
|
13829
|
+
import { z as z24 } from "zod";
|
|
13241
13830
|
var GEMINI_IMAGE_TIMEOUT_MS = 6e5;
|
|
13242
13831
|
var defaultGoogleImageDeps = {
|
|
13243
13832
|
createGoogleClient: (opts) => createGoogleGenerativeAI2(opts),
|
|
13244
13833
|
runTextGeneration: (opts) => generateText(opts)
|
|
13245
13834
|
};
|
|
13246
|
-
var causeChainNodeSchema =
|
|
13247
|
-
message:
|
|
13248
|
-
cause:
|
|
13835
|
+
var causeChainNodeSchema = z24.object({
|
|
13836
|
+
message: z24.string().optional(),
|
|
13837
|
+
cause: z24.unknown().optional()
|
|
13249
13838
|
});
|
|
13250
13839
|
function extractBlockReason(cause) {
|
|
13251
13840
|
let current = cause;
|
|
@@ -13345,7 +13934,7 @@ function createGoogleImageAdapter(deps = defaultGoogleImageDeps) {
|
|
|
13345
13934
|
retryable: false
|
|
13346
13935
|
});
|
|
13347
13936
|
}
|
|
13348
|
-
const
|
|
13937
|
+
const usage4 = {
|
|
13349
13938
|
model: ctx.model.id,
|
|
13350
13939
|
provider: "google-image",
|
|
13351
13940
|
modality: "IMAGE",
|
|
@@ -13353,19 +13942,19 @@ function createGoogleImageAdapter(deps = defaultGoogleImageDeps) {
|
|
|
13353
13942
|
quantity: images.length,
|
|
13354
13943
|
imageQuality: "auto"
|
|
13355
13944
|
};
|
|
13356
|
-
if (req.size !== void 0)
|
|
13945
|
+
if (req.size !== void 0) usage4.imageSize = req.size;
|
|
13357
13946
|
if (result.usage?.inputTokens !== void 0)
|
|
13358
|
-
|
|
13947
|
+
usage4.inputTokens = result.usage.inputTokens;
|
|
13359
13948
|
if (result.usage?.outputTokens !== void 0)
|
|
13360
|
-
|
|
13361
|
-
return { images, usage:
|
|
13949
|
+
usage4.outputTokens = result.usage.outputTokens;
|
|
13950
|
+
return { images, usage: usage4, raw: result };
|
|
13362
13951
|
}
|
|
13363
13952
|
};
|
|
13364
13953
|
}
|
|
13365
13954
|
var googleImageAdapter = createGoogleImageAdapter();
|
|
13366
13955
|
|
|
13367
13956
|
// src/adapters/higgsfield.ts
|
|
13368
|
-
import { z as
|
|
13957
|
+
import { z as z25 } from "zod";
|
|
13369
13958
|
|
|
13370
13959
|
// src/adapters/higgsfield-motions.ts
|
|
13371
13960
|
var MOTION_MAP = {
|
|
@@ -13584,14 +14173,14 @@ function klingEndpointFields(providerModelId) {
|
|
|
13584
14173
|
const path = (providerModelId.startsWith("/") ? providerModelId.slice(1) : providerModelId).toLowerCase();
|
|
13585
14174
|
return KLING_ENDPOINT_FIELDS.get(path) ?? UNLISTED_KLING_FIELDS;
|
|
13586
14175
|
}
|
|
13587
|
-
var klingCreateSchema =
|
|
13588
|
-
var klingStatusSchema =
|
|
13589
|
-
status:
|
|
13590
|
-
video:
|
|
14176
|
+
var klingCreateSchema = z25.object({ status_url: z25.string() });
|
|
14177
|
+
var klingStatusSchema = z25.object({
|
|
14178
|
+
status: z25.string().optional(),
|
|
14179
|
+
video: z25.object({ url: z25.string().optional() }).optional(),
|
|
13591
14180
|
error: JsonValueSchema.optional()
|
|
13592
14181
|
});
|
|
13593
|
-
var errorMessageSchema =
|
|
13594
|
-
var textValueSchema =
|
|
14182
|
+
var errorMessageSchema = z25.object({ message: z25.string().optional() });
|
|
14183
|
+
var textValueSchema = z25.string();
|
|
13595
14184
|
function klingErrorDetail(error) {
|
|
13596
14185
|
if (error === void 0) return "unknown_error";
|
|
13597
14186
|
const asText = textValueSchema.safeParse(error);
|
|
@@ -13747,8 +14336,8 @@ async function generateKlingVideo(req, ctx) {
|
|
|
13747
14336
|
}
|
|
13748
14337
|
};
|
|
13749
14338
|
}
|
|
13750
|
-
var dopMotionOptionsSchema =
|
|
13751
|
-
modelkit:
|
|
14339
|
+
var dopMotionOptionsSchema = z25.object({
|
|
14340
|
+
modelkit: z25.object({ motion: z25.string().optional() }).optional()
|
|
13752
14341
|
});
|
|
13753
14342
|
function dopMotionId(ctx) {
|
|
13754
14343
|
const parsed = dopMotionOptionsSchema.safeParse(ctx.model.providerOptions);
|
|
@@ -13764,7 +14353,7 @@ function dopMotionId(ctx) {
|
|
|
13764
14353
|
});
|
|
13765
14354
|
return id;
|
|
13766
14355
|
}
|
|
13767
|
-
var jsonRecordSchema =
|
|
14356
|
+
var jsonRecordSchema = z25.record(z25.string(), JsonValueSchema);
|
|
13768
14357
|
var DOP_URL_KEYS = ["url", "video_url", "output_url", "result_url", "download_url"];
|
|
13769
14358
|
var DOP_NESTED_KEYS = ["video", "result", "results"];
|
|
13770
14359
|
function dopUrl(body) {
|
|
@@ -13792,8 +14381,8 @@ function dopUrl(body) {
|
|
|
13792
14381
|
}
|
|
13793
14382
|
return void 0;
|
|
13794
14383
|
}
|
|
13795
|
-
var dopCreateSchema =
|
|
13796
|
-
var dopStatusSchema =
|
|
14384
|
+
var dopCreateSchema = z25.object({ id: z25.string() });
|
|
14385
|
+
var dopStatusSchema = z25.object({ status: z25.string().optional() });
|
|
13797
14386
|
async function generateDopVideo(req, ctx) {
|
|
13798
14387
|
const firstFrame = req.firstFrame ? refToUrl(req.firstFrame) : void 0;
|
|
13799
14388
|
if (!firstFrame) {
|
|
@@ -13920,7 +14509,7 @@ var higgsfieldAdapter = {
|
|
|
13920
14509
|
};
|
|
13921
14510
|
|
|
13922
14511
|
// src/adapters/luma.ts
|
|
13923
|
-
import { z as
|
|
14512
|
+
import { z as z26 } from "zod";
|
|
13924
14513
|
|
|
13925
14514
|
// src/adapters/mp4-duration.ts
|
|
13926
14515
|
function mp4DurationSeconds(bytes) {
|
|
@@ -13976,7 +14565,7 @@ function findBox(bytes, from, to, type) {
|
|
|
13976
14565
|
}
|
|
13977
14566
|
|
|
13978
14567
|
// src/adapters/luma.ts
|
|
13979
|
-
var
|
|
14568
|
+
var DEFAULT_BASE_URL2 = "https://agents.lumalabs.ai";
|
|
13980
14569
|
var IMAGE_POLL_INTERVAL_MS = 3e3;
|
|
13981
14570
|
var IMAGE_TIMEOUT_MS = 5 * 6e4;
|
|
13982
14571
|
var VIDEO_POLL_INTERVAL_MS = 5e3;
|
|
@@ -14005,7 +14594,7 @@ function lumaModel(ctx) {
|
|
|
14005
14594
|
return ctx.model.providerModelId.toLowerCase();
|
|
14006
14595
|
}
|
|
14007
14596
|
function lumaBase(ctx) {
|
|
14008
|
-
return ctx.endpoints?.luma ??
|
|
14597
|
+
return ctx.endpoints?.luma ?? DEFAULT_BASE_URL2;
|
|
14009
14598
|
}
|
|
14010
14599
|
function lumaKey(ctx) {
|
|
14011
14600
|
const key = ctx.keys.luma;
|
|
@@ -14137,17 +14726,17 @@ function lumaReframeResolution(req, ctx) {
|
|
|
14137
14726
|
});
|
|
14138
14727
|
return "720p";
|
|
14139
14728
|
}
|
|
14140
|
-
var lumaGenerationSchema =
|
|
14141
|
-
id:
|
|
14142
|
-
state:
|
|
14143
|
-
output:
|
|
14144
|
-
|
|
14145
|
-
type:
|
|
14146
|
-
url:
|
|
14729
|
+
var lumaGenerationSchema = z26.looseObject({
|
|
14730
|
+
id: z26.string(),
|
|
14731
|
+
state: z26.string().optional(),
|
|
14732
|
+
output: z26.array(
|
|
14733
|
+
z26.looseObject({
|
|
14734
|
+
type: z26.string().optional(),
|
|
14735
|
+
url: z26.string().optional()
|
|
14147
14736
|
})
|
|
14148
14737
|
).optional(),
|
|
14149
|
-
failure_reason:
|
|
14150
|
-
failure_code:
|
|
14738
|
+
failure_reason: z26.string().optional().nullable(),
|
|
14739
|
+
failure_code: z26.string().optional().nullable()
|
|
14151
14740
|
});
|
|
14152
14741
|
function lumaFailure(ctx, code, reason) {
|
|
14153
14742
|
const detail = reason ?? code ?? "unknown_error";
|
|
@@ -14579,7 +15168,7 @@ var lumaAdapter = {
|
|
|
14579
15168
|
|
|
14580
15169
|
// src/adapters/openai-image.ts
|
|
14581
15170
|
import OpenAI from "openai";
|
|
14582
|
-
import { z as
|
|
15171
|
+
import { z as z27 } from "zod";
|
|
14583
15172
|
var MAX_EDIT_REFERENCES = 16;
|
|
14584
15173
|
function aspectRatioToSize(ratio, tier) {
|
|
14585
15174
|
const TIER_LONG_EDGE = {
|
|
@@ -14662,9 +15251,9 @@ function toProviderError2(cause, ctx) {
|
|
|
14662
15251
|
ctx.model.id
|
|
14663
15252
|
);
|
|
14664
15253
|
}
|
|
14665
|
-
var openaiUsageSchema =
|
|
14666
|
-
input_tokens:
|
|
14667
|
-
output_tokens:
|
|
15254
|
+
var openaiUsageSchema = z27.object({
|
|
15255
|
+
input_tokens: z27.number().optional(),
|
|
15256
|
+
output_tokens: z27.number().optional()
|
|
14668
15257
|
});
|
|
14669
15258
|
var openaiImageAdapter = {
|
|
14670
15259
|
id: "openai-image",
|
|
@@ -14789,7 +15378,7 @@ var openaiImageAdapter = {
|
|
|
14789
15378
|
const usageParsed = openaiUsageSchema.safeParse(response.usage);
|
|
14790
15379
|
const inputTokens = usageParsed.success ? usageParsed.data.input_tokens : void 0;
|
|
14791
15380
|
const outputTokens = usageParsed.success ? usageParsed.data.output_tokens : void 0;
|
|
14792
|
-
const
|
|
15381
|
+
const usage4 = {
|
|
14793
15382
|
model: ctx.model.id,
|
|
14794
15383
|
provider: "openai-image",
|
|
14795
15384
|
modality: "IMAGE",
|
|
@@ -14797,10 +15386,10 @@ var openaiImageAdapter = {
|
|
|
14797
15386
|
quantity: images.length,
|
|
14798
15387
|
imageQuality: quality
|
|
14799
15388
|
};
|
|
14800
|
-
if (inputTokens !== void 0)
|
|
14801
|
-
if (outputTokens !== void 0)
|
|
14802
|
-
if (req.size !== void 0)
|
|
14803
|
-
return { images, usage:
|
|
15389
|
+
if (inputTokens !== void 0) usage4.inputTokens = inputTokens;
|
|
15390
|
+
if (outputTokens !== void 0) usage4.outputTokens = outputTokens;
|
|
15391
|
+
if (req.size !== void 0) usage4.imageSize = req.size;
|
|
15392
|
+
return { images, usage: usage4, raw: response };
|
|
14804
15393
|
}
|
|
14805
15394
|
};
|
|
14806
15395
|
|
|
@@ -15056,16 +15645,16 @@ async function generateProdiaImage(req, ctx) {
|
|
|
15056
15645
|
new Uint8Array(await res.arrayBuffer()),
|
|
15057
15646
|
res.headers.get("content-type")
|
|
15058
15647
|
);
|
|
15059
|
-
const
|
|
15648
|
+
const usage4 = {
|
|
15060
15649
|
model: ctx.model.id,
|
|
15061
15650
|
provider: "prodia",
|
|
15062
15651
|
modality: "IMAGE",
|
|
15063
15652
|
unit: "images",
|
|
15064
15653
|
quantity: 1
|
|
15065
15654
|
};
|
|
15066
|
-
if (req.size !== void 0)
|
|
15067
|
-
if (req.quality !== void 0)
|
|
15068
|
-
return { images: [{ bytes, mime }], usage:
|
|
15655
|
+
if (req.size !== void 0) usage4.imageSize = req.size;
|
|
15656
|
+
if (req.quality !== void 0) usage4.imageQuality = req.quality;
|
|
15657
|
+
return { images: [{ bytes, mime }], usage: usage4, raw: void 0 };
|
|
15069
15658
|
}
|
|
15070
15659
|
var prodiaAdapter = {
|
|
15071
15660
|
id: "prodia",
|
|
@@ -15076,13 +15665,13 @@ var prodiaAdapter = {
|
|
|
15076
15665
|
import Replicate from "replicate";
|
|
15077
15666
|
|
|
15078
15667
|
// src/adapters/replicate-http.ts
|
|
15079
|
-
import { z as
|
|
15080
|
-
var predictionSchema =
|
|
15081
|
-
id:
|
|
15082
|
-
status:
|
|
15668
|
+
import { z as z28 } from "zod";
|
|
15669
|
+
var predictionSchema = z28.object({
|
|
15670
|
+
id: z28.string(),
|
|
15671
|
+
status: z28.string(),
|
|
15083
15672
|
output: JsonValueSchema.optional(),
|
|
15084
15673
|
error: JsonValueSchema.optional(),
|
|
15085
|
-
metrics:
|
|
15674
|
+
metrics: z28.object({ predict_time: z28.number().optional() }).optional()
|
|
15086
15675
|
});
|
|
15087
15676
|
function createReplicateHttpClient(opts) {
|
|
15088
15677
|
async function request(path, body, signal) {
|
|
@@ -15133,7 +15722,7 @@ function createReplicateHttpClient(opts) {
|
|
|
15133
15722
|
}
|
|
15134
15723
|
|
|
15135
15724
|
// src/adapters/replicate.ts
|
|
15136
|
-
import { z as
|
|
15725
|
+
import { z as z29 } from "zod";
|
|
15137
15726
|
var POLL_INTERVAL_MS = 1e3;
|
|
15138
15727
|
var POLL_TIMEOUT_MS = 15 * 6e4;
|
|
15139
15728
|
var defaultReplicateDeps = {
|
|
@@ -15173,8 +15762,8 @@ function route(providerModelId) {
|
|
|
15173
15762
|
if (!providerModelId.includes("/")) return { version: providerModelId };
|
|
15174
15763
|
return { model: providerModelId };
|
|
15175
15764
|
}
|
|
15176
|
-
var replicateResponseStatusSchema =
|
|
15177
|
-
response:
|
|
15765
|
+
var replicateResponseStatusSchema = z29.object({
|
|
15766
|
+
response: z29.object({ status: z29.number() }).partial()
|
|
15178
15767
|
});
|
|
15179
15768
|
function replicateError(cause, ctx) {
|
|
15180
15769
|
if (isModelKitError(cause)) return cause;
|
|
@@ -15197,7 +15786,7 @@ function isUrlFn(value) {
|
|
|
15197
15786
|
function extractOutputUrl(output) {
|
|
15198
15787
|
const root = Array.isArray(output) ? output[0] : output;
|
|
15199
15788
|
if (root === void 0) throw noOutput();
|
|
15200
|
-
const asString =
|
|
15789
|
+
const asString = z29.string().safeParse(root);
|
|
15201
15790
|
if (asString.success && asString.data) return asString.data;
|
|
15202
15791
|
if (root instanceof URL) return root.href;
|
|
15203
15792
|
if (isObjectOutput(root)) {
|
|
@@ -15206,15 +15795,15 @@ function extractOutputUrl(output) {
|
|
|
15206
15795
|
if (urlValue !== void 0 && isUrlFn(urlValue)) {
|
|
15207
15796
|
const called = urlValue();
|
|
15208
15797
|
if (called instanceof URL) return called.href;
|
|
15209
|
-
const calledString =
|
|
15798
|
+
const calledString = z29.string().safeParse(called);
|
|
15210
15799
|
if (calledString.success && calledString.data) return calledString.data;
|
|
15211
15800
|
} else {
|
|
15212
|
-
const direct =
|
|
15801
|
+
const direct = z29.string().safeParse(urlValue);
|
|
15213
15802
|
if (direct.success && direct.data) return direct.data;
|
|
15214
15803
|
}
|
|
15215
15804
|
}
|
|
15216
15805
|
if ("default" in root) {
|
|
15217
|
-
const fallback =
|
|
15806
|
+
const fallback = z29.string().safeParse(root.default);
|
|
15218
15807
|
if (fallback.success && fallback.data) return fallback.data;
|
|
15219
15808
|
}
|
|
15220
15809
|
}
|
|
@@ -15275,7 +15864,7 @@ async function runPrediction(ctx, input, deps) {
|
|
|
15275
15864
|
}
|
|
15276
15865
|
return void 0;
|
|
15277
15866
|
}, pollOpts);
|
|
15278
|
-
const predictTime =
|
|
15867
|
+
const predictTime = z29.number().safeParse(done.metrics?.predict_time);
|
|
15279
15868
|
if (done.output === void 0) throw noOutput();
|
|
15280
15869
|
return {
|
|
15281
15870
|
url: extractOutputUrl(done.output),
|
|
@@ -15521,9 +16110,9 @@ async function generateReplicateImage(req, ctx, deps) {
|
|
|
15521
16110
|
}
|
|
15522
16111
|
const { url, predictTime, raw } = await runPrediction(ctx, input, deps);
|
|
15523
16112
|
const file = await download(ctx, url);
|
|
15524
|
-
const
|
|
15525
|
-
|
|
15526
|
-
return { images: [{ bytes: file.bytes, mime: file.mime }], usage:
|
|
16113
|
+
const usage4 = imageUsage3(ctx, req);
|
|
16114
|
+
usage4.quantity = predictTime;
|
|
16115
|
+
return { images: [{ bytes: file.bytes, mime: file.mime }], usage: usage4, raw, outputUrl: url };
|
|
15527
16116
|
}
|
|
15528
16117
|
function klingInput(req) {
|
|
15529
16118
|
const images = (req.firstFrame ? [req.firstFrame] : []).map(refToUrl);
|
|
@@ -15628,7 +16217,7 @@ async function generateReplicateVideo(req, ctx, deps) {
|
|
|
15628
16217
|
throw replicateError(cause, ctx);
|
|
15629
16218
|
}
|
|
15630
16219
|
if (current.status === "succeeded") {
|
|
15631
|
-
const predictTime =
|
|
16220
|
+
const predictTime = z29.number().safeParse(current.metrics?.predict_time);
|
|
15632
16221
|
if (current.output === void 0) throw noOutput();
|
|
15633
16222
|
return {
|
|
15634
16223
|
url: extractOutputUrl(current.output),
|
|
@@ -15647,9 +16236,9 @@ async function generateReplicateVideo(req, ctx, deps) {
|
|
|
15647
16236
|
return void 0;
|
|
15648
16237
|
};
|
|
15649
16238
|
const toResult = (done) => {
|
|
15650
|
-
const
|
|
15651
|
-
|
|
15652
|
-
return { video: { url: done.url }, usage:
|
|
16239
|
+
const usage4 = videoUsage5(ctx, req);
|
|
16240
|
+
usage4.quantity = done.predictTime;
|
|
16241
|
+
return { video: { url: done.url }, usage: usage4, raw: done.raw };
|
|
15653
16242
|
};
|
|
15654
16243
|
return {
|
|
15655
16244
|
jobId,
|
|
@@ -15756,21 +16345,21 @@ async function generateReplicateAudio(req, ctx, deps) {
|
|
|
15756
16345
|
input = specResult.input;
|
|
15757
16346
|
}
|
|
15758
16347
|
const { url, predictTime, raw } = await runPrediction(ctx, input, deps);
|
|
15759
|
-
const
|
|
16348
|
+
const usage4 = audioUsage(ctx, req);
|
|
15760
16349
|
if (ctx.model.usage.unit === "seconds") {
|
|
15761
16350
|
const seconds3 = elevenLabsMusicDuration(req.durationSeconds);
|
|
15762
|
-
|
|
15763
|
-
|
|
16351
|
+
usage4.quantity = seconds3;
|
|
16352
|
+
usage4.durationSeconds = seconds3;
|
|
15764
16353
|
} else {
|
|
15765
|
-
|
|
16354
|
+
usage4.quantity = predictTime;
|
|
15766
16355
|
}
|
|
15767
|
-
return { audio: { url }, usage:
|
|
16356
|
+
return { audio: { url }, usage: usage4, raw: predictionRaw(raw) };
|
|
15768
16357
|
}
|
|
15769
16358
|
|
|
15770
16359
|
// src/adapters/xai-video.ts
|
|
15771
16360
|
import { experimental_generateVideo } from "ai";
|
|
15772
16361
|
import { createXai as createXai2 } from "@ai-sdk/xai";
|
|
15773
|
-
import { z as
|
|
16362
|
+
import { z as z30 } from "zod";
|
|
15774
16363
|
var POLL_INTERVAL_MS2 = 1e4;
|
|
15775
16364
|
var POLL_TIMEOUT_MS2 = 15 * 6e4;
|
|
15776
16365
|
var defaultXaiDeps = {
|
|
@@ -15783,8 +16372,8 @@ function createXaiVideoAdapter(deps = defaultXaiDeps) {
|
|
|
15783
16372
|
};
|
|
15784
16373
|
}
|
|
15785
16374
|
var xaiVideoAdapter = createXaiVideoAdapter();
|
|
15786
|
-
var xaiResponseStatusSchema =
|
|
15787
|
-
response:
|
|
16375
|
+
var xaiResponseStatusSchema = z30.object({
|
|
16376
|
+
response: z30.object({ status: z30.number() }).partial()
|
|
15788
16377
|
});
|
|
15789
16378
|
function xaiError(cause, ctx) {
|
|
15790
16379
|
const info = describeThrown(cause);
|
|
@@ -15792,12 +16381,12 @@ function xaiError(cause, ctx) {
|
|
|
15792
16381
|
const status = info.status ?? (nested.success ? nested.data.response?.status : void 0);
|
|
15793
16382
|
return classifyThrown("xai-video", cause, ctx.model.id, { status, body: info.body });
|
|
15794
16383
|
}
|
|
15795
|
-
var xaiMetaSchema =
|
|
16384
|
+
var xaiMetaSchema = z30.object({
|
|
15796
16385
|
videoUrl: JsonValueSchema.optional(),
|
|
15797
16386
|
costInUsdTicks: JsonValueSchema.optional(),
|
|
15798
16387
|
duration: JsonValueSchema.optional()
|
|
15799
16388
|
});
|
|
15800
|
-
var xaiProviderMetadataSchema =
|
|
16389
|
+
var xaiProviderMetadataSchema = z30.object({ xai: xaiMetaSchema });
|
|
15801
16390
|
function metaOf(result) {
|
|
15802
16391
|
const parsed = xaiProviderMetadataSchema.partial().safeParse(result.providerMetadata);
|
|
15803
16392
|
if (!parsed.success) return {};
|
|
@@ -15909,12 +16498,12 @@ async function mapResult(ctx, req, result) {
|
|
|
15909
16498
|
if (first) {
|
|
15910
16499
|
return {
|
|
15911
16500
|
video: { bytes: Uint8Array.from(first.uint8Array), mime: first.mediaType },
|
|
15912
|
-
usage:
|
|
16501
|
+
usage: usage3(ctx, req, metaOf(result)),
|
|
15913
16502
|
raw: result.providerMetadata
|
|
15914
16503
|
};
|
|
15915
16504
|
}
|
|
15916
16505
|
const meta = metaOf(result);
|
|
15917
|
-
const videoUrl =
|
|
16506
|
+
const videoUrl = z30.string().safeParse(meta.videoUrl);
|
|
15918
16507
|
if (videoUrl.success && videoUrl.data) {
|
|
15919
16508
|
const res = await ctx.fetch(videoUrl.data);
|
|
15920
16509
|
if (!res.ok) {
|
|
@@ -15924,7 +16513,7 @@ async function mapResult(ctx, req, result) {
|
|
|
15924
16513
|
const mime = res.headers.get("content-type") ?? "video/mp4";
|
|
15925
16514
|
return {
|
|
15926
16515
|
video: { bytes: new Uint8Array(await res.arrayBuffer()), mime },
|
|
15927
|
-
usage:
|
|
16516
|
+
usage: usage3(ctx, req, meta),
|
|
15928
16517
|
raw: result.providerMetadata
|
|
15929
16518
|
};
|
|
15930
16519
|
}
|
|
@@ -15936,8 +16525,8 @@ async function mapResult(ctx, req, result) {
|
|
|
15936
16525
|
retryable: false
|
|
15937
16526
|
});
|
|
15938
16527
|
}
|
|
15939
|
-
function
|
|
15940
|
-
const costTicks =
|
|
16528
|
+
function usage3(ctx, req, meta) {
|
|
16529
|
+
const costTicks = z30.number().safeParse(meta.costInUsdTicks);
|
|
15941
16530
|
const cost = costTicks.success ? costTicks.data / 1e10 : void 0;
|
|
15942
16531
|
const event = {
|
|
15943
16532
|
model: ctx.model.id,
|
|
@@ -15976,7 +16565,8 @@ var DEFAULT_ADAPTERS = {
|
|
|
15976
16565
|
prodia: prodiaAdapter,
|
|
15977
16566
|
higgsfield: higgsfieldAdapter,
|
|
15978
16567
|
"xai-video": xaiVideoAdapter,
|
|
15979
|
-
luma: lumaAdapter
|
|
16568
|
+
luma: lumaAdapter,
|
|
16569
|
+
fish: fishAdapter
|
|
15980
16570
|
};
|
|
15981
16571
|
|
|
15982
16572
|
// src/catalog/data-only.ts
|
|
@@ -16000,6 +16590,8 @@ function adapterServesType(adapter, type) {
|
|
|
16000
16590
|
if (type === "dubbing") return adapter.dub !== void 0;
|
|
16001
16591
|
if (type === "lipsync") return adapter.lipsync !== void 0;
|
|
16002
16592
|
if (type === "transcription") return adapter.transcribe !== void 0;
|
|
16593
|
+
if (type === "voice-clone") return adapter.createVoice !== void 0;
|
|
16594
|
+
if (type === "voice-design") return adapter.designVoice !== void 0;
|
|
16003
16595
|
if (type === "video-tool") return adapter.submitVideoTool !== void 0;
|
|
16004
16596
|
if (type === "model3d") return adapter.submitModel3d !== void 0;
|
|
16005
16597
|
return adapter.languageModel !== void 0;
|
|
@@ -16013,12 +16605,15 @@ var FAL_NODE_TYPES = /* @__PURE__ */ new Set([
|
|
|
16013
16605
|
"transcription",
|
|
16014
16606
|
"mask"
|
|
16015
16607
|
]);
|
|
16608
|
+
function fishSpeech(row2) {
|
|
16609
|
+
return row2.adapter === "fish" && row2.type === "speech";
|
|
16610
|
+
}
|
|
16016
16611
|
function dataOnlyCapable(row2) {
|
|
16017
16612
|
const adapter = DEFAULT_ADAPTERS[row2.adapter];
|
|
16018
16613
|
if (!adapterServesType(adapter, row2.type)) {
|
|
16019
16614
|
return { ok: false, reason: `${row2.adapter} cannot serve ${row2.type} rows` };
|
|
16020
16615
|
}
|
|
16021
|
-
if (FAL_NODE_TYPES.has(row2.type) && row2.adapter !== "fal") {
|
|
16616
|
+
if (FAL_NODE_TYPES.has(row2.type) && row2.adapter !== "fal" && !fishSpeech(row2)) {
|
|
16022
16617
|
return { ok: false, reason: `only fal serves ${row2.type} rows` };
|
|
16023
16618
|
}
|
|
16024
16619
|
switch (row2.adapter) {
|
|
@@ -16096,6 +16691,10 @@ function dataOnlyCapable(row2) {
|
|
|
16096
16691
|
const reason = lumaRowRefusal(row2);
|
|
16097
16692
|
return reason === void 0 ? { ok: true } : { ok: false, reason };
|
|
16098
16693
|
}
|
|
16694
|
+
case "fish": {
|
|
16695
|
+
const reason = fishRowRefusal(row2);
|
|
16696
|
+
return reason === void 0 ? { ok: true } : { ok: false, reason };
|
|
16697
|
+
}
|
|
16099
16698
|
default: {
|
|
16100
16699
|
return assertNever(row2.adapter);
|
|
16101
16700
|
}
|
|
@@ -16115,22 +16714,22 @@ var liveState = store[KEY] ??= {
|
|
|
16115
16714
|
var liveCatalog = liveState.catalog;
|
|
16116
16715
|
|
|
16117
16716
|
// src/catalog/load.ts
|
|
16118
|
-
import { z as
|
|
16717
|
+
import { z as z31 } from "zod";
|
|
16119
16718
|
function rowCount() {
|
|
16120
16719
|
return liveCatalog.list({ lifecycle: ["active", "deprecated", "retired"] }).length;
|
|
16121
16720
|
}
|
|
16122
16721
|
function authHeaders(auth) {
|
|
16123
16722
|
return "bearer" in auth ? { Authorization: `Bearer ${auth.bearer}` } : { "x-api-key": auth.apiKey };
|
|
16124
16723
|
}
|
|
16125
|
-
var EnvelopeSchema =
|
|
16126
|
-
rows:
|
|
16127
|
-
revision:
|
|
16724
|
+
var EnvelopeSchema = z31.object({
|
|
16725
|
+
rows: z31.array(JsonValueSchema),
|
|
16726
|
+
revision: z31.string().optional()
|
|
16128
16727
|
});
|
|
16129
16728
|
function dropReason(path, message) {
|
|
16130
16729
|
return path.length === 0 ? message : `${path.map((part) => String(part)).join(".")} ${message}`;
|
|
16131
16730
|
}
|
|
16132
16731
|
function rowId(raw) {
|
|
16133
|
-
const parsed =
|
|
16732
|
+
const parsed = z31.object({ id: z31.string().min(1) }).loose().safeParse(raw);
|
|
16134
16733
|
if (!parsed.success) return "?";
|
|
16135
16734
|
return parsed.data.id;
|
|
16136
16735
|
}
|
|
@@ -17046,8 +17645,17 @@ function resolveSpeechOptions(model, request, onUnsupported = "error") {
|
|
|
17046
17645
|
const warnings = [];
|
|
17047
17646
|
checkScript(model, request.text);
|
|
17048
17647
|
const resolved = { model: model.id, text: request.text };
|
|
17049
|
-
const
|
|
17050
|
-
if (
|
|
17648
|
+
const customVoice = request.customVoice?.trim();
|
|
17649
|
+
if (customVoice) {
|
|
17650
|
+
if (model.capabilities?.customVoices !== true) {
|
|
17651
|
+
throw unsupported3(model, "does not take a custom voice");
|
|
17652
|
+
}
|
|
17653
|
+
if (request.voice?.trim()) throw unsupported3(model, "takes voice or customVoice, not both");
|
|
17654
|
+
resolved.customVoice = customVoice;
|
|
17655
|
+
} else {
|
|
17656
|
+
const voice = resolveVoice(model, request.voice, onUnsupported, warnings);
|
|
17657
|
+
if (voice !== void 0) resolved.voice = voice;
|
|
17658
|
+
}
|
|
17051
17659
|
const language = resolveListed(
|
|
17052
17660
|
model,
|
|
17053
17661
|
{
|
|
@@ -17169,6 +17777,106 @@ function resolveTranscriptionOptions(model, request, onUnsupported = "error") {
|
|
|
17169
17777
|
return { request: resolved, warnings };
|
|
17170
17778
|
}
|
|
17171
17779
|
|
|
17780
|
+
// src/resolve-voice.ts
|
|
17781
|
+
function refuse(model, code, message) {
|
|
17782
|
+
return new ModelKitError({ code, message: `${model.label} ${message}`, model: model.id });
|
|
17783
|
+
}
|
|
17784
|
+
function checkSample(model, sample, index) {
|
|
17785
|
+
const limits = model.constraints.references?.audioSeconds;
|
|
17786
|
+
const length = sample.audio.durationSeconds;
|
|
17787
|
+
if (limits === void 0 || length === void 0) return;
|
|
17788
|
+
if (limits.min !== void 0 && length < limits.min || limits.max !== void 0 && length > limits.max) {
|
|
17789
|
+
const range2 = `${limits.min ?? 0}-${limits.max ?? "any"} s`;
|
|
17790
|
+
throw refuse(
|
|
17791
|
+
model,
|
|
17792
|
+
"unsupported_option",
|
|
17793
|
+
`takes samples of ${range2}; sample ${index + 1} is ${length} s`
|
|
17794
|
+
);
|
|
17795
|
+
}
|
|
17796
|
+
}
|
|
17797
|
+
function resolveVoiceCloneOptions(model, request) {
|
|
17798
|
+
const title = request.title.trim();
|
|
17799
|
+
if (!title) throw refuse(model, "missing_input", "needs a title");
|
|
17800
|
+
if (request.samples.length === 0) throw refuse(model, "missing_input", "needs a voice sample");
|
|
17801
|
+
const max = model.constraints.references?.audios;
|
|
17802
|
+
if (max !== void 0 && request.samples.length > max) {
|
|
17803
|
+
throw refuse(
|
|
17804
|
+
model,
|
|
17805
|
+
"unsupported_option",
|
|
17806
|
+
`takes up to ${max} samples; got ${request.samples.length}`
|
|
17807
|
+
);
|
|
17808
|
+
}
|
|
17809
|
+
request.samples.forEach((sample, index) => checkSample(model, sample, index));
|
|
17810
|
+
const total = model.constraints.references?.audioSeconds?.total;
|
|
17811
|
+
const seconds3 = request.samples.reduce((sum, s) => sum + (s.audio.durationSeconds ?? 0), 0);
|
|
17812
|
+
if (total !== void 0 && seconds3 > total) {
|
|
17813
|
+
throw refuse(
|
|
17814
|
+
model,
|
|
17815
|
+
"unsupported_option",
|
|
17816
|
+
`takes up to ${total} s of samples; got ${seconds3} s`
|
|
17817
|
+
);
|
|
17818
|
+
}
|
|
17819
|
+
for (const field of ["transcript", "designSignature"]) {
|
|
17820
|
+
const set = request.samples.filter((s) => s[field]?.trim()).length;
|
|
17821
|
+
if (set !== 0 && set !== request.samples.length) {
|
|
17822
|
+
throw refuse(model, "missing_input", `needs ${field} on every sample or on none`);
|
|
17823
|
+
}
|
|
17824
|
+
}
|
|
17825
|
+
return { request: { ...request, model: model.id, title }, warnings: [] };
|
|
17826
|
+
}
|
|
17827
|
+
function resolveVoiceDesignOptions(model, request, onUnsupported = "error") {
|
|
17828
|
+
const warnings = [];
|
|
17829
|
+
const prompt = request.prompt.trim();
|
|
17830
|
+
if (!prompt) throw refuse(model, "missing_input", "needs a voice description");
|
|
17831
|
+
const maxChars = promptConventions(model).maxChars;
|
|
17832
|
+
if (maxChars !== void 0 && prompt.length > maxChars) {
|
|
17833
|
+
throw refuse(
|
|
17834
|
+
model,
|
|
17835
|
+
"unsupported_option",
|
|
17836
|
+
`takes up to ${maxChars} characters; got ${prompt.length}`
|
|
17837
|
+
);
|
|
17838
|
+
}
|
|
17839
|
+
const limits = model.constraints.voiceDesign;
|
|
17840
|
+
const resolved = { model: model.id, prompt };
|
|
17841
|
+
const preview2 = request.previewText?.trim();
|
|
17842
|
+
if (preview2) {
|
|
17843
|
+
if (limits !== void 0 && preview2.length > limits.previewMaxChars) {
|
|
17844
|
+
throw refuse(
|
|
17845
|
+
model,
|
|
17846
|
+
"unsupported_option",
|
|
17847
|
+
`takes a preview line of up to ${limits.previewMaxChars} characters; got ${preview2.length}`
|
|
17848
|
+
);
|
|
17849
|
+
}
|
|
17850
|
+
resolved.previewText = preview2;
|
|
17851
|
+
}
|
|
17852
|
+
const language = request.language?.trim();
|
|
17853
|
+
if (language) resolved.language = language;
|
|
17854
|
+
if (request.seed !== void 0) resolved.seed = request.seed;
|
|
17855
|
+
const count2 = request.count ?? model.defaults.count;
|
|
17856
|
+
if (count2 !== void 0) {
|
|
17857
|
+
const cap = limits?.maxCandidates ?? count2;
|
|
17858
|
+
if (!Number.isInteger(count2) || count2 < 1 || count2 > cap) {
|
|
17859
|
+
if (onUnsupported === "error" || !Number.isInteger(count2)) {
|
|
17860
|
+
throw refuse(
|
|
17861
|
+
model,
|
|
17862
|
+
"unsupported_option",
|
|
17863
|
+
`returns 1-${cap} candidates; got ${count2}`
|
|
17864
|
+
);
|
|
17865
|
+
}
|
|
17866
|
+
const to = Math.min(Math.max(count2, 1), cap);
|
|
17867
|
+
warnings.push({
|
|
17868
|
+
code: "option_ignored",
|
|
17869
|
+
field: "count",
|
|
17870
|
+
from: String(count2),
|
|
17871
|
+
to: String(to),
|
|
17872
|
+
message: `count ${count2} replaced by ${to} for ${model.id}`
|
|
17873
|
+
});
|
|
17874
|
+
resolved.count = to;
|
|
17875
|
+
} else resolved.count = count2;
|
|
17876
|
+
}
|
|
17877
|
+
return { request: resolved, warnings };
|
|
17878
|
+
}
|
|
17879
|
+
|
|
17172
17880
|
// src/keys.ts
|
|
17173
17881
|
var ADAPTER_KEYS = {
|
|
17174
17882
|
"ai-sdk-text": [],
|
|
@@ -17181,7 +17889,8 @@ var ADAPTER_KEYS = {
|
|
|
17181
17889
|
prodia: ["prodia"],
|
|
17182
17890
|
higgsfield: ["higgsfield"],
|
|
17183
17891
|
"xai-video": ["xai"],
|
|
17184
|
-
luma: ["luma"]
|
|
17892
|
+
luma: ["luma"],
|
|
17893
|
+
fish: ["fish"]
|
|
17185
17894
|
};
|
|
17186
17895
|
function hasAll(keys, names) {
|
|
17187
17896
|
if (!keys) return false;
|
|
@@ -17240,6 +17949,7 @@ function keysFromEnv(env, prefix = "") {
|
|
|
17240
17949
|
set("higgsfield", pick2("HIGGSFIELD_API_KEY"));
|
|
17241
17950
|
set("higgsfieldSecret", pick2("HIGGSFIELD_API_SECRET"));
|
|
17242
17951
|
set("luma", pick2("LUMA_API_KEY", "LUMA_AGENTS_API_KEY"));
|
|
17952
|
+
set("fish", pick2("FISH_AUDIO_API_KEY"));
|
|
17243
17953
|
set("cloudflare", pick2("CLOUDFLARE_AI_GATEWAY_TOKEN", "CF_AIG_TOKEN"));
|
|
17244
17954
|
const bearer = pick2("AWS_BEARER_TOKEN_BEDROCK");
|
|
17245
17955
|
const accessKeyId = pick2("AWS_ACCESS_KEY_ID");
|
|
@@ -17262,7 +17972,7 @@ function keysFromEnv(env, prefix = "") {
|
|
|
17262
17972
|
|
|
17263
17973
|
// src/text.ts
|
|
17264
17974
|
import "ai";
|
|
17265
|
-
import { z as
|
|
17975
|
+
import { z as z32 } from "zod";
|
|
17266
17976
|
function mergeTextProviderOptions(catalog, caller) {
|
|
17267
17977
|
const merged = {};
|
|
17268
17978
|
const catalogOptions = catalog.providerOptions ?? {};
|
|
@@ -17301,17 +18011,17 @@ function passthroughTextModel(model) {
|
|
|
17301
18011
|
pricingKind: "token"
|
|
17302
18012
|
};
|
|
17303
18013
|
}
|
|
17304
|
-
var perplexityCostSchema =
|
|
17305
|
-
perplexity:
|
|
18014
|
+
var perplexityCostSchema = z32.object({
|
|
18015
|
+
perplexity: z32.object({ cost: z32.object({ totalCost: z32.number().finite().nonnegative() }) })
|
|
17306
18016
|
});
|
|
17307
18017
|
function reportedCostUsd(metadata) {
|
|
17308
18018
|
const parsed = perplexityCostSchema.safeParse(metadata);
|
|
17309
18019
|
return parsed.success ? parsed.data.perplexity.cost.totalCost : void 0;
|
|
17310
18020
|
}
|
|
17311
|
-
function textUsageEvent(model, provider,
|
|
17312
|
-
const inputTokens =
|
|
17313
|
-
const outputTokens =
|
|
17314
|
-
const total =
|
|
18021
|
+
function textUsageEvent(model, provider, usage4, providerMetadata) {
|
|
18022
|
+
const inputTokens = usage4.inputTokens ?? 0;
|
|
18023
|
+
const outputTokens = usage4.outputTokens ?? 0;
|
|
18024
|
+
const total = usage4.totalTokens ?? inputTokens + outputTokens;
|
|
17315
18025
|
const event = {
|
|
17316
18026
|
model: model.id,
|
|
17317
18027
|
provider,
|
|
@@ -17346,7 +18056,7 @@ function createTextSteps(initial, resolve, callerProviderOptions) {
|
|
|
17346
18056
|
return { ...prepared, providerOptions };
|
|
17347
18057
|
};
|
|
17348
18058
|
}
|
|
17349
|
-
function
|
|
18059
|
+
function usage4(results) {
|
|
17350
18060
|
const grouped = /* @__PURE__ */ new Map();
|
|
17351
18061
|
for (const [index, step] of results.entries()) {
|
|
17352
18062
|
const target = steps.get(index) ?? initial;
|
|
@@ -17370,7 +18080,7 @@ function createTextSteps(initial, resolve, callerProviderOptions) {
|
|
|
17370
18080
|
}
|
|
17371
18081
|
return [...grouped.values()];
|
|
17372
18082
|
}
|
|
17373
|
-
return { wrap, usage:
|
|
18083
|
+
return { wrap, usage: usage4 };
|
|
17374
18084
|
}
|
|
17375
18085
|
|
|
17376
18086
|
// src/client.ts
|
|
@@ -17382,7 +18092,7 @@ import {
|
|
|
17382
18092
|
streamObject as aiStreamObject2,
|
|
17383
18093
|
streamText as aiStreamText2
|
|
17384
18094
|
} from "ai";
|
|
17385
|
-
import { z as
|
|
18095
|
+
import { z as z33 } from "zod";
|
|
17386
18096
|
|
|
17387
18097
|
// src/generated-image.ts
|
|
17388
18098
|
function toGeneratedImage(image) {
|
|
@@ -17504,9 +18214,9 @@ function providerJobMethods(kind, deps) {
|
|
|
17504
18214
|
if (!methods.result) throw missing3(adapter, ctx.model);
|
|
17505
18215
|
const result = await methods.result(sub, ctx, webhook);
|
|
17506
18216
|
const base = { ...result.usage, model: ctx.model.id, unit: ctx.model.usage.unit };
|
|
17507
|
-
const
|
|
17508
|
-
await deps.emit(
|
|
17509
|
-
return { ...result, usage:
|
|
18217
|
+
const usage4 = sub.submittedAt === void 0 ? base : deps.timed(base, sub.submittedAt);
|
|
18218
|
+
await deps.emit(usage4);
|
|
18219
|
+
return { ...result, usage: usage4 };
|
|
17510
18220
|
},
|
|
17511
18221
|
async cancel(sub, call = {}) {
|
|
17512
18222
|
const { methods, adapter, ctx } = target(sub.model, call);
|
|
@@ -17531,6 +18241,9 @@ var MEDIA_METHODS = {
|
|
|
17531
18241
|
lipsync: ["lipsync"],
|
|
17532
18242
|
dubbing: ["dub"],
|
|
17533
18243
|
transcription: ["transcribe"],
|
|
18244
|
+
// deleteVoice runs on the voice-clone row too; it checks with assertMethod("createVoice").
|
|
18245
|
+
"voice-clone": ["createVoice"],
|
|
18246
|
+
"voice-design": ["designVoice"],
|
|
17534
18247
|
"video-tool": ["submitVideoTool"],
|
|
17535
18248
|
// 3D jobs run through submitModel3d, which checks the row type itself; their preflight
|
|
17536
18249
|
// is model3dInputRefusal, not resolveOptions.
|
|
@@ -17545,6 +18258,8 @@ var METHOD_NOUN = {
|
|
|
17545
18258
|
lipsync: "a lipsync model",
|
|
17546
18259
|
dub: "a dubbing model",
|
|
17547
18260
|
transcribe: "a transcription model",
|
|
18261
|
+
createVoice: "a voice cloning model",
|
|
18262
|
+
designVoice: "a voice design model",
|
|
17548
18263
|
submitVideoTool: "a video tool"
|
|
17549
18264
|
};
|
|
17550
18265
|
function assertMethod(model, method) {
|
|
@@ -17587,6 +18302,14 @@ function resolveTranscriptionCall(model, request, onUnsupported = "error") {
|
|
|
17587
18302
|
assertMethod(model, "transcribe");
|
|
17588
18303
|
return resolveTranscriptionOptions(model, request, onUnsupported);
|
|
17589
18304
|
}
|
|
18305
|
+
function resolveVoiceCloneCall(model, request) {
|
|
18306
|
+
assertMethod(model, "createVoice");
|
|
18307
|
+
return resolveVoiceCloneOptions(model, request);
|
|
18308
|
+
}
|
|
18309
|
+
function resolveVoiceDesignCall(model, request, onUnsupported = "error") {
|
|
18310
|
+
assertMethod(model, "designVoice");
|
|
18311
|
+
return resolveVoiceDesignOptions(model, request, onUnsupported);
|
|
18312
|
+
}
|
|
17590
18313
|
|
|
17591
18314
|
// src/client-audio.ts
|
|
17592
18315
|
function noMethod(adapter, model, what) {
|
|
@@ -17676,6 +18399,49 @@ function audioNodeMethods(deps) {
|
|
|
17676
18399
|
const result = await adapter.transcribe(resolved, ctx);
|
|
17677
18400
|
return { ...result, usage: await deps.settle(model, result.usage, startedAt) };
|
|
17678
18401
|
},
|
|
18402
|
+
async createVoice(req, call = {}) {
|
|
18403
|
+
mediaRetryOptions(call);
|
|
18404
|
+
const { abortSignal, ...request } = req;
|
|
18405
|
+
const model = catalog.require(req.model);
|
|
18406
|
+
const { request: resolved, warnings } = resolveVoiceCloneCall(model, request);
|
|
18407
|
+
const { adapter, ctx } = prepare(model, call, abortSignal, warnings);
|
|
18408
|
+
if (!adapter.createVoice) throw noMethod(adapter, model, "clone a voice");
|
|
18409
|
+
const startedAt = Date.now();
|
|
18410
|
+
const result = await adapter.createVoice(resolved, ctx);
|
|
18411
|
+
return { ...result, usage: await deps.settle(model, result.usage, startedAt) };
|
|
18412
|
+
},
|
|
18413
|
+
async designVoice(req, call = {}) {
|
|
18414
|
+
mediaRetryOptions(call);
|
|
18415
|
+
const { abortSignal, ...request } = req;
|
|
18416
|
+
const model = catalog.require(req.model);
|
|
18417
|
+
const { request: resolved, warnings } = resolveVoiceDesignCall(
|
|
18418
|
+
model,
|
|
18419
|
+
request,
|
|
18420
|
+
call.onUnsupported ?? "error"
|
|
18421
|
+
);
|
|
18422
|
+
const { adapter, ctx } = prepare(model, call, abortSignal, warnings);
|
|
18423
|
+
if (!adapter.designVoice) throw noMethod(adapter, model, "design a voice");
|
|
18424
|
+
const startedAt = Date.now();
|
|
18425
|
+
const result = await adapter.designVoice(resolved, ctx);
|
|
18426
|
+
return { ...result, usage: await deps.settle(model, result.usage, startedAt) };
|
|
18427
|
+
},
|
|
18428
|
+
async deleteVoice(req, call = {}) {
|
|
18429
|
+
mediaRetryOptions(call);
|
|
18430
|
+
const { abortSignal, ...request } = req;
|
|
18431
|
+
const model = catalog.require(req.model);
|
|
18432
|
+
assertMethod(model, "createVoice");
|
|
18433
|
+
const voiceId = request.voiceId.trim();
|
|
18434
|
+
if (!voiceId) {
|
|
18435
|
+
throw new ModelKitError({
|
|
18436
|
+
code: "missing_input",
|
|
18437
|
+
message: `${model.id} requires voiceId`,
|
|
18438
|
+
model: model.id
|
|
18439
|
+
});
|
|
18440
|
+
}
|
|
18441
|
+
const { adapter, ctx } = prepare(model, call, abortSignal, []);
|
|
18442
|
+
if (!adapter.deleteVoice) throw noMethod(adapter, model, "delete a voice");
|
|
18443
|
+
await adapter.deleteVoice({ model: model.id, voiceId }, ctx);
|
|
18444
|
+
},
|
|
17679
18445
|
async dub(req, call = {}) {
|
|
17680
18446
|
mediaRetryOptions(call);
|
|
17681
18447
|
const { abortSignal, ...request } = req;
|
|
@@ -17690,10 +18456,10 @@ function audioNodeMethods(deps) {
|
|
|
17690
18456
|
const startedAt = Date.now();
|
|
17691
18457
|
const outcome = await adapter.dub(resolved, ctx);
|
|
17692
18458
|
if (outcome.kind === "audio") {
|
|
17693
|
-
const { audio, usage:
|
|
18459
|
+
const { audio, usage: usage4, raw } = outcome.result;
|
|
17694
18460
|
return {
|
|
17695
18461
|
audio,
|
|
17696
|
-
usage: await deps.settle(model,
|
|
18462
|
+
usage: await deps.settle(model, usage4, startedAt),
|
|
17697
18463
|
...raw !== void 0 && { raw }
|
|
17698
18464
|
};
|
|
17699
18465
|
}
|
|
@@ -17731,10 +18497,10 @@ function textAbortOptions(sdk, context) {
|
|
|
17731
18497
|
if (abortSignal) return { abortSignal };
|
|
17732
18498
|
return {};
|
|
17733
18499
|
}
|
|
17734
|
-
var catalogId =
|
|
17735
|
-
var exactSize =
|
|
17736
|
-
var sdkRatio =
|
|
17737
|
-
var sizeTier =
|
|
18500
|
+
var catalogId = z33.string();
|
|
18501
|
+
var exactSize = z33.templateLiteral([z33.number(), "x", z33.number()]);
|
|
18502
|
+
var sdkRatio = z33.templateLiteral([z33.number(), ":", z33.number()]);
|
|
18503
|
+
var sizeTier = z33.enum(["512", "1K", "2K", "4K"]);
|
|
17738
18504
|
function isCatalogId(model) {
|
|
17739
18505
|
return catalogId.safeParse(model).success;
|
|
17740
18506
|
}
|
|
@@ -17947,7 +18713,7 @@ function createModelKit(config, adapters) {
|
|
|
17947
18713
|
const images = result.images.map(
|
|
17948
18714
|
(file) => toGeneratedImage({ bytes: file.uint8Array, mime: file.mediaType })
|
|
17949
18715
|
);
|
|
17950
|
-
const
|
|
18716
|
+
const usage4 = timed(
|
|
17951
18717
|
{
|
|
17952
18718
|
model: model.modelId,
|
|
17953
18719
|
provider: model.provider,
|
|
@@ -17957,8 +18723,8 @@ function createModelKit(config, adapters) {
|
|
|
17957
18723
|
},
|
|
17958
18724
|
startedAt
|
|
17959
18725
|
);
|
|
17960
|
-
await emit(
|
|
17961
|
-
return { image: images[0], images, usage:
|
|
18726
|
+
await emit(usage4);
|
|
18727
|
+
return { image: images[0], images, usage: usage4, raw: result, warnings };
|
|
17962
18728
|
}
|
|
17963
18729
|
function passthroughVideo(req, call) {
|
|
17964
18730
|
const {
|
|
@@ -18034,7 +18800,7 @@ function createModelKit(config, adapters) {
|
|
|
18034
18800
|
let settled;
|
|
18035
18801
|
let failed = false;
|
|
18036
18802
|
const done = pending.then(async (result) => {
|
|
18037
|
-
const
|
|
18803
|
+
const usage4 = timed(
|
|
18038
18804
|
{
|
|
18039
18805
|
model: model.modelId,
|
|
18040
18806
|
provider: model.provider,
|
|
@@ -18047,10 +18813,10 @@ function createModelKit(config, adapters) {
|
|
|
18047
18813
|
);
|
|
18048
18814
|
settled = {
|
|
18049
18815
|
video: { bytes: result.video.uint8Array, mime: result.video.mediaType },
|
|
18050
|
-
usage:
|
|
18816
|
+
usage: usage4,
|
|
18051
18817
|
raw: result
|
|
18052
18818
|
};
|
|
18053
|
-
await emit(
|
|
18819
|
+
await emit(usage4);
|
|
18054
18820
|
return settled;
|
|
18055
18821
|
});
|
|
18056
18822
|
done.catch(() => {
|
|
@@ -18077,12 +18843,12 @@ function createModelKit(config, adapters) {
|
|
|
18077
18843
|
if (settled) return settled;
|
|
18078
18844
|
const pending = result(opts).then(
|
|
18079
18845
|
async (out) => {
|
|
18080
|
-
const
|
|
18846
|
+
const usage4 = timed(
|
|
18081
18847
|
{ ...out.usage, model: model.id, unit: model.usage.unit },
|
|
18082
18848
|
startedAt
|
|
18083
18849
|
);
|
|
18084
|
-
await emit(
|
|
18085
|
-
return { ...out, usage:
|
|
18850
|
+
await emit(usage4);
|
|
18851
|
+
return { ...out, usage: usage4 };
|
|
18086
18852
|
},
|
|
18087
18853
|
(cause) => {
|
|
18088
18854
|
settled = void 0;
|
|
@@ -18102,9 +18868,9 @@ function createModelKit(config, adapters) {
|
|
|
18102
18868
|
return context(model, signal ? { ...call, signal } : call, warnings);
|
|
18103
18869
|
},
|
|
18104
18870
|
async settle(model, event, startedAt) {
|
|
18105
|
-
const
|
|
18106
|
-
await emit(
|
|
18107
|
-
return
|
|
18871
|
+
const usage4 = timed({ ...event, model: model.id, unit: model.usage.unit }, startedAt);
|
|
18872
|
+
await emit(usage4);
|
|
18873
|
+
return usage4;
|
|
18108
18874
|
},
|
|
18109
18875
|
wrapVideoJob
|
|
18110
18876
|
});
|
|
@@ -18140,11 +18906,11 @@ function createModelKit(config, adapters) {
|
|
|
18140
18906
|
});
|
|
18141
18907
|
const startedAt = Date.now();
|
|
18142
18908
|
const result = await adapter.generateImage(request, ctx);
|
|
18143
|
-
const
|
|
18909
|
+
const usage4 = timed(
|
|
18144
18910
|
{ ...result.usage, model: model.id, unit: model.usage.unit },
|
|
18145
18911
|
startedAt
|
|
18146
18912
|
);
|
|
18147
|
-
await emit(
|
|
18913
|
+
await emit(usage4);
|
|
18148
18914
|
const images = result.images.map(toGeneratedImage);
|
|
18149
18915
|
const first = images[0];
|
|
18150
18916
|
if (!first)
|
|
@@ -18153,7 +18919,7 @@ function createModelKit(config, adapters) {
|
|
|
18153
18919
|
message: `${model.id} returned no image`,
|
|
18154
18920
|
model: model.id
|
|
18155
18921
|
});
|
|
18156
|
-
return { ...result, usage:
|
|
18922
|
+
return { ...result, usage: usage4, image: first, images, warnings };
|
|
18157
18923
|
},
|
|
18158
18924
|
async generateVideo(req, call = {}) {
|
|
18159
18925
|
mediaRetryOptions(call);
|
|
@@ -18252,12 +19018,12 @@ function createModelKit(config, adapters) {
|
|
|
18252
19018
|
}
|
|
18253
19019
|
const startedAt = Date.now();
|
|
18254
19020
|
const result = await adapter.generateAudio(resolved, ctx);
|
|
18255
|
-
const
|
|
19021
|
+
const usage4 = timed(
|
|
18256
19022
|
{ ...result.usage, model: model.id, unit: model.usage.unit },
|
|
18257
19023
|
startedAt
|
|
18258
19024
|
);
|
|
18259
|
-
await emit(
|
|
18260
|
-
return { ...result, usage:
|
|
19025
|
+
await emit(usage4);
|
|
19026
|
+
return { ...result, usage: usage4 };
|
|
18261
19027
|
},
|
|
18262
19028
|
async prepareMediaPart(modelId, ref, mediaType, call = {}) {
|
|
18263
19029
|
mediaRetryOptions(call);
|
|
@@ -18337,8 +19103,8 @@ function createModelKit(config, adapters) {
|
|
|
18337
19103
|
options.prepareStep ?? options.experimental_prepareStep
|
|
18338
19104
|
),
|
|
18339
19105
|
onFinish: async (event) => {
|
|
18340
|
-
for (const
|
|
18341
|
-
await emit(textTimed(withRowUnit(
|
|
19106
|
+
for (const usage4 of steps.usage(event.steps))
|
|
19107
|
+
await emit(textTimed(withRowUnit(usage4), event.steps.length, startedAt));
|
|
18342
19108
|
await callerOnFinish?.(event);
|
|
18343
19109
|
}
|
|
18344
19110
|
});
|
|
@@ -18460,6 +19226,7 @@ export {
|
|
|
18460
19226
|
falAdapter,
|
|
18461
19227
|
falWebhookBodySchema,
|
|
18462
19228
|
fileCatalogCache,
|
|
19229
|
+
fishAdapter,
|
|
18463
19230
|
generateAudio,
|
|
18464
19231
|
generateImage,
|
|
18465
19232
|
generateObject,
|
|
@@ -18512,6 +19279,8 @@ export {
|
|
|
18512
19279
|
resolveTranscriptionOptions,
|
|
18513
19280
|
resolveVideoOptions,
|
|
18514
19281
|
resolveVoiceChangeOptions,
|
|
19282
|
+
resolveVoiceCloneOptions,
|
|
19283
|
+
resolveVoiceDesignOptions,
|
|
18515
19284
|
shouldRetry,
|
|
18516
19285
|
sleep,
|
|
18517
19286
|
sortCatalogRows,
|