@brotu/ai 0.3.0 → 0.4.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/README.md +13 -6
- package/dist/adapters/brotu.adapter.d.ts +46 -0
- package/dist/adapters/brotu.adapter.d.ts.map +1 -0
- package/dist/catalog.cjs +36 -14
- package/dist/catalog.d.ts +1 -0
- package/dist/catalog.d.ts.map +1 -1
- package/dist/catalog.js +3 -1
- package/dist/{chunk-PL534BFN.js → chunk-QOWHHKSI.js} +35 -14
- package/dist/client.d.ts +1 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/helpers/result.d.ts +1 -1
- package/dist/helpers/result.d.ts.map +1 -1
- package/dist/index.cjs +376 -36
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +342 -23
- package/dist/types.d.ts +14 -2
- package/dist/types.d.ts.map +1 -1
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -32,7 +32,9 @@ var index_exports = {};
|
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
BYTEPLUS_CATALOG: () => BYTEPLUS_CATALOG,
|
|
34
34
|
BYTEPLUS_MODELS: () => BYTEPLUS_MODELS,
|
|
35
|
+
BrotuAdapter: () => BrotuAdapter,
|
|
35
36
|
BytePlusAdapter: () => BytePlusAdapter,
|
|
37
|
+
DEFAULT_BROTU_API_URL: () => DEFAULT_BROTU_API_URL,
|
|
36
38
|
ELEVENLABS_CATALOG: () => ELEVENLABS_CATALOG,
|
|
37
39
|
ELEVENLABS_MODELS: () => ELEVENLABS_MODELS,
|
|
38
40
|
ELEVENLABS_OUTPUT_FORMATS: () => ELEVENLABS_OUTPUT_FORMATS,
|
|
@@ -1267,8 +1269,16 @@ var PROVIDER_BASE_URLS = {
|
|
|
1267
1269
|
elevenlabs: "https://api.elevenlabs.io",
|
|
1268
1270
|
google: "https://generativelanguage.googleapis.com",
|
|
1269
1271
|
openai: "https://api.openai.com",
|
|
1270
|
-
qwen: "https://dashscope-intl.aliyuncs.com"
|
|
1272
|
+
qwen: "https://dashscope-intl.aliyuncs.com",
|
|
1273
|
+
brotu: "https://api.brotu.app"
|
|
1271
1274
|
};
|
|
1275
|
+
var DEFAULT_BROTU_API_URL = PROVIDER_BASE_URLS.brotu;
|
|
1276
|
+
function vendorProviders(options) {
|
|
1277
|
+
return options.providers ?? {};
|
|
1278
|
+
}
|
|
1279
|
+
function brotuApiKey(options) {
|
|
1280
|
+
return options.apiKey?.trim() || void 0;
|
|
1281
|
+
}
|
|
1272
1282
|
var BUILT_IN = [
|
|
1273
1283
|
...KLING_CATALOG,
|
|
1274
1284
|
...KLING_AUDIO_CATALOG,
|
|
@@ -1324,24 +1334,36 @@ function resolveProvider(modelId, options) {
|
|
|
1324
1334
|
`Model "${modelId}" declares no provider, so nothing knows how to run it.`
|
|
1325
1335
|
);
|
|
1326
1336
|
}
|
|
1327
|
-
const configured = options
|
|
1328
|
-
if (
|
|
1329
|
-
const
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1337
|
+
const configured = vendorProviders(options)[id];
|
|
1338
|
+
if (configured) {
|
|
1339
|
+
const baseUrl = configured.baseUrl ?? PROVIDER_BASE_URLS[id];
|
|
1340
|
+
if (!baseUrl) {
|
|
1341
|
+
throw new Error(
|
|
1342
|
+
`Provider "${id}" has no known base URL \u2014 pass providers.${id}.baseUrl.`
|
|
1343
|
+
);
|
|
1344
|
+
}
|
|
1345
|
+
return { id, apiKey: configured.apiKey, baseUrl: baseUrl.replace(/\/$/, "") };
|
|
1333
1346
|
}
|
|
1334
|
-
const
|
|
1335
|
-
if (
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1347
|
+
const platformKey = brotuApiKey(options);
|
|
1348
|
+
if (platformKey) {
|
|
1349
|
+
return {
|
|
1350
|
+
id: "brotu",
|
|
1351
|
+
apiKey: platformKey,
|
|
1352
|
+
baseUrl: (options.apiUrl ?? DEFAULT_BROTU_API_URL).replace(/\/$/, "")
|
|
1353
|
+
};
|
|
1339
1354
|
}
|
|
1340
|
-
|
|
1355
|
+
const owned = Object.keys(vendorProviders(options)).join(", ") || "none";
|
|
1356
|
+
throw new Error(
|
|
1357
|
+
`Model "${modelId}" runs on "${id}", but no API key was given for it (configured: ${owned}). Pass a Brotu key to generate on the platform.`
|
|
1358
|
+
);
|
|
1341
1359
|
}
|
|
1342
1360
|
function getAvailableModels(options) {
|
|
1361
|
+
if (brotuApiKey(options)) {
|
|
1362
|
+
return catalog.filter((model) => Boolean(model.provider));
|
|
1363
|
+
}
|
|
1364
|
+
const vendors = vendorProviders(options);
|
|
1343
1365
|
return catalog.filter(
|
|
1344
|
-
(model) => model.provider && model.provider in
|
|
1366
|
+
(model) => model.provider && model.provider in vendors
|
|
1345
1367
|
);
|
|
1346
1368
|
}
|
|
1347
1369
|
|
|
@@ -1371,12 +1393,316 @@ function estimateFor(provider, type, params, defaults) {
|
|
|
1371
1393
|
};
|
|
1372
1394
|
}
|
|
1373
1395
|
|
|
1396
|
+
// src/adapters/brotu.adapter.ts
|
|
1397
|
+
var DEFAULT_API_URL = "https://api.brotu.app";
|
|
1398
|
+
var POLL_INTERVAL_MS = 3e3;
|
|
1399
|
+
var DEFAULT_MAX_POLL_ATTEMPTS = 400;
|
|
1400
|
+
var PLATFORM_MODEL_IDS = {
|
|
1401
|
+
"kling/v2-6": "kling-2.6",
|
|
1402
|
+
"kling/v3": "kling-3.0/video",
|
|
1403
|
+
"dreamina-seedance-2-5-260628": "bytedance/seedance-2-5",
|
|
1404
|
+
"dreamina-seedance-2-0-260128": "bytedance/seedance-2",
|
|
1405
|
+
"dreamina-seedance-2-0-fast-260128": "bytedance/seedance-2-fast",
|
|
1406
|
+
"gpt-image-1.5": "gpt-image/1.5"
|
|
1407
|
+
};
|
|
1408
|
+
var UNSUPPORTED_VIA_CREDITS = "Speech and text generate on the vendor. Pass that provider's key.";
|
|
1409
|
+
var BrotuAdapter = class {
|
|
1410
|
+
constructor(opts) {
|
|
1411
|
+
this.opts = opts;
|
|
1412
|
+
}
|
|
1413
|
+
opts;
|
|
1414
|
+
providerName = "brotu";
|
|
1415
|
+
supportedTypes = ["image", "video"];
|
|
1416
|
+
workspaceIdCache;
|
|
1417
|
+
get origin() {
|
|
1418
|
+
return (this.opts.apiUrl ?? DEFAULT_API_URL).replace(/\/$/, "");
|
|
1419
|
+
}
|
|
1420
|
+
headers() {
|
|
1421
|
+
return {
|
|
1422
|
+
Authorization: `Bearer ${this.opts.apiKey}`,
|
|
1423
|
+
"Content-Type": "application/json"
|
|
1424
|
+
};
|
|
1425
|
+
}
|
|
1426
|
+
async workspaceId() {
|
|
1427
|
+
if (this.opts.workspaceId) return this.opts.workspaceId;
|
|
1428
|
+
if (this.workspaceIdCache) return this.workspaceIdCache;
|
|
1429
|
+
const payload = await this.request("/api/v1/studio/default-workspace");
|
|
1430
|
+
const id = payload.workspaceId?.trim();
|
|
1431
|
+
if (!id) {
|
|
1432
|
+
throw new Error(
|
|
1433
|
+
"This Brotu account has no workspace. Open https://brotu.app and create one."
|
|
1434
|
+
);
|
|
1435
|
+
}
|
|
1436
|
+
this.workspaceIdCache = id;
|
|
1437
|
+
return id;
|
|
1438
|
+
}
|
|
1439
|
+
studioPath(path, workspaceId) {
|
|
1440
|
+
const joiner = path.includes("?") ? "&" : "?";
|
|
1441
|
+
return `${path}${joiner}workspaceId=${encodeURIComponent(workspaceId)}`;
|
|
1442
|
+
}
|
|
1443
|
+
async request(path, init) {
|
|
1444
|
+
const response = await fetch(`${this.origin}${path}`, {
|
|
1445
|
+
...init,
|
|
1446
|
+
headers: { ...this.headers(), ...init?.headers }
|
|
1447
|
+
});
|
|
1448
|
+
const text = await response.text();
|
|
1449
|
+
let body = void 0;
|
|
1450
|
+
if (text) {
|
|
1451
|
+
try {
|
|
1452
|
+
body = JSON.parse(text);
|
|
1453
|
+
} catch {
|
|
1454
|
+
body = text;
|
|
1455
|
+
}
|
|
1456
|
+
}
|
|
1457
|
+
if (!response.ok) {
|
|
1458
|
+
const parsed = body;
|
|
1459
|
+
const message = parsed && typeof parsed === "object" ? parsed.error?.message || parsed.message || text : text;
|
|
1460
|
+
throw new Error(message || `Brotu API ${response.status}`);
|
|
1461
|
+
}
|
|
1462
|
+
return body;
|
|
1463
|
+
}
|
|
1464
|
+
platformModel(modelId) {
|
|
1465
|
+
return PLATFORM_MODEL_IDS[modelId] ?? modelId;
|
|
1466
|
+
}
|
|
1467
|
+
async startGeneration(kind, params) {
|
|
1468
|
+
const modelId = params.model ?? "";
|
|
1469
|
+
const workspaceId = await this.workspaceId();
|
|
1470
|
+
const path = kind === "video" ? "/api/v1/studio/videos" : "/api/v1/studio/images";
|
|
1471
|
+
const body = kind === "video" ? this.videoBody(params, modelId) : this.imageBody(params, modelId);
|
|
1472
|
+
const result = await this.request(
|
|
1473
|
+
this.studioPath(path, workspaceId),
|
|
1474
|
+
{ method: "POST", body: JSON.stringify(body) }
|
|
1475
|
+
);
|
|
1476
|
+
const generationId = result.generationId?.trim();
|
|
1477
|
+
if (!generationId) {
|
|
1478
|
+
throw new Error("Brotu accepted the request but returned no generation id.");
|
|
1479
|
+
}
|
|
1480
|
+
return { generationId, workspaceId };
|
|
1481
|
+
}
|
|
1482
|
+
imageBody(params, modelId) {
|
|
1483
|
+
return {
|
|
1484
|
+
prompt: params.prompt,
|
|
1485
|
+
model: this.platformModel(modelId),
|
|
1486
|
+
aspectRatio: params.aspectRatio,
|
|
1487
|
+
resolution: params.resolution,
|
|
1488
|
+
negativePrompt: params.negativePrompt,
|
|
1489
|
+
outputFormat: params.outputFormat,
|
|
1490
|
+
seed: params.seed,
|
|
1491
|
+
referenceImages: params.referenceImages
|
|
1492
|
+
};
|
|
1493
|
+
}
|
|
1494
|
+
videoBody(params, modelId) {
|
|
1495
|
+
return {
|
|
1496
|
+
prompt: params.prompt,
|
|
1497
|
+
model: this.platformModel(modelId),
|
|
1498
|
+
duration: params.duration,
|
|
1499
|
+
resolution: params.resolution,
|
|
1500
|
+
aspectRatio: params.aspectRatio,
|
|
1501
|
+
mode: params.mode,
|
|
1502
|
+
withAudio: params.withAudio,
|
|
1503
|
+
seed: params.seed,
|
|
1504
|
+
imageUrl: params.imageUrl,
|
|
1505
|
+
imageUrls: params.imageUrls,
|
|
1506
|
+
videoUrl: params.videoUrl,
|
|
1507
|
+
videoUrls: params.videoUrls,
|
|
1508
|
+
referenceImages: params.referenceImages
|
|
1509
|
+
};
|
|
1510
|
+
}
|
|
1511
|
+
async run(kind, params) {
|
|
1512
|
+
const startedAt = Date.now();
|
|
1513
|
+
const modelId = params.model ?? "(none)";
|
|
1514
|
+
const failure = (error) => ({
|
|
1515
|
+
success: false,
|
|
1516
|
+
outputs: [],
|
|
1517
|
+
creditsUsed: 0,
|
|
1518
|
+
provider: this.providerName,
|
|
1519
|
+
model: modelId,
|
|
1520
|
+
processingTimeMs: Date.now() - startedAt,
|
|
1521
|
+
error
|
|
1522
|
+
});
|
|
1523
|
+
let submitted;
|
|
1524
|
+
try {
|
|
1525
|
+
submitted = await this.startGeneration(kind, params);
|
|
1526
|
+
} catch (error) {
|
|
1527
|
+
return failure(error instanceof Error ? error.message : String(error));
|
|
1528
|
+
}
|
|
1529
|
+
const pollEndpoint = this.studioPath(
|
|
1530
|
+
`/api/v1/studio/generations/${submitted.generationId}`,
|
|
1531
|
+
submitted.workspaceId
|
|
1532
|
+
);
|
|
1533
|
+
if (isSubmitMode()) {
|
|
1534
|
+
throw new PendingJob(submitted.generationId, pollEndpoint);
|
|
1535
|
+
}
|
|
1536
|
+
const job = {
|
|
1537
|
+
id: submitted.generationId,
|
|
1538
|
+
provider: this.providerName,
|
|
1539
|
+
model: modelId,
|
|
1540
|
+
kind,
|
|
1541
|
+
pollEndpoint,
|
|
1542
|
+
params,
|
|
1543
|
+
submittedAt: new Date(startedAt).toISOString()
|
|
1544
|
+
};
|
|
1545
|
+
const maxAttempts = this.opts.maxPollAttempts ?? DEFAULT_MAX_POLL_ATTEMPTS;
|
|
1546
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
1547
|
+
const snapshot = await this.completeJob(job);
|
|
1548
|
+
if (snapshot.status === "failed") {
|
|
1549
|
+
return failure(snapshot.error ?? "Brotu generation failed.");
|
|
1550
|
+
}
|
|
1551
|
+
if (snapshot.status === "succeeded" && snapshot.result) {
|
|
1552
|
+
return { ...snapshot.result, processingTimeMs: Date.now() - startedAt };
|
|
1553
|
+
}
|
|
1554
|
+
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
|
|
1555
|
+
}
|
|
1556
|
+
return failure(
|
|
1557
|
+
`Brotu generation ${submitted.generationId} did not finish after ${maxAttempts} checks.`
|
|
1558
|
+
);
|
|
1559
|
+
}
|
|
1560
|
+
async completeJob(job) {
|
|
1561
|
+
const workspaceId = this.workspaceFromPoll(job.pollEndpoint) ?? await this.workspaceId();
|
|
1562
|
+
const path = this.studioPath(
|
|
1563
|
+
`/api/v1/studio/generations/${job.id}`,
|
|
1564
|
+
workspaceId
|
|
1565
|
+
);
|
|
1566
|
+
const generation = await this.request(path);
|
|
1567
|
+
const status = (generation.status ?? "").toLowerCase();
|
|
1568
|
+
if (status === "failed") {
|
|
1569
|
+
return {
|
|
1570
|
+
status: "failed",
|
|
1571
|
+
error: generation.errorMessage ?? "Brotu generation failed."
|
|
1572
|
+
};
|
|
1573
|
+
}
|
|
1574
|
+
if (status !== "completed") {
|
|
1575
|
+
return { status: "pending" };
|
|
1576
|
+
}
|
|
1577
|
+
const outputs = outputsFrom(generation, job.kind);
|
|
1578
|
+
return {
|
|
1579
|
+
status: "succeeded",
|
|
1580
|
+
result: {
|
|
1581
|
+
success: true,
|
|
1582
|
+
outputs,
|
|
1583
|
+
creditsUsed: generation.creditsUsed ?? 0,
|
|
1584
|
+
provider: this.providerName,
|
|
1585
|
+
model: job.model,
|
|
1586
|
+
processingTimeMs: 0
|
|
1587
|
+
}
|
|
1588
|
+
};
|
|
1589
|
+
}
|
|
1590
|
+
workspaceFromPoll(pollEndpoint) {
|
|
1591
|
+
if (!pollEndpoint) return void 0;
|
|
1592
|
+
try {
|
|
1593
|
+
const url = new URL(pollEndpoint, "https://brotu.invalid");
|
|
1594
|
+
return url.searchParams.get("workspaceId") ?? void 0;
|
|
1595
|
+
} catch {
|
|
1596
|
+
return void 0;
|
|
1597
|
+
}
|
|
1598
|
+
}
|
|
1599
|
+
generateImage(params) {
|
|
1600
|
+
return this.run("image", params);
|
|
1601
|
+
}
|
|
1602
|
+
generateVideo(params) {
|
|
1603
|
+
return this.run("video", params);
|
|
1604
|
+
}
|
|
1605
|
+
async generateText(params) {
|
|
1606
|
+
return {
|
|
1607
|
+
success: false,
|
|
1608
|
+
outputs: [],
|
|
1609
|
+
creditsUsed: 0,
|
|
1610
|
+
provider: this.providerName,
|
|
1611
|
+
model: params.model ?? "(none)",
|
|
1612
|
+
processingTimeMs: 0,
|
|
1613
|
+
error: UNSUPPORTED_VIA_CREDITS
|
|
1614
|
+
};
|
|
1615
|
+
}
|
|
1616
|
+
async generateAudio(params) {
|
|
1617
|
+
return {
|
|
1618
|
+
success: false,
|
|
1619
|
+
outputs: [],
|
|
1620
|
+
creditsUsed: 0,
|
|
1621
|
+
provider: this.providerName,
|
|
1622
|
+
model: params.model ?? "(none)",
|
|
1623
|
+
processingTimeMs: 0,
|
|
1624
|
+
error: UNSUPPORTED_VIA_CREDITS
|
|
1625
|
+
};
|
|
1626
|
+
}
|
|
1627
|
+
async estimateCost(type, params) {
|
|
1628
|
+
if (type === "audio" || type === "text") {
|
|
1629
|
+
const estimate = estimateFor(this.providerName, type, params);
|
|
1630
|
+
return {
|
|
1631
|
+
...estimate,
|
|
1632
|
+
usd: null,
|
|
1633
|
+
note: UNSUPPORTED_VIA_CREDITS
|
|
1634
|
+
};
|
|
1635
|
+
}
|
|
1636
|
+
try {
|
|
1637
|
+
const workspaceId = await this.workspaceId();
|
|
1638
|
+
const video = params;
|
|
1639
|
+
const image = params;
|
|
1640
|
+
const payload = await this.request(
|
|
1641
|
+
this.studioPath("/api/v1/studio/estimate", workspaceId),
|
|
1642
|
+
{
|
|
1643
|
+
method: "POST",
|
|
1644
|
+
body: JSON.stringify({
|
|
1645
|
+
model: this.platformModel(params.model ?? ""),
|
|
1646
|
+
duration: video.duration,
|
|
1647
|
+
resolution: video.resolution ?? image.resolution,
|
|
1648
|
+
aspectRatio: video.aspectRatio ?? image.aspectRatio,
|
|
1649
|
+
withAudio: video.withAudio,
|
|
1650
|
+
hasReferenceImage: Boolean(
|
|
1651
|
+
video.imageUrl || video.imageUrls?.length || video.referenceImages?.length || image.referenceImages?.length
|
|
1652
|
+
),
|
|
1653
|
+
hasReferenceVideo: Boolean(video.videoUrl || video.videoUrls?.length),
|
|
1654
|
+
quality: image.quality
|
|
1655
|
+
})
|
|
1656
|
+
}
|
|
1657
|
+
);
|
|
1658
|
+
const credits = payload.estimatedCredits ?? 0;
|
|
1659
|
+
return {
|
|
1660
|
+
unit: type === "video" ? "second" : "image",
|
|
1661
|
+
units: credits,
|
|
1662
|
+
usd: null,
|
|
1663
|
+
note: `${credits} Brotu credit${credits === 1 ? "" : "s"}. A vendor key generates on that provider.`,
|
|
1664
|
+
provider: this.providerName,
|
|
1665
|
+
model: params.model ?? ""
|
|
1666
|
+
};
|
|
1667
|
+
} catch (error) {
|
|
1668
|
+
const estimate = estimateFor(this.providerName, type, params);
|
|
1669
|
+
return {
|
|
1670
|
+
...estimate,
|
|
1671
|
+
usd: null,
|
|
1672
|
+
note: error instanceof Error ? error.message : "Could not estimate Brotu credits."
|
|
1673
|
+
};
|
|
1674
|
+
}
|
|
1675
|
+
}
|
|
1676
|
+
supportsModel() {
|
|
1677
|
+
return true;
|
|
1678
|
+
}
|
|
1679
|
+
getAvailableModels() {
|
|
1680
|
+
return [];
|
|
1681
|
+
}
|
|
1682
|
+
};
|
|
1683
|
+
function outputsFrom(generation, kind) {
|
|
1684
|
+
const bucket = generation.outputs;
|
|
1685
|
+
const urls = kind === "video" ? bucket?.videos ?? bucket?.images ?? [] : bucket?.images ?? bucket?.videos ?? [];
|
|
1686
|
+
const copies = bucket?.copies ?? [];
|
|
1687
|
+
const mimeType = kind === "video" ? "video/mp4" : "image/png";
|
|
1688
|
+
const fromUrls = urls.filter(Boolean).map((url) => ({
|
|
1689
|
+
url,
|
|
1690
|
+
mimeType
|
|
1691
|
+
}));
|
|
1692
|
+
if (fromUrls.length > 0) return fromUrls;
|
|
1693
|
+
return copies.filter(Boolean).map((url) => ({
|
|
1694
|
+
url,
|
|
1695
|
+
mimeType: "text/plain",
|
|
1696
|
+
raw: { text: url }
|
|
1697
|
+
}));
|
|
1698
|
+
}
|
|
1699
|
+
|
|
1374
1700
|
// src/adapters/byteplus.adapter.ts
|
|
1375
1701
|
var DEFAULT_BASE_URL = "https://ark.ap-southeast.bytepluses.com";
|
|
1376
1702
|
var TASKS_PATH = "/api/v3/contents/generations/tasks";
|
|
1377
1703
|
var IMAGES_PATH = "/api/v3/images/generations";
|
|
1378
|
-
var
|
|
1379
|
-
var
|
|
1704
|
+
var POLL_INTERVAL_MS2 = 5e3;
|
|
1705
|
+
var DEFAULT_MAX_POLL_ATTEMPTS2 = 240;
|
|
1380
1706
|
var BytePlusAdapter = class {
|
|
1381
1707
|
providerName = "byteplus";
|
|
1382
1708
|
supportedTypes = ["image", "video"];
|
|
@@ -1576,7 +1902,7 @@ var BytePlusAdapter = class {
|
|
|
1576
1902
|
params,
|
|
1577
1903
|
submittedAt: new Date(startedAt).toISOString()
|
|
1578
1904
|
};
|
|
1579
|
-
const maxAttempts = this.opts.maxPollAttempts ??
|
|
1905
|
+
const maxAttempts = this.opts.maxPollAttempts ?? DEFAULT_MAX_POLL_ATTEMPTS2;
|
|
1580
1906
|
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
1581
1907
|
const snapshot = await this.completeJob(job);
|
|
1582
1908
|
if (snapshot.status === "failed") {
|
|
@@ -1585,7 +1911,7 @@ var BytePlusAdapter = class {
|
|
|
1585
1911
|
if (snapshot.status === "succeeded" && snapshot.result) {
|
|
1586
1912
|
return { ...snapshot.result, processingTimeMs: Date.now() - startedAt };
|
|
1587
1913
|
}
|
|
1588
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
1914
|
+
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS2));
|
|
1589
1915
|
}
|
|
1590
1916
|
return failure(
|
|
1591
1917
|
`Ark task ${taskId} did not finish after ${maxAttempts} checks.`
|
|
@@ -1862,8 +2188,8 @@ var ElevenLabsAdapter = class {
|
|
|
1862
2188
|
// src/adapters/google.adapter.ts
|
|
1863
2189
|
var DEFAULT_BASE_URL3 = "https://generativelanguage.googleapis.com";
|
|
1864
2190
|
var INTERACTIONS_PATH = "/v1beta/interactions";
|
|
1865
|
-
var
|
|
1866
|
-
var
|
|
2191
|
+
var POLL_INTERVAL_MS3 = 1e4;
|
|
2192
|
+
var DEFAULT_MAX_POLL_ATTEMPTS3 = 120;
|
|
1867
2193
|
var GoogleAdapter = class {
|
|
1868
2194
|
providerName = "google";
|
|
1869
2195
|
supportedTypes = [
|
|
@@ -2135,7 +2461,7 @@ var GoogleAdapter = class {
|
|
|
2135
2461
|
params,
|
|
2136
2462
|
submittedAt: new Date(startedAt).toISOString()
|
|
2137
2463
|
};
|
|
2138
|
-
const maxAttempts = this.opts.maxPollAttempts ??
|
|
2464
|
+
const maxAttempts = this.opts.maxPollAttempts ?? DEFAULT_MAX_POLL_ATTEMPTS3;
|
|
2139
2465
|
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
2140
2466
|
const snapshot = await this.completeJob(job);
|
|
2141
2467
|
if (snapshot.status === "failed") {
|
|
@@ -2144,7 +2470,7 @@ var GoogleAdapter = class {
|
|
|
2144
2470
|
if (snapshot.status === "succeeded" && snapshot.result) {
|
|
2145
2471
|
return { ...snapshot.result, processingTimeMs: Date.now() - startedAt };
|
|
2146
2472
|
}
|
|
2147
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
2473
|
+
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS3));
|
|
2148
2474
|
}
|
|
2149
2475
|
return failure(`Veo operation ${operation} did not finish in time.`);
|
|
2150
2476
|
}
|
|
@@ -2359,8 +2685,8 @@ var GoogleAdapter = class {
|
|
|
2359
2685
|
|
|
2360
2686
|
// src/adapters/kling.adapter.ts
|
|
2361
2687
|
var DEFAULT_BASE_URL4 = "https://api-singapore.klingai.com";
|
|
2362
|
-
var
|
|
2363
|
-
var
|
|
2688
|
+
var POLL_INTERVAL_MS4 = 5e3;
|
|
2689
|
+
var DEFAULT_MAX_POLL_ATTEMPTS4 = 240;
|
|
2364
2690
|
function stateOf(task) {
|
|
2365
2691
|
const raw = (task.status ?? task.task_status ?? "").toLowerCase();
|
|
2366
2692
|
if (raw === "failed") return "failed";
|
|
@@ -2557,7 +2883,7 @@ var KlingAdapter = class {
|
|
|
2557
2883
|
params,
|
|
2558
2884
|
submittedAt: new Date(startedAt).toISOString()
|
|
2559
2885
|
};
|
|
2560
|
-
const maxAttempts = this.opts.maxPollAttempts ??
|
|
2886
|
+
const maxAttempts = this.opts.maxPollAttempts ?? DEFAULT_MAX_POLL_ATTEMPTS4;
|
|
2561
2887
|
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
2562
2888
|
const snapshot = await this.completeJob(job);
|
|
2563
2889
|
if (snapshot.status === "failed") {
|
|
@@ -2566,7 +2892,7 @@ var KlingAdapter = class {
|
|
|
2566
2892
|
if (snapshot.status === "succeeded" && snapshot.result) {
|
|
2567
2893
|
return { ...snapshot.result, processingTimeMs: Date.now() - startedAt };
|
|
2568
2894
|
}
|
|
2569
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
2895
|
+
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS4));
|
|
2570
2896
|
}
|
|
2571
2897
|
return failure(
|
|
2572
2898
|
`Kling task ${submitted.taskId} did not finish after ${maxAttempts} checks.`
|
|
@@ -2937,8 +3263,8 @@ var OpenAIAdapter = class {
|
|
|
2937
3263
|
// src/adapters/qwen.adapter.ts
|
|
2938
3264
|
var DEFAULT_BASE_URL6 = "https://dashscope-intl.aliyuncs.com";
|
|
2939
3265
|
var TASKS_PATH2 = "/api/v1/tasks";
|
|
2940
|
-
var
|
|
2941
|
-
var
|
|
3266
|
+
var POLL_INTERVAL_MS5 = 5e3;
|
|
3267
|
+
var DEFAULT_MAX_POLL_ATTEMPTS5 = 240;
|
|
2942
3268
|
var QwenAdapter = class {
|
|
2943
3269
|
providerName = "qwen";
|
|
2944
3270
|
supportedTypes = ["image", "video"];
|
|
@@ -3145,7 +3471,7 @@ var QwenAdapter = class {
|
|
|
3145
3471
|
params,
|
|
3146
3472
|
submittedAt: new Date(startedAt).toISOString()
|
|
3147
3473
|
};
|
|
3148
|
-
const maxAttempts = this.opts.maxPollAttempts ??
|
|
3474
|
+
const maxAttempts = this.opts.maxPollAttempts ?? DEFAULT_MAX_POLL_ATTEMPTS5;
|
|
3149
3475
|
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
3150
3476
|
const snapshot = await this.completeJob(job);
|
|
3151
3477
|
if (snapshot.status === "failed") {
|
|
@@ -3154,7 +3480,7 @@ var QwenAdapter = class {
|
|
|
3154
3480
|
if (snapshot.status === "succeeded" && snapshot.result) {
|
|
3155
3481
|
return { ...snapshot.result, processingTimeMs: Date.now() - startedAt };
|
|
3156
3482
|
}
|
|
3157
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
3483
|
+
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS5));
|
|
3158
3484
|
}
|
|
3159
3485
|
return failure(
|
|
3160
3486
|
`DashScope task ${taskId} did not finish after ${maxAttempts} checks.`
|
|
@@ -3585,9 +3911,14 @@ var NATIVE_PROVIDERS = [
|
|
|
3585
3911
|
"qwen"
|
|
3586
3912
|
];
|
|
3587
3913
|
function brotuClient(options) {
|
|
3588
|
-
|
|
3589
|
-
|
|
3914
|
+
const apiKey = options.apiKey?.trim();
|
|
3915
|
+
if (!apiKey) {
|
|
3916
|
+
throw new Error(
|
|
3917
|
+
"Pass a Brotu API key (brotu_sk_\u2026). Get one at https://brotu.app."
|
|
3918
|
+
);
|
|
3590
3919
|
}
|
|
3920
|
+
const optionsWithKey = { ...options, apiKey };
|
|
3921
|
+
const vendors = optionsWithKey.providers ?? {};
|
|
3591
3922
|
registerModels(options.models);
|
|
3592
3923
|
let registeredWebhook = resolveWebhook(options.webhook);
|
|
3593
3924
|
const notifiedJobIds = /* @__PURE__ */ new Set();
|
|
@@ -3611,7 +3942,7 @@ function brotuClient(options) {
|
|
|
3611
3942
|
}
|
|
3612
3943
|
let provider;
|
|
3613
3944
|
try {
|
|
3614
|
-
provider = resolveProvider(modelId,
|
|
3945
|
+
provider = resolveProvider(modelId, optionsWithKey);
|
|
3615
3946
|
} catch (error) {
|
|
3616
3947
|
return failFrom("missing_key", error, { model: modelId });
|
|
3617
3948
|
}
|
|
@@ -3632,6 +3963,13 @@ function brotuClient(options) {
|
|
|
3632
3963
|
return ok({ adapter, provider: provider.id, model: modelId });
|
|
3633
3964
|
}
|
|
3634
3965
|
function buildAdapter(provider) {
|
|
3966
|
+
if (provider.id === "brotu") {
|
|
3967
|
+
return new BrotuAdapter({
|
|
3968
|
+
apiKey,
|
|
3969
|
+
apiUrl: optionsWithKey.apiUrl,
|
|
3970
|
+
workspaceId: optionsWithKey.workspaceId
|
|
3971
|
+
});
|
|
3972
|
+
}
|
|
3635
3973
|
if (provider.id === "kling") {
|
|
3636
3974
|
return new KlingAdapter({
|
|
3637
3975
|
apiKey: provider.apiKey,
|
|
@@ -3906,7 +4244,7 @@ function brotuClient(options) {
|
|
|
3906
4244
|
}
|
|
3907
4245
|
}
|
|
3908
4246
|
function klingNamespace() {
|
|
3909
|
-
const configured =
|
|
4247
|
+
const configured = vendors.kling;
|
|
3910
4248
|
if (!configured) return void 0;
|
|
3911
4249
|
const adapter = new KlingAdapter({
|
|
3912
4250
|
apiKey: configured.apiKey,
|
|
@@ -3931,7 +4269,7 @@ function brotuClient(options) {
|
|
|
3931
4269
|
};
|
|
3932
4270
|
}
|
|
3933
4271
|
function googleNamespace() {
|
|
3934
|
-
const configured =
|
|
4272
|
+
const configured = vendors.google;
|
|
3935
4273
|
if (!configured) return void 0;
|
|
3936
4274
|
const adapter = new GoogleAdapter({
|
|
3937
4275
|
apiKey: configured.apiKey,
|
|
@@ -4014,7 +4352,7 @@ function brotuClient(options) {
|
|
|
4014
4352
|
}
|
|
4015
4353
|
}
|
|
4016
4354
|
},
|
|
4017
|
-
models: () => getAvailableModels(
|
|
4355
|
+
models: () => getAvailableModels(optionsWithKey),
|
|
4018
4356
|
estimateCost: async (type, params) => {
|
|
4019
4357
|
const routed = route(params.model);
|
|
4020
4358
|
if (routed.error) return fail(routed.error);
|
|
@@ -4033,7 +4371,9 @@ function brotuClient(options) {
|
|
|
4033
4371
|
0 && (module.exports = {
|
|
4034
4372
|
BYTEPLUS_CATALOG,
|
|
4035
4373
|
BYTEPLUS_MODELS,
|
|
4374
|
+
BrotuAdapter,
|
|
4036
4375
|
BytePlusAdapter,
|
|
4376
|
+
DEFAULT_BROTU_API_URL,
|
|
4037
4377
|
ELEVENLABS_CATALOG,
|
|
4038
4378
|
ELEVENLABS_MODELS,
|
|
4039
4379
|
ELEVENLABS_OUTPUT_FORMATS,
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
export type { BrotuAdapterOptions } from "./adapters/brotu.adapter";
|
|
2
|
+
export { BrotuAdapter } from "./adapters/brotu.adapter";
|
|
1
3
|
export type { BytePlusAdapterOptions } from "./adapters/byteplus.adapter";
|
|
2
4
|
export { BytePlusAdapter } from "./adapters/byteplus.adapter";
|
|
3
5
|
export type { ElevenLabsAdapterOptions, ElevenLabsVoice, } from "./adapters/elevenlabs.adapter";
|
|
@@ -10,7 +12,7 @@ export type { OpenAIAdapterOptions } from "./adapters/openai.adapter";
|
|
|
10
12
|
export { OpenAIAdapter } from "./adapters/openai.adapter";
|
|
11
13
|
export type { QwenAdapterOptions } from "./adapters/qwen.adapter";
|
|
12
14
|
export { QwenAdapter } from "./adapters/qwen.adapter";
|
|
13
|
-
export { getAvailableModels, getModel, getModels, getProviders, hasModel, registerModels, resetCatalog, resolveProvider, } from "./catalog";
|
|
15
|
+
export { DEFAULT_BROTU_API_URL, getAvailableModels, getModel, getModels, getProviders, hasModel, registerModels, resetCatalog, resolveProvider, } from "./catalog";
|
|
14
16
|
export type { BrotuAI } from "./client";
|
|
15
17
|
export { brotuClient } from "./client";
|
|
16
18
|
export type * from "./constants/model.types";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAC1E,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,YAAY,EACX,wBAAwB,EACxB,eAAe,GACf,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAClE,YAAY,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,YAAY,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,YAAY,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,YAAY,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EACN,kBAAkB,EAClB,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,QAAQ,EACR,cAAc,EACd,YAAY,EACZ,eAAe,GACf,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,mBAAmB,yBAAyB,CAAC;AAC7C,OAAO,EACN,KAAK,OAAO,EACZ,KAAK,WAAW,EAChB,IAAI,EACJ,KAAK,UAAU,EACf,EAAE,EACF,KAAK,MAAM,GACX,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACN,YAAY,EACZ,KAAK,GAAG,EACR,KAAK,WAAW,EAChB,KAAK,SAAS,EACd,UAAU,GACV,MAAM,YAAY,CAAC;AACpB,OAAO,EACN,eAAe,EACf,cAAc,EACd,KAAK,eAAe,EACpB,KAAK,OAAO,GACZ,MAAM,eAAe,CAAC;AACvB,OAAO,EACN,cAAc,EACd,cAAc,EACd,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,gBAAgB,GACrB,MAAM,eAAe,CAAC;AACvB,mBAAmB,gCAAgC,CAAC;AACpD,OAAO,EACN,gBAAgB,EAChB,eAAe,EACf,KAAK,oBAAoB,GACzB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACN,kBAAkB,EAClB,iBAAiB,EACjB,yBAAyB,GACzB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACN,mBAAmB,EACnB,cAAc,EACd,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,GACnB,MAAM,2BAA2B,CAAC;AACnC,YAAY,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EACN,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,kBAAkB,EAClB,aAAa,EACb,YAAY,EACZ,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,gBAAgB,GACrB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACN,cAAc,EACd,mBAAmB,EACnB,kBAAkB,GAClB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACN,iBAAiB,EACjB,YAAY,EACZ,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,GACrB,MAAM,yBAAyB,CAAC;AACjC,YAAY,EACX,cAAc,EACd,cAAc,EACd,kBAAkB,EAClB,gBAAgB,GAChB,MAAM,SAAS,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|