@shop-os/modelkit 0.9.0 → 0.10.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 +15 -0
- package/README.md +2 -1
- package/dist/catalog.cjs +454 -386
- package/dist/catalog.cjs.map +1 -1
- package/dist/catalog.d.cts +6 -3
- package/dist/catalog.d.ts +6 -3
- package/dist/catalog.js +454 -386
- package/dist/catalog.js.map +1 -1
- package/dist/index.cjs +967 -617
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -4
- package/dist/index.d.ts +9 -4
- package/dist/index.js +966 -617
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1230,303 +1230,6 @@ 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
|
-
|
|
1530
1233
|
// src/catalog/languages-audio.ts
|
|
1531
1234
|
var ELEVENLABS_V4_LANGUAGES = [
|
|
1532
1235
|
{ code: "af", name: "Afrikaans" },
|
|
@@ -1901,131 +1604,494 @@ var ELEVENLABS_VOICES = [
|
|
|
1901
1604
|
previewUrl: "https://storage.googleapis.com/eleven-public-prod/premade/voices/IKne3meq5aSn9XLyUdCD/102de6f2-22ed-43e0-a1f1-111fa75c5481.mp3"
|
|
1902
1605
|
},
|
|
1903
1606
|
{
|
|
1904
|
-
id: "George",
|
|
1905
|
-
name: "George",
|
|
1906
|
-
gender: "male",
|
|
1607
|
+
id: "George",
|
|
1608
|
+
name: "George",
|
|
1609
|
+
gender: "male",
|
|
1610
|
+
accent: "british",
|
|
1611
|
+
languages: ["en", "fr", "ar", "ja", "cs", "fil", "es", "hi"],
|
|
1612
|
+
description: "Warm resonance that instantly captivates listeners.",
|
|
1613
|
+
previewUrl: "https://storage.googleapis.com/eleven-public-prod/premade/voices/JBFqnCBsd6RMkjVDRZzb/e6206d1a-0721-4787-aafb-06a6e705cac5.mp3"
|
|
1614
|
+
},
|
|
1615
|
+
{
|
|
1616
|
+
id: "Callum",
|
|
1617
|
+
name: "Callum",
|
|
1618
|
+
gender: "male",
|
|
1619
|
+
accent: "american",
|
|
1620
|
+
languages: ["en", "fr", "hi"],
|
|
1621
|
+
description: "Deceptively gravelly, yet unsettling edge.",
|
|
1622
|
+
previewUrl: "https://storage.googleapis.com/eleven-public-prod/premade/voices/N2lVS1w4EtoT3dr4eOWO/ac833bd8-ffda-4938-9ebc-b0f99ca25481.mp3"
|
|
1623
|
+
},
|
|
1624
|
+
{
|
|
1625
|
+
id: "River",
|
|
1626
|
+
name: "River",
|
|
1627
|
+
gender: "neutral",
|
|
1628
|
+
accent: "american",
|
|
1629
|
+
languages: ["en", "it", "fr", "pt", "zh"],
|
|
1630
|
+
description: "A relaxed, neutral voice ready for narrations or conversational projects.",
|
|
1631
|
+
previewUrl: "https://storage.googleapis.com/eleven-public-prod/premade/voices/SAz9YHcvj6GT2YYXdXww/e6c95f0b-2227-491a-b3d7-2249240decb7.mp3"
|
|
1632
|
+
},
|
|
1633
|
+
{
|
|
1634
|
+
id: "Liam",
|
|
1635
|
+
name: "Liam",
|
|
1636
|
+
gender: "male",
|
|
1637
|
+
accent: "american",
|
|
1638
|
+
languages: ["en", "de", "pt", "cs", "pl", "tr", "hi"],
|
|
1639
|
+
description: "A young adult with energy and warmth - suitable for reels and shorts.",
|
|
1640
|
+
previewUrl: "https://storage.googleapis.com/eleven-public-prod/premade/voices/TX3LPaxmHKxFdv7VOQHJ/63148076-6363-42db-aea8-31424308b92c.mp3"
|
|
1641
|
+
},
|
|
1642
|
+
{ id: "Charlotte", name: "Charlotte" },
|
|
1643
|
+
{
|
|
1644
|
+
id: "Alice",
|
|
1645
|
+
name: "Alice",
|
|
1646
|
+
gender: "female",
|
|
1647
|
+
accent: "british",
|
|
1648
|
+
languages: ["en", "it", "fr", "ar", "ja", "pl", "hi"],
|
|
1649
|
+
description: "Clear and engaging, friendly woman with a British accent suitable for e-learning.",
|
|
1650
|
+
previewUrl: "https://storage.googleapis.com/eleven-public-prod/premade/voices/Xb7hH8MSUJpSbSDYk0k2/d10f7534-11f6-41fe-a012-2de1e482d336.mp3"
|
|
1651
|
+
},
|
|
1652
|
+
{
|
|
1653
|
+
id: "Matilda",
|
|
1654
|
+
name: "Matilda",
|
|
1655
|
+
gender: "female",
|
|
1656
|
+
accent: "american",
|
|
1657
|
+
languages: ["en", "it", "fr", "de", "ar", "es"],
|
|
1658
|
+
description: "A professional woman with a pleasing alto pitch. Suitable for many use cases.",
|
|
1659
|
+
previewUrl: "https://storage.googleapis.com/eleven-public-prod/premade/voices/XrExE9yKIg1WjnnlVkGX/b930e18d-6b4d-466e-bab2-0ae97c6d8535.mp3"
|
|
1660
|
+
},
|
|
1661
|
+
{
|
|
1662
|
+
id: "Will",
|
|
1663
|
+
name: "Will",
|
|
1664
|
+
gender: "male",
|
|
1665
|
+
accent: "american",
|
|
1666
|
+
languages: ["en", "fr", "de", "pt", "zh", "cs", "fil", "sk", "es", "sv"],
|
|
1667
|
+
description: "Conversational and laid back.",
|
|
1668
|
+
previewUrl: "https://storage.googleapis.com/eleven-public-prod/premade/voices/bIHbv24MWmeRgasZH58o/8caf8f3d-ad29-4980-af41-53f20c72d7a4.mp3"
|
|
1669
|
+
},
|
|
1670
|
+
{
|
|
1671
|
+
id: "Jessica",
|
|
1672
|
+
name: "Jessica",
|
|
1673
|
+
gender: "female",
|
|
1674
|
+
accent: "american",
|
|
1675
|
+
languages: ["en", "fr", "ar", "ja", "zh", "de", "cs", "hi"],
|
|
1676
|
+
description: "Young and popular, this playful American female voice is perfect for trendy content.",
|
|
1677
|
+
previewUrl: "https://storage.googleapis.com/eleven-public-prod/premade/voices/cgSgspJ2msm6clMCkdW9/56a97bf8-b69b-448f-846c-c3a11683d45a.mp3"
|
|
1678
|
+
},
|
|
1679
|
+
{
|
|
1680
|
+
id: "Eric",
|
|
1681
|
+
name: "Eric",
|
|
1682
|
+
gender: "male",
|
|
1683
|
+
accent: "american",
|
|
1684
|
+
languages: ["en", "fr", "pt", "de", "sk", "es"],
|
|
1685
|
+
description: "A smooth tenor pitch from a man in his 40s - perfect for agentic use cases.",
|
|
1686
|
+
previewUrl: "https://storage.googleapis.com/eleven-public-prod/premade/voices/cjVigY5qzO86Huf0OWal/d098fda0-6456-4030-b3d8-63aa048c9070.mp3"
|
|
1687
|
+
},
|
|
1688
|
+
{
|
|
1689
|
+
id: "Chris",
|
|
1690
|
+
name: "Chris",
|
|
1691
|
+
gender: "male",
|
|
1692
|
+
accent: "american",
|
|
1693
|
+
languages: ["en", "fr", "ar", "pt", "sv", "hi"],
|
|
1694
|
+
description: "Natural and real, this down-to-earth voice is great across many use-cases.",
|
|
1695
|
+
previewUrl: "https://storage.googleapis.com/eleven-public-prod/premade/voices/iP95p4xoKVk53GoZ742B/3f4bde72-cc48-40dd-829f-57fbf906f4d7.mp3"
|
|
1696
|
+
},
|
|
1697
|
+
{
|
|
1698
|
+
id: "Brian",
|
|
1699
|
+
name: "Brian",
|
|
1700
|
+
gender: "male",
|
|
1701
|
+
accent: "american",
|
|
1702
|
+
languages: ["en", "ar", "zh", "pt", "de", "nl", "sk", "ro", "hi"],
|
|
1703
|
+
description: "Middle-aged man with a resonant and comforting tone. Great for narrations and advertisements.",
|
|
1704
|
+
previewUrl: "https://storage.googleapis.com/eleven-public-prod/premade/voices/nPczCjzI2devNBz1zQrb/2dd3e72c-4fd3-42f1-93ea-abc5d4e5aa1d.mp3"
|
|
1705
|
+
},
|
|
1706
|
+
{
|
|
1707
|
+
id: "Daniel",
|
|
1708
|
+
name: "Daniel",
|
|
1709
|
+
gender: "male",
|
|
1710
|
+
accent: "british",
|
|
1711
|
+
languages: ["en", "de", "tr"],
|
|
1712
|
+
description: "A strong voice perfect for delivering a professional broadcast or news story.",
|
|
1713
|
+
previewUrl: "https://storage.googleapis.com/eleven-public-prod/premade/voices/onwK4e9ZLuTAKqWW03F9/7eee0236-1a72-4b86-b303-5dcadc007ba9.mp3"
|
|
1714
|
+
},
|
|
1715
|
+
{
|
|
1716
|
+
id: "Lily",
|
|
1717
|
+
name: "Lily",
|
|
1718
|
+
gender: "female",
|
|
1719
|
+
accent: "british",
|
|
1720
|
+
languages: ["en", "it", "de", "zh", "cs", "nl", "pl"],
|
|
1721
|
+
description: "Velvety British female voice delivers news and narrations with warmth and clarity.",
|
|
1722
|
+
previewUrl: "https://storage.googleapis.com/eleven-public-prod/premade/voices/pFZP5JQG7iQjIQuC4Bku/89b68b35-b3dd-4348-a84a-a3c13a3c2b30.mp3"
|
|
1723
|
+
},
|
|
1724
|
+
{
|
|
1725
|
+
id: "Bill",
|
|
1726
|
+
name: "Bill",
|
|
1727
|
+
gender: "male",
|
|
1728
|
+
accent: "american",
|
|
1729
|
+
languages: ["en", "fr", "ar", "zh", "de", "cs"],
|
|
1730
|
+
description: "Friendly and comforting voice ready to narrate your stories.",
|
|
1731
|
+
previewUrl: "https://storage.googleapis.com/eleven-public-prod/premade/voices/pqHfZKP75CvOlQylNhV4/d782b3ff-84ba-4029-848c-acf01285524d.mp3"
|
|
1732
|
+
}
|
|
1733
|
+
];
|
|
1734
|
+
var PREMADE_ID = /\/premade\/voices\/([A-Za-z0-9]+)\//;
|
|
1735
|
+
var ELEVENLABS_DIRECT_VOICES = ELEVENLABS_VOICES.flatMap((v) => {
|
|
1736
|
+
const id = v.previewUrl ? PREMADE_ID.exec(v.previewUrl)?.[1] : void 0;
|
|
1737
|
+
return id ? [{ ...v, id }] : [];
|
|
1738
|
+
});
|
|
1739
|
+
var ELEVENLABS_DIRECT_DEFAULT_VOICE = "EXAVITQu4vr4xnSDxMaL";
|
|
1740
|
+
|
|
1741
|
+
// src/catalog/speech-elevenlabs-direct.ts
|
|
1742
|
+
var ELEVENLABS_LOGO = "https://cdn.jsdelivr.net/npm/@lobehub/icons-static-png@1.97.0/light/elevenlabs.png";
|
|
1743
|
+
var PER_CALL = { unit: "images" };
|
|
1744
|
+
var PER_REQUEST = { unit: "requests" };
|
|
1745
|
+
var ELEVENLABS_DIRECT_MODELS = [
|
|
1746
|
+
{
|
|
1747
|
+
id: "elevenlabs-v4-direct",
|
|
1748
|
+
aliases: [],
|
|
1749
|
+
label: "ElevenLabs v4 (direct)",
|
|
1750
|
+
type: "speech",
|
|
1751
|
+
adapter: "elevenlabs",
|
|
1752
|
+
providerModelId: "eleven_v4",
|
|
1753
|
+
lifecycle: "active",
|
|
1754
|
+
exposure: [],
|
|
1755
|
+
constraints: {
|
|
1756
|
+
// Premade voices under their ElevenLabs ids (the direct API takes ids, not names).
|
|
1757
|
+
voices: ELEVENLABS_DIRECT_VOICES,
|
|
1758
|
+
languages: ELEVENLABS_V4_LANGUAGES,
|
|
1759
|
+
outputFormats: ELEVENLABS_MP3_FORMATS,
|
|
1760
|
+
supports: [],
|
|
1761
|
+
// ElevenLabs docs: 10,000 characters per request.
|
|
1762
|
+
prompt: { referenceSyntax: "numbered", maxChars: 1e4 }
|
|
1763
|
+
},
|
|
1764
|
+
defaults: { voice: ELEVENLABS_DIRECT_DEFAULT_VOICE, outputFormat: "mp3_44100_128" },
|
|
1765
|
+
usage: PER_CALL,
|
|
1766
|
+
pricingKind: "flat",
|
|
1767
|
+
display: {
|
|
1768
|
+
provider: "elevenlabs",
|
|
1769
|
+
logo: ELEVENLABS_LOGO,
|
|
1770
|
+
description: "ElevenLabs v4 text to speech with audio tags, in a premade voice or your own cloned voice; up to 10,000 characters."
|
|
1771
|
+
},
|
|
1772
|
+
capabilities: { customVoices: true }
|
|
1773
|
+
},
|
|
1774
|
+
{
|
|
1775
|
+
id: "elevenlabs-ivc",
|
|
1776
|
+
aliases: [],
|
|
1777
|
+
label: "ElevenLabs Instant Voice Clone",
|
|
1778
|
+
type: "voice-clone",
|
|
1779
|
+
adapter: "elevenlabs",
|
|
1780
|
+
providerModelId: "ivc",
|
|
1781
|
+
lifecycle: "active",
|
|
1782
|
+
exposure: [],
|
|
1783
|
+
constraints: {
|
|
1784
|
+
// POST /v1/voices/add; ElevenLabs takes up to 25 samples and advises 1-2 minutes of
|
|
1785
|
+
// clean speech in total. Each clone uses a voice slot on our plan until deleted.
|
|
1786
|
+
references: { audios: 25, audioFormats: ["mp3", "wav", "m4a", "webm", "ogg"] },
|
|
1787
|
+
supports: []
|
|
1788
|
+
},
|
|
1789
|
+
defaults: {},
|
|
1790
|
+
usage: PER_REQUEST,
|
|
1791
|
+
pricingKind: "flat",
|
|
1792
|
+
display: {
|
|
1793
|
+
provider: "elevenlabs",
|
|
1794
|
+
logo: ELEVENLABS_LOGO,
|
|
1795
|
+
description: "Clone a private, reusable voice from one or more clean recordings, then speak with it on ElevenLabs v4 (direct)."
|
|
1796
|
+
},
|
|
1797
|
+
capabilities: {}
|
|
1798
|
+
}
|
|
1799
|
+
];
|
|
1800
|
+
|
|
1801
|
+
// src/catalog/voices-fish.ts
|
|
1802
|
+
var FISH_VOICES = [
|
|
1803
|
+
{
|
|
1804
|
+
id: "933563129e564b19a115bedd57b7406a",
|
|
1805
|
+
name: "Sarah",
|
|
1806
|
+
gender: "female",
|
|
1807
|
+
languages: ["en"],
|
|
1808
|
+
description: "An engaged speaker.",
|
|
1809
|
+
previewUrl: "https://platform.r2.fish.audio/task/4e204945670c460c86fdab57512cb308.mp3"
|
|
1810
|
+
},
|
|
1811
|
+
{
|
|
1812
|
+
id: "bf322df2096a46f18c579d0baa36f41d",
|
|
1813
|
+
name: "Adrian",
|
|
1814
|
+
gender: "male",
|
|
1815
|
+
languages: ["en"],
|
|
1816
|
+
description: "A steady and reliable narrator.",
|
|
1817
|
+
previewUrl: "https://platform.r2.fish.audio/task/d730b09f4a484316a77ecc86137e85fb.mp3"
|
|
1818
|
+
},
|
|
1819
|
+
{
|
|
1820
|
+
id: "536d3a5e000945adb7038665781a4aca",
|
|
1821
|
+
name: "Ethan",
|
|
1822
|
+
gender: "male",
|
|
1823
|
+
languages: ["en"],
|
|
1824
|
+
description: "A curious explainer.",
|
|
1825
|
+
previewUrl: "https://platform.r2.fish.audio/task/bdd677ed767744fc91f166468786264b.mp3"
|
|
1826
|
+
},
|
|
1827
|
+
{
|
|
1828
|
+
id: "b347db033a6549378b48d00acb0d06cd",
|
|
1829
|
+
name: "Selene",
|
|
1830
|
+
gender: "female",
|
|
1831
|
+
languages: ["en"],
|
|
1832
|
+
description: "A meditative female voice.",
|
|
1833
|
+
previewUrl: "https://platform.r2.fish.audio/task/fcf629b4a0b343558f461338ba1b9da4.mp3"
|
|
1834
|
+
},
|
|
1835
|
+
{
|
|
1836
|
+
id: "9a9cf47702da476aa4629e2506d4a857",
|
|
1837
|
+
name: "Hannah",
|
|
1838
|
+
gender: "female",
|
|
1839
|
+
languages: ["en"],
|
|
1840
|
+
description: "A conversation specialist.",
|
|
1841
|
+
previewUrl: "https://platform.r2.fish.audio/task/08d658835feb427db808e37060b78eb0.mp3"
|
|
1842
|
+
},
|
|
1843
|
+
{
|
|
1844
|
+
id: "79d0bd3e4e5444b18f7b6d89b5927bf1",
|
|
1845
|
+
name: "Jordan",
|
|
1846
|
+
gender: "male",
|
|
1847
|
+
languages: ["en"],
|
|
1848
|
+
description: "A motivational speaker.",
|
|
1849
|
+
previewUrl: "https://platform.r2.fish.audio/task/edecbc0bdd4c46c39eda8520a0f729ef.mp3"
|
|
1850
|
+
},
|
|
1851
|
+
{
|
|
1852
|
+
id: "e3cd384158934cc9a01029cd7d278634",
|
|
1853
|
+
name: "Laura",
|
|
1854
|
+
gender: "female",
|
|
1855
|
+
languages: ["en"],
|
|
1856
|
+
description: "A confident female narrator.",
|
|
1857
|
+
previewUrl: "https://platform.r2.fish.audio/task/e821bef995344d519caa1c93d808db23.mp3"
|
|
1858
|
+
},
|
|
1859
|
+
{
|
|
1860
|
+
id: "f3a2b90078d54a65af4b95f63bc7798e",
|
|
1861
|
+
name: "Sheila",
|
|
1862
|
+
gender: "female",
|
|
1863
|
+
accent: "american",
|
|
1864
|
+
languages: ["en"],
|
|
1865
|
+
description: "A young American English woman's voice.",
|
|
1866
|
+
previewUrl: "https://platform.r2.fish.audio/tasks/2026-08-24/9bb9e1a1cf3f47f38700da1c5c0a678a.mp3"
|
|
1867
|
+
},
|
|
1868
|
+
{
|
|
1869
|
+
id: "0db6e93af420470b9d9b9a886dbaa954",
|
|
1870
|
+
name: "Kai",
|
|
1871
|
+
gender: "male",
|
|
1872
|
+
languages: ["en"],
|
|
1873
|
+
description: "A friendly English man's voice for companion apps and everyday conversation.",
|
|
1874
|
+
previewUrl: "https://platform.r2.fish.audio/tasks/2026-08-24/13306f1172544c3ba3106d1e363feaa6.mp3"
|
|
1875
|
+
},
|
|
1876
|
+
{
|
|
1877
|
+
id: "8abfa9ebd4c24a3399b68c3cdac8c7b5",
|
|
1878
|
+
name: "Freya",
|
|
1879
|
+
gender: "female",
|
|
1907
1880
|
accent: "british",
|
|
1908
|
-
languages: ["en"
|
|
1909
|
-
description: "
|
|
1910
|
-
previewUrl: "https://
|
|
1881
|
+
languages: ["en"],
|
|
1882
|
+
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.",
|
|
1883
|
+
previewUrl: "https://platform.r2.fish.audio/tasks/2026-08-25/07918705a56b42daaab149f65392cea7.mp3"
|
|
1911
1884
|
},
|
|
1912
1885
|
{
|
|
1913
|
-
id: "
|
|
1914
|
-
name: "
|
|
1886
|
+
id: "2f64e528a4f2406691925ab1e0ed5b7f",
|
|
1887
|
+
name: "Ananya",
|
|
1888
|
+
gender: "female",
|
|
1889
|
+
languages: ["hi"],
|
|
1890
|
+
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",
|
|
1891
|
+
previewUrl: "https://platform.r2.fish.audio/tasks/2026-08-25/a17a700668d8405f8316db120733145c.mp3"
|
|
1892
|
+
},
|
|
1893
|
+
{
|
|
1894
|
+
id: "cefd91a07b99468f9148e2580990082d",
|
|
1895
|
+
name: "Arjun",
|
|
1915
1896
|
gender: "male",
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
previewUrl: "https://storage.googleapis.com/eleven-public-prod/premade/voices/N2lVS1w4EtoT3dr4eOWO/ac833bd8-ffda-4938-9ebc-b0f99ca25481.mp3"
|
|
1897
|
+
languages: ["hi"],
|
|
1898
|
+
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",
|
|
1899
|
+
previewUrl: "https://platform.r2.fish.audio/tasks/2026-08-24/a0c4a8eadb7841cdae8e5e68031a2dfb.mp3"
|
|
1920
1900
|
},
|
|
1921
1901
|
{
|
|
1922
|
-
id: "
|
|
1923
|
-
name: "
|
|
1924
|
-
gender: "
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
previewUrl: "https://storage.googleapis.com/eleven-public-prod/premade/voices/SAz9YHcvj6GT2YYXdXww/e6c95f0b-2227-491a-b3d7-2249240decb7.mp3"
|
|
1902
|
+
id: "3f065d660212478a9c697fa965b4d098",
|
|
1903
|
+
name: "Carmen",
|
|
1904
|
+
gender: "female",
|
|
1905
|
+
languages: ["es"],
|
|
1906
|
+
description: "Una voz clara y segura para asistentes de voz, atenci\xF3n al cliente y presentaciones.",
|
|
1907
|
+
previewUrl: "https://platform.r2.fish.audio/tasks/2026-08-25/3421be48b6cb4c28bf829c25188e7e74.mp3"
|
|
1929
1908
|
},
|
|
1930
1909
|
{
|
|
1931
|
-
id: "
|
|
1932
|
-
name: "
|
|
1910
|
+
id: "ec0718028a2445fb9be8e8bfb56a0150",
|
|
1911
|
+
name: "Rodrigo",
|
|
1933
1912
|
gender: "male",
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
previewUrl: "https://storage.googleapis.com/eleven-public-prod/premade/voices/TX3LPaxmHKxFdv7VOQHJ/63148076-6363-42db-aea8-31424308b92c.mp3"
|
|
1913
|
+
languages: ["es"],
|
|
1914
|
+
description: "Una voz clara y segura para asistentes de voz, atenci\xF3n al cliente y presentaciones.",
|
|
1915
|
+
previewUrl: "https://platform.r2.fish.audio/tasks/2026-08-25/5a77c32365604800ad5b4eb13c5585df.mp3"
|
|
1938
1916
|
},
|
|
1939
|
-
{ id: "Charlotte", name: "Charlotte" },
|
|
1940
1917
|
{
|
|
1941
|
-
id: "
|
|
1942
|
-
name: "
|
|
1918
|
+
id: "10a3a20742114a4ea6dd441e7591850f",
|
|
1919
|
+
name: "Manon",
|
|
1943
1920
|
gender: "female",
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
previewUrl: "https://storage.googleapis.com/eleven-public-prod/premade/voices/Xb7hH8MSUJpSbSDYk0k2/d10f7534-11f6-41fe-a012-2de1e482d336.mp3"
|
|
1921
|
+
languages: ["fr"],
|
|
1922
|
+
description: "Une voix claire et vive, adapt\xE9e aux assistants vocaux et au support client.",
|
|
1923
|
+
previewUrl: "https://platform.r2.fish.audio/tasks/2026-08-25/f7b75ee1fa524e48a8cefb003cf72952.mp3"
|
|
1948
1924
|
},
|
|
1949
1925
|
{
|
|
1950
|
-
id: "
|
|
1951
|
-
name: "
|
|
1926
|
+
id: "f69bca092b674168a8d02d61ca20943c",
|
|
1927
|
+
name: "Lucas",
|
|
1928
|
+
gender: "male",
|
|
1929
|
+
languages: ["fr"],
|
|
1930
|
+
description: "Une voix claire et assur\xE9e, adapt\xE9e aux assistants vocaux et au service client.",
|
|
1931
|
+
previewUrl: "https://platform.r2.fish.audio/tasks/2026-08-25/86fca3e56a014a3d8a11450854bb8311.mp3"
|
|
1932
|
+
},
|
|
1933
|
+
{
|
|
1934
|
+
id: "3937b44b604249f18b94913daef94043",
|
|
1935
|
+
name: "Lena",
|
|
1952
1936
|
gender: "female",
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
previewUrl: "https://storage.googleapis.com/eleven-public-prod/premade/voices/XrExE9yKIg1WjnnlVkGX/b930e18d-6b4d-466e-bab2-0ae97c6d8535.mp3"
|
|
1937
|
+
languages: ["de"],
|
|
1938
|
+
description: "Eine klare, souver\xE4ne Stimme f\xFCr Sprachassistenten, Kundenservice und Pr\xE4sentationen.",
|
|
1939
|
+
previewUrl: "https://platform.r2.fish.audio/tasks/2026-08-25/8659fec80b74442dab68a7755716a401.mp3"
|
|
1957
1940
|
},
|
|
1958
1941
|
{
|
|
1959
|
-
id: "
|
|
1960
|
-
name: "
|
|
1942
|
+
id: "c1e7cc926aa5469aa966c353094d4b0b",
|
|
1943
|
+
name: "Lukas",
|
|
1961
1944
|
gender: "male",
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
previewUrl: "https://storage.googleapis.com/eleven-public-prod/premade/voices/bIHbv24MWmeRgasZH58o/8caf8f3d-ad29-4980-af41-53f20c72d7a4.mp3"
|
|
1945
|
+
languages: ["de"],
|
|
1946
|
+
description: "Eine klare, souver\xE4ne Stimme f\xFCr Sprachassistenten, Kundenservice und Pr\xE4sentationen.",
|
|
1947
|
+
previewUrl: "https://platform.r2.fish.audio/tasks/2026-08-25/fb1d538126bb4fe38f8366250f6a2136.mp3"
|
|
1966
1948
|
},
|
|
1967
1949
|
{
|
|
1968
|
-
id: "
|
|
1969
|
-
name: "
|
|
1950
|
+
id: "b3c060cc41544a7da94a2c487647c902",
|
|
1951
|
+
name: "Let\xEDcia",
|
|
1970
1952
|
gender: "female",
|
|
1971
|
-
accent: "
|
|
1972
|
-
languages: ["
|
|
1973
|
-
description: "
|
|
1974
|
-
previewUrl: "https://
|
|
1953
|
+
accent: "brazilian",
|
|
1954
|
+
languages: ["pt"],
|
|
1955
|
+
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.",
|
|
1956
|
+
previewUrl: "https://platform.r2.fish.audio/tasks/2026-10-12/13c6c0d96b5c4069951f89868ee15360.mp3"
|
|
1975
1957
|
},
|
|
1976
1958
|
{
|
|
1977
|
-
id: "
|
|
1978
|
-
name: "
|
|
1959
|
+
id: "add7bcb8d3c8423bbfa152ca232aad6e",
|
|
1960
|
+
name: "Ricardo",
|
|
1979
1961
|
gender: "male",
|
|
1980
|
-
accent: "
|
|
1981
|
-
languages: ["
|
|
1982
|
-
description: "A
|
|
1983
|
-
previewUrl: "https://
|
|
1962
|
+
accent: "brazilian",
|
|
1963
|
+
languages: ["pt"],
|
|
1964
|
+
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.",
|
|
1965
|
+
previewUrl: "https://platform.r2.fish.audio/tasks/2026-10-12/67475fc717ae45cbb38e647a2dd37fe1.mp3"
|
|
1984
1966
|
},
|
|
1985
1967
|
{
|
|
1986
|
-
id: "
|
|
1987
|
-
name: "
|
|
1988
|
-
gender: "
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
previewUrl: "https://storage.googleapis.com/eleven-public-prod/premade/voices/iP95p4xoKVk53GoZ742B/3f4bde72-cc48-40dd-829f-57fbf906f4d7.mp3"
|
|
1968
|
+
id: "b2d9d8db057042688a5e318b8f405bc2",
|
|
1969
|
+
name: "Kyoko",
|
|
1970
|
+
gender: "female",
|
|
1971
|
+
languages: ["ja"],
|
|
1972
|
+
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",
|
|
1973
|
+
previewUrl: "https://platform.r2.fish.audio/task/993b3ccb52124341aff79580f1ce5a5a.mp3"
|
|
1993
1974
|
},
|
|
1994
1975
|
{
|
|
1995
|
-
id: "
|
|
1996
|
-
name: "
|
|
1976
|
+
id: "297a6fd278df47c3b9da9bfdf55ac89a",
|
|
1977
|
+
name: "Satoru",
|
|
1997
1978
|
gender: "male",
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
previewUrl: "https://storage.googleapis.com/eleven-public-prod/premade/voices/nPczCjzI2devNBz1zQrb/2dd3e72c-4fd3-42f1-93ea-abc5d4e5aa1d.mp3"
|
|
1979
|
+
languages: ["ja"],
|
|
1980
|
+
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",
|
|
1981
|
+
previewUrl: "https://platform.r2.fish.audio/task/1b4712fb831f4c149eef6b0133157418.mp3"
|
|
2002
1982
|
},
|
|
2003
1983
|
{
|
|
2004
|
-
id: "
|
|
2005
|
-
name: "
|
|
2006
|
-
gender: "
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
previewUrl: "https://storage.googleapis.com/eleven-public-prod/premade/voices/onwK4e9ZLuTAKqWW03F9/7eee0236-1a72-4b86-b303-5dcadc007ba9.mp3"
|
|
1984
|
+
id: "0b14f34a13a94ed88fe6113193749bb0",
|
|
1985
|
+
name: "Fatima",
|
|
1986
|
+
gender: "female",
|
|
1987
|
+
languages: ["ar"],
|
|
1988
|
+
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.",
|
|
1989
|
+
previewUrl: "https://platform.r2.fish.audio/tasks/2026-08-24/93406e1b905a4c4994306e3421243390.mp3"
|
|
2011
1990
|
},
|
|
2012
1991
|
{
|
|
2013
|
-
id: "
|
|
2014
|
-
name: "
|
|
1992
|
+
id: "74c6aba5cbf94a15bbdc547ffce5cb38",
|
|
1993
|
+
name: "Yutong",
|
|
2015
1994
|
gender: "female",
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
1995
|
+
languages: ["zh"],
|
|
1996
|
+
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",
|
|
1997
|
+
previewUrl: "https://platform.r2.fish.audio/tasks/2026-08-25/a48320f37fe44c4699549a1afc3778e8.mp3"
|
|
1998
|
+
}
|
|
1999
|
+
];
|
|
2000
|
+
|
|
2001
|
+
// src/catalog/speech-fish.ts
|
|
2002
|
+
var FISH_LOGO = "https://cdn.jsdelivr.net/npm/@lobehub/icons-static-png@1.97.0/light/fishaudio.png";
|
|
2003
|
+
var PER_CALL2 = { unit: "images" };
|
|
2004
|
+
var PER_REQUEST2 = { unit: "requests" };
|
|
2005
|
+
var TTS_MAX_CHARS = 1e4;
|
|
2006
|
+
function fishTts(id, label, providerModelId, description) {
|
|
2007
|
+
return {
|
|
2008
|
+
id,
|
|
2009
|
+
aliases: [],
|
|
2010
|
+
label,
|
|
2011
|
+
type: "speech",
|
|
2012
|
+
adapter: "fish",
|
|
2013
|
+
providerModelId,
|
|
2014
|
+
lifecycle: "active",
|
|
2015
|
+
exposure: [],
|
|
2016
|
+
constraints: {
|
|
2017
|
+
voices: FISH_VOICES,
|
|
2018
|
+
outputFormats: ["mp3", "wav"],
|
|
2019
|
+
supports: [],
|
|
2020
|
+
prompt: { referenceSyntax: "numbered", maxChars: TTS_MAX_CHARS }
|
|
2021
|
+
},
|
|
2022
|
+
defaults: { voice: "9a9cf47702da476aa4629e2506d4a857", outputFormat: "mp3" },
|
|
2023
|
+
usage: PER_CALL2,
|
|
2024
|
+
pricingKind: "flat",
|
|
2025
|
+
display: { provider: "fishaudio", logo: FISH_LOGO, description },
|
|
2026
|
+
capabilities: { customVoices: true }
|
|
2027
|
+
};
|
|
2028
|
+
}
|
|
2029
|
+
var FISH_MODELS = [
|
|
2030
|
+
fishTts(
|
|
2031
|
+
"fish-s2.1-pro",
|
|
2032
|
+
"Fish Audio S2.1 Pro",
|
|
2033
|
+
"s2.1-pro",
|
|
2034
|
+
"Fish Audio S2.1 Pro text to speech in 83 languages, with [bracket] directions and your own cloned voices."
|
|
2035
|
+
),
|
|
2036
|
+
fishTts(
|
|
2037
|
+
"fish-s2.1-pro-free",
|
|
2038
|
+
"Fish Audio S2.1 Pro Free",
|
|
2039
|
+
"s2.1-pro-free",
|
|
2040
|
+
"Fish Audio S2.1 Pro on the free developer tier: the same voices at no cost, without latency or data-processing guarantees."
|
|
2041
|
+
),
|
|
2042
|
+
fishTts(
|
|
2043
|
+
"fish-drama-3",
|
|
2044
|
+
"Fish Audio Drama 3",
|
|
2045
|
+
"drama-3",
|
|
2046
|
+
"Fish Audio Drama 3 text to speech you direct like an actor: [directions], sounds, pauses and per-word tags."
|
|
2047
|
+
),
|
|
2048
|
+
{
|
|
2049
|
+
id: "fish-voice-clone",
|
|
2050
|
+
aliases: [],
|
|
2051
|
+
label: "Fish Audio Voice Clone",
|
|
2052
|
+
type: "voice-clone",
|
|
2053
|
+
adapter: "fish",
|
|
2054
|
+
providerModelId: "voice-clone",
|
|
2055
|
+
lifecycle: "active",
|
|
2056
|
+
exposure: [],
|
|
2057
|
+
constraints: {
|
|
2058
|
+
// POST /model takes 1-20 voice files; Fish advises 10 s or more of clean speech each.
|
|
2059
|
+
references: { audios: 20, audioFormats: ["wav", "mp3", "m4a", "opus"] },
|
|
2060
|
+
supports: []
|
|
2061
|
+
},
|
|
2062
|
+
defaults: {},
|
|
2063
|
+
usage: PER_REQUEST2,
|
|
2064
|
+
pricingKind: "flat",
|
|
2065
|
+
display: {
|
|
2066
|
+
provider: "fishaudio",
|
|
2067
|
+
logo: FISH_LOGO,
|
|
2068
|
+
description: "Clone a private, reusable voice from one or more clean recordings, then speak with it on the Fish Audio speech models."
|
|
2069
|
+
},
|
|
2070
|
+
capabilities: {}
|
|
2020
2071
|
},
|
|
2021
2072
|
{
|
|
2022
|
-
id: "
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2073
|
+
id: "fish-voice-design-1",
|
|
2074
|
+
aliases: [],
|
|
2075
|
+
label: "Fish Audio Voice Design",
|
|
2076
|
+
type: "voice-design",
|
|
2077
|
+
adapter: "fish",
|
|
2078
|
+
providerModelId: "voice-design-1",
|
|
2079
|
+
lifecycle: "active",
|
|
2080
|
+
exposure: [],
|
|
2081
|
+
constraints: {
|
|
2082
|
+
voiceDesign: { maxCandidates: 4, previewMaxChars: 150 },
|
|
2083
|
+
supports: [],
|
|
2084
|
+
prompt: { referenceSyntax: "numbered", maxChars: 2e3 }
|
|
2085
|
+
},
|
|
2086
|
+
defaults: {},
|
|
2087
|
+
usage: PER_REQUEST2,
|
|
2088
|
+
pricingKind: "flat",
|
|
2089
|
+
display: {
|
|
2090
|
+
provider: "fishaudio",
|
|
2091
|
+
logo: FISH_LOGO,
|
|
2092
|
+
description: "Describe a voice and get up to four short candidates; keep one as a cloned voice."
|
|
2093
|
+
},
|
|
2094
|
+
capabilities: {}
|
|
2029
2095
|
}
|
|
2030
2096
|
];
|
|
2031
2097
|
|
|
@@ -3604,11 +3670,11 @@ var MINIMAX_VOICES = [
|
|
|
3604
3670
|
];
|
|
3605
3671
|
|
|
3606
3672
|
// src/catalog/media-nodes.ts
|
|
3607
|
-
var
|
|
3673
|
+
var ELEVENLABS_LOGO2 = "https://cdn.jsdelivr.net/npm/@lobehub/icons-static-png@1.97.0/light/elevenlabs.png";
|
|
3608
3674
|
var GOOGLE_LOGO = "https://d31vvfpk2ppdyq.cloudfront.net/assets/image/192485d2-a76a-4657-9c06-930b2c70badd_compressed.png";
|
|
3609
3675
|
var MINIMAX_LOGO = "https://d31vvfpk2ppdyq.cloudfront.net/assets/image/f4c2e906-28b7-4a4a-b491-df8fef7808ed.png";
|
|
3610
3676
|
var SYNC_LOGO = "https://cdn.jsdelivr.net/npm/@lobehub/icons-static-png@1.97.0/light/sync.png";
|
|
3611
|
-
var
|
|
3677
|
+
var PER_CALL3 = { unit: "images" };
|
|
3612
3678
|
var EXPOSURE4 = ["cowork", "space_builder"];
|
|
3613
3679
|
var LIPSYNC_AUDIO = { audioSeconds: { max: 30 } };
|
|
3614
3680
|
function elevenLabsTts(tts) {
|
|
@@ -3629,9 +3695,9 @@ function elevenLabsTts(tts) {
|
|
|
3629
3695
|
prompt: { referenceSyntax: "numbered", maxChars: tts.maxChars }
|
|
3630
3696
|
},
|
|
3631
3697
|
defaults: { voice: "Rachel", ...tts.formats && { outputFormat: "mp3_44100_128" } },
|
|
3632
|
-
usage:
|
|
3698
|
+
usage: PER_CALL3,
|
|
3633
3699
|
pricingKind: "flat",
|
|
3634
|
-
display: { provider: "elevenlabs", logo:
|
|
3700
|
+
display: { provider: "elevenlabs", logo: ELEVENLABS_LOGO2, description: tts.description },
|
|
3635
3701
|
capabilities: {}
|
|
3636
3702
|
};
|
|
3637
3703
|
}
|
|
@@ -3653,7 +3719,7 @@ function geminiTts(id, label, description) {
|
|
|
3653
3719
|
prompt: { referenceSyntax: "numbered", maxChars: 8192 }
|
|
3654
3720
|
},
|
|
3655
3721
|
defaults: { voice: "Kore" },
|
|
3656
|
-
usage:
|
|
3722
|
+
usage: PER_CALL3,
|
|
3657
3723
|
pricingKind: "flat",
|
|
3658
3724
|
display: { provider: "google", logo: GOOGLE_LOGO, description },
|
|
3659
3725
|
capabilities: {}
|
|
@@ -3676,7 +3742,7 @@ function syncLipsync(id, label, providerModelId, syncModel, description) {
|
|
|
3676
3742
|
},
|
|
3677
3743
|
defaults: {},
|
|
3678
3744
|
...syncModel !== void 0 && { providerOptions: { fal: { model: syncModel } } },
|
|
3679
|
-
usage:
|
|
3745
|
+
usage: PER_CALL3,
|
|
3680
3746
|
pricingKind: "flat",
|
|
3681
3747
|
display: { provider: "sync", logo: SYNC_LOGO, description },
|
|
3682
3748
|
capabilities: { acceptsSourceVideo: true }
|
|
@@ -3737,7 +3803,7 @@ var MEDIA_NODE_MODELS = [
|
|
|
3737
3803
|
prompt: { referenceSyntax: "numbered", maxChars: 1e4 }
|
|
3738
3804
|
},
|
|
3739
3805
|
defaults: { voice: "Wise_Woman" },
|
|
3740
|
-
usage:
|
|
3806
|
+
usage: PER_CALL3,
|
|
3741
3807
|
pricingKind: "flat",
|
|
3742
3808
|
display: {
|
|
3743
3809
|
provider: "minimax",
|
|
@@ -3764,11 +3830,11 @@ var MEDIA_NODE_MODELS = [
|
|
|
3764
3830
|
supports: []
|
|
3765
3831
|
},
|
|
3766
3832
|
defaults: { voice: "Rachel", outputFormat: "mp3_44100_128" },
|
|
3767
|
-
usage:
|
|
3833
|
+
usage: PER_CALL3,
|
|
3768
3834
|
pricingKind: "flat",
|
|
3769
3835
|
display: {
|
|
3770
3836
|
provider: "elevenlabs",
|
|
3771
|
-
logo:
|
|
3837
|
+
logo: ELEVENLABS_LOGO2,
|
|
3772
3838
|
description: "ElevenLabs speech to speech; re-voices a recording in another voice and keeps its timing and delivery."
|
|
3773
3839
|
},
|
|
3774
3840
|
capabilities: {}
|
|
@@ -3791,11 +3857,11 @@ var MEDIA_NODE_MODELS = [
|
|
|
3791
3857
|
supports: []
|
|
3792
3858
|
},
|
|
3793
3859
|
defaults: {},
|
|
3794
|
-
usage:
|
|
3860
|
+
usage: PER_CALL3,
|
|
3795
3861
|
pricingKind: "flat",
|
|
3796
3862
|
display: {
|
|
3797
3863
|
provider: "elevenlabs",
|
|
3798
|
-
logo:
|
|
3864
|
+
logo: ELEVENLABS_LOGO2,
|
|
3799
3865
|
description: "ElevenLabs dubbing; translates the speech in a video or audio file into another language in the original voices."
|
|
3800
3866
|
},
|
|
3801
3867
|
capabilities: { acceptsSourceVideo: true }
|
|
@@ -3838,7 +3904,7 @@ var MEDIA_NODE_MODELS = [
|
|
|
3838
3904
|
supports: []
|
|
3839
3905
|
},
|
|
3840
3906
|
defaults: {},
|
|
3841
|
-
usage:
|
|
3907
|
+
usage: PER_CALL3,
|
|
3842
3908
|
pricingKind: "flat",
|
|
3843
3909
|
display: {
|
|
3844
3910
|
provider: "veed",
|
|
@@ -3890,17 +3956,18 @@ var MEDIA_NODE_MODELS = [
|
|
|
3890
3956
|
supports: []
|
|
3891
3957
|
},
|
|
3892
3958
|
defaults: {},
|
|
3893
|
-
usage:
|
|
3959
|
+
usage: PER_CALL3,
|
|
3894
3960
|
pricingKind: "flat",
|
|
3895
3961
|
display: {
|
|
3896
3962
|
provider: "elevenlabs",
|
|
3897
|
-
logo:
|
|
3963
|
+
logo: ELEVENLABS_LOGO2,
|
|
3898
3964
|
description: "ElevenLabs Scribe v2 speech to text with word timings, speaker labels and audio-event tags."
|
|
3899
3965
|
},
|
|
3900
3966
|
capabilities: {}
|
|
3901
3967
|
},
|
|
3902
3968
|
SAM_3_IMAGE,
|
|
3903
|
-
...FISH_MODELS
|
|
3969
|
+
...FISH_MODELS,
|
|
3970
|
+
...ELEVENLABS_DIRECT_MODELS
|
|
3904
3971
|
];
|
|
3905
3972
|
|
|
3906
3973
|
// src/catalog/model3d.ts
|
|
@@ -4096,7 +4163,7 @@ var MODEL3D_MODELS = [
|
|
|
4096
4163
|
|
|
4097
4164
|
// src/catalog/other.ts
|
|
4098
4165
|
var GOOGLE_LOGO2 = "https://d31vvfpk2ppdyq.cloudfront.net/assets/image/192485d2-a76a-4657-9c06-930b2c70badd_compressed.png";
|
|
4099
|
-
var
|
|
4166
|
+
var ELEVENLABS_LOGO3 = "https://cdn.jsdelivr.net/npm/@lobehub/icons-static-png@1.97.0/light/elevenlabs.png";
|
|
4100
4167
|
var MINIMAX_LOGO2 = "https://d31vvfpk2ppdyq.cloudfront.net/assets/image/f4c2e906-28b7-4a4a-b491-df8fef7808ed.png";
|
|
4101
4168
|
var OTHER_MODELS = [
|
|
4102
4169
|
{
|
|
@@ -4261,7 +4328,7 @@ var OTHER_MODELS = [
|
|
|
4261
4328
|
pricingKind: "flat",
|
|
4262
4329
|
display: {
|
|
4263
4330
|
provider: "elevenlabs",
|
|
4264
|
-
logo:
|
|
4331
|
+
logo: ELEVENLABS_LOGO3,
|
|
4265
4332
|
description: "ElevenLabs Music v2.5 text-to-music; full songs or instrumentals from 3 seconds to 1 minute."
|
|
4266
4333
|
},
|
|
4267
4334
|
capabilities: {}
|
|
@@ -4313,7 +4380,7 @@ var OTHER_MODELS = [
|
|
|
4313
4380
|
pricingKind: "flat",
|
|
4314
4381
|
display: {
|
|
4315
4382
|
provider: "elevenlabs",
|
|
4316
|
-
logo:
|
|
4383
|
+
logo: ELEVENLABS_LOGO3,
|
|
4317
4384
|
description: "ElevenLabs Sound Effects v2; a sound effect from a text description, up to 22 seconds."
|
|
4318
4385
|
},
|
|
4319
4386
|
capabilities: {}
|
|
@@ -7536,7 +7603,8 @@ var ADAPTER_IDS = [
|
|
|
7536
7603
|
"higgsfield",
|
|
7537
7604
|
"xai-video",
|
|
7538
7605
|
"luma",
|
|
7539
|
-
"fish"
|
|
7606
|
+
"fish",
|
|
7607
|
+
"elevenlabs"
|
|
7540
7608
|
];
|
|
7541
7609
|
var ModelTypeSchema = z3.enum([
|
|
7542
7610
|
"text",
|
|
@@ -8749,16 +8817,16 @@ async function generateSeedreamImage(req, ctx) {
|
|
|
8749
8817
|
} else {
|
|
8750
8818
|
throwArkError(void 0, "Seedream returned no image URL or base64 data", modelId);
|
|
8751
8819
|
}
|
|
8752
|
-
const
|
|
8820
|
+
const usage5 = {
|
|
8753
8821
|
model: modelId,
|
|
8754
8822
|
provider: "ark",
|
|
8755
8823
|
modality: "IMAGE",
|
|
8756
8824
|
unit: "images",
|
|
8757
8825
|
quantity: 1
|
|
8758
8826
|
};
|
|
8759
|
-
if (req.size !== void 0)
|
|
8760
|
-
if (req.quality !== void 0)
|
|
8761
|
-
return { images: [{ bytes, mime: sniffedImageMime(bytes) }], usage:
|
|
8827
|
+
if (req.size !== void 0) usage5.imageSize = req.size;
|
|
8828
|
+
if (req.quality !== void 0) usage5.imageQuality = req.quality;
|
|
8829
|
+
return { images: [{ bytes, mime: sniffedImageMime(bytes) }], usage: usage5, raw: data };
|
|
8762
8830
|
}
|
|
8763
8831
|
var SeedanceUsageSchema = z7.object({
|
|
8764
8832
|
total_tokens: z7.number().optional(),
|
|
@@ -8799,7 +8867,7 @@ function seedanceErrorMessage(error, status) {
|
|
|
8799
8867
|
if (asObject.success && asObject.data.message !== void 0) return asObject.data.message;
|
|
8800
8868
|
return `Seedance task ${status}`;
|
|
8801
8869
|
}
|
|
8802
|
-
function seedanceJob(ctx, key, jobId,
|
|
8870
|
+
function seedanceJob(ctx, key, jobId, usage5) {
|
|
8803
8871
|
const modelId = ctx.model.id;
|
|
8804
8872
|
const fetchStatus = async () => {
|
|
8805
8873
|
const res = await arkFetch(ctx, `${arkBaseUrl(ctx)}${SUBMIT_PATH}/${jobId}`, {
|
|
@@ -8849,21 +8917,21 @@ function seedanceJob(ctx, key, jobId, usage4) {
|
|
|
8849
8917
|
modelId
|
|
8850
8918
|
);
|
|
8851
8919
|
if (polled.duration !== void 0 && polled.duration > 0) {
|
|
8852
|
-
|
|
8853
|
-
|
|
8920
|
+
usage5.quantity = polled.duration;
|
|
8921
|
+
usage5.durationSeconds = polled.duration;
|
|
8854
8922
|
}
|
|
8855
8923
|
const rendered = VideoResolutionSchema.safeParse(
|
|
8856
8924
|
polled.resolution?.toLowerCase()
|
|
8857
8925
|
);
|
|
8858
|
-
if (rendered.success)
|
|
8926
|
+
if (rendered.success) usage5.resolution = rendered.data;
|
|
8859
8927
|
const tokens = polled.usage;
|
|
8860
8928
|
if (tokens?.total_tokens !== void 0 && tokens.completion_tokens !== void 0) {
|
|
8861
|
-
|
|
8862
|
-
|
|
8929
|
+
usage5.inputTokens = tokens.total_tokens - tokens.completion_tokens;
|
|
8930
|
+
usage5.outputTokens = tokens.completion_tokens;
|
|
8863
8931
|
}
|
|
8864
8932
|
return {
|
|
8865
8933
|
video: { url, expiresAt: new Date(Date.now() + VIDEO_URL_TTL_MS) },
|
|
8866
|
-
usage:
|
|
8934
|
+
usage: usage5,
|
|
8867
8935
|
raw: polled
|
|
8868
8936
|
};
|
|
8869
8937
|
}
|
|
@@ -8969,8 +9037,8 @@ async function generateSeedanceVideo(req, ctx) {
|
|
|
8969
9037
|
);
|
|
8970
9038
|
if (!submit.id) throwArkError(void 0, "Seedance task create returned no id", modelId);
|
|
8971
9039
|
const jobId = submit.id;
|
|
8972
|
-
const
|
|
8973
|
-
return seedanceJob(ctx, key, jobId,
|
|
9040
|
+
const usage5 = seedanceUsage(ctx, req, taskType === "edit" ? requestedDuration : duration);
|
|
9041
|
+
return seedanceJob(ctx, key, jobId, usage5);
|
|
8974
9042
|
}
|
|
8975
9043
|
|
|
8976
9044
|
// src/adapters/fal.ts
|
|
@@ -10458,7 +10526,7 @@ async function collectFalPlanImages(payload, plan4, ctx, req) {
|
|
|
10458
10526
|
return { bytes, mime: mime || "image/png" };
|
|
10459
10527
|
})
|
|
10460
10528
|
);
|
|
10461
|
-
const
|
|
10529
|
+
const usage5 = {
|
|
10462
10530
|
model: ctx.model.id,
|
|
10463
10531
|
provider: "fal",
|
|
10464
10532
|
modality: "IMAGE",
|
|
@@ -10466,9 +10534,9 @@ async function collectFalPlanImages(payload, plan4, ctx, req) {
|
|
|
10466
10534
|
quantity: images.length
|
|
10467
10535
|
};
|
|
10468
10536
|
const billedSize = plan4.imageSize ?? req.size;
|
|
10469
|
-
if (billedSize !== void 0 && ctx.model.type === "image")
|
|
10470
|
-
if (plan4.imageQuality !== void 0)
|
|
10471
|
-
const result = { images, usage:
|
|
10537
|
+
if (billedSize !== void 0 && ctx.model.type === "image") usage5.imageSize = billedSize;
|
|
10538
|
+
if (plan4.imageQuality !== void 0) usage5.imageQuality = plan4.imageQuality;
|
|
10539
|
+
const result = { images, usage: usage5, raw: payload };
|
|
10472
10540
|
const remote = files.find((f) => !f.url.startsWith("data:"));
|
|
10473
10541
|
if (remote !== void 0) result.outputUrl = remote.url;
|
|
10474
10542
|
return result;
|
|
@@ -12631,9 +12699,282 @@ function planUsage(ctx, plan4) {
|
|
|
12631
12699
|
};
|
|
12632
12700
|
}
|
|
12633
12701
|
|
|
12634
|
-
// src/adapters/
|
|
12702
|
+
// src/adapters/elevenlabs.ts
|
|
12635
12703
|
import { z as z21 } from "zod";
|
|
12636
|
-
var DEFAULT_BASE_URL = "https://api.
|
|
12704
|
+
var DEFAULT_BASE_URL = "https://api.elevenlabs.io";
|
|
12705
|
+
var DEFAULT_FORMAT = "mp3_44100_128";
|
|
12706
|
+
var ELEVENLABS_TTS_MODEL_IDS = /* @__PURE__ */ new Set(["eleven_v4"]);
|
|
12707
|
+
var ELEVENLABS_IVC = "ivc";
|
|
12708
|
+
var VOICE_ID = /^[A-Za-z0-9_-]{1,64}$/;
|
|
12709
|
+
function elevenLabsRowRefusal(row2) {
|
|
12710
|
+
const id = row2.providerModelId;
|
|
12711
|
+
if (row2.type === "speech") {
|
|
12712
|
+
return ELEVENLABS_TTS_MODEL_IDS.has(id) ? void 0 : `elevenlabs speech rows need providerModelId ${[...ELEVENLABS_TTS_MODEL_IDS].join(", ")}`;
|
|
12713
|
+
}
|
|
12714
|
+
if (row2.type === "voice-clone") {
|
|
12715
|
+
return id === ELEVENLABS_IVC ? void 0 : `elevenlabs voice-clone rows need providerModelId ${ELEVENLABS_IVC}`;
|
|
12716
|
+
}
|
|
12717
|
+
return `elevenlabs has no ${row2.type} rows`;
|
|
12718
|
+
}
|
|
12719
|
+
function elevenLabsError(ctx, code, message) {
|
|
12720
|
+
return new ModelKitError({
|
|
12721
|
+
code,
|
|
12722
|
+
message,
|
|
12723
|
+
provider: "elevenlabs",
|
|
12724
|
+
model: ctx.model.id,
|
|
12725
|
+
retryable: false
|
|
12726
|
+
});
|
|
12727
|
+
}
|
|
12728
|
+
function checkRow(ctx, type) {
|
|
12729
|
+
const refusal2 = ctx.model.type === type ? elevenLabsRowRefusal(ctx.model) : void 0;
|
|
12730
|
+
if (ctx.model.type !== type || refusal2 !== void 0) {
|
|
12731
|
+
throw elevenLabsError(
|
|
12732
|
+
ctx,
|
|
12733
|
+
"unsupported_option",
|
|
12734
|
+
refusal2 ?? `${ctx.model.id} is not a ${type} row`
|
|
12735
|
+
);
|
|
12736
|
+
}
|
|
12737
|
+
}
|
|
12738
|
+
function checkVoiceId(ctx, field, id) {
|
|
12739
|
+
if (!VOICE_ID.test(id))
|
|
12740
|
+
throw elevenLabsError(ctx, "unsupported_option", `${field} is not a voice id`);
|
|
12741
|
+
return id;
|
|
12742
|
+
}
|
|
12743
|
+
function elevenLabsKey(ctx) {
|
|
12744
|
+
const key = ctx.keys.elevenlabs;
|
|
12745
|
+
if (!key) throw elevenLabsError(ctx, "auth", "Missing API key for elevenlabs");
|
|
12746
|
+
return key;
|
|
12747
|
+
}
|
|
12748
|
+
function elevenLabsUrl(ctx, path) {
|
|
12749
|
+
return `${ctx.endpoints?.elevenlabs ?? DEFAULT_BASE_URL}${path}`;
|
|
12750
|
+
}
|
|
12751
|
+
var errorDetail = z21.object({
|
|
12752
|
+
detail: z21.object({ status: z21.string(), message: z21.string().optional() })
|
|
12753
|
+
});
|
|
12754
|
+
function errorStatus(body) {
|
|
12755
|
+
const parsed = errorDetail.safeParse(body);
|
|
12756
|
+
return parsed.success ? parsed.data.detail : void 0;
|
|
12757
|
+
}
|
|
12758
|
+
function classifyResponse(ctx, status, body) {
|
|
12759
|
+
const error = classifyHttpError(status, body, "elevenlabs", ctx.model.id);
|
|
12760
|
+
const detail = errorStatus(body);
|
|
12761
|
+
if (detail?.status === "voice_limit_reached") {
|
|
12762
|
+
return new ModelKitError({
|
|
12763
|
+
code: "provider_rejected",
|
|
12764
|
+
message: detail.message ?? "ElevenLabs voice limit reached",
|
|
12765
|
+
provider: "elevenlabs",
|
|
12766
|
+
model: ctx.model.id,
|
|
12767
|
+
status,
|
|
12768
|
+
body,
|
|
12769
|
+
cause: error,
|
|
12770
|
+
retryable: false
|
|
12771
|
+
});
|
|
12772
|
+
}
|
|
12773
|
+
if (detail?.status === "quota_exceeded") {
|
|
12774
|
+
return new ModelKitError({
|
|
12775
|
+
code: "provider_billing",
|
|
12776
|
+
message: error.message,
|
|
12777
|
+
provider: "elevenlabs",
|
|
12778
|
+
model: ctx.model.id,
|
|
12779
|
+
status,
|
|
12780
|
+
body,
|
|
12781
|
+
cause: error,
|
|
12782
|
+
retryable: false
|
|
12783
|
+
});
|
|
12784
|
+
}
|
|
12785
|
+
return error;
|
|
12786
|
+
}
|
|
12787
|
+
async function elevenLabsFetch(ctx, path, init) {
|
|
12788
|
+
throwIfAborted(ctx.signal);
|
|
12789
|
+
const request = {
|
|
12790
|
+
method: init.method,
|
|
12791
|
+
headers: { "xi-api-key": elevenLabsKey(ctx), ...init.headers }
|
|
12792
|
+
};
|
|
12793
|
+
if (init.body !== void 0) request.body = init.body;
|
|
12794
|
+
if (ctx.signal !== void 0) request.signal = ctx.signal;
|
|
12795
|
+
let res;
|
|
12796
|
+
try {
|
|
12797
|
+
res = await ctx.fetch(elevenLabsUrl(ctx, path), request);
|
|
12798
|
+
} catch (cause) {
|
|
12799
|
+
throw classifyThrown("elevenlabs", cause, ctx.model.id);
|
|
12800
|
+
}
|
|
12801
|
+
if (!res.ok) throw classifyResponse(ctx, res.status, await readBody(res));
|
|
12802
|
+
return res;
|
|
12803
|
+
}
|
|
12804
|
+
function usage2(ctx) {
|
|
12805
|
+
return {
|
|
12806
|
+
model: ctx.model.id,
|
|
12807
|
+
provider: "elevenlabs",
|
|
12808
|
+
modality: "AUDIO",
|
|
12809
|
+
unit: ctx.model.usage.unit,
|
|
12810
|
+
quantity: 1
|
|
12811
|
+
};
|
|
12812
|
+
}
|
|
12813
|
+
function audioMime(res) {
|
|
12814
|
+
const header = res.headers.get("content-type")?.split(";")[0]?.trim().toLowerCase();
|
|
12815
|
+
return header?.startsWith("audio/") ? header : "audio/mpeg";
|
|
12816
|
+
}
|
|
12817
|
+
async function generateSpeech(req, ctx) {
|
|
12818
|
+
checkRow(ctx, "speech");
|
|
12819
|
+
const voice = req.customVoice ?? req.voice;
|
|
12820
|
+
if (voice === void 0) throw elevenLabsError(ctx, "missing_input", "needs a voice");
|
|
12821
|
+
const voiceId = checkVoiceId(ctx, req.customVoice ? "customVoice" : "voice", voice);
|
|
12822
|
+
const format = req.outputFormat ?? DEFAULT_FORMAT;
|
|
12823
|
+
const body = { text: req.text, model_id: ctx.model.providerModelId };
|
|
12824
|
+
if (req.language !== void 0) body.language_code = req.language;
|
|
12825
|
+
const path = `/v1/text-to-speech/${encodeURIComponent(voiceId)}?output_format=${encodeURIComponent(format)}`;
|
|
12826
|
+
const { bytes, mime } = await withRetry(
|
|
12827
|
+
async () => {
|
|
12828
|
+
const res = await elevenLabsFetch(ctx, path, {
|
|
12829
|
+
method: "POST",
|
|
12830
|
+
headers: { "Content-Type": "application/json" },
|
|
12831
|
+
body: JSON.stringify(body)
|
|
12832
|
+
});
|
|
12833
|
+
let audio;
|
|
12834
|
+
try {
|
|
12835
|
+
audio = new Uint8Array(await res.arrayBuffer());
|
|
12836
|
+
} catch (cause) {
|
|
12837
|
+
throw classifyThrown("elevenlabs", cause, ctx.model.id);
|
|
12838
|
+
}
|
|
12839
|
+
return { bytes: audio, mime: audioMime(res) };
|
|
12840
|
+
},
|
|
12841
|
+
mediaRetryOptions(ctx.call, ctx.signal)
|
|
12842
|
+
);
|
|
12843
|
+
if (bytes.byteLength === 0)
|
|
12844
|
+
throw elevenLabsError(ctx, "provider_rejected", "ElevenLabs TTS returned no audio");
|
|
12845
|
+
return { audio: { bytes, mime }, usage: usage2(ctx) };
|
|
12846
|
+
}
|
|
12847
|
+
var createdVoiceSchema = z21.object({
|
|
12848
|
+
voice_id: z21.string().min(1),
|
|
12849
|
+
requires_verification: z21.boolean().optional().catch(void 0)
|
|
12850
|
+
});
|
|
12851
|
+
function sampleMime(mime) {
|
|
12852
|
+
return mime.startsWith("audio/") || mime.startsWith("video/") ? mime : "application/octet-stream";
|
|
12853
|
+
}
|
|
12854
|
+
function fileName(index, mime, ref) {
|
|
12855
|
+
const fromMime = mime === "application/octet-stream" ? void 0 : mime.split("/")[1]?.replace("mpeg", "mp3").replace("x-", "");
|
|
12856
|
+
const fromUrl = "url" in ref ? /\.([A-Za-z0-9]{2,4})$/.exec(new URL(ref.url).pathname)?.[1] : void 0;
|
|
12857
|
+
const ext = fromMime || fromUrl?.toLowerCase();
|
|
12858
|
+
return ext ? `sample-${index + 1}.${ext}` : `sample-${index + 1}`;
|
|
12859
|
+
}
|
|
12860
|
+
async function cloneForm(req, ctx) {
|
|
12861
|
+
if (req.samples.length === 0)
|
|
12862
|
+
throw elevenLabsError(ctx, "missing_input", "needs a voice sample");
|
|
12863
|
+
if (req.samples.some((s) => s.designSignature?.trim())) {
|
|
12864
|
+
throw elevenLabsError(
|
|
12865
|
+
ctx,
|
|
12866
|
+
"unsupported_option",
|
|
12867
|
+
"ElevenLabs cannot keep a voice design signature; clone from recordings only"
|
|
12868
|
+
);
|
|
12869
|
+
}
|
|
12870
|
+
const form = new FormData();
|
|
12871
|
+
form.append("name", req.title.trim());
|
|
12872
|
+
if (req.description?.trim()) form.append("description", req.description.trim());
|
|
12873
|
+
if (req.enhance !== void 0) form.append("remove_background_noise", String(req.enhance));
|
|
12874
|
+
for (const [index, sample] of req.samples.entries()) {
|
|
12875
|
+
const { bytes, mime } = await mediaRefToBytes(sample.audio, ctx.fetch, {
|
|
12876
|
+
signal: ctx.signal,
|
|
12877
|
+
provider: "elevenlabs",
|
|
12878
|
+
model: ctx.model.id
|
|
12879
|
+
});
|
|
12880
|
+
const type = sampleMime(mime);
|
|
12881
|
+
const audio = new Blob([new Uint8Array(bytes)], { type });
|
|
12882
|
+
form.append("files", audio, fileName(index, type, sample.audio));
|
|
12883
|
+
}
|
|
12884
|
+
return form;
|
|
12885
|
+
}
|
|
12886
|
+
async function onlyRateLimitRetries(fn) {
|
|
12887
|
+
try {
|
|
12888
|
+
return await fn();
|
|
12889
|
+
} catch (cause) {
|
|
12890
|
+
if (!isModelKitError(cause) || !cause.retryable || cause.code === "rate_limited")
|
|
12891
|
+
throw cause;
|
|
12892
|
+
throw new ModelKitError({
|
|
12893
|
+
code: cause.code,
|
|
12894
|
+
message: cause.message,
|
|
12895
|
+
...cause.provider !== void 0 && { provider: cause.provider },
|
|
12896
|
+
...cause.model !== void 0 && { model: cause.model },
|
|
12897
|
+
...cause.status !== void 0 && { status: cause.status },
|
|
12898
|
+
...cause.body !== void 0 && { body: cause.body },
|
|
12899
|
+
cause,
|
|
12900
|
+
retryable: false
|
|
12901
|
+
});
|
|
12902
|
+
}
|
|
12903
|
+
}
|
|
12904
|
+
async function createVoice(req, ctx) {
|
|
12905
|
+
checkRow(ctx, "voice-clone");
|
|
12906
|
+
const form = await cloneForm(req, ctx);
|
|
12907
|
+
const res = await withRetry(
|
|
12908
|
+
() => onlyRateLimitRetries(
|
|
12909
|
+
() => elevenLabsFetch(ctx, "/v1/voices/add", { method: "POST", body: form })
|
|
12910
|
+
),
|
|
12911
|
+
mediaRetryOptions(ctx.call, ctx.signal)
|
|
12912
|
+
);
|
|
12913
|
+
const raw = await readBody(res);
|
|
12914
|
+
const parsed = createdVoiceSchema.safeParse(raw);
|
|
12915
|
+
if (!parsed.success) {
|
|
12916
|
+
throw new ModelKitError({
|
|
12917
|
+
code: "provider_rejected",
|
|
12918
|
+
message: "ElevenLabs returned no voice id",
|
|
12919
|
+
provider: "elevenlabs",
|
|
12920
|
+
model: ctx.model.id,
|
|
12921
|
+
status: res.status,
|
|
12922
|
+
body: raw,
|
|
12923
|
+
retryable: false
|
|
12924
|
+
});
|
|
12925
|
+
}
|
|
12926
|
+
return {
|
|
12927
|
+
voiceId: parsed.data.voice_id,
|
|
12928
|
+
state: parsed.data.requires_verification === true ? "created" : "trained",
|
|
12929
|
+
usage: usage2(ctx),
|
|
12930
|
+
raw
|
|
12931
|
+
};
|
|
12932
|
+
}
|
|
12933
|
+
var NOT_FOUND_STATUSES = /* @__PURE__ */ new Set([
|
|
12934
|
+
"voice_not_found",
|
|
12935
|
+
"voice_does_not_exist"
|
|
12936
|
+
]);
|
|
12937
|
+
function notFound(cause) {
|
|
12938
|
+
if (cause.status === 404) return true;
|
|
12939
|
+
const status = errorStatus(cause.body)?.status;
|
|
12940
|
+
return cause.status === 400 && status !== void 0 && NOT_FOUND_STATUSES.has(status);
|
|
12941
|
+
}
|
|
12942
|
+
async function deleteVoice(req, ctx) {
|
|
12943
|
+
checkRow(ctx, "voice-clone");
|
|
12944
|
+
const id = encodeURIComponent(checkVoiceId(ctx, "voiceId", req.voiceId));
|
|
12945
|
+
let attempts = 0;
|
|
12946
|
+
await withRetry(
|
|
12947
|
+
async () => {
|
|
12948
|
+
attempts += 1;
|
|
12949
|
+
try {
|
|
12950
|
+
await elevenLabsFetch(ctx, `/v1/voices/${id}`, { method: "DELETE" });
|
|
12951
|
+
} catch (cause) {
|
|
12952
|
+
if (!isModelKitError(cause) || !notFound(cause)) throw cause;
|
|
12953
|
+
if (attempts > 1) return;
|
|
12954
|
+
throw new ModelKitError({
|
|
12955
|
+
code: "provider_rejected",
|
|
12956
|
+
message: `ElevenLabs has no voice ${req.voiceId} under this key set; delete with the tier that created it`,
|
|
12957
|
+
provider: "elevenlabs",
|
|
12958
|
+
model: ctx.model.id,
|
|
12959
|
+
...cause.status !== void 0 && { status: cause.status },
|
|
12960
|
+
cause,
|
|
12961
|
+
retryable: false
|
|
12962
|
+
});
|
|
12963
|
+
}
|
|
12964
|
+
},
|
|
12965
|
+
mediaRetryOptions(ctx.call, ctx.signal)
|
|
12966
|
+
);
|
|
12967
|
+
}
|
|
12968
|
+
var elevenLabsAdapter = {
|
|
12969
|
+
id: "elevenlabs",
|
|
12970
|
+
generateSpeech,
|
|
12971
|
+
createVoice,
|
|
12972
|
+
deleteVoice
|
|
12973
|
+
};
|
|
12974
|
+
|
|
12975
|
+
// src/adapters/fish.ts
|
|
12976
|
+
import { z as z22 } from "zod";
|
|
12977
|
+
var DEFAULT_BASE_URL2 = "https://api.fish.audio";
|
|
12637
12978
|
var FISH_TTS_MODEL_IDS = /* @__PURE__ */ new Set([
|
|
12638
12979
|
"s2.1-pro",
|
|
12639
12980
|
"s2.1-pro-free",
|
|
@@ -12641,7 +12982,7 @@ var FISH_TTS_MODEL_IDS = /* @__PURE__ */ new Set([
|
|
|
12641
12982
|
]);
|
|
12642
12983
|
var FISH_VOICE_CLONE = "voice-clone";
|
|
12643
12984
|
var FISH_VOICE_DESIGN = "voice-design-1";
|
|
12644
|
-
var
|
|
12985
|
+
var VOICE_ID2 = /^[A-Za-z0-9_-]{1,64}$/;
|
|
12645
12986
|
function fishRowRefusal(row2) {
|
|
12646
12987
|
const id = row2.providerModelId;
|
|
12647
12988
|
if (row2.type === "speech") {
|
|
@@ -12664,7 +13005,7 @@ function fishError(ctx, code, message) {
|
|
|
12664
13005
|
retryable: false
|
|
12665
13006
|
});
|
|
12666
13007
|
}
|
|
12667
|
-
function
|
|
13008
|
+
function checkRow2(ctx, type) {
|
|
12668
13009
|
const refusal2 = ctx.model.type === type ? fishRowRefusal(ctx.model) : void 0;
|
|
12669
13010
|
if (ctx.model.type !== type || refusal2 !== void 0) {
|
|
12670
13011
|
throw fishError(
|
|
@@ -12674,8 +13015,8 @@ function checkRow(ctx, type) {
|
|
|
12674
13015
|
);
|
|
12675
13016
|
}
|
|
12676
13017
|
}
|
|
12677
|
-
function
|
|
12678
|
-
if (!
|
|
13018
|
+
function checkVoiceId2(ctx, field, id) {
|
|
13019
|
+
if (!VOICE_ID2.test(id))
|
|
12679
13020
|
throw fishError(ctx, "unsupported_option", `${field} is not a voice id`);
|
|
12680
13021
|
return id;
|
|
12681
13022
|
}
|
|
@@ -12685,7 +13026,7 @@ function fishKey(ctx) {
|
|
|
12685
13026
|
return key;
|
|
12686
13027
|
}
|
|
12687
13028
|
function fishUrl(ctx, path) {
|
|
12688
|
-
return `${ctx.endpoints?.fish ??
|
|
13029
|
+
return `${ctx.endpoints?.fish ?? DEFAULT_BASE_URL2}${path}`;
|
|
12689
13030
|
}
|
|
12690
13031
|
async function fishFetch(ctx, path, init) {
|
|
12691
13032
|
throwIfAborted(ctx.signal);
|
|
@@ -12704,7 +13045,7 @@ async function fishFetch(ctx, path, init) {
|
|
|
12704
13045
|
if (!res.ok) throw classifyHttpError(res.status, await readBody(res), "fish", ctx.model.id);
|
|
12705
13046
|
return res;
|
|
12706
13047
|
}
|
|
12707
|
-
function
|
|
13048
|
+
function usage3(ctx) {
|
|
12708
13049
|
return {
|
|
12709
13050
|
model: ctx.model.id,
|
|
12710
13051
|
provider: "fish",
|
|
@@ -12713,18 +13054,18 @@ function usage2(ctx) {
|
|
|
12713
13054
|
quantity: 1
|
|
12714
13055
|
};
|
|
12715
13056
|
}
|
|
12716
|
-
function
|
|
13057
|
+
function audioMime2(res, format) {
|
|
12717
13058
|
const header = res.headers.get("content-type")?.split(";")[0]?.trim().toLowerCase();
|
|
12718
13059
|
if (header?.startsWith("audio/")) return header;
|
|
12719
13060
|
return format === "wav" ? "audio/wav" : "audio/mpeg";
|
|
12720
13061
|
}
|
|
12721
|
-
async function
|
|
12722
|
-
|
|
13062
|
+
async function generateSpeech2(req, ctx) {
|
|
13063
|
+
checkRow2(ctx, "speech");
|
|
12723
13064
|
const format = req.outputFormat ?? "mp3";
|
|
12724
13065
|
const body = { text: req.text, format };
|
|
12725
13066
|
const voice = req.customVoice ?? req.voice;
|
|
12726
13067
|
if (voice !== void 0) {
|
|
12727
|
-
body.reference_id =
|
|
13068
|
+
body.reference_id = checkVoiceId2(ctx, req.customVoice ? "customVoice" : "voice", voice);
|
|
12728
13069
|
}
|
|
12729
13070
|
if (req.language !== void 0) body.language = req.language;
|
|
12730
13071
|
const { bytes, mime } = await withRetry(
|
|
@@ -12740,19 +13081,19 @@ async function generateSpeech(req, ctx) {
|
|
|
12740
13081
|
} catch (cause) {
|
|
12741
13082
|
throw classifyThrown("fish", cause, ctx.model.id);
|
|
12742
13083
|
}
|
|
12743
|
-
return { bytes: audio, mime:
|
|
13084
|
+
return { bytes: audio, mime: audioMime2(res, format) };
|
|
12744
13085
|
},
|
|
12745
13086
|
mediaRetryOptions(ctx.call, ctx.signal)
|
|
12746
13087
|
);
|
|
12747
13088
|
if (bytes.byteLength === 0)
|
|
12748
13089
|
throw fishError(ctx, "provider_rejected", "Fish TTS returned no audio");
|
|
12749
|
-
return { audio: { bytes, mime }, usage:
|
|
13090
|
+
return { audio: { bytes, mime }, usage: usage3(ctx) };
|
|
12750
13091
|
}
|
|
12751
|
-
var createdModelSchema =
|
|
12752
|
-
_id:
|
|
12753
|
-
state:
|
|
13092
|
+
var createdModelSchema = z22.object({
|
|
13093
|
+
_id: z22.string().min(1),
|
|
13094
|
+
state: z22.enum(["created", "training", "trained", "failed"]).optional().catch(void 0)
|
|
12754
13095
|
});
|
|
12755
|
-
function
|
|
13096
|
+
function fileName2(index, mime) {
|
|
12756
13097
|
const ext = mime.split("/")[1]?.replace("mpeg", "mp3").replace("x-", "") || "bin";
|
|
12757
13098
|
return `sample-${index + 1}.${ext}`;
|
|
12758
13099
|
}
|
|
@@ -12764,7 +13105,7 @@ function allOrNone(ctx, field, values) {
|
|
|
12764
13105
|
}
|
|
12765
13106
|
return set;
|
|
12766
13107
|
}
|
|
12767
|
-
async function
|
|
13108
|
+
async function cloneForm2(req, ctx) {
|
|
12768
13109
|
if (req.samples.length === 0) throw fishError(ctx, "missing_input", "needs a voice sample");
|
|
12769
13110
|
const transcripts = allOrNone(
|
|
12770
13111
|
ctx,
|
|
@@ -12790,13 +13131,13 @@ async function cloneForm(req, ctx) {
|
|
|
12790
13131
|
model: ctx.model.id
|
|
12791
13132
|
});
|
|
12792
13133
|
const audio = new Blob([new Uint8Array(bytes)], { type: mime });
|
|
12793
|
-
form.append("voices", audio,
|
|
13134
|
+
form.append("voices", audio, fileName2(index, mime));
|
|
12794
13135
|
}
|
|
12795
13136
|
for (const text2 of transcripts) form.append("texts", text2.trim());
|
|
12796
13137
|
for (const signature of signatures) form.append("voice_design_signatures", signature);
|
|
12797
13138
|
return form;
|
|
12798
13139
|
}
|
|
12799
|
-
async function
|
|
13140
|
+
async function onlyRateLimitRetries2(fn) {
|
|
12800
13141
|
try {
|
|
12801
13142
|
return await fn();
|
|
12802
13143
|
} catch (cause) {
|
|
@@ -12814,11 +13155,11 @@ async function onlyRateLimitRetries(fn) {
|
|
|
12814
13155
|
});
|
|
12815
13156
|
}
|
|
12816
13157
|
}
|
|
12817
|
-
async function
|
|
12818
|
-
|
|
12819
|
-
const form = await
|
|
13158
|
+
async function createVoice2(req, ctx) {
|
|
13159
|
+
checkRow2(ctx, "voice-clone");
|
|
13160
|
+
const form = await cloneForm2(req, ctx);
|
|
12820
13161
|
const res = await withRetry(
|
|
12821
|
-
() =>
|
|
13162
|
+
() => onlyRateLimitRetries2(() => fishFetch(ctx, "/model", { method: "POST", body: form })),
|
|
12822
13163
|
mediaRetryOptions(ctx.call, ctx.signal)
|
|
12823
13164
|
);
|
|
12824
13165
|
const raw = await readBody(res);
|
|
@@ -12834,23 +13175,23 @@ async function createVoice(req, ctx) {
|
|
|
12834
13175
|
retryable: false
|
|
12835
13176
|
});
|
|
12836
13177
|
}
|
|
12837
|
-
const result = { voiceId: parsed.data._id, usage:
|
|
13178
|
+
const result = { voiceId: parsed.data._id, usage: usage3(ctx), raw };
|
|
12838
13179
|
if (parsed.data.state !== void 0) result.state = parsed.data.state;
|
|
12839
13180
|
return result;
|
|
12840
13181
|
}
|
|
12841
|
-
var designSchema =
|
|
12842
|
-
candidates:
|
|
12843
|
-
|
|
12844
|
-
id:
|
|
12845
|
-
index:
|
|
12846
|
-
audio_base64:
|
|
12847
|
-
duration_ms:
|
|
12848
|
-
signature:
|
|
13182
|
+
var designSchema = z22.object({
|
|
13183
|
+
candidates: z22.array(
|
|
13184
|
+
z22.looseObject({
|
|
13185
|
+
id: z22.string().min(1),
|
|
13186
|
+
index: z22.number().int(),
|
|
13187
|
+
audio_base64: z22.string().min(1),
|
|
13188
|
+
duration_ms: z22.number().nonnegative(),
|
|
13189
|
+
signature: z22.string().min(1).optional()
|
|
12849
13190
|
})
|
|
12850
13191
|
).min(1)
|
|
12851
13192
|
});
|
|
12852
13193
|
async function designVoice(req, ctx) {
|
|
12853
|
-
|
|
13194
|
+
checkRow2(ctx, "voice-design");
|
|
12854
13195
|
const body = { instruction: req.prompt.trim() };
|
|
12855
13196
|
if (req.previewText?.trim()) body.reference_text = req.previewText.trim();
|
|
12856
13197
|
if (req.language !== void 0) body.language = req.language;
|
|
@@ -12878,11 +13219,11 @@ async function designVoice(req, ctx) {
|
|
|
12878
13219
|
// rejects a clone whose signature does not verify, so a wrong one fails loudly.
|
|
12879
13220
|
signature: c.signature ?? c.id
|
|
12880
13221
|
}));
|
|
12881
|
-
return { candidates, usage:
|
|
13222
|
+
return { candidates, usage: usage3(ctx) };
|
|
12882
13223
|
}
|
|
12883
|
-
async function
|
|
12884
|
-
|
|
12885
|
-
const id = encodeURIComponent(
|
|
13224
|
+
async function deleteVoice2(req, ctx) {
|
|
13225
|
+
checkRow2(ctx, "voice-clone");
|
|
13226
|
+
const id = encodeURIComponent(checkVoiceId2(ctx, "voiceId", req.voiceId));
|
|
12886
13227
|
let attempts = 0;
|
|
12887
13228
|
await withRetry(
|
|
12888
13229
|
async () => {
|
|
@@ -12908,20 +13249,20 @@ async function deleteVoice(req, ctx) {
|
|
|
12908
13249
|
}
|
|
12909
13250
|
var fishAdapter = {
|
|
12910
13251
|
id: "fish",
|
|
12911
|
-
generateSpeech,
|
|
12912
|
-
createVoice,
|
|
13252
|
+
generateSpeech: generateSpeech2,
|
|
13253
|
+
createVoice: createVoice2,
|
|
12913
13254
|
designVoice,
|
|
12914
|
-
deleteVoice
|
|
13255
|
+
deleteVoice: deleteVoice2
|
|
12915
13256
|
};
|
|
12916
13257
|
|
|
12917
13258
|
// src/adapters/google-genai.ts
|
|
12918
|
-
import { z as
|
|
13259
|
+
import { z as z24 } from "zod";
|
|
12919
13260
|
import {
|
|
12920
13261
|
GoogleGenAI
|
|
12921
13262
|
} from "@google/genai";
|
|
12922
13263
|
|
|
12923
13264
|
// src/adapters/google-files.ts
|
|
12924
|
-
import { z as
|
|
13265
|
+
import { z as z23 } from "zod";
|
|
12925
13266
|
var GOOGLE_FILES_BASE = "https://generativelanguage.googleapis.com";
|
|
12926
13267
|
var GOOGLE_FILES_POLL_INTERVAL_MS = 2e3;
|
|
12927
13268
|
var GOOGLE_FILES_POLL_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
@@ -12931,17 +13272,17 @@ var GENERIC_MEDIA_TYPES = /* @__PURE__ */ new Set([
|
|
|
12931
13272
|
"binary/octet-stream",
|
|
12932
13273
|
"application/binary"
|
|
12933
13274
|
]);
|
|
12934
|
-
var uploadedFileSchema =
|
|
12935
|
-
file:
|
|
12936
|
-
uri:
|
|
12937
|
-
name:
|
|
12938
|
-
state:
|
|
12939
|
-
mimeType:
|
|
13275
|
+
var uploadedFileSchema = z23.object({
|
|
13276
|
+
file: z23.object({
|
|
13277
|
+
uri: z23.string().optional(),
|
|
13278
|
+
name: z23.string().optional(),
|
|
13279
|
+
state: z23.string().optional(),
|
|
13280
|
+
mimeType: z23.string().optional()
|
|
12940
13281
|
}).optional()
|
|
12941
13282
|
});
|
|
12942
|
-
var fileStateSchema =
|
|
12943
|
-
state:
|
|
12944
|
-
error:
|
|
13283
|
+
var fileStateSchema = z23.object({
|
|
13284
|
+
state: z23.string().optional(),
|
|
13285
|
+
error: z23.object({ message: z23.string().optional() }).optional()
|
|
12945
13286
|
});
|
|
12946
13287
|
function resolveMime(declared, fallback) {
|
|
12947
13288
|
const clean = declared?.split(";")[0]?.trim().toLowerCase();
|
|
@@ -13048,7 +13389,7 @@ async function startAndUpload(bytes, mimeType, opts) {
|
|
|
13048
13389
|
if (uploaded.file?.state !== void 0) ref.state = uploaded.file.state;
|
|
13049
13390
|
return ref;
|
|
13050
13391
|
}
|
|
13051
|
-
async function waitForActive(
|
|
13392
|
+
async function waitForActive(fileName3, opts) {
|
|
13052
13393
|
const pollOptions2 = {
|
|
13053
13394
|
intervalMs: GOOGLE_FILES_POLL_INTERVAL_MS,
|
|
13054
13395
|
timeoutMs: GOOGLE_FILES_POLL_TIMEOUT_MS
|
|
@@ -13061,14 +13402,14 @@ async function waitForActive(fileName2, opts) {
|
|
|
13061
13402
|
retryInit.signal = opts.signal;
|
|
13062
13403
|
}
|
|
13063
13404
|
await pollUntil(async () => {
|
|
13064
|
-
const res = await opts.fetchImpl(`${GOOGLE_FILES_BASE}/v1beta/${
|
|
13405
|
+
const res = await opts.fetchImpl(`${GOOGLE_FILES_BASE}/v1beta/${fileName3}`, retryInit);
|
|
13065
13406
|
if (res.ok) {
|
|
13066
13407
|
const json = fileStateSchema.parse(await res.json());
|
|
13067
13408
|
if (json.state === "ACTIVE") return true;
|
|
13068
13409
|
if (json.state === "FAILED") {
|
|
13069
13410
|
throw classifyHttpError(
|
|
13070
13411
|
void 0,
|
|
13071
|
-
`Files API processing failed for ${
|
|
13412
|
+
`Files API processing failed for ${fileName3}: ${json.error?.message ?? "unknown error"}`,
|
|
13072
13413
|
"google-genai",
|
|
13073
13414
|
opts.model
|
|
13074
13415
|
);
|
|
@@ -13080,9 +13421,9 @@ async function waitForActive(fileName2, opts) {
|
|
|
13080
13421
|
throw classifyHttpError(res.status, text2, "google-genai", opts.model);
|
|
13081
13422
|
}, pollOptions2);
|
|
13082
13423
|
}
|
|
13083
|
-
async function deleteGoogleFile(
|
|
13424
|
+
async function deleteGoogleFile(fileName3, apiKey, fetchImpl) {
|
|
13084
13425
|
try {
|
|
13085
|
-
await fetchImpl(`${GOOGLE_FILES_BASE}/v1beta/${
|
|
13426
|
+
await fetchImpl(`${GOOGLE_FILES_BASE}/v1beta/${fileName3}`, {
|
|
13086
13427
|
method: "DELETE",
|
|
13087
13428
|
headers: { "x-goog-api-key": apiKey }
|
|
13088
13429
|
});
|
|
@@ -13162,7 +13503,7 @@ var OMNI_POLL_INTERVAL_MS = 1e4;
|
|
|
13162
13503
|
var RESULT_TIMEOUT_MS3 = 15 * 60 * 1e3;
|
|
13163
13504
|
var OMNI_INLINE_LIMIT_BYTES = 4 * 1024 * 1024;
|
|
13164
13505
|
var MEDIA_PART_INLINE_LIMIT_BYTES = 10 * 1024 * 1024;
|
|
13165
|
-
var errorTextSchema =
|
|
13506
|
+
var errorTextSchema = z24.string();
|
|
13166
13507
|
function isGoogleGenaiVideoKnown(providerModelId) {
|
|
13167
13508
|
return providerModelId.startsWith("veo-") || providerModelId.startsWith("gemini-omni");
|
|
13168
13509
|
}
|
|
@@ -13357,7 +13698,7 @@ async function generateVeoVideo(req, ctx, createGenAIClient) {
|
|
|
13357
13698
|
}
|
|
13358
13699
|
};
|
|
13359
13700
|
const jobId = operation.name ?? crypto.randomUUID();
|
|
13360
|
-
const
|
|
13701
|
+
const usage5 = videoUsage2(ctx, duration, req.resolution ?? "720p");
|
|
13361
13702
|
return {
|
|
13362
13703
|
jobId,
|
|
13363
13704
|
async poll() {
|
|
@@ -13395,7 +13736,7 @@ async function generateVeoVideo(req, ctx, createGenAIClient) {
|
|
|
13395
13736
|
modelId
|
|
13396
13737
|
);
|
|
13397
13738
|
}
|
|
13398
|
-
return { video: await downloadVideo(ctx, uri, apiKey, signal), usage:
|
|
13739
|
+
return { video: await downloadVideo(ctx, uri, apiKey, signal), usage: usage5, raw: finished };
|
|
13399
13740
|
}
|
|
13400
13741
|
};
|
|
13401
13742
|
}
|
|
@@ -13506,7 +13847,7 @@ async function generateOmniVideo(req, ctx, createGenAIClient) {
|
|
|
13506
13847
|
return file.fileUri;
|
|
13507
13848
|
};
|
|
13508
13849
|
const cleanupUploads = async () => {
|
|
13509
|
-
for (const
|
|
13850
|
+
for (const fileName3 of uploadedNames) await deleteGoogleFile(fileName3, apiKey, ctx.fetch);
|
|
13510
13851
|
};
|
|
13511
13852
|
const callCreate = (input) => client2.interactions.create(
|
|
13512
13853
|
previousId !== void 0 ? {
|
|
@@ -13600,7 +13941,7 @@ async function generateOmniVideo(req, ctx, createGenAIClient) {
|
|
|
13600
13941
|
if (!(extend && !chained)) await cleanupUploads();
|
|
13601
13942
|
}
|
|
13602
13943
|
const jobId = interaction.id ?? crypto.randomUUID();
|
|
13603
|
-
const
|
|
13944
|
+
const usage5 = videoUsage2(ctx, duration, omniResolution ?? "720p");
|
|
13604
13945
|
const getInteraction = async () => {
|
|
13605
13946
|
try {
|
|
13606
13947
|
const getParams = { stream: false };
|
|
@@ -13648,7 +13989,7 @@ async function generateOmniVideo(req, ctx, createGenAIClient) {
|
|
|
13648
13989
|
bytes: Buffer.from(video.data, "base64"),
|
|
13649
13990
|
mime: video.mime_type ?? "video/mp4"
|
|
13650
13991
|
},
|
|
13651
|
-
usage:
|
|
13992
|
+
usage: usage5,
|
|
13652
13993
|
raw: done,
|
|
13653
13994
|
providerRef
|
|
13654
13995
|
};
|
|
@@ -13656,7 +13997,7 @@ async function generateOmniVideo(req, ctx, createGenAIClient) {
|
|
|
13656
13997
|
if (video.uri)
|
|
13657
13998
|
return {
|
|
13658
13999
|
video: await downloadVideo(ctx, video.uri, apiKey, signal),
|
|
13659
|
-
usage:
|
|
14000
|
+
usage: usage5,
|
|
13660
14001
|
raw: done,
|
|
13661
14002
|
providerRef
|
|
13662
14003
|
};
|
|
@@ -13826,15 +14167,15 @@ async function prepareGoogleMediaPart(ref, mediaType, ctx) {
|
|
|
13826
14167
|
// src/adapters/google-image.ts
|
|
13827
14168
|
import { createGoogleGenerativeAI as createGoogleGenerativeAI2 } from "@ai-sdk/google";
|
|
13828
14169
|
import { generateText } from "ai";
|
|
13829
|
-
import { z as
|
|
14170
|
+
import { z as z25 } from "zod";
|
|
13830
14171
|
var GEMINI_IMAGE_TIMEOUT_MS = 6e5;
|
|
13831
14172
|
var defaultGoogleImageDeps = {
|
|
13832
14173
|
createGoogleClient: (opts) => createGoogleGenerativeAI2(opts),
|
|
13833
14174
|
runTextGeneration: (opts) => generateText(opts)
|
|
13834
14175
|
};
|
|
13835
|
-
var causeChainNodeSchema =
|
|
13836
|
-
message:
|
|
13837
|
-
cause:
|
|
14176
|
+
var causeChainNodeSchema = z25.object({
|
|
14177
|
+
message: z25.string().optional(),
|
|
14178
|
+
cause: z25.unknown().optional()
|
|
13838
14179
|
});
|
|
13839
14180
|
function extractBlockReason(cause) {
|
|
13840
14181
|
let current = cause;
|
|
@@ -13934,7 +14275,7 @@ function createGoogleImageAdapter(deps = defaultGoogleImageDeps) {
|
|
|
13934
14275
|
retryable: false
|
|
13935
14276
|
});
|
|
13936
14277
|
}
|
|
13937
|
-
const
|
|
14278
|
+
const usage5 = {
|
|
13938
14279
|
model: ctx.model.id,
|
|
13939
14280
|
provider: "google-image",
|
|
13940
14281
|
modality: "IMAGE",
|
|
@@ -13942,19 +14283,19 @@ function createGoogleImageAdapter(deps = defaultGoogleImageDeps) {
|
|
|
13942
14283
|
quantity: images.length,
|
|
13943
14284
|
imageQuality: "auto"
|
|
13944
14285
|
};
|
|
13945
|
-
if (req.size !== void 0)
|
|
14286
|
+
if (req.size !== void 0) usage5.imageSize = req.size;
|
|
13946
14287
|
if (result.usage?.inputTokens !== void 0)
|
|
13947
|
-
|
|
14288
|
+
usage5.inputTokens = result.usage.inputTokens;
|
|
13948
14289
|
if (result.usage?.outputTokens !== void 0)
|
|
13949
|
-
|
|
13950
|
-
return { images, usage:
|
|
14290
|
+
usage5.outputTokens = result.usage.outputTokens;
|
|
14291
|
+
return { images, usage: usage5, raw: result };
|
|
13951
14292
|
}
|
|
13952
14293
|
};
|
|
13953
14294
|
}
|
|
13954
14295
|
var googleImageAdapter = createGoogleImageAdapter();
|
|
13955
14296
|
|
|
13956
14297
|
// src/adapters/higgsfield.ts
|
|
13957
|
-
import { z as
|
|
14298
|
+
import { z as z26 } from "zod";
|
|
13958
14299
|
|
|
13959
14300
|
// src/adapters/higgsfield-motions.ts
|
|
13960
14301
|
var MOTION_MAP = {
|
|
@@ -14173,14 +14514,14 @@ function klingEndpointFields(providerModelId) {
|
|
|
14173
14514
|
const path = (providerModelId.startsWith("/") ? providerModelId.slice(1) : providerModelId).toLowerCase();
|
|
14174
14515
|
return KLING_ENDPOINT_FIELDS.get(path) ?? UNLISTED_KLING_FIELDS;
|
|
14175
14516
|
}
|
|
14176
|
-
var klingCreateSchema =
|
|
14177
|
-
var klingStatusSchema =
|
|
14178
|
-
status:
|
|
14179
|
-
video:
|
|
14517
|
+
var klingCreateSchema = z26.object({ status_url: z26.string() });
|
|
14518
|
+
var klingStatusSchema = z26.object({
|
|
14519
|
+
status: z26.string().optional(),
|
|
14520
|
+
video: z26.object({ url: z26.string().optional() }).optional(),
|
|
14180
14521
|
error: JsonValueSchema.optional()
|
|
14181
14522
|
});
|
|
14182
|
-
var errorMessageSchema =
|
|
14183
|
-
var textValueSchema =
|
|
14523
|
+
var errorMessageSchema = z26.object({ message: z26.string().optional() });
|
|
14524
|
+
var textValueSchema = z26.string();
|
|
14184
14525
|
function klingErrorDetail(error) {
|
|
14185
14526
|
if (error === void 0) return "unknown_error";
|
|
14186
14527
|
const asText = textValueSchema.safeParse(error);
|
|
@@ -14336,8 +14677,8 @@ async function generateKlingVideo(req, ctx) {
|
|
|
14336
14677
|
}
|
|
14337
14678
|
};
|
|
14338
14679
|
}
|
|
14339
|
-
var dopMotionOptionsSchema =
|
|
14340
|
-
modelkit:
|
|
14680
|
+
var dopMotionOptionsSchema = z26.object({
|
|
14681
|
+
modelkit: z26.object({ motion: z26.string().optional() }).optional()
|
|
14341
14682
|
});
|
|
14342
14683
|
function dopMotionId(ctx) {
|
|
14343
14684
|
const parsed = dopMotionOptionsSchema.safeParse(ctx.model.providerOptions);
|
|
@@ -14353,7 +14694,7 @@ function dopMotionId(ctx) {
|
|
|
14353
14694
|
});
|
|
14354
14695
|
return id;
|
|
14355
14696
|
}
|
|
14356
|
-
var jsonRecordSchema =
|
|
14697
|
+
var jsonRecordSchema = z26.record(z26.string(), JsonValueSchema);
|
|
14357
14698
|
var DOP_URL_KEYS = ["url", "video_url", "output_url", "result_url", "download_url"];
|
|
14358
14699
|
var DOP_NESTED_KEYS = ["video", "result", "results"];
|
|
14359
14700
|
function dopUrl(body) {
|
|
@@ -14381,8 +14722,8 @@ function dopUrl(body) {
|
|
|
14381
14722
|
}
|
|
14382
14723
|
return void 0;
|
|
14383
14724
|
}
|
|
14384
|
-
var dopCreateSchema =
|
|
14385
|
-
var dopStatusSchema =
|
|
14725
|
+
var dopCreateSchema = z26.object({ id: z26.string() });
|
|
14726
|
+
var dopStatusSchema = z26.object({ status: z26.string().optional() });
|
|
14386
14727
|
async function generateDopVideo(req, ctx) {
|
|
14387
14728
|
const firstFrame = req.firstFrame ? refToUrl(req.firstFrame) : void 0;
|
|
14388
14729
|
if (!firstFrame) {
|
|
@@ -14509,7 +14850,7 @@ var higgsfieldAdapter = {
|
|
|
14509
14850
|
};
|
|
14510
14851
|
|
|
14511
14852
|
// src/adapters/luma.ts
|
|
14512
|
-
import { z as
|
|
14853
|
+
import { z as z27 } from "zod";
|
|
14513
14854
|
|
|
14514
14855
|
// src/adapters/mp4-duration.ts
|
|
14515
14856
|
function mp4DurationSeconds(bytes) {
|
|
@@ -14565,7 +14906,7 @@ function findBox(bytes, from, to, type) {
|
|
|
14565
14906
|
}
|
|
14566
14907
|
|
|
14567
14908
|
// src/adapters/luma.ts
|
|
14568
|
-
var
|
|
14909
|
+
var DEFAULT_BASE_URL3 = "https://agents.lumalabs.ai";
|
|
14569
14910
|
var IMAGE_POLL_INTERVAL_MS = 3e3;
|
|
14570
14911
|
var IMAGE_TIMEOUT_MS = 5 * 6e4;
|
|
14571
14912
|
var VIDEO_POLL_INTERVAL_MS = 5e3;
|
|
@@ -14594,7 +14935,7 @@ function lumaModel(ctx) {
|
|
|
14594
14935
|
return ctx.model.providerModelId.toLowerCase();
|
|
14595
14936
|
}
|
|
14596
14937
|
function lumaBase(ctx) {
|
|
14597
|
-
return ctx.endpoints?.luma ??
|
|
14938
|
+
return ctx.endpoints?.luma ?? DEFAULT_BASE_URL3;
|
|
14598
14939
|
}
|
|
14599
14940
|
function lumaKey(ctx) {
|
|
14600
14941
|
const key = ctx.keys.luma;
|
|
@@ -14726,17 +15067,17 @@ function lumaReframeResolution(req, ctx) {
|
|
|
14726
15067
|
});
|
|
14727
15068
|
return "720p";
|
|
14728
15069
|
}
|
|
14729
|
-
var lumaGenerationSchema =
|
|
14730
|
-
id:
|
|
14731
|
-
state:
|
|
14732
|
-
output:
|
|
14733
|
-
|
|
14734
|
-
type:
|
|
14735
|
-
url:
|
|
15070
|
+
var lumaGenerationSchema = z27.looseObject({
|
|
15071
|
+
id: z27.string(),
|
|
15072
|
+
state: z27.string().optional(),
|
|
15073
|
+
output: z27.array(
|
|
15074
|
+
z27.looseObject({
|
|
15075
|
+
type: z27.string().optional(),
|
|
15076
|
+
url: z27.string().optional()
|
|
14736
15077
|
})
|
|
14737
15078
|
).optional(),
|
|
14738
|
-
failure_reason:
|
|
14739
|
-
failure_code:
|
|
15079
|
+
failure_reason: z27.string().optional().nullable(),
|
|
15080
|
+
failure_code: z27.string().optional().nullable()
|
|
14740
15081
|
});
|
|
14741
15082
|
function lumaFailure(ctx, code, reason) {
|
|
14742
15083
|
const detail = reason ?? code ?? "unknown_error";
|
|
@@ -15168,7 +15509,7 @@ var lumaAdapter = {
|
|
|
15168
15509
|
|
|
15169
15510
|
// src/adapters/openai-image.ts
|
|
15170
15511
|
import OpenAI from "openai";
|
|
15171
|
-
import { z as
|
|
15512
|
+
import { z as z28 } from "zod";
|
|
15172
15513
|
var MAX_EDIT_REFERENCES = 16;
|
|
15173
15514
|
function aspectRatioToSize(ratio, tier) {
|
|
15174
15515
|
const TIER_LONG_EDGE = {
|
|
@@ -15251,9 +15592,9 @@ function toProviderError2(cause, ctx) {
|
|
|
15251
15592
|
ctx.model.id
|
|
15252
15593
|
);
|
|
15253
15594
|
}
|
|
15254
|
-
var openaiUsageSchema =
|
|
15255
|
-
input_tokens:
|
|
15256
|
-
output_tokens:
|
|
15595
|
+
var openaiUsageSchema = z28.object({
|
|
15596
|
+
input_tokens: z28.number().optional(),
|
|
15597
|
+
output_tokens: z28.number().optional()
|
|
15257
15598
|
});
|
|
15258
15599
|
var openaiImageAdapter = {
|
|
15259
15600
|
id: "openai-image",
|
|
@@ -15378,7 +15719,7 @@ var openaiImageAdapter = {
|
|
|
15378
15719
|
const usageParsed = openaiUsageSchema.safeParse(response.usage);
|
|
15379
15720
|
const inputTokens = usageParsed.success ? usageParsed.data.input_tokens : void 0;
|
|
15380
15721
|
const outputTokens = usageParsed.success ? usageParsed.data.output_tokens : void 0;
|
|
15381
|
-
const
|
|
15722
|
+
const usage5 = {
|
|
15382
15723
|
model: ctx.model.id,
|
|
15383
15724
|
provider: "openai-image",
|
|
15384
15725
|
modality: "IMAGE",
|
|
@@ -15386,10 +15727,10 @@ var openaiImageAdapter = {
|
|
|
15386
15727
|
quantity: images.length,
|
|
15387
15728
|
imageQuality: quality
|
|
15388
15729
|
};
|
|
15389
|
-
if (inputTokens !== void 0)
|
|
15390
|
-
if (outputTokens !== void 0)
|
|
15391
|
-
if (req.size !== void 0)
|
|
15392
|
-
return { images, usage:
|
|
15730
|
+
if (inputTokens !== void 0) usage5.inputTokens = inputTokens;
|
|
15731
|
+
if (outputTokens !== void 0) usage5.outputTokens = outputTokens;
|
|
15732
|
+
if (req.size !== void 0) usage5.imageSize = req.size;
|
|
15733
|
+
return { images, usage: usage5, raw: response };
|
|
15393
15734
|
}
|
|
15394
15735
|
};
|
|
15395
15736
|
|
|
@@ -15645,16 +15986,16 @@ async function generateProdiaImage(req, ctx) {
|
|
|
15645
15986
|
new Uint8Array(await res.arrayBuffer()),
|
|
15646
15987
|
res.headers.get("content-type")
|
|
15647
15988
|
);
|
|
15648
|
-
const
|
|
15989
|
+
const usage5 = {
|
|
15649
15990
|
model: ctx.model.id,
|
|
15650
15991
|
provider: "prodia",
|
|
15651
15992
|
modality: "IMAGE",
|
|
15652
15993
|
unit: "images",
|
|
15653
15994
|
quantity: 1
|
|
15654
15995
|
};
|
|
15655
|
-
if (req.size !== void 0)
|
|
15656
|
-
if (req.quality !== void 0)
|
|
15657
|
-
return { images: [{ bytes, mime }], usage:
|
|
15996
|
+
if (req.size !== void 0) usage5.imageSize = req.size;
|
|
15997
|
+
if (req.quality !== void 0) usage5.imageQuality = req.quality;
|
|
15998
|
+
return { images: [{ bytes, mime }], usage: usage5, raw: void 0 };
|
|
15658
15999
|
}
|
|
15659
16000
|
var prodiaAdapter = {
|
|
15660
16001
|
id: "prodia",
|
|
@@ -15665,13 +16006,13 @@ var prodiaAdapter = {
|
|
|
15665
16006
|
import Replicate from "replicate";
|
|
15666
16007
|
|
|
15667
16008
|
// src/adapters/replicate-http.ts
|
|
15668
|
-
import { z as
|
|
15669
|
-
var predictionSchema =
|
|
15670
|
-
id:
|
|
15671
|
-
status:
|
|
16009
|
+
import { z as z29 } from "zod";
|
|
16010
|
+
var predictionSchema = z29.object({
|
|
16011
|
+
id: z29.string(),
|
|
16012
|
+
status: z29.string(),
|
|
15672
16013
|
output: JsonValueSchema.optional(),
|
|
15673
16014
|
error: JsonValueSchema.optional(),
|
|
15674
|
-
metrics:
|
|
16015
|
+
metrics: z29.object({ predict_time: z29.number().optional() }).optional()
|
|
15675
16016
|
});
|
|
15676
16017
|
function createReplicateHttpClient(opts) {
|
|
15677
16018
|
async function request(path, body, signal) {
|
|
@@ -15722,7 +16063,7 @@ function createReplicateHttpClient(opts) {
|
|
|
15722
16063
|
}
|
|
15723
16064
|
|
|
15724
16065
|
// src/adapters/replicate.ts
|
|
15725
|
-
import { z as
|
|
16066
|
+
import { z as z30 } from "zod";
|
|
15726
16067
|
var POLL_INTERVAL_MS = 1e3;
|
|
15727
16068
|
var POLL_TIMEOUT_MS = 15 * 6e4;
|
|
15728
16069
|
var defaultReplicateDeps = {
|
|
@@ -15762,8 +16103,8 @@ function route(providerModelId) {
|
|
|
15762
16103
|
if (!providerModelId.includes("/")) return { version: providerModelId };
|
|
15763
16104
|
return { model: providerModelId };
|
|
15764
16105
|
}
|
|
15765
|
-
var replicateResponseStatusSchema =
|
|
15766
|
-
response:
|
|
16106
|
+
var replicateResponseStatusSchema = z30.object({
|
|
16107
|
+
response: z30.object({ status: z30.number() }).partial()
|
|
15767
16108
|
});
|
|
15768
16109
|
function replicateError(cause, ctx) {
|
|
15769
16110
|
if (isModelKitError(cause)) return cause;
|
|
@@ -15786,7 +16127,7 @@ function isUrlFn(value) {
|
|
|
15786
16127
|
function extractOutputUrl(output) {
|
|
15787
16128
|
const root = Array.isArray(output) ? output[0] : output;
|
|
15788
16129
|
if (root === void 0) throw noOutput();
|
|
15789
|
-
const asString =
|
|
16130
|
+
const asString = z30.string().safeParse(root);
|
|
15790
16131
|
if (asString.success && asString.data) return asString.data;
|
|
15791
16132
|
if (root instanceof URL) return root.href;
|
|
15792
16133
|
if (isObjectOutput(root)) {
|
|
@@ -15795,15 +16136,15 @@ function extractOutputUrl(output) {
|
|
|
15795
16136
|
if (urlValue !== void 0 && isUrlFn(urlValue)) {
|
|
15796
16137
|
const called = urlValue();
|
|
15797
16138
|
if (called instanceof URL) return called.href;
|
|
15798
|
-
const calledString =
|
|
16139
|
+
const calledString = z30.string().safeParse(called);
|
|
15799
16140
|
if (calledString.success && calledString.data) return calledString.data;
|
|
15800
16141
|
} else {
|
|
15801
|
-
const direct =
|
|
16142
|
+
const direct = z30.string().safeParse(urlValue);
|
|
15802
16143
|
if (direct.success && direct.data) return direct.data;
|
|
15803
16144
|
}
|
|
15804
16145
|
}
|
|
15805
16146
|
if ("default" in root) {
|
|
15806
|
-
const fallback =
|
|
16147
|
+
const fallback = z30.string().safeParse(root.default);
|
|
15807
16148
|
if (fallback.success && fallback.data) return fallback.data;
|
|
15808
16149
|
}
|
|
15809
16150
|
}
|
|
@@ -15864,7 +16205,7 @@ async function runPrediction(ctx, input, deps) {
|
|
|
15864
16205
|
}
|
|
15865
16206
|
return void 0;
|
|
15866
16207
|
}, pollOpts);
|
|
15867
|
-
const predictTime =
|
|
16208
|
+
const predictTime = z30.number().safeParse(done.metrics?.predict_time);
|
|
15868
16209
|
if (done.output === void 0) throw noOutput();
|
|
15869
16210
|
return {
|
|
15870
16211
|
url: extractOutputUrl(done.output),
|
|
@@ -16110,9 +16451,9 @@ async function generateReplicateImage(req, ctx, deps) {
|
|
|
16110
16451
|
}
|
|
16111
16452
|
const { url, predictTime, raw } = await runPrediction(ctx, input, deps);
|
|
16112
16453
|
const file = await download(ctx, url);
|
|
16113
|
-
const
|
|
16114
|
-
|
|
16115
|
-
return { images: [{ bytes: file.bytes, mime: file.mime }], usage:
|
|
16454
|
+
const usage5 = imageUsage3(ctx, req);
|
|
16455
|
+
usage5.quantity = predictTime;
|
|
16456
|
+
return { images: [{ bytes: file.bytes, mime: file.mime }], usage: usage5, raw, outputUrl: url };
|
|
16116
16457
|
}
|
|
16117
16458
|
function klingInput(req) {
|
|
16118
16459
|
const images = (req.firstFrame ? [req.firstFrame] : []).map(refToUrl);
|
|
@@ -16217,7 +16558,7 @@ async function generateReplicateVideo(req, ctx, deps) {
|
|
|
16217
16558
|
throw replicateError(cause, ctx);
|
|
16218
16559
|
}
|
|
16219
16560
|
if (current.status === "succeeded") {
|
|
16220
|
-
const predictTime =
|
|
16561
|
+
const predictTime = z30.number().safeParse(current.metrics?.predict_time);
|
|
16221
16562
|
if (current.output === void 0) throw noOutput();
|
|
16222
16563
|
return {
|
|
16223
16564
|
url: extractOutputUrl(current.output),
|
|
@@ -16236,9 +16577,9 @@ async function generateReplicateVideo(req, ctx, deps) {
|
|
|
16236
16577
|
return void 0;
|
|
16237
16578
|
};
|
|
16238
16579
|
const toResult = (done) => {
|
|
16239
|
-
const
|
|
16240
|
-
|
|
16241
|
-
return { video: { url: done.url }, usage:
|
|
16580
|
+
const usage5 = videoUsage5(ctx, req);
|
|
16581
|
+
usage5.quantity = done.predictTime;
|
|
16582
|
+
return { video: { url: done.url }, usage: usage5, raw: done.raw };
|
|
16242
16583
|
};
|
|
16243
16584
|
return {
|
|
16244
16585
|
jobId,
|
|
@@ -16345,21 +16686,21 @@ async function generateReplicateAudio(req, ctx, deps) {
|
|
|
16345
16686
|
input = specResult.input;
|
|
16346
16687
|
}
|
|
16347
16688
|
const { url, predictTime, raw } = await runPrediction(ctx, input, deps);
|
|
16348
|
-
const
|
|
16689
|
+
const usage5 = audioUsage(ctx, req);
|
|
16349
16690
|
if (ctx.model.usage.unit === "seconds") {
|
|
16350
16691
|
const seconds3 = elevenLabsMusicDuration(req.durationSeconds);
|
|
16351
|
-
|
|
16352
|
-
|
|
16692
|
+
usage5.quantity = seconds3;
|
|
16693
|
+
usage5.durationSeconds = seconds3;
|
|
16353
16694
|
} else {
|
|
16354
|
-
|
|
16695
|
+
usage5.quantity = predictTime;
|
|
16355
16696
|
}
|
|
16356
|
-
return { audio: { url }, usage:
|
|
16697
|
+
return { audio: { url }, usage: usage5, raw: predictionRaw(raw) };
|
|
16357
16698
|
}
|
|
16358
16699
|
|
|
16359
16700
|
// src/adapters/xai-video.ts
|
|
16360
16701
|
import { experimental_generateVideo } from "ai";
|
|
16361
16702
|
import { createXai as createXai2 } from "@ai-sdk/xai";
|
|
16362
|
-
import { z as
|
|
16703
|
+
import { z as z31 } from "zod";
|
|
16363
16704
|
var POLL_INTERVAL_MS2 = 1e4;
|
|
16364
16705
|
var POLL_TIMEOUT_MS2 = 15 * 6e4;
|
|
16365
16706
|
var defaultXaiDeps = {
|
|
@@ -16372,8 +16713,8 @@ function createXaiVideoAdapter(deps = defaultXaiDeps) {
|
|
|
16372
16713
|
};
|
|
16373
16714
|
}
|
|
16374
16715
|
var xaiVideoAdapter = createXaiVideoAdapter();
|
|
16375
|
-
var xaiResponseStatusSchema =
|
|
16376
|
-
response:
|
|
16716
|
+
var xaiResponseStatusSchema = z31.object({
|
|
16717
|
+
response: z31.object({ status: z31.number() }).partial()
|
|
16377
16718
|
});
|
|
16378
16719
|
function xaiError(cause, ctx) {
|
|
16379
16720
|
const info = describeThrown(cause);
|
|
@@ -16381,12 +16722,12 @@ function xaiError(cause, ctx) {
|
|
|
16381
16722
|
const status = info.status ?? (nested.success ? nested.data.response?.status : void 0);
|
|
16382
16723
|
return classifyThrown("xai-video", cause, ctx.model.id, { status, body: info.body });
|
|
16383
16724
|
}
|
|
16384
|
-
var xaiMetaSchema =
|
|
16725
|
+
var xaiMetaSchema = z31.object({
|
|
16385
16726
|
videoUrl: JsonValueSchema.optional(),
|
|
16386
16727
|
costInUsdTicks: JsonValueSchema.optional(),
|
|
16387
16728
|
duration: JsonValueSchema.optional()
|
|
16388
16729
|
});
|
|
16389
|
-
var xaiProviderMetadataSchema =
|
|
16730
|
+
var xaiProviderMetadataSchema = z31.object({ xai: xaiMetaSchema });
|
|
16390
16731
|
function metaOf(result) {
|
|
16391
16732
|
const parsed = xaiProviderMetadataSchema.partial().safeParse(result.providerMetadata);
|
|
16392
16733
|
if (!parsed.success) return {};
|
|
@@ -16498,12 +16839,12 @@ async function mapResult(ctx, req, result) {
|
|
|
16498
16839
|
if (first) {
|
|
16499
16840
|
return {
|
|
16500
16841
|
video: { bytes: Uint8Array.from(first.uint8Array), mime: first.mediaType },
|
|
16501
|
-
usage:
|
|
16842
|
+
usage: usage4(ctx, req, metaOf(result)),
|
|
16502
16843
|
raw: result.providerMetadata
|
|
16503
16844
|
};
|
|
16504
16845
|
}
|
|
16505
16846
|
const meta = metaOf(result);
|
|
16506
|
-
const videoUrl =
|
|
16847
|
+
const videoUrl = z31.string().safeParse(meta.videoUrl);
|
|
16507
16848
|
if (videoUrl.success && videoUrl.data) {
|
|
16508
16849
|
const res = await ctx.fetch(videoUrl.data);
|
|
16509
16850
|
if (!res.ok) {
|
|
@@ -16513,7 +16854,7 @@ async function mapResult(ctx, req, result) {
|
|
|
16513
16854
|
const mime = res.headers.get("content-type") ?? "video/mp4";
|
|
16514
16855
|
return {
|
|
16515
16856
|
video: { bytes: new Uint8Array(await res.arrayBuffer()), mime },
|
|
16516
|
-
usage:
|
|
16857
|
+
usage: usage4(ctx, req, meta),
|
|
16517
16858
|
raw: result.providerMetadata
|
|
16518
16859
|
};
|
|
16519
16860
|
}
|
|
@@ -16525,8 +16866,8 @@ async function mapResult(ctx, req, result) {
|
|
|
16525
16866
|
retryable: false
|
|
16526
16867
|
});
|
|
16527
16868
|
}
|
|
16528
|
-
function
|
|
16529
|
-
const costTicks =
|
|
16869
|
+
function usage4(ctx, req, meta) {
|
|
16870
|
+
const costTicks = z31.number().safeParse(meta.costInUsdTicks);
|
|
16530
16871
|
const cost = costTicks.success ? costTicks.data / 1e10 : void 0;
|
|
16531
16872
|
const event = {
|
|
16532
16873
|
model: ctx.model.id,
|
|
@@ -16566,7 +16907,8 @@ var DEFAULT_ADAPTERS = {
|
|
|
16566
16907
|
higgsfield: higgsfieldAdapter,
|
|
16567
16908
|
"xai-video": xaiVideoAdapter,
|
|
16568
16909
|
luma: lumaAdapter,
|
|
16569
|
-
fish: fishAdapter
|
|
16910
|
+
fish: fishAdapter,
|
|
16911
|
+
elevenlabs: elevenLabsAdapter
|
|
16570
16912
|
};
|
|
16571
16913
|
|
|
16572
16914
|
// src/catalog/data-only.ts
|
|
@@ -16605,15 +16947,15 @@ var FAL_NODE_TYPES = /* @__PURE__ */ new Set([
|
|
|
16605
16947
|
"transcription",
|
|
16606
16948
|
"mask"
|
|
16607
16949
|
]);
|
|
16608
|
-
function
|
|
16609
|
-
return row2.adapter === "fish" && row2.type === "speech";
|
|
16950
|
+
function directSpeech(row2) {
|
|
16951
|
+
return (row2.adapter === "fish" || row2.adapter === "elevenlabs") && row2.type === "speech";
|
|
16610
16952
|
}
|
|
16611
16953
|
function dataOnlyCapable(row2) {
|
|
16612
16954
|
const adapter = DEFAULT_ADAPTERS[row2.adapter];
|
|
16613
16955
|
if (!adapterServesType(adapter, row2.type)) {
|
|
16614
16956
|
return { ok: false, reason: `${row2.adapter} cannot serve ${row2.type} rows` };
|
|
16615
16957
|
}
|
|
16616
|
-
if (FAL_NODE_TYPES.has(row2.type) && row2.adapter !== "fal" && !
|
|
16958
|
+
if (FAL_NODE_TYPES.has(row2.type) && row2.adapter !== "fal" && !directSpeech(row2)) {
|
|
16617
16959
|
return { ok: false, reason: `only fal serves ${row2.type} rows` };
|
|
16618
16960
|
}
|
|
16619
16961
|
switch (row2.adapter) {
|
|
@@ -16695,6 +17037,10 @@ function dataOnlyCapable(row2) {
|
|
|
16695
17037
|
const reason = fishRowRefusal(row2);
|
|
16696
17038
|
return reason === void 0 ? { ok: true } : { ok: false, reason };
|
|
16697
17039
|
}
|
|
17040
|
+
case "elevenlabs": {
|
|
17041
|
+
const reason = elevenLabsRowRefusal(row2);
|
|
17042
|
+
return reason === void 0 ? { ok: true } : { ok: false, reason };
|
|
17043
|
+
}
|
|
16698
17044
|
default: {
|
|
16699
17045
|
return assertNever(row2.adapter);
|
|
16700
17046
|
}
|
|
@@ -16714,22 +17060,22 @@ var liveState = store[KEY] ??= {
|
|
|
16714
17060
|
var liveCatalog = liveState.catalog;
|
|
16715
17061
|
|
|
16716
17062
|
// src/catalog/load.ts
|
|
16717
|
-
import { z as
|
|
17063
|
+
import { z as z32 } from "zod";
|
|
16718
17064
|
function rowCount() {
|
|
16719
17065
|
return liveCatalog.list({ lifecycle: ["active", "deprecated", "retired"] }).length;
|
|
16720
17066
|
}
|
|
16721
17067
|
function authHeaders(auth) {
|
|
16722
17068
|
return "bearer" in auth ? { Authorization: `Bearer ${auth.bearer}` } : { "x-api-key": auth.apiKey };
|
|
16723
17069
|
}
|
|
16724
|
-
var EnvelopeSchema =
|
|
16725
|
-
rows:
|
|
16726
|
-
revision:
|
|
17070
|
+
var EnvelopeSchema = z32.object({
|
|
17071
|
+
rows: z32.array(JsonValueSchema),
|
|
17072
|
+
revision: z32.string().optional()
|
|
16727
17073
|
});
|
|
16728
17074
|
function dropReason(path, message) {
|
|
16729
17075
|
return path.length === 0 ? message : `${path.map((part) => String(part)).join(".")} ${message}`;
|
|
16730
17076
|
}
|
|
16731
17077
|
function rowId(raw) {
|
|
16732
|
-
const parsed =
|
|
17078
|
+
const parsed = z32.object({ id: z32.string().min(1) }).loose().safeParse(raw);
|
|
16733
17079
|
if (!parsed.success) return "?";
|
|
16734
17080
|
return parsed.data.id;
|
|
16735
17081
|
}
|
|
@@ -17890,7 +18236,8 @@ var ADAPTER_KEYS = {
|
|
|
17890
18236
|
higgsfield: ["higgsfield"],
|
|
17891
18237
|
"xai-video": ["xai"],
|
|
17892
18238
|
luma: ["luma"],
|
|
17893
|
-
fish: ["fish"]
|
|
18239
|
+
fish: ["fish"],
|
|
18240
|
+
elevenlabs: ["elevenlabs"]
|
|
17894
18241
|
};
|
|
17895
18242
|
function hasAll(keys, names) {
|
|
17896
18243
|
if (!keys) return false;
|
|
@@ -17950,6 +18297,7 @@ function keysFromEnv(env, prefix = "") {
|
|
|
17950
18297
|
set("higgsfieldSecret", pick2("HIGGSFIELD_API_SECRET"));
|
|
17951
18298
|
set("luma", pick2("LUMA_API_KEY", "LUMA_AGENTS_API_KEY"));
|
|
17952
18299
|
set("fish", pick2("FISH_AUDIO_API_KEY"));
|
|
18300
|
+
set("elevenlabs", pick2("ELEVENLABS_API_KEY"));
|
|
17953
18301
|
set("cloudflare", pick2("CLOUDFLARE_AI_GATEWAY_TOKEN", "CF_AIG_TOKEN"));
|
|
17954
18302
|
const bearer = pick2("AWS_BEARER_TOKEN_BEDROCK");
|
|
17955
18303
|
const accessKeyId = pick2("AWS_ACCESS_KEY_ID");
|
|
@@ -17972,7 +18320,7 @@ function keysFromEnv(env, prefix = "") {
|
|
|
17972
18320
|
|
|
17973
18321
|
// src/text.ts
|
|
17974
18322
|
import "ai";
|
|
17975
|
-
import { z as
|
|
18323
|
+
import { z as z33 } from "zod";
|
|
17976
18324
|
function mergeTextProviderOptions(catalog, caller) {
|
|
17977
18325
|
const merged = {};
|
|
17978
18326
|
const catalogOptions = catalog.providerOptions ?? {};
|
|
@@ -18011,17 +18359,17 @@ function passthroughTextModel(model) {
|
|
|
18011
18359
|
pricingKind: "token"
|
|
18012
18360
|
};
|
|
18013
18361
|
}
|
|
18014
|
-
var perplexityCostSchema =
|
|
18015
|
-
perplexity:
|
|
18362
|
+
var perplexityCostSchema = z33.object({
|
|
18363
|
+
perplexity: z33.object({ cost: z33.object({ totalCost: z33.number().finite().nonnegative() }) })
|
|
18016
18364
|
});
|
|
18017
18365
|
function reportedCostUsd(metadata) {
|
|
18018
18366
|
const parsed = perplexityCostSchema.safeParse(metadata);
|
|
18019
18367
|
return parsed.success ? parsed.data.perplexity.cost.totalCost : void 0;
|
|
18020
18368
|
}
|
|
18021
|
-
function textUsageEvent(model, provider,
|
|
18022
|
-
const inputTokens =
|
|
18023
|
-
const outputTokens =
|
|
18024
|
-
const total =
|
|
18369
|
+
function textUsageEvent(model, provider, usage5, providerMetadata) {
|
|
18370
|
+
const inputTokens = usage5.inputTokens ?? 0;
|
|
18371
|
+
const outputTokens = usage5.outputTokens ?? 0;
|
|
18372
|
+
const total = usage5.totalTokens ?? inputTokens + outputTokens;
|
|
18025
18373
|
const event = {
|
|
18026
18374
|
model: model.id,
|
|
18027
18375
|
provider,
|
|
@@ -18056,7 +18404,7 @@ function createTextSteps(initial, resolve, callerProviderOptions) {
|
|
|
18056
18404
|
return { ...prepared, providerOptions };
|
|
18057
18405
|
};
|
|
18058
18406
|
}
|
|
18059
|
-
function
|
|
18407
|
+
function usage5(results) {
|
|
18060
18408
|
const grouped = /* @__PURE__ */ new Map();
|
|
18061
18409
|
for (const [index, step] of results.entries()) {
|
|
18062
18410
|
const target = steps.get(index) ?? initial;
|
|
@@ -18080,7 +18428,7 @@ function createTextSteps(initial, resolve, callerProviderOptions) {
|
|
|
18080
18428
|
}
|
|
18081
18429
|
return [...grouped.values()];
|
|
18082
18430
|
}
|
|
18083
|
-
return { wrap, usage:
|
|
18431
|
+
return { wrap, usage: usage5 };
|
|
18084
18432
|
}
|
|
18085
18433
|
|
|
18086
18434
|
// src/client.ts
|
|
@@ -18092,7 +18440,7 @@ import {
|
|
|
18092
18440
|
streamObject as aiStreamObject2,
|
|
18093
18441
|
streamText as aiStreamText2
|
|
18094
18442
|
} from "ai";
|
|
18095
|
-
import { z as
|
|
18443
|
+
import { z as z34 } from "zod";
|
|
18096
18444
|
|
|
18097
18445
|
// src/generated-image.ts
|
|
18098
18446
|
function toGeneratedImage(image) {
|
|
@@ -18214,9 +18562,9 @@ function providerJobMethods(kind, deps) {
|
|
|
18214
18562
|
if (!methods.result) throw missing3(adapter, ctx.model);
|
|
18215
18563
|
const result = await methods.result(sub, ctx, webhook);
|
|
18216
18564
|
const base = { ...result.usage, model: ctx.model.id, unit: ctx.model.usage.unit };
|
|
18217
|
-
const
|
|
18218
|
-
await deps.emit(
|
|
18219
|
-
return { ...result, usage:
|
|
18565
|
+
const usage5 = sub.submittedAt === void 0 ? base : deps.timed(base, sub.submittedAt);
|
|
18566
|
+
await deps.emit(usage5);
|
|
18567
|
+
return { ...result, usage: usage5 };
|
|
18220
18568
|
},
|
|
18221
18569
|
async cancel(sub, call = {}) {
|
|
18222
18570
|
const { methods, adapter, ctx } = target(sub.model, call);
|
|
@@ -18456,10 +18804,10 @@ function audioNodeMethods(deps) {
|
|
|
18456
18804
|
const startedAt = Date.now();
|
|
18457
18805
|
const outcome = await adapter.dub(resolved, ctx);
|
|
18458
18806
|
if (outcome.kind === "audio") {
|
|
18459
|
-
const { audio, usage:
|
|
18807
|
+
const { audio, usage: usage5, raw } = outcome.result;
|
|
18460
18808
|
return {
|
|
18461
18809
|
audio,
|
|
18462
|
-
usage: await deps.settle(model,
|
|
18810
|
+
usage: await deps.settle(model, usage5, startedAt),
|
|
18463
18811
|
...raw !== void 0 && { raw }
|
|
18464
18812
|
};
|
|
18465
18813
|
}
|
|
@@ -18497,10 +18845,10 @@ function textAbortOptions(sdk, context) {
|
|
|
18497
18845
|
if (abortSignal) return { abortSignal };
|
|
18498
18846
|
return {};
|
|
18499
18847
|
}
|
|
18500
|
-
var catalogId =
|
|
18501
|
-
var exactSize =
|
|
18502
|
-
var sdkRatio =
|
|
18503
|
-
var sizeTier =
|
|
18848
|
+
var catalogId = z34.string();
|
|
18849
|
+
var exactSize = z34.templateLiteral([z34.number(), "x", z34.number()]);
|
|
18850
|
+
var sdkRatio = z34.templateLiteral([z34.number(), ":", z34.number()]);
|
|
18851
|
+
var sizeTier = z34.enum(["512", "1K", "2K", "4K"]);
|
|
18504
18852
|
function isCatalogId(model) {
|
|
18505
18853
|
return catalogId.safeParse(model).success;
|
|
18506
18854
|
}
|
|
@@ -18713,7 +19061,7 @@ function createModelKit(config, adapters) {
|
|
|
18713
19061
|
const images = result.images.map(
|
|
18714
19062
|
(file) => toGeneratedImage({ bytes: file.uint8Array, mime: file.mediaType })
|
|
18715
19063
|
);
|
|
18716
|
-
const
|
|
19064
|
+
const usage5 = timed(
|
|
18717
19065
|
{
|
|
18718
19066
|
model: model.modelId,
|
|
18719
19067
|
provider: model.provider,
|
|
@@ -18723,8 +19071,8 @@ function createModelKit(config, adapters) {
|
|
|
18723
19071
|
},
|
|
18724
19072
|
startedAt
|
|
18725
19073
|
);
|
|
18726
|
-
await emit(
|
|
18727
|
-
return { image: images[0], images, usage:
|
|
19074
|
+
await emit(usage5);
|
|
19075
|
+
return { image: images[0], images, usage: usage5, raw: result, warnings };
|
|
18728
19076
|
}
|
|
18729
19077
|
function passthroughVideo(req, call) {
|
|
18730
19078
|
const {
|
|
@@ -18800,7 +19148,7 @@ function createModelKit(config, adapters) {
|
|
|
18800
19148
|
let settled;
|
|
18801
19149
|
let failed = false;
|
|
18802
19150
|
const done = pending.then(async (result) => {
|
|
18803
|
-
const
|
|
19151
|
+
const usage5 = timed(
|
|
18804
19152
|
{
|
|
18805
19153
|
model: model.modelId,
|
|
18806
19154
|
provider: model.provider,
|
|
@@ -18813,10 +19161,10 @@ function createModelKit(config, adapters) {
|
|
|
18813
19161
|
);
|
|
18814
19162
|
settled = {
|
|
18815
19163
|
video: { bytes: result.video.uint8Array, mime: result.video.mediaType },
|
|
18816
|
-
usage:
|
|
19164
|
+
usage: usage5,
|
|
18817
19165
|
raw: result
|
|
18818
19166
|
};
|
|
18819
|
-
await emit(
|
|
19167
|
+
await emit(usage5);
|
|
18820
19168
|
return settled;
|
|
18821
19169
|
});
|
|
18822
19170
|
done.catch(() => {
|
|
@@ -18843,12 +19191,12 @@ function createModelKit(config, adapters) {
|
|
|
18843
19191
|
if (settled) return settled;
|
|
18844
19192
|
const pending = result(opts).then(
|
|
18845
19193
|
async (out) => {
|
|
18846
|
-
const
|
|
19194
|
+
const usage5 = timed(
|
|
18847
19195
|
{ ...out.usage, model: model.id, unit: model.usage.unit },
|
|
18848
19196
|
startedAt
|
|
18849
19197
|
);
|
|
18850
|
-
await emit(
|
|
18851
|
-
return { ...out, usage:
|
|
19198
|
+
await emit(usage5);
|
|
19199
|
+
return { ...out, usage: usage5 };
|
|
18852
19200
|
},
|
|
18853
19201
|
(cause) => {
|
|
18854
19202
|
settled = void 0;
|
|
@@ -18868,9 +19216,9 @@ function createModelKit(config, adapters) {
|
|
|
18868
19216
|
return context(model, signal ? { ...call, signal } : call, warnings);
|
|
18869
19217
|
},
|
|
18870
19218
|
async settle(model, event, startedAt) {
|
|
18871
|
-
const
|
|
18872
|
-
await emit(
|
|
18873
|
-
return
|
|
19219
|
+
const usage5 = timed({ ...event, model: model.id, unit: model.usage.unit }, startedAt);
|
|
19220
|
+
await emit(usage5);
|
|
19221
|
+
return usage5;
|
|
18874
19222
|
},
|
|
18875
19223
|
wrapVideoJob
|
|
18876
19224
|
});
|
|
@@ -18906,11 +19254,11 @@ function createModelKit(config, adapters) {
|
|
|
18906
19254
|
});
|
|
18907
19255
|
const startedAt = Date.now();
|
|
18908
19256
|
const result = await adapter.generateImage(request, ctx);
|
|
18909
|
-
const
|
|
19257
|
+
const usage5 = timed(
|
|
18910
19258
|
{ ...result.usage, model: model.id, unit: model.usage.unit },
|
|
18911
19259
|
startedAt
|
|
18912
19260
|
);
|
|
18913
|
-
await emit(
|
|
19261
|
+
await emit(usage5);
|
|
18914
19262
|
const images = result.images.map(toGeneratedImage);
|
|
18915
19263
|
const first = images[0];
|
|
18916
19264
|
if (!first)
|
|
@@ -18919,7 +19267,7 @@ function createModelKit(config, adapters) {
|
|
|
18919
19267
|
message: `${model.id} returned no image`,
|
|
18920
19268
|
model: model.id
|
|
18921
19269
|
});
|
|
18922
|
-
return { ...result, usage:
|
|
19270
|
+
return { ...result, usage: usage5, image: first, images, warnings };
|
|
18923
19271
|
},
|
|
18924
19272
|
async generateVideo(req, call = {}) {
|
|
18925
19273
|
mediaRetryOptions(call);
|
|
@@ -19018,12 +19366,12 @@ function createModelKit(config, adapters) {
|
|
|
19018
19366
|
}
|
|
19019
19367
|
const startedAt = Date.now();
|
|
19020
19368
|
const result = await adapter.generateAudio(resolved, ctx);
|
|
19021
|
-
const
|
|
19369
|
+
const usage5 = timed(
|
|
19022
19370
|
{ ...result.usage, model: model.id, unit: model.usage.unit },
|
|
19023
19371
|
startedAt
|
|
19024
19372
|
);
|
|
19025
|
-
await emit(
|
|
19026
|
-
return { ...result, usage:
|
|
19373
|
+
await emit(usage5);
|
|
19374
|
+
return { ...result, usage: usage5 };
|
|
19027
19375
|
},
|
|
19028
19376
|
async prepareMediaPart(modelId, ref, mediaType, call = {}) {
|
|
19029
19377
|
mediaRetryOptions(call);
|
|
@@ -19103,8 +19451,8 @@ function createModelKit(config, adapters) {
|
|
|
19103
19451
|
options.prepareStep ?? options.experimental_prepareStep
|
|
19104
19452
|
),
|
|
19105
19453
|
onFinish: async (event) => {
|
|
19106
|
-
for (const
|
|
19107
|
-
await emit(textTimed(withRowUnit(
|
|
19454
|
+
for (const usage5 of steps.usage(event.steps))
|
|
19455
|
+
await emit(textTimed(withRowUnit(usage5), event.steps.length, startedAt));
|
|
19108
19456
|
await callerOnFinish?.(event);
|
|
19109
19457
|
}
|
|
19110
19458
|
});
|
|
@@ -19222,6 +19570,7 @@ export {
|
|
|
19222
19570
|
dataOnlyCapable,
|
|
19223
19571
|
describe,
|
|
19224
19572
|
describeThrown,
|
|
19573
|
+
elevenLabsAdapter,
|
|
19225
19574
|
generateImage as experimental_generateImage,
|
|
19226
19575
|
falAdapter,
|
|
19227
19576
|
falWebhookBodySchema,
|