@mux/ai 0.31.0 → 0.32.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 +37 -12
- package/dist/{index-ooikuED7.d.ts → index-D_nj_Nr4.d.ts} +18 -14
- package/dist/{index-CJtQiGj7.d.ts → index-SjpXUdXl.d.ts} +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.js +372 -132
- package/dist/index.js.map +1 -1
- package/dist/primitives/index.d.ts +2 -2
- package/dist/primitives/index.js +45 -3
- package/dist/primitives/index.js.map +1 -1
- package/dist/{shots-Bh0GrvLx.d.ts → shots-BMbViFbZ.d.ts} +12 -0
- package/dist/workflows/index.d.ts +2 -2
- package/dist/workflows/index.js +369 -131
- package/dist/workflows/index.js.map +1 -1
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ var __export = (target, all) => {
|
|
|
5
5
|
};
|
|
6
6
|
|
|
7
7
|
// package.json
|
|
8
|
-
var version = "0.
|
|
8
|
+
var version = "0.32.0";
|
|
9
9
|
|
|
10
10
|
// src/lib/language-codes.ts
|
|
11
11
|
var ISO639_1_TO_3 = {
|
|
@@ -250,6 +250,43 @@ var EnvSchema = z.object({
|
|
|
250
250
|
MUX_AI_EVAL_MODELS: optionalString("Comma-separated eval model pairs.", "Comma-separated provider:model pairs (e.g. 'openai:gpt-5.6-luna,anthropic:claude-sonnet-4-5,google:gemini-3-flash-preview')"),
|
|
251
251
|
// AI Providers
|
|
252
252
|
OPENAI_API_KEY: optionalString("OpenAI API key for OpenAI-backed workflows.", "OpenAI API key"),
|
|
253
|
+
BASETEN_API_KEY: optionalString("Baseten API key for Baseten-backed workflows.", "Baseten API key"),
|
|
254
|
+
BASETEN_URL: optionalString(
|
|
255
|
+
"Optional Baseten language endpoint URL: a dedicated deployment's /sync/v1 URL (such as https://model-{MODEL_ID}.api.baseten.co/environments/production/sync/v1) or a shared OpenAI-compatible base URL. Omit to use Baseten Model APIs.",
|
|
256
|
+
"Baseten URL"
|
|
257
|
+
),
|
|
258
|
+
BASETEN_EMBEDDING_URL: optionalString(
|
|
259
|
+
"Baseten dedicated embedding deployment URL, such as https://model-{MODEL_ID}.api.baseten.co/environments/production/sync. Required for Baseten embeddings.",
|
|
260
|
+
"Baseten embedding URL"
|
|
261
|
+
),
|
|
262
|
+
BASETEN_MODEL: optionalString(
|
|
263
|
+
"Default Baseten language model identifier used when provider='baseten' and no explicit model is passed.",
|
|
264
|
+
"Baseten model"
|
|
265
|
+
),
|
|
266
|
+
BASETEN_EMBEDDING_MODEL: optionalString(
|
|
267
|
+
"Default Baseten embedding model identifier used when provider='baseten' and no explicit model is passed.",
|
|
268
|
+
"Baseten embedding model"
|
|
269
|
+
),
|
|
270
|
+
OPENAI_COMPATIBLE_API_KEY: optionalString(
|
|
271
|
+
"Optional API key for OpenAI-compatible endpoints. Some local or self-hosted endpoints do not require one.",
|
|
272
|
+
"OpenAI-compatible API key"
|
|
273
|
+
),
|
|
274
|
+
OPENAI_COMPATIBLE_BASE_URL: optionalString(
|
|
275
|
+
"Base URL of an OpenAI-compatible API, such as https://my-endpoint.example.com/v1.",
|
|
276
|
+
"OpenAI-compatible base URL"
|
|
277
|
+
),
|
|
278
|
+
OPENAI_COMPATIBLE_EMBEDDING_BASE_URL: optionalString(
|
|
279
|
+
"Optional embedding-specific OpenAI-compatible base URL. Falls back to OPENAI_COMPATIBLE_BASE_URL.",
|
|
280
|
+
"OpenAI-compatible embedding base URL"
|
|
281
|
+
),
|
|
282
|
+
OPENAI_COMPATIBLE_MODEL: optionalString(
|
|
283
|
+
"Default language model identifier used when provider='openai-compatible' and no explicit model is passed.",
|
|
284
|
+
"OpenAI-compatible model"
|
|
285
|
+
),
|
|
286
|
+
OPENAI_COMPATIBLE_EMBEDDING_MODEL: optionalString(
|
|
287
|
+
"Default embedding model identifier used when provider='openai-compatible' and no explicit model is passed.",
|
|
288
|
+
"OpenAI-compatible embedding model"
|
|
289
|
+
),
|
|
253
290
|
ANTHROPIC_API_KEY: optionalString("Anthropic API key for Claude-backed workflows.", "Anthropic API key"),
|
|
254
291
|
GOOGLE_GENERATIVE_AI_API_KEY: optionalString("Google Generative AI API key for Gemini-backed workflows.", "Google Generative AI API key"),
|
|
255
292
|
ELEVENLABS_API_KEY: optionalString("ElevenLabs API key for audio translation.", "ElevenLabs API key"),
|
|
@@ -1025,6 +1062,7 @@ async function resolveMuxClient(credentials) {
|
|
|
1025
1062
|
function resolveProviderApiKeyFromCredentials(provider, resolved) {
|
|
1026
1063
|
const record = resolved;
|
|
1027
1064
|
const openaiApiKey = readString(record, "openaiApiKey");
|
|
1065
|
+
const basetenApiKey = readString(record, "basetenApiKey");
|
|
1028
1066
|
const anthropicApiKey = readString(record, "anthropicApiKey");
|
|
1029
1067
|
const googleApiKey = readString(record, "googleApiKey");
|
|
1030
1068
|
const googleVisionApiKey = readString(record, "googleVisionApiKey");
|
|
@@ -1032,6 +1070,7 @@ function resolveProviderApiKeyFromCredentials(provider, resolved) {
|
|
|
1032
1070
|
const elevenLabsApiKey = readString(record, "elevenLabsApiKey");
|
|
1033
1071
|
const apiKeyMap = {
|
|
1034
1072
|
"openai": openaiApiKey ?? env_default.OPENAI_API_KEY,
|
|
1073
|
+
"baseten": basetenApiKey ?? env_default.BASETEN_API_KEY,
|
|
1035
1074
|
"anthropic": anthropicApiKey ?? env_default.ANTHROPIC_API_KEY,
|
|
1036
1075
|
"google": googleApiKey ?? env_default.GOOGLE_GENERATIVE_AI_API_KEY,
|
|
1037
1076
|
"google-vision-api": googleVisionApiKey ?? env_default.GOOGLE_VISION_API_KEY,
|
|
@@ -1042,6 +1081,7 @@ function resolveProviderApiKeyFromCredentials(provider, resolved) {
|
|
|
1042
1081
|
if (!apiKey) {
|
|
1043
1082
|
const envVarNames = {
|
|
1044
1083
|
"openai": "OPENAI_API_KEY",
|
|
1084
|
+
"baseten": "BASETEN_API_KEY",
|
|
1045
1085
|
"anthropic": "ANTHROPIC_API_KEY",
|
|
1046
1086
|
"google": "GOOGLE_GENERATIVE_AI_API_KEY",
|
|
1047
1087
|
"google-vision-api": "GOOGLE_VISION_API_KEY",
|
|
@@ -1410,6 +1450,7 @@ __export(primitives_exports, {
|
|
|
1410
1450
|
import { createAnthropic } from "@ai-sdk/anthropic";
|
|
1411
1451
|
import { createGoogleGenerativeAI } from "@ai-sdk/google";
|
|
1412
1452
|
import { createOpenAI } from "@ai-sdk/openai";
|
|
1453
|
+
import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
|
|
1413
1454
|
var DEFAULT_LANGUAGE_MODELS = {
|
|
1414
1455
|
// GPT-5.6 models default to medium reasoning when no effort is specified.
|
|
1415
1456
|
openai: "gpt-5.6-luna",
|
|
@@ -1420,6 +1461,60 @@ var DEFAULT_EMBEDDING_MODELS = {
|
|
|
1420
1461
|
openai: "text-embedding-3-small",
|
|
1421
1462
|
google: "gemini-embedding-001"
|
|
1422
1463
|
};
|
|
1464
|
+
function resolveBasetenLanguageModelId(model) {
|
|
1465
|
+
const resolved = model ?? env_default.BASETEN_MODEL;
|
|
1466
|
+
if (!resolved) {
|
|
1467
|
+
throw new Error(
|
|
1468
|
+
'Baseten model is required. Pass `model` when provider is "baseten" or set BASETEN_MODEL.'
|
|
1469
|
+
);
|
|
1470
|
+
}
|
|
1471
|
+
return resolved;
|
|
1472
|
+
}
|
|
1473
|
+
function resolveBasetenEmbeddingModelId(model) {
|
|
1474
|
+
const resolved = model ?? env_default.BASETEN_EMBEDDING_MODEL;
|
|
1475
|
+
if (!resolved) {
|
|
1476
|
+
throw new Error(
|
|
1477
|
+
'Baseten embedding model is required. Pass `model` when provider is "baseten" or set BASETEN_EMBEDDING_MODEL.'
|
|
1478
|
+
);
|
|
1479
|
+
}
|
|
1480
|
+
return resolved;
|
|
1481
|
+
}
|
|
1482
|
+
function resolveOpenAICompatibleLanguageModelId(model) {
|
|
1483
|
+
const resolved = model ?? env_default.OPENAI_COMPATIBLE_MODEL;
|
|
1484
|
+
if (!resolved) {
|
|
1485
|
+
throw new Error(
|
|
1486
|
+
'OpenAI-compatible model is required. Pass `model` when provider is "openai-compatible" or set OPENAI_COMPATIBLE_MODEL.'
|
|
1487
|
+
);
|
|
1488
|
+
}
|
|
1489
|
+
return resolved;
|
|
1490
|
+
}
|
|
1491
|
+
function resolveOpenAICompatibleEmbeddingModelId(model) {
|
|
1492
|
+
const resolved = model ?? env_default.OPENAI_COMPATIBLE_EMBEDDING_MODEL;
|
|
1493
|
+
if (!resolved) {
|
|
1494
|
+
throw new Error(
|
|
1495
|
+
'OpenAI-compatible embedding model is required. Pass `model` when provider is "openai-compatible" or set OPENAI_COMPATIBLE_EMBEDDING_MODEL.'
|
|
1496
|
+
);
|
|
1497
|
+
}
|
|
1498
|
+
return resolved;
|
|
1499
|
+
}
|
|
1500
|
+
function getDefaultLanguageModel(provider) {
|
|
1501
|
+
if (provider === "baseten") {
|
|
1502
|
+
return resolveBasetenLanguageModelId();
|
|
1503
|
+
}
|
|
1504
|
+
if (provider === "openai-compatible") {
|
|
1505
|
+
return resolveOpenAICompatibleLanguageModelId();
|
|
1506
|
+
}
|
|
1507
|
+
return DEFAULT_LANGUAGE_MODELS[provider];
|
|
1508
|
+
}
|
|
1509
|
+
function getDefaultEmbeddingModel(provider) {
|
|
1510
|
+
if (provider === "baseten") {
|
|
1511
|
+
return resolveBasetenEmbeddingModelId();
|
|
1512
|
+
}
|
|
1513
|
+
if (provider === "openai-compatible") {
|
|
1514
|
+
return resolveOpenAICompatibleEmbeddingModelId();
|
|
1515
|
+
}
|
|
1516
|
+
return DEFAULT_EMBEDDING_MODELS[provider];
|
|
1517
|
+
}
|
|
1423
1518
|
var LANGUAGE_MODELS = {
|
|
1424
1519
|
openai: ["gpt-5.6-luna", "gpt-5.1", "gpt-5-mini"],
|
|
1425
1520
|
anthropic: ["claude-sonnet-4-5"],
|
|
@@ -1485,7 +1580,7 @@ function getDefaultEvalModelConfigs() {
|
|
|
1485
1580
|
function getAllEvalModelConfigs() {
|
|
1486
1581
|
return Object.entries(LANGUAGE_MODELS).flatMap(([provider, models]) => models.map((modelId) => ({ provider, modelId })));
|
|
1487
1582
|
}
|
|
1488
|
-
function
|
|
1583
|
+
function isSupportedEvalProvider(value) {
|
|
1489
1584
|
return value === "openai" || value === "anthropic" || value === "google";
|
|
1490
1585
|
}
|
|
1491
1586
|
function parseEvalModelPair(value) {
|
|
@@ -1498,7 +1593,10 @@ function parseEvalModelPair(value) {
|
|
|
1498
1593
|
`Invalid eval model pair "${value}". Use "provider:model" (example: "openai:gpt-5.6-luna").`
|
|
1499
1594
|
);
|
|
1500
1595
|
}
|
|
1501
|
-
if (
|
|
1596
|
+
if (provider === "baseten" || provider === "openai-compatible") {
|
|
1597
|
+
return void 0;
|
|
1598
|
+
}
|
|
1599
|
+
if (!isSupportedEvalProvider(provider)) {
|
|
1502
1600
|
throw new Error(
|
|
1503
1601
|
`Unsupported eval provider "${provider}" in "${value}". Supported providers: ${Object.keys(LANGUAGE_MODELS).join(", ")}.`
|
|
1504
1602
|
);
|
|
@@ -1519,7 +1617,7 @@ function resolveEvalModelConfigs(options = {}) {
|
|
|
1519
1617
|
const explicitPairs = options.modelPairs?.map((value) => value.trim()).filter(Boolean) ?? [];
|
|
1520
1618
|
if (explicitPairs.length > 0) {
|
|
1521
1619
|
const dedupedPairs = Array.from(new Set(explicitPairs));
|
|
1522
|
-
return dedupedPairs.map(parseEvalModelPair);
|
|
1620
|
+
return dedupedPairs.map(parseEvalModelPair).filter((config) => Boolean(config));
|
|
1523
1621
|
}
|
|
1524
1622
|
const selection = options.selection ?? "default";
|
|
1525
1623
|
if (selection === "all") {
|
|
@@ -1552,30 +1650,140 @@ function resolveEvalModelConfigsFromEnv(environment = env_default) {
|
|
|
1552
1650
|
var EVAL_MODEL_CONFIGS = resolveEvalModelConfigsFromEnv();
|
|
1553
1651
|
function resolveLanguageModelConfig(options = {}) {
|
|
1554
1652
|
const provider = options.provider || "openai";
|
|
1555
|
-
const modelId = options.model ||
|
|
1653
|
+
const modelId = options.model || getDefaultLanguageModel(provider);
|
|
1556
1654
|
maybeWarnOrThrowForDeprecatedLanguageModel(provider, modelId);
|
|
1557
1655
|
return { provider, modelId };
|
|
1558
1656
|
}
|
|
1559
1657
|
function resolveEmbeddingModelConfig(options = {}) {
|
|
1560
1658
|
const provider = options.provider || "openai";
|
|
1561
|
-
const modelId = options.model ||
|
|
1659
|
+
const modelId = options.model || getDefaultEmbeddingModel(provider);
|
|
1562
1660
|
return { provider, modelId };
|
|
1563
1661
|
}
|
|
1662
|
+
var BASETEN_MODEL_APIS_BASE_URL = "https://inference.baseten.co/v1";
|
|
1663
|
+
function readCredentialString(record, key) {
|
|
1664
|
+
const value = record?.[key];
|
|
1665
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
1666
|
+
}
|
|
1667
|
+
function normalizeBaseUrl(value) {
|
|
1668
|
+
const trimmed = value?.trim();
|
|
1669
|
+
if (!trimmed) {
|
|
1670
|
+
return void 0;
|
|
1671
|
+
}
|
|
1672
|
+
return trimmed.replace(/\/(chat\/completions|responses|embeddings)\/?$/, "").replace(/\/$/, "");
|
|
1673
|
+
}
|
|
1674
|
+
function isDedicatedBasetenModelUrl(value) {
|
|
1675
|
+
return Boolean(value && (value.includes("/sync") || value.includes("/predict")));
|
|
1676
|
+
}
|
|
1677
|
+
function validateDedicatedBasetenUrl(url, kind) {
|
|
1678
|
+
if (kind === "language") {
|
|
1679
|
+
if (!url.includes("/sync/v1")) {
|
|
1680
|
+
throw new Error(
|
|
1681
|
+
`Baseten dedicated deployment URLs must be /sync/v1 endpoints for language models ("/predict" URLs are not supported). Update BASETEN_URL (or basetenUrl in credentials) to the deployment's /sync/v1 URL.`
|
|
1682
|
+
);
|
|
1683
|
+
}
|
|
1684
|
+
return url;
|
|
1685
|
+
}
|
|
1686
|
+
if (!url.includes("/sync")) {
|
|
1687
|
+
throw new Error(
|
|
1688
|
+
"Baseten embeddings require a dedicated /sync or /sync/v1 deployment URL. Set BASETEN_EMBEDDING_URL or provide basetenEmbeddingUrl in credentials."
|
|
1689
|
+
);
|
|
1690
|
+
}
|
|
1691
|
+
return url;
|
|
1692
|
+
}
|
|
1693
|
+
function basetenEndpointBaseUrl(url, kind) {
|
|
1694
|
+
if (kind === "embedding" && !url.includes("/sync/v1")) {
|
|
1695
|
+
return `${url}/v1`;
|
|
1696
|
+
}
|
|
1697
|
+
return url;
|
|
1698
|
+
}
|
|
1699
|
+
function basetenBaseUrlFromUrl(url, kind) {
|
|
1700
|
+
const normalized = normalizeBaseUrl(url);
|
|
1701
|
+
if (!normalized) {
|
|
1702
|
+
if (kind === "embedding") {
|
|
1703
|
+
throw new Error(
|
|
1704
|
+
"Baseten embedding URL is required. Set BASETEN_EMBEDDING_URL or provide basetenEmbeddingUrl in credentials."
|
|
1705
|
+
);
|
|
1706
|
+
}
|
|
1707
|
+
return BASETEN_MODEL_APIS_BASE_URL;
|
|
1708
|
+
}
|
|
1709
|
+
if (isDedicatedBasetenModelUrl(normalized)) {
|
|
1710
|
+
return basetenEndpointBaseUrl(validateDedicatedBasetenUrl(normalized, kind), kind);
|
|
1711
|
+
}
|
|
1712
|
+
if (kind === "embedding") {
|
|
1713
|
+
throw new Error(
|
|
1714
|
+
"Baseten embeddings require a dedicated /sync or /sync/v1 deployment URL. Set BASETEN_EMBEDDING_URL or provide basetenEmbeddingUrl in credentials."
|
|
1715
|
+
);
|
|
1716
|
+
}
|
|
1717
|
+
return normalized;
|
|
1718
|
+
}
|
|
1719
|
+
function resolveBasetenBaseUrlFromRecord(record, kind) {
|
|
1720
|
+
if (kind === "embedding") {
|
|
1721
|
+
return basetenBaseUrlFromUrl(
|
|
1722
|
+
readCredentialString(record, "basetenEmbeddingUrl") ?? env_default.BASETEN_EMBEDDING_URL,
|
|
1723
|
+
kind
|
|
1724
|
+
);
|
|
1725
|
+
}
|
|
1726
|
+
return basetenBaseUrlFromUrl(
|
|
1727
|
+
readCredentialString(record, "basetenUrl") ?? env_default.BASETEN_URL,
|
|
1728
|
+
kind
|
|
1729
|
+
);
|
|
1730
|
+
}
|
|
1731
|
+
function resolveOpenAICompatibleSettingsFromRecord(record, kind) {
|
|
1732
|
+
const apiKey = readCredentialString(record, "openaiCompatibleApiKey") ?? env_default.OPENAI_COMPATIBLE_API_KEY;
|
|
1733
|
+
const sharedBaseUrl = readCredentialString(record, "openaiCompatibleBaseUrl") ?? env_default.OPENAI_COMPATIBLE_BASE_URL;
|
|
1734
|
+
const baseUrl = normalizeBaseUrl(
|
|
1735
|
+
kind === "embedding" ? readCredentialString(record, "openaiCompatibleEmbeddingBaseUrl") ?? env_default.OPENAI_COMPATIBLE_EMBEDDING_BASE_URL ?? sharedBaseUrl : sharedBaseUrl
|
|
1736
|
+
);
|
|
1737
|
+
if (!baseUrl) {
|
|
1738
|
+
throw new Error(
|
|
1739
|
+
"OpenAI-compatible base URL is required. Set OPENAI_COMPATIBLE_BASE_URL or provide openaiCompatibleBaseUrl in credentials."
|
|
1740
|
+
);
|
|
1741
|
+
}
|
|
1742
|
+
return { apiKey, baseURL: baseUrl };
|
|
1743
|
+
}
|
|
1744
|
+
function createBasetenProvider(apiKey, baseURL) {
|
|
1745
|
+
return createOpenAICompatible({
|
|
1746
|
+
name: "baseten",
|
|
1747
|
+
apiKey,
|
|
1748
|
+
baseURL,
|
|
1749
|
+
supportsStructuredOutputs: true
|
|
1750
|
+
});
|
|
1751
|
+
}
|
|
1752
|
+
function createGenericOpenAICompatibleProvider(settings) {
|
|
1753
|
+
return createOpenAICompatible({
|
|
1754
|
+
name: "openai-compatible",
|
|
1755
|
+
...settings,
|
|
1756
|
+
supportsStructuredOutputs: true
|
|
1757
|
+
});
|
|
1758
|
+
}
|
|
1564
1759
|
async function createLanguageModelFromConfig(provider, modelId, credentials) {
|
|
1565
1760
|
maybeWarnOrThrowForDeprecatedLanguageModel(provider, modelId);
|
|
1761
|
+
const resolvedCredentials = await resolveWorkflowCredentials(credentials);
|
|
1762
|
+
const credentialsRecord = resolvedCredentials;
|
|
1566
1763
|
switch (provider) {
|
|
1567
1764
|
case "openai": {
|
|
1568
|
-
const apiKey =
|
|
1765
|
+
const apiKey = resolveProviderApiKeyFromCredentials("openai", resolvedCredentials);
|
|
1569
1766
|
const openai = createOpenAI({ apiKey });
|
|
1570
1767
|
return openai(modelId);
|
|
1571
1768
|
}
|
|
1769
|
+
case "baseten": {
|
|
1770
|
+
const apiKey = resolveProviderApiKeyFromCredentials("baseten", resolvedCredentials);
|
|
1771
|
+
const baseten = createBasetenProvider(apiKey, resolveBasetenBaseUrlFromRecord(credentialsRecord, "language"));
|
|
1772
|
+
return baseten.chatModel(modelId);
|
|
1773
|
+
}
|
|
1774
|
+
case "openai-compatible": {
|
|
1775
|
+
const compatible = createGenericOpenAICompatibleProvider(
|
|
1776
|
+
resolveOpenAICompatibleSettingsFromRecord(credentialsRecord, "language")
|
|
1777
|
+
);
|
|
1778
|
+
return compatible.chatModel(modelId);
|
|
1779
|
+
}
|
|
1572
1780
|
case "anthropic": {
|
|
1573
|
-
const apiKey =
|
|
1781
|
+
const apiKey = resolveProviderApiKeyFromCredentials("anthropic", resolvedCredentials);
|
|
1574
1782
|
const anthropic = createAnthropic({ apiKey });
|
|
1575
1783
|
return anthropic(modelId);
|
|
1576
1784
|
}
|
|
1577
1785
|
case "google": {
|
|
1578
|
-
const apiKey =
|
|
1786
|
+
const apiKey = resolveProviderApiKeyFromCredentials("google", resolvedCredentials);
|
|
1579
1787
|
const google = createGoogleGenerativeAI({ apiKey });
|
|
1580
1788
|
return google(modelId);
|
|
1581
1789
|
}
|
|
@@ -1586,14 +1794,27 @@ async function createLanguageModelFromConfig(provider, modelId, credentials) {
|
|
|
1586
1794
|
}
|
|
1587
1795
|
}
|
|
1588
1796
|
async function createEmbeddingModelFromConfig(provider, modelId, credentials) {
|
|
1797
|
+
const resolvedCredentials = await resolveWorkflowCredentials(credentials);
|
|
1798
|
+
const credentialsRecord = resolvedCredentials;
|
|
1589
1799
|
switch (provider) {
|
|
1590
1800
|
case "openai": {
|
|
1591
|
-
const apiKey =
|
|
1801
|
+
const apiKey = resolveProviderApiKeyFromCredentials("openai", resolvedCredentials);
|
|
1592
1802
|
const openai = createOpenAI({ apiKey });
|
|
1593
1803
|
return openai.embedding(modelId);
|
|
1594
1804
|
}
|
|
1805
|
+
case "baseten": {
|
|
1806
|
+
const apiKey = resolveProviderApiKeyFromCredentials("baseten", resolvedCredentials);
|
|
1807
|
+
const baseten = createBasetenProvider(apiKey, resolveBasetenBaseUrlFromRecord(credentialsRecord, "embedding"));
|
|
1808
|
+
return baseten.textEmbeddingModel(modelId);
|
|
1809
|
+
}
|
|
1810
|
+
case "openai-compatible": {
|
|
1811
|
+
const compatible = createGenericOpenAICompatibleProvider(
|
|
1812
|
+
resolveOpenAICompatibleSettingsFromRecord(credentialsRecord, "embedding")
|
|
1813
|
+
);
|
|
1814
|
+
return compatible.textEmbeddingModel(modelId);
|
|
1815
|
+
}
|
|
1595
1816
|
case "google": {
|
|
1596
|
-
const apiKey =
|
|
1817
|
+
const apiKey = resolveProviderApiKeyFromCredentials("google", resolvedCredentials);
|
|
1597
1818
|
const google = createGoogleGenerativeAI({ apiKey });
|
|
1598
1819
|
return google.textEmbeddingModel(modelId);
|
|
1599
1820
|
}
|
|
@@ -2266,6 +2487,7 @@ async function getThumbnailUrls(playbackId, duration, options = {}) {
|
|
|
2266
2487
|
timestamps.push(time);
|
|
2267
2488
|
}
|
|
2268
2489
|
}
|
|
2490
|
+
timestamps = [...new Set(timestamps)];
|
|
2269
2491
|
if (maxSamples !== void 0 && timestamps.length > maxSamples) {
|
|
2270
2492
|
const newTimestamps = [];
|
|
2271
2493
|
newTimestamps.push(resolvedScope.startTime);
|
|
@@ -2831,8 +3053,71 @@ import dedent2 from "dedent";
|
|
|
2831
3053
|
import { z as z3 } from "zod";
|
|
2832
3054
|
|
|
2833
3055
|
// src/lib/content-policy-error.ts
|
|
2834
|
-
import { APICallError, NoObjectGeneratedError, RetryError } from "ai";
|
|
3056
|
+
import { APICallError as APICallError2, NoObjectGeneratedError, RetryError } from "ai";
|
|
2835
3057
|
import { z as z2 } from "zod";
|
|
3058
|
+
|
|
3059
|
+
// src/lib/retry.ts
|
|
3060
|
+
import { APICallError, DownloadError, NoOutputGeneratedError } from "ai";
|
|
3061
|
+
var DEFAULT_RETRY_OPTIONS = {
|
|
3062
|
+
maxRetries: 3,
|
|
3063
|
+
baseDelay: 2e3,
|
|
3064
|
+
maxDelay: 1e4
|
|
3065
|
+
};
|
|
3066
|
+
function defaultShouldRetry(error, _attempt) {
|
|
3067
|
+
if (error.message.includes("Timeout while downloading")) {
|
|
3068
|
+
return true;
|
|
3069
|
+
}
|
|
3070
|
+
if (NoOutputGeneratedError.isInstance(error) || error.name === "AI_NoOutputGeneratedError" || error.name === "AI_NoObjectGeneratedError") {
|
|
3071
|
+
return true;
|
|
3072
|
+
}
|
|
3073
|
+
if (APICallError.isInstance(error) || error.name === "AI_APICallError") {
|
|
3074
|
+
const apiError = error;
|
|
3075
|
+
if (typeof apiError.isRetryable === "boolean") {
|
|
3076
|
+
return apiError.isRetryable;
|
|
3077
|
+
}
|
|
3078
|
+
return apiError.statusCode === 408 || apiError.statusCode === 409 || apiError.statusCode === 429 || apiError.statusCode !== void 0 && apiError.statusCode >= 500;
|
|
3079
|
+
}
|
|
3080
|
+
const isDownloadError = DownloadError.isInstance(error);
|
|
3081
|
+
const isSerializedDownloadError = error.name === "AI_DownloadError";
|
|
3082
|
+
if (!isDownloadError && !isSerializedDownloadError) {
|
|
3083
|
+
return false;
|
|
3084
|
+
}
|
|
3085
|
+
const statusCode = error.statusCode;
|
|
3086
|
+
return statusCode === void 0 || statusCode === 408 || statusCode === 425 || statusCode === 429 || statusCode >= 500;
|
|
3087
|
+
}
|
|
3088
|
+
function calculateDelay(attempt, baseDelay, maxDelay) {
|
|
3089
|
+
const exponentialDelay = baseDelay * 2 ** (attempt - 1);
|
|
3090
|
+
const delayWithJitter = exponentialDelay * (0.5 + Math.random() * 0.5);
|
|
3091
|
+
return Math.min(delayWithJitter, maxDelay);
|
|
3092
|
+
}
|
|
3093
|
+
async function withRetry(fn, {
|
|
3094
|
+
maxRetries = DEFAULT_RETRY_OPTIONS.maxRetries,
|
|
3095
|
+
baseDelay = DEFAULT_RETRY_OPTIONS.baseDelay,
|
|
3096
|
+
maxDelay = DEFAULT_RETRY_OPTIONS.maxDelay,
|
|
3097
|
+
shouldRetry = defaultShouldRetry
|
|
3098
|
+
} = {}) {
|
|
3099
|
+
let lastError;
|
|
3100
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
3101
|
+
try {
|
|
3102
|
+
return await fn();
|
|
3103
|
+
} catch (error) {
|
|
3104
|
+
lastError = error;
|
|
3105
|
+
const retryError = error instanceof Error ? error : new Error(String(error));
|
|
3106
|
+
const isLastAttempt = attempt === maxRetries;
|
|
3107
|
+
if (isLastAttempt || !shouldRetry(retryError, attempt + 1)) {
|
|
3108
|
+
throw error;
|
|
3109
|
+
}
|
|
3110
|
+
const delay = calculateDelay(attempt + 1, baseDelay, maxDelay);
|
|
3111
|
+
console.warn(
|
|
3112
|
+
`Attempt ${attempt + 1} failed: ${retryError.message}. Retrying in ${Math.round(delay)}ms...`
|
|
3113
|
+
);
|
|
3114
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
3115
|
+
}
|
|
3116
|
+
}
|
|
3117
|
+
throw lastError ?? new Error("Retry failed with unknown error");
|
|
3118
|
+
}
|
|
3119
|
+
|
|
3120
|
+
// src/lib/content-policy-error.ts
|
|
2836
3121
|
var PolicyTokenSchema = z2.string().trim().min(1).max(64).regex(/^[A-Z0-9_]+$/);
|
|
2837
3122
|
var SafetyRatingSchema = z2.object({
|
|
2838
3123
|
category: PolicyTokenSchema.nullish(),
|
|
@@ -2877,6 +3162,12 @@ async function withContentPolicyErrorHandling(operation) {
|
|
|
2877
3162
|
rethrowContentPolicyError(error);
|
|
2878
3163
|
}
|
|
2879
3164
|
}
|
|
3165
|
+
async function withContentPolicyAwareRetry(operation, retryOptions) {
|
|
3166
|
+
return withRetry(
|
|
3167
|
+
() => withContentPolicyErrorHandling(operation),
|
|
3168
|
+
retryOptions
|
|
3169
|
+
);
|
|
3170
|
+
}
|
|
2880
3171
|
function rethrowContentPolicyError(error) {
|
|
2881
3172
|
const block = extractContentPolicyBlock(error);
|
|
2882
3173
|
if (!block) {
|
|
@@ -2913,7 +3204,7 @@ function extractContentPolicyBlock(error) {
|
|
|
2913
3204
|
if (NoObjectGeneratedError.isInstance(error) && error.finishReason === "content-filter") {
|
|
2914
3205
|
return { reason: "CONTENT_FILTER" };
|
|
2915
3206
|
}
|
|
2916
|
-
if (!
|
|
3207
|
+
if (!APICallError2.isInstance(error) || !error.responseBody) {
|
|
2917
3208
|
return void 0;
|
|
2918
3209
|
}
|
|
2919
3210
|
try {
|
|
@@ -2952,7 +3243,7 @@ function getContentPolicyTokenUsage(error) {
|
|
|
2952
3243
|
if (RetryError.isInstance(error)) {
|
|
2953
3244
|
return getContentPolicyTokenUsage(error.lastError);
|
|
2954
3245
|
}
|
|
2955
|
-
if (!
|
|
3246
|
+
if (!APICallError2.isInstance(error) || !error.responseBody) {
|
|
2956
3247
|
return void 0;
|
|
2957
3248
|
}
|
|
2958
3249
|
try {
|
|
@@ -3166,57 +3457,6 @@ function createLanguageSection(languageName) {
|
|
|
3166
3457
|
};
|
|
3167
3458
|
}
|
|
3168
3459
|
|
|
3169
|
-
// src/lib/retry.ts
|
|
3170
|
-
import { DownloadError } from "ai";
|
|
3171
|
-
var DEFAULT_RETRY_OPTIONS = {
|
|
3172
|
-
maxRetries: 3,
|
|
3173
|
-
baseDelay: 2e3,
|
|
3174
|
-
maxDelay: 1e4
|
|
3175
|
-
};
|
|
3176
|
-
function defaultShouldRetry(error, _attempt) {
|
|
3177
|
-
if (error.message.includes("Timeout while downloading")) {
|
|
3178
|
-
return true;
|
|
3179
|
-
}
|
|
3180
|
-
const isDownloadError = DownloadError.isInstance(error);
|
|
3181
|
-
const isSerializedDownloadError = error.name === "AI_DownloadError";
|
|
3182
|
-
if (!isDownloadError && !isSerializedDownloadError) {
|
|
3183
|
-
return false;
|
|
3184
|
-
}
|
|
3185
|
-
const statusCode = error.statusCode;
|
|
3186
|
-
return statusCode === void 0 || statusCode === 408 || statusCode === 425 || statusCode === 429 || statusCode >= 500;
|
|
3187
|
-
}
|
|
3188
|
-
function calculateDelay(attempt, baseDelay, maxDelay) {
|
|
3189
|
-
const exponentialDelay = baseDelay * 2 ** (attempt - 1);
|
|
3190
|
-
const delayWithJitter = exponentialDelay * (0.5 + Math.random() * 0.5);
|
|
3191
|
-
return Math.min(delayWithJitter, maxDelay);
|
|
3192
|
-
}
|
|
3193
|
-
async function withRetry(fn, {
|
|
3194
|
-
maxRetries = DEFAULT_RETRY_OPTIONS.maxRetries,
|
|
3195
|
-
baseDelay = DEFAULT_RETRY_OPTIONS.baseDelay,
|
|
3196
|
-
maxDelay = DEFAULT_RETRY_OPTIONS.maxDelay,
|
|
3197
|
-
shouldRetry = defaultShouldRetry
|
|
3198
|
-
} = {}) {
|
|
3199
|
-
let lastError;
|
|
3200
|
-
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
3201
|
-
try {
|
|
3202
|
-
return await fn();
|
|
3203
|
-
} catch (error) {
|
|
3204
|
-
lastError = error;
|
|
3205
|
-
const retryError = error instanceof Error ? error : new Error(String(error));
|
|
3206
|
-
const isLastAttempt = attempt === maxRetries;
|
|
3207
|
-
if (isLastAttempt || !shouldRetry(retryError, attempt + 1)) {
|
|
3208
|
-
throw error;
|
|
3209
|
-
}
|
|
3210
|
-
const delay = calculateDelay(attempt + 1, baseDelay, maxDelay);
|
|
3211
|
-
console.warn(
|
|
3212
|
-
`Attempt ${attempt + 1} failed: ${retryError.message}. Retrying in ${Math.round(delay)}ms...`
|
|
3213
|
-
);
|
|
3214
|
-
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
3215
|
-
}
|
|
3216
|
-
}
|
|
3217
|
-
throw lastError ?? new Error("Retry failed with unknown error");
|
|
3218
|
-
}
|
|
3219
|
-
|
|
3220
3460
|
// src/workflows/ask-questions.ts
|
|
3221
3461
|
var ASK_QUESTIONS_MAX_QUESTION_LENGTH = 600;
|
|
3222
3462
|
var ASK_QUESTIONS_DEFAULT_MAX_ANSWER_OPTION_LENGTH = 150;
|
|
@@ -3604,8 +3844,9 @@ async function analyzeQuestions({
|
|
|
3604
3844
|
normalizedQuestions,
|
|
3605
3845
|
maxFreeFormAnswerLength
|
|
3606
3846
|
);
|
|
3607
|
-
const response = await
|
|
3847
|
+
const response = await withContentPolicyAwareRetry(() => generateText({
|
|
3608
3848
|
model,
|
|
3849
|
+
maxRetries: 0,
|
|
3609
3850
|
output: Output.object({ schema: responseSchema }),
|
|
3610
3851
|
experimental_telemetry: { isEnabled: true },
|
|
3611
3852
|
messages: [
|
|
@@ -3804,18 +4045,16 @@ async function askQuestionsInternal(assetId, questions, options, collectedUsage)
|
|
|
3804
4045
|
credentials
|
|
3805
4046
|
});
|
|
3806
4047
|
} else {
|
|
3807
|
-
analysisResponse = await
|
|
3808
|
-
|
|
3809
|
-
|
|
3810
|
-
|
|
3811
|
-
|
|
3812
|
-
|
|
3813
|
-
|
|
3814
|
-
|
|
3815
|
-
|
|
3816
|
-
|
|
3817
|
-
})
|
|
3818
|
-
);
|
|
4048
|
+
analysisResponse = await analyzeQuestions({
|
|
4049
|
+
provider: modelConfig.provider,
|
|
4050
|
+
modelId: modelConfig.modelId,
|
|
4051
|
+
userPrompt,
|
|
4052
|
+
systemPrompt,
|
|
4053
|
+
normalizedQuestions,
|
|
4054
|
+
maxFreeFormAnswerLength,
|
|
4055
|
+
imageDataUrl: storyboardUrl,
|
|
4056
|
+
credentials
|
|
4057
|
+
});
|
|
3819
4058
|
}
|
|
3820
4059
|
}
|
|
3821
4060
|
} catch (error) {
|
|
@@ -4017,8 +4256,9 @@ async function analyzeStoryboard({
|
|
|
4017
4256
|
}) {
|
|
4018
4257
|
"use step";
|
|
4019
4258
|
const model = await createLanguageModelFromConfig(provider, modelId, credentials);
|
|
4020
|
-
const response = await
|
|
4259
|
+
const response = await withContentPolicyAwareRetry(() => generateText2({
|
|
4021
4260
|
model,
|
|
4261
|
+
maxRetries: 0,
|
|
4022
4262
|
output: Output2.object({ schema: burnedInCaptionsSchema }),
|
|
4023
4263
|
experimental_telemetry: { isEnabled: true },
|
|
4024
4264
|
messages: [
|
|
@@ -4108,14 +4348,14 @@ async function hasBurnedInCaptionsInternal(assetId, options, collectedUsage) {
|
|
|
4108
4348
|
credentials
|
|
4109
4349
|
});
|
|
4110
4350
|
} else {
|
|
4111
|
-
analysisResponse = await
|
|
4351
|
+
analysisResponse = await analyzeStoryboard({
|
|
4112
4352
|
imageDataUrl: imageUrl,
|
|
4113
4353
|
provider: modelConfig.provider,
|
|
4114
4354
|
modelId: modelConfig.modelId,
|
|
4115
4355
|
userPrompt,
|
|
4116
4356
|
systemPrompt: SYSTEM_PROMPT2,
|
|
4117
4357
|
credentials
|
|
4118
|
-
})
|
|
4358
|
+
});
|
|
4119
4359
|
}
|
|
4120
4360
|
collectedUsage.push(analysisResponse.usage);
|
|
4121
4361
|
if (!analysisResponse.result) {
|
|
@@ -4166,24 +4406,21 @@ async function generateChaptersWithAI({
|
|
|
4166
4406
|
}) {
|
|
4167
4407
|
"use step";
|
|
4168
4408
|
const model = await createLanguageModelFromConfig(provider, modelId, credentials);
|
|
4169
|
-
const response = await
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
})
|
|
4185
|
-
)
|
|
4186
|
-
);
|
|
4409
|
+
const response = await withContentPolicyAwareRetry(() => generateText3({
|
|
4410
|
+
model,
|
|
4411
|
+
maxRetries: 0,
|
|
4412
|
+
output: Output3.object({ schema: chaptersSchema }),
|
|
4413
|
+
messages: [
|
|
4414
|
+
{
|
|
4415
|
+
role: "system",
|
|
4416
|
+
content: systemPrompt
|
|
4417
|
+
},
|
|
4418
|
+
{
|
|
4419
|
+
role: "user",
|
|
4420
|
+
content: userPrompt
|
|
4421
|
+
}
|
|
4422
|
+
]
|
|
4423
|
+
}));
|
|
4187
4424
|
const output = getGeneratedOutputWithContentPolicyHandling(response);
|
|
4188
4425
|
const unexpectedRootKeys = detectUnexpectedKeysFromRawText(
|
|
4189
4426
|
response.text,
|
|
@@ -4712,8 +4949,9 @@ async function identifyProfanityWithAI({
|
|
|
4712
4949
|
tag: "transcript",
|
|
4713
4950
|
content: plainText
|
|
4714
4951
|
});
|
|
4715
|
-
const response = await
|
|
4952
|
+
const response = await withContentPolicyAwareRetry(() => generateText4({
|
|
4716
4953
|
model,
|
|
4954
|
+
maxRetries: 0,
|
|
4717
4955
|
output: Output4.object({ schema: profanityDetectionSchema }),
|
|
4718
4956
|
messages: [
|
|
4719
4957
|
{
|
|
@@ -4998,9 +5236,10 @@ async function generateSingleChunkEmbedding({
|
|
|
4998
5236
|
}) {
|
|
4999
5237
|
"use step";
|
|
5000
5238
|
const model = await createEmbeddingModelFromConfig(provider, modelId, credentials);
|
|
5001
|
-
const response = await
|
|
5239
|
+
const response = await withContentPolicyAwareRetry(
|
|
5002
5240
|
() => embed({
|
|
5003
5241
|
model,
|
|
5242
|
+
maxRetries: 0,
|
|
5004
5243
|
value: chunk.text
|
|
5005
5244
|
})
|
|
5006
5245
|
);
|
|
@@ -5419,28 +5658,25 @@ async function fetchEngagementData(assetId, options) {
|
|
|
5419
5658
|
async function generateInsightsWithAI(provider, modelId, systemPrompt, userPrompt, imageUrls, credentials) {
|
|
5420
5659
|
"use step";
|
|
5421
5660
|
const model = await createLanguageModelFromConfig(provider, modelId, credentials);
|
|
5422
|
-
const response = await
|
|
5423
|
-
|
|
5424
|
-
|
|
5425
|
-
|
|
5426
|
-
|
|
5427
|
-
|
|
5428
|
-
|
|
5429
|
-
|
|
5430
|
-
|
|
5431
|
-
|
|
5432
|
-
|
|
5433
|
-
|
|
5434
|
-
|
|
5435
|
-
|
|
5436
|
-
|
|
5437
|
-
...imageUrls.map((url) => ({ type: "image", image: url }))
|
|
5438
|
-
]
|
|
5439
|
-
}
|
|
5661
|
+
const response = await withContentPolicyAwareRetry(() => generateText5({
|
|
5662
|
+
model,
|
|
5663
|
+
maxRetries: 0,
|
|
5664
|
+
output: Output5.object({ schema: engagementInsightsSchema }),
|
|
5665
|
+
experimental_telemetry: { isEnabled: true },
|
|
5666
|
+
messages: [
|
|
5667
|
+
{
|
|
5668
|
+
role: "system",
|
|
5669
|
+
content: systemPrompt
|
|
5670
|
+
},
|
|
5671
|
+
{
|
|
5672
|
+
role: "user",
|
|
5673
|
+
content: [
|
|
5674
|
+
{ type: "text", text: userPrompt },
|
|
5675
|
+
...imageUrls.map((url) => ({ type: "image", image: url }))
|
|
5440
5676
|
]
|
|
5441
|
-
}
|
|
5442
|
-
|
|
5443
|
-
);
|
|
5677
|
+
}
|
|
5678
|
+
]
|
|
5679
|
+
}));
|
|
5444
5680
|
const output = getGeneratedOutputWithContentPolicyHandling(response);
|
|
5445
5681
|
if (!output) {
|
|
5446
5682
|
throw new Error("AI returned empty or unparseable response");
|
|
@@ -6198,8 +6434,8 @@ async function getThumbnailUrlsFromTimestamps(playbackId, timestampsMs, options)
|
|
|
6198
6434
|
"use step";
|
|
6199
6435
|
const { width, shouldSign, credentials } = options;
|
|
6200
6436
|
const baseUrl = getMuxThumbnailBaseUrl(playbackId);
|
|
6201
|
-
const
|
|
6202
|
-
|
|
6437
|
+
const times = [...new Set(timestampsMs.map(toThumbnailTimeSeconds))];
|
|
6438
|
+
const urlPromises = times.map(async (time) => {
|
|
6203
6439
|
const url = shouldSign ? await signUrl(baseUrl, playbackId, "thumbnail", { time, width }, credentials) : `${baseUrl}?time=${time}&width=${width}`;
|
|
6204
6440
|
return { url, time };
|
|
6205
6441
|
});
|
|
@@ -6685,8 +6921,9 @@ async function analyzeStoryboard2(imageDataUrl, provider, modelId, userPrompt, s
|
|
|
6685
6921
|
"use step";
|
|
6686
6922
|
const model = await createLanguageModelFromConfig(provider, modelId, credentials);
|
|
6687
6923
|
const schema = buildSummarySchema(descriptionLength);
|
|
6688
|
-
const response = await
|
|
6924
|
+
const response = await withContentPolicyAwareRetry(() => generateText6({
|
|
6689
6925
|
model,
|
|
6926
|
+
maxRetries: 0,
|
|
6690
6927
|
output: Output6.object({
|
|
6691
6928
|
name: "summary_metadata",
|
|
6692
6929
|
description: "Structured summary with title, description, and keywords.",
|
|
@@ -6732,8 +6969,9 @@ async function analyzeAudioOnly(provider, modelId, userPrompt, systemPrompt, des
|
|
|
6732
6969
|
"use step";
|
|
6733
6970
|
const model = await createLanguageModelFromConfig(provider, modelId, credentials);
|
|
6734
6971
|
const schema = buildSummarySchema(descriptionLength);
|
|
6735
|
-
const response = await
|
|
6972
|
+
const response = await withContentPolicyAwareRetry(() => generateText6({
|
|
6736
6973
|
model,
|
|
6974
|
+
maxRetries: 0,
|
|
6737
6975
|
output: Output6.object({
|
|
6738
6976
|
name: "summary_metadata",
|
|
6739
6977
|
description: "Structured summary with title, description, and keywords.",
|
|
@@ -6916,7 +7154,7 @@ async function getSummaryAndTagsInternal(assetId, options, collectedUsage) {
|
|
|
6916
7154
|
workflowCredentials
|
|
6917
7155
|
);
|
|
6918
7156
|
} else {
|
|
6919
|
-
analysisResponse = await
|
|
7157
|
+
analysisResponse = await analyzeStoryboard2(
|
|
6920
7158
|
storyboardUrl,
|
|
6921
7159
|
modelConfig.provider,
|
|
6922
7160
|
modelConfig.modelId,
|
|
@@ -6924,7 +7162,7 @@ async function getSummaryAndTagsInternal(assetId, options, collectedUsage) {
|
|
|
6924
7162
|
systemPrompt,
|
|
6925
7163
|
effectiveDescriptionLength,
|
|
6926
7164
|
workflowCredentials
|
|
6927
|
-
)
|
|
7165
|
+
);
|
|
6928
7166
|
}
|
|
6929
7167
|
}
|
|
6930
7168
|
} catch (error) {
|
|
@@ -7430,7 +7668,7 @@ async function translateAudio(assetId, toLanguageCode, options = {}) {
|
|
|
7430
7668
|
|
|
7431
7669
|
// src/workflows/translate-captions.ts
|
|
7432
7670
|
import {
|
|
7433
|
-
APICallError as
|
|
7671
|
+
APICallError as APICallError3,
|
|
7434
7672
|
generateText as generateText7,
|
|
7435
7673
|
NoObjectGeneratedError as NoObjectGeneratedError2,
|
|
7436
7674
|
Output as Output7,
|
|
@@ -7509,7 +7747,7 @@ function isProviderServiceError(error) {
|
|
|
7509
7747
|
if (RetryError2.isInstance(error)) {
|
|
7510
7748
|
return isProviderServiceError(error.lastError);
|
|
7511
7749
|
}
|
|
7512
|
-
if (
|
|
7750
|
+
if (APICallError3.isInstance(error)) {
|
|
7513
7751
|
return true;
|
|
7514
7752
|
}
|
|
7515
7753
|
if (error instanceof Error && "cause" in error) {
|
|
@@ -7682,8 +7920,9 @@ async function translateVttWithAI({
|
|
|
7682
7920
|
"use step";
|
|
7683
7921
|
const model = await createLanguageModelFromConfig(provider, modelId, credentials);
|
|
7684
7922
|
const sanitisedVttContent = stripVttMetadataBlocks(vttContent);
|
|
7685
|
-
const response = await
|
|
7923
|
+
const response = await withContentPolicyAwareRetry(() => generateText7({
|
|
7686
7924
|
model,
|
|
7925
|
+
maxRetries: 0,
|
|
7687
7926
|
output: Output7.object({ schema: translationSchema }),
|
|
7688
7927
|
messages: [
|
|
7689
7928
|
{
|
|
@@ -7748,8 +7987,9 @@ async function translateCueChunkWithAI({
|
|
|
7748
7987
|
endTime: cue.endTime,
|
|
7749
7988
|
text: cue.text
|
|
7750
7989
|
}));
|
|
7751
|
-
const response = await
|
|
7990
|
+
const response = await withContentPolicyAwareRetry(() => generateText7({
|
|
7752
7991
|
model,
|
|
7992
|
+
maxRetries: 0,
|
|
7753
7993
|
output: Output7.object({ schema }),
|
|
7754
7994
|
messages: [
|
|
7755
7995
|
{
|