@mux/ai 0.29.0 → 0.30.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 +1 -1
- package/dist/{index-CXwsu679.d.ts → index-CJtQiGj7.d.ts} +1 -1
- package/dist/{index-DJirK4fh.d.ts → index-D3cB2ltG.d.ts} +35 -3
- package/dist/index.d.ts +7 -6
- package/dist/index.js +340 -145
- package/dist/index.js.map +1 -1
- package/dist/primitives/index.d.ts +2 -2
- package/dist/primitives/index.js +26 -6
- package/dist/primitives/index.js.map +1 -1
- package/dist/{shots-BKd7TMFN.d.ts → shots-Bh0GrvLx.d.ts} +2 -0
- package/dist/workflows/index.d.ts +2 -2
- package/dist/workflows/index.js +448 -251
- package/dist/workflows/index.js.map +1 -1
- package/package.json +1 -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.30.0";
|
|
9
9
|
|
|
10
10
|
// src/lib/language-codes.ts
|
|
11
11
|
var ISO639_1_TO_3 = {
|
|
@@ -247,7 +247,7 @@ var EnvSchema = z.object({
|
|
|
247
247
|
MUX_TEST_ASSET_ID_VIOLENT_AUDIO_ONLY: optionalString("Mux test asset ID for audio-only assets with violent content.", "Mux test asset id for audio-only assets with violent content for testing"),
|
|
248
248
|
// Eval config
|
|
249
249
|
MUX_AI_EVAL_MODEL_SET: optionalString("Eval model selection mode.", "Choose between 'default' (provider defaults only) or 'all' (all configured models)"),
|
|
250
|
-
MUX_AI_EVAL_MODELS: optionalString("Comma-separated eval model pairs.", "Comma-separated provider:model pairs (e.g. 'openai:gpt-5.
|
|
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
253
|
ANTHROPIC_API_KEY: optionalString("Anthropic API key for Claude-backed workflows.", "Anthropic API key"),
|
|
@@ -566,7 +566,8 @@ var TOKEN_USAGE_FIELDS = [
|
|
|
566
566
|
"outputTokens",
|
|
567
567
|
"totalTokens",
|
|
568
568
|
"reasoningTokens",
|
|
569
|
-
"cachedInputTokens"
|
|
569
|
+
"cachedInputTokens",
|
|
570
|
+
"cacheWriteTokens"
|
|
570
571
|
];
|
|
571
572
|
function isDefinedTokenUsageValue(value) {
|
|
572
573
|
return typeof value === "number";
|
|
@@ -608,6 +609,12 @@ function getErrorTokenUsage(error) {
|
|
|
608
609
|
extracted.cachedInputTokens = cacheReadTokens;
|
|
609
610
|
}
|
|
610
611
|
}
|
|
612
|
+
if (extracted.cacheWriteTokens === void 0) {
|
|
613
|
+
const cacheWriteTokens = source.inputTokenDetails?.cacheWriteTokens;
|
|
614
|
+
if (typeof cacheWriteTokens === "number") {
|
|
615
|
+
extracted.cacheWriteTokens = cacheWriteTokens;
|
|
616
|
+
}
|
|
617
|
+
}
|
|
611
618
|
return Object.keys(extracted).length > 0 ? extracted : void 0;
|
|
612
619
|
}
|
|
613
620
|
function rethrowWithTokenUsage(error, collectedUsage) {
|
|
@@ -633,6 +640,9 @@ var MuxAiError = class extends Error {
|
|
|
633
640
|
this.publicMessage = message;
|
|
634
641
|
this.retryable = opts?.retryable ?? false;
|
|
635
642
|
}
|
|
643
|
+
static is(value) {
|
|
644
|
+
return typeof value === "object" && value !== null && "__robots_error" in value && value.__robots_error === true;
|
|
645
|
+
}
|
|
636
646
|
};
|
|
637
647
|
function extractErrorDetail(error) {
|
|
638
648
|
if (error instanceof Error && error.message) {
|
|
@@ -650,7 +660,7 @@ function extractErrorDetail(error) {
|
|
|
650
660
|
return "Unknown error";
|
|
651
661
|
}
|
|
652
662
|
function wrapError(error, message) {
|
|
653
|
-
if (error
|
|
663
|
+
if (MuxAiError.is(error)) {
|
|
654
664
|
throw error;
|
|
655
665
|
}
|
|
656
666
|
const rawDetail = extractErrorDetail(error);
|
|
@@ -1401,7 +1411,8 @@ import { createAnthropic } from "@ai-sdk/anthropic";
|
|
|
1401
1411
|
import { createGoogleGenerativeAI } from "@ai-sdk/google";
|
|
1402
1412
|
import { createOpenAI } from "@ai-sdk/openai";
|
|
1403
1413
|
var DEFAULT_LANGUAGE_MODELS = {
|
|
1404
|
-
|
|
1414
|
+
// GPT-5.6 models default to medium reasoning when no effort is specified.
|
|
1415
|
+
openai: "gpt-5.6-luna",
|
|
1405
1416
|
anthropic: "claude-sonnet-4-5",
|
|
1406
1417
|
google: "gemini-3-flash-preview"
|
|
1407
1418
|
};
|
|
@@ -1410,11 +1421,20 @@ var DEFAULT_EMBEDDING_MODELS = {
|
|
|
1410
1421
|
google: "gemini-embedding-001"
|
|
1411
1422
|
};
|
|
1412
1423
|
var LANGUAGE_MODELS = {
|
|
1413
|
-
openai: ["gpt-5.1", "gpt-5-mini"],
|
|
1424
|
+
openai: ["gpt-5.6-luna", "gpt-5.1", "gpt-5-mini"],
|
|
1414
1425
|
anthropic: ["claude-sonnet-4-5"],
|
|
1415
1426
|
google: ["gemini-3-flash-preview", "gemini-3.1-flash-lite", "gemini-2.5-flash"]
|
|
1416
1427
|
};
|
|
1417
1428
|
var LANGUAGE_MODEL_DEPRECATIONS = [
|
|
1429
|
+
{
|
|
1430
|
+
provider: "openai",
|
|
1431
|
+
modelId: "gpt-5.1",
|
|
1432
|
+
replacementModelId: "gpt-5.6-luna",
|
|
1433
|
+
phase: "warn",
|
|
1434
|
+
deprecatedOn: "2026-08-01",
|
|
1435
|
+
sunsetOn: "2026-10-01",
|
|
1436
|
+
reason: "GPT-5.6 Luna with its default medium reasoning effort is the new OpenAI default."
|
|
1437
|
+
},
|
|
1418
1438
|
{
|
|
1419
1439
|
provider: "google",
|
|
1420
1440
|
modelId: "gemini-2.5-flash",
|
|
@@ -1475,7 +1495,7 @@ function parseEvalModelPair(value) {
|
|
|
1475
1495
|
const modelId = modelIdRaw?.trim();
|
|
1476
1496
|
if (!provider || !modelId) {
|
|
1477
1497
|
throw new Error(
|
|
1478
|
-
`Invalid eval model pair "${value}". Use "provider:model" (example: "openai:gpt-5.
|
|
1498
|
+
`Invalid eval model pair "${value}". Use "provider:model" (example: "openai:gpt-5.6-luna").`
|
|
1479
1499
|
);
|
|
1480
1500
|
}
|
|
1481
1501
|
if (!isSupportedProvider(provider)) {
|
|
@@ -2765,6 +2785,9 @@ async function fetchTranscriptForAsset(asset, playbackId, options = {}) {
|
|
|
2765
2785
|
// src/workflows/index.ts
|
|
2766
2786
|
var workflows_exports = {};
|
|
2767
2787
|
__export(workflows_exports, {
|
|
2788
|
+
ASK_QUESTIONS_DEFAULT_MAX_ANSWER_OPTION_LENGTH: () => ASK_QUESTIONS_DEFAULT_MAX_ANSWER_OPTION_LENGTH,
|
|
2789
|
+
ASK_QUESTIONS_DEFAULT_MAX_FREE_FORM_ANSWER_LENGTH: () => ASK_QUESTIONS_DEFAULT_MAX_FREE_FORM_ANSWER_LENGTH,
|
|
2790
|
+
ASK_QUESTIONS_MAX_QUESTION_LENGTH: () => ASK_QUESTIONS_MAX_QUESTION_LENGTH,
|
|
2768
2791
|
DEFAULT_DESCRIPTION_LENGTH: () => DEFAULT_DESCRIPTION_LENGTH,
|
|
2769
2792
|
DEFAULT_SUMMARY_KEYWORD_LIMIT: () => DEFAULT_SUMMARY_KEYWORD_LIMIT,
|
|
2770
2793
|
DEFAULT_TITLE_LENGTH: () => DEFAULT_TITLE_LENGTH,
|
|
@@ -2805,7 +2828,156 @@ __export(workflows_exports, {
|
|
|
2805
2828
|
// src/workflows/ask-questions.ts
|
|
2806
2829
|
import { generateText, Output } from "ai";
|
|
2807
2830
|
import dedent2 from "dedent";
|
|
2831
|
+
import { z as z3 } from "zod";
|
|
2832
|
+
|
|
2833
|
+
// src/lib/content-policy-error.ts
|
|
2834
|
+
import { APICallError, NoObjectGeneratedError, RetryError } from "ai";
|
|
2808
2835
|
import { z as z2 } from "zod";
|
|
2836
|
+
var PolicyTokenSchema = z2.string().trim().min(1).max(64).regex(/^[A-Z0-9_]+$/);
|
|
2837
|
+
var SafetyRatingSchema = z2.object({
|
|
2838
|
+
category: PolicyTokenSchema.nullish(),
|
|
2839
|
+
blocked: z2.boolean().nullish()
|
|
2840
|
+
});
|
|
2841
|
+
var ContentPolicyResponseSchema = z2.object({
|
|
2842
|
+
promptFeedback: z2.object({
|
|
2843
|
+
blockReason: PolicyTokenSchema.nullish(),
|
|
2844
|
+
safetyRatings: z2.array(SafetyRatingSchema).max(32).nullish()
|
|
2845
|
+
}).nullish(),
|
|
2846
|
+
candidates: z2.array(z2.object({
|
|
2847
|
+
finishReason: PolicyTokenSchema.nullish(),
|
|
2848
|
+
safetyRatings: z2.array(SafetyRatingSchema).max(32).nullish()
|
|
2849
|
+
})).max(8).nullish()
|
|
2850
|
+
});
|
|
2851
|
+
var ContentPolicyUsageResponseSchema = z2.object({
|
|
2852
|
+
usageMetadata: z2.object({
|
|
2853
|
+
promptTokenCount: z2.number().finite().nonnegative().nullish(),
|
|
2854
|
+
candidatesTokenCount: z2.number().finite().nonnegative().nullish(),
|
|
2855
|
+
totalTokenCount: z2.number().finite().nonnegative().nullish(),
|
|
2856
|
+
cachedContentTokenCount: z2.number().finite().nonnegative().nullish(),
|
|
2857
|
+
thoughtsTokenCount: z2.number().finite().nonnegative().nullish()
|
|
2858
|
+
}).nullish()
|
|
2859
|
+
});
|
|
2860
|
+
var CONTENT_POLICY_REASONS = /* @__PURE__ */ new Set([
|
|
2861
|
+
"BLOCKLIST",
|
|
2862
|
+
"ESCALATION",
|
|
2863
|
+
"IMAGE_PROHIBITED_CONTENT",
|
|
2864
|
+
"IMAGE_RECITATION",
|
|
2865
|
+
"IMAGE_SAFETY",
|
|
2866
|
+
"JAILBREAK",
|
|
2867
|
+
"MODEL_ARMOR",
|
|
2868
|
+
"PROHIBITED_CONTENT",
|
|
2869
|
+
"RECITATION",
|
|
2870
|
+
"SAFETY",
|
|
2871
|
+
"SPII"
|
|
2872
|
+
]);
|
|
2873
|
+
async function withContentPolicyErrorHandling(operation) {
|
|
2874
|
+
try {
|
|
2875
|
+
return await operation();
|
|
2876
|
+
} catch (error) {
|
|
2877
|
+
rethrowContentPolicyError(error);
|
|
2878
|
+
}
|
|
2879
|
+
}
|
|
2880
|
+
function rethrowContentPolicyError(error) {
|
|
2881
|
+
const block = extractContentPolicyBlock(error);
|
|
2882
|
+
if (!block) {
|
|
2883
|
+
throw error;
|
|
2884
|
+
}
|
|
2885
|
+
throwContentPolicyError(block, getContentPolicyTokenUsage(error));
|
|
2886
|
+
}
|
|
2887
|
+
function getGeneratedOutputWithContentPolicyHandling(response) {
|
|
2888
|
+
if (response.finishReason === "content-filter") {
|
|
2889
|
+
const rawReason = PolicyTokenSchema.safeParse(response.rawFinishReason);
|
|
2890
|
+
const reason = rawReason.success && isContentPolicyReason(rawReason.data) ? rawReason.data : "CONTENT_FILTER";
|
|
2891
|
+
throwContentPolicyError({ reason }, getErrorTokenUsage(response));
|
|
2892
|
+
}
|
|
2893
|
+
return response.output;
|
|
2894
|
+
}
|
|
2895
|
+
function throwContentPolicyError(block, usage) {
|
|
2896
|
+
const category = block.category ? `; category: ${block.category}` : "";
|
|
2897
|
+
const contentPolicyError = new MuxAiError(
|
|
2898
|
+
`The supplied content was blocked by a content policy (reason: ${block.reason}${category}).`,
|
|
2899
|
+
{
|
|
2900
|
+
type: "content_policy_error",
|
|
2901
|
+
retryable: false
|
|
2902
|
+
}
|
|
2903
|
+
);
|
|
2904
|
+
if (usage) {
|
|
2905
|
+
contentPolicyError.usage = usage;
|
|
2906
|
+
}
|
|
2907
|
+
throw contentPolicyError;
|
|
2908
|
+
}
|
|
2909
|
+
function extractContentPolicyBlock(error) {
|
|
2910
|
+
if (RetryError.isInstance(error)) {
|
|
2911
|
+
return extractContentPolicyBlock(error.lastError);
|
|
2912
|
+
}
|
|
2913
|
+
if (NoObjectGeneratedError.isInstance(error) && error.finishReason === "content-filter") {
|
|
2914
|
+
return { reason: "CONTENT_FILTER" };
|
|
2915
|
+
}
|
|
2916
|
+
if (!APICallError.isInstance(error) || !error.responseBody) {
|
|
2917
|
+
return void 0;
|
|
2918
|
+
}
|
|
2919
|
+
try {
|
|
2920
|
+
const parsed = ContentPolicyResponseSchema.safeParse(JSON.parse(error.responseBody));
|
|
2921
|
+
if (!parsed.success) {
|
|
2922
|
+
return void 0;
|
|
2923
|
+
}
|
|
2924
|
+
const promptReason = parsed.data.promptFeedback?.blockReason;
|
|
2925
|
+
if (isContentPolicyReason(promptReason)) {
|
|
2926
|
+
return {
|
|
2927
|
+
reason: promptReason,
|
|
2928
|
+
category: findBlockedCategory(parsed.data.promptFeedback?.safetyRatings)
|
|
2929
|
+
};
|
|
2930
|
+
}
|
|
2931
|
+
for (const candidate of parsed.data.candidates ?? []) {
|
|
2932
|
+
if (isContentPolicyReason(candidate.finishReason)) {
|
|
2933
|
+
return {
|
|
2934
|
+
reason: candidate.finishReason,
|
|
2935
|
+
category: findBlockedCategory(candidate.safetyRatings)
|
|
2936
|
+
};
|
|
2937
|
+
}
|
|
2938
|
+
}
|
|
2939
|
+
} catch {
|
|
2940
|
+
return void 0;
|
|
2941
|
+
}
|
|
2942
|
+
return void 0;
|
|
2943
|
+
}
|
|
2944
|
+
function isContentPolicyReason(reason) {
|
|
2945
|
+
return Boolean(reason && CONTENT_POLICY_REASONS.has(reason));
|
|
2946
|
+
}
|
|
2947
|
+
function getContentPolicyTokenUsage(error) {
|
|
2948
|
+
const errorUsage = getErrorTokenUsage(error);
|
|
2949
|
+
if (errorUsage) {
|
|
2950
|
+
return errorUsage;
|
|
2951
|
+
}
|
|
2952
|
+
if (RetryError.isInstance(error)) {
|
|
2953
|
+
return getContentPolicyTokenUsage(error.lastError);
|
|
2954
|
+
}
|
|
2955
|
+
if (!APICallError.isInstance(error) || !error.responseBody) {
|
|
2956
|
+
return void 0;
|
|
2957
|
+
}
|
|
2958
|
+
try {
|
|
2959
|
+
const parsed = ContentPolicyUsageResponseSchema.safeParse(JSON.parse(error.responseBody));
|
|
2960
|
+
const usage = parsed.success ? parsed.data.usageMetadata : void 0;
|
|
2961
|
+
if (!usage) {
|
|
2962
|
+
return void 0;
|
|
2963
|
+
}
|
|
2964
|
+
const inputTokens = usage.promptTokenCount ?? 0;
|
|
2965
|
+
const reasoningTokens = usage.thoughtsTokenCount ?? 0;
|
|
2966
|
+
const outputTokens = (usage.candidatesTokenCount ?? 0) + reasoningTokens;
|
|
2967
|
+
return {
|
|
2968
|
+
inputTokens,
|
|
2969
|
+
outputTokens,
|
|
2970
|
+
totalTokens: usage.totalTokenCount ?? inputTokens + outputTokens,
|
|
2971
|
+
reasoningTokens,
|
|
2972
|
+
cachedInputTokens: usage.cachedContentTokenCount ?? 0
|
|
2973
|
+
};
|
|
2974
|
+
} catch {
|
|
2975
|
+
return void 0;
|
|
2976
|
+
}
|
|
2977
|
+
}
|
|
2978
|
+
function findBlockedCategory(ratings) {
|
|
2979
|
+
return ratings?.find((rating) => rating.blocked === true)?.category ?? void 0;
|
|
2980
|
+
}
|
|
2809
2981
|
|
|
2810
2982
|
// src/lib/image-download.ts
|
|
2811
2983
|
import pRetry, { AbortError } from "p-retry";
|
|
@@ -3019,33 +3191,37 @@ async function withRetry(fn, {
|
|
|
3019
3191
|
try {
|
|
3020
3192
|
return await fn();
|
|
3021
3193
|
} catch (error) {
|
|
3022
|
-
lastError = error
|
|
3194
|
+
lastError = error;
|
|
3195
|
+
const retryError = error instanceof Error ? error : new Error(String(error));
|
|
3023
3196
|
const isLastAttempt = attempt === maxRetries;
|
|
3024
|
-
if (isLastAttempt || !shouldRetry(
|
|
3025
|
-
throw
|
|
3197
|
+
if (isLastAttempt || !shouldRetry(retryError, attempt + 1)) {
|
|
3198
|
+
throw error;
|
|
3026
3199
|
}
|
|
3027
3200
|
const delay = calculateDelay(attempt + 1, baseDelay, maxDelay);
|
|
3028
3201
|
console.warn(
|
|
3029
|
-
`Attempt ${attempt + 1} failed: ${
|
|
3202
|
+
`Attempt ${attempt + 1} failed: ${retryError.message}. Retrying in ${Math.round(delay)}ms...`
|
|
3030
3203
|
);
|
|
3031
3204
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
3032
3205
|
}
|
|
3033
3206
|
}
|
|
3034
|
-
throw lastError
|
|
3207
|
+
throw lastError ?? new Error("Retry failed with unknown error");
|
|
3035
3208
|
}
|
|
3036
3209
|
|
|
3037
3210
|
// src/workflows/ask-questions.ts
|
|
3038
|
-
var
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3211
|
+
var ASK_QUESTIONS_MAX_QUESTION_LENGTH = 600;
|
|
3212
|
+
var ASK_QUESTIONS_DEFAULT_MAX_ANSWER_OPTION_LENGTH = 150;
|
|
3213
|
+
var ASK_QUESTIONS_DEFAULT_MAX_FREE_FORM_ANSWER_LENGTH = 500;
|
|
3214
|
+
var questionAnswerSchema = z3.object({
|
|
3215
|
+
question: z3.string().describe("The full text of the original question"),
|
|
3216
|
+
answer: z3.string().nullable(),
|
|
3217
|
+
confidence: z3.number(),
|
|
3218
|
+
reasoning: z3.string().max(1e3),
|
|
3219
|
+
skipped: z3.boolean()
|
|
3044
3220
|
});
|
|
3045
3221
|
var SKIP_SENTINEL = "__SKIPPED__";
|
|
3046
3222
|
function createAskQuestionsSchema(answerSchema) {
|
|
3047
|
-
return
|
|
3048
|
-
answers:
|
|
3223
|
+
return z3.object({
|
|
3224
|
+
answers: z3.array(
|
|
3049
3225
|
questionAnswerSchema.extend({
|
|
3050
3226
|
answer: answerSchema
|
|
3051
3227
|
})
|
|
@@ -3395,12 +3571,12 @@ function buildResponseSchemaForQuestions(normalizedQuestions, maxFreeFormAnswerL
|
|
|
3395
3571
|
SKIP_SENTINEL.length,
|
|
3396
3572
|
longestConstrained
|
|
3397
3573
|
);
|
|
3398
|
-
return createAskQuestionsSchema(
|
|
3574
|
+
return createAskQuestionsSchema(z3.string().min(1).max(schemaMax));
|
|
3399
3575
|
}
|
|
3400
3576
|
const allowed = Array.from(
|
|
3401
3577
|
new Set(normalizedQuestions.flatMap(allowedAnswersForQuestion))
|
|
3402
3578
|
);
|
|
3403
|
-
return createAskQuestionsSchema(
|
|
3579
|
+
return createAskQuestionsSchema(z3.enum([...allowed, SKIP_SENTINEL]));
|
|
3404
3580
|
}
|
|
3405
3581
|
async function analyzeQuestions({
|
|
3406
3582
|
provider,
|
|
@@ -3418,7 +3594,7 @@ async function analyzeQuestions({
|
|
|
3418
3594
|
normalizedQuestions,
|
|
3419
3595
|
maxFreeFormAnswerLength
|
|
3420
3596
|
);
|
|
3421
|
-
const response = await generateText({
|
|
3597
|
+
const response = await withContentPolicyErrorHandling(() => generateText({
|
|
3422
3598
|
model,
|
|
3423
3599
|
output: Output.object({ schema: responseSchema }),
|
|
3424
3600
|
experimental_telemetry: { isEnabled: true },
|
|
@@ -3435,11 +3611,12 @@ async function analyzeQuestions({
|
|
|
3435
3611
|
] : userPrompt
|
|
3436
3612
|
}
|
|
3437
3613
|
]
|
|
3438
|
-
});
|
|
3439
|
-
|
|
3614
|
+
}));
|
|
3615
|
+
const output = getGeneratedOutputWithContentPolicyHandling(response);
|
|
3616
|
+
if (!output) {
|
|
3440
3617
|
throw new Error("Ask-questions output missing");
|
|
3441
3618
|
}
|
|
3442
|
-
const parsed = responseSchema.parse(
|
|
3619
|
+
const parsed = responseSchema.parse(output);
|
|
3443
3620
|
const unexpectedRootKeys = detectUnexpectedKeysFromRawText(
|
|
3444
3621
|
response.text,
|
|
3445
3622
|
responseSchema.keyof().options
|
|
@@ -3461,7 +3638,8 @@ async function analyzeQuestions({
|
|
|
3461
3638
|
outputTokens: response.usage.outputTokens,
|
|
3462
3639
|
totalTokens: response.usage.totalTokens,
|
|
3463
3640
|
reasoningTokens: response.usage.reasoningTokens,
|
|
3464
|
-
cachedInputTokens: response.usage.cachedInputTokens
|
|
3641
|
+
cachedInputTokens: response.usage.cachedInputTokens,
|
|
3642
|
+
cacheWriteTokens: response.usage.inputTokenDetails?.cacheWriteTokens
|
|
3465
3643
|
},
|
|
3466
3644
|
unexpectedRootKeys,
|
|
3467
3645
|
unexpectedAnswerKeys
|
|
@@ -3480,7 +3658,6 @@ async function askQuestionsInternal(assetId, questions, options, collectedUsage)
|
|
|
3480
3658
|
if (!questions || questions.length === 0) {
|
|
3481
3659
|
throw new MuxAiError("At least one question must be provided.", { type: "validation_error" });
|
|
3482
3660
|
}
|
|
3483
|
-
const MAX_QUESTION_LENGTH = 500;
|
|
3484
3661
|
questions.forEach((q, idx) => {
|
|
3485
3662
|
if (!q.question || typeof q.question !== "string" || !q.question.trim()) {
|
|
3486
3663
|
throw new MuxAiError(
|
|
@@ -3488,15 +3665,14 @@ async function askQuestionsInternal(assetId, questions, options, collectedUsage)
|
|
|
3488
3665
|
{ type: "validation_error" }
|
|
3489
3666
|
);
|
|
3490
3667
|
}
|
|
3491
|
-
if (q.question.length >
|
|
3668
|
+
if (q.question.length > ASK_QUESTIONS_MAX_QUESTION_LENGTH) {
|
|
3492
3669
|
throw new MuxAiError(
|
|
3493
|
-
`Question at index ${idx} exceeds the ${
|
|
3670
|
+
`Question at index ${idx} exceeds the ${ASK_QUESTIONS_MAX_QUESTION_LENGTH}-character limit (received ${q.question.length}).`,
|
|
3494
3671
|
{ type: "validation_error" }
|
|
3495
3672
|
);
|
|
3496
3673
|
}
|
|
3497
3674
|
});
|
|
3498
|
-
const
|
|
3499
|
-
const maxAnswerOptionLength = options?.maxAnswerOptionLength ?? DEFAULT_MAX_ANSWER_OPTION_LENGTH;
|
|
3675
|
+
const maxAnswerOptionLength = options?.maxAnswerOptionLength ?? ASK_QUESTIONS_DEFAULT_MAX_ANSWER_OPTION_LENGTH;
|
|
3500
3676
|
if (!Number.isFinite(maxAnswerOptionLength) || maxAnswerOptionLength <= 0) {
|
|
3501
3677
|
throw new MuxAiError(
|
|
3502
3678
|
`maxAnswerOptionLength must be a positive number (received ${maxAnswerOptionLength}).`,
|
|
@@ -3515,8 +3691,7 @@ async function askQuestionsInternal(assetId, questions, options, collectedUsage)
|
|
|
3515
3691
|
}
|
|
3516
3692
|
}
|
|
3517
3693
|
});
|
|
3518
|
-
const
|
|
3519
|
-
const maxFreeFormAnswerLength = options?.maxFreeFormAnswerLength ?? DEFAULT_MAX_FREE_FORM_ANSWER_LENGTH;
|
|
3694
|
+
const maxFreeFormAnswerLength = options?.maxFreeFormAnswerLength ?? ASK_QUESTIONS_DEFAULT_MAX_FREE_FORM_ANSWER_LENGTH;
|
|
3520
3695
|
if (!Number.isFinite(maxFreeFormAnswerLength) || maxFreeFormAnswerLength <= 0) {
|
|
3521
3696
|
throw new MuxAiError(
|
|
3522
3697
|
`maxFreeFormAnswerLength must be a positive number (received ${maxFreeFormAnswerLength}).`,
|
|
@@ -3718,11 +3893,11 @@ async function askQuestionsInternal(assetId, questions, options, collectedUsage)
|
|
|
3718
3893
|
// src/workflows/burned-in-captions.ts
|
|
3719
3894
|
import { generateText as generateText2, Output as Output2 } from "ai";
|
|
3720
3895
|
import dedent3 from "dedent";
|
|
3721
|
-
import { z as
|
|
3722
|
-
var burnedInCaptionsSchema =
|
|
3723
|
-
hasBurnedInCaptions:
|
|
3724
|
-
confidence:
|
|
3725
|
-
detectedLanguage:
|
|
3896
|
+
import { z as z4 } from "zod";
|
|
3897
|
+
var burnedInCaptionsSchema = z4.object({
|
|
3898
|
+
hasBurnedInCaptions: z4.boolean(),
|
|
3899
|
+
confidence: z4.number(),
|
|
3900
|
+
detectedLanguage: z4.string().max(100).nullable()
|
|
3726
3901
|
});
|
|
3727
3902
|
var SYSTEM_PROMPT2 = promptDedent`
|
|
3728
3903
|
<role>
|
|
@@ -3832,7 +4007,7 @@ async function analyzeStoryboard({
|
|
|
3832
4007
|
}) {
|
|
3833
4008
|
"use step";
|
|
3834
4009
|
const model = await createLanguageModelFromConfig(provider, modelId, credentials);
|
|
3835
|
-
const response = await generateText2({
|
|
4010
|
+
const response = await withContentPolicyErrorHandling(() => generateText2({
|
|
3836
4011
|
model,
|
|
3837
4012
|
output: Output2.object({ schema: burnedInCaptionsSchema }),
|
|
3838
4013
|
experimental_telemetry: { isEnabled: true },
|
|
@@ -3849,22 +4024,24 @@ async function analyzeStoryboard({
|
|
|
3849
4024
|
]
|
|
3850
4025
|
}
|
|
3851
4026
|
]
|
|
3852
|
-
});
|
|
4027
|
+
}));
|
|
4028
|
+
const output = getGeneratedOutputWithContentPolicyHandling(response);
|
|
3853
4029
|
const unexpectedKeys = detectUnexpectedKeysFromRawText(
|
|
3854
4030
|
response.text,
|
|
3855
4031
|
burnedInCaptionsSchema.keyof().options
|
|
3856
4032
|
);
|
|
3857
4033
|
return {
|
|
3858
4034
|
result: {
|
|
3859
|
-
...
|
|
3860
|
-
confidence: Math.min(1, Math.max(0,
|
|
4035
|
+
...output,
|
|
4036
|
+
confidence: Math.min(1, Math.max(0, output.confidence))
|
|
3861
4037
|
},
|
|
3862
4038
|
usage: {
|
|
3863
4039
|
inputTokens: response.usage.inputTokens,
|
|
3864
4040
|
outputTokens: response.usage.outputTokens,
|
|
3865
4041
|
totalTokens: response.usage.totalTokens,
|
|
3866
4042
|
reasoningTokens: response.usage.reasoningTokens,
|
|
3867
|
-
cachedInputTokens: response.usage.cachedInputTokens
|
|
4043
|
+
cachedInputTokens: response.usage.cachedInputTokens,
|
|
4044
|
+
cacheWriteTokens: response.usage.inputTokenDetails?.cacheWriteTokens
|
|
3868
4045
|
},
|
|
3869
4046
|
unexpectedKeys
|
|
3870
4047
|
};
|
|
@@ -3962,13 +4139,13 @@ async function hasBurnedInCaptionsInternal(assetId, options, collectedUsage) {
|
|
|
3962
4139
|
// src/workflows/chapters.ts
|
|
3963
4140
|
import { generateText as generateText3, Output as Output3 } from "ai";
|
|
3964
4141
|
import dedent4 from "dedent";
|
|
3965
|
-
import { z as
|
|
3966
|
-
var chapterSchema =
|
|
3967
|
-
startTime:
|
|
3968
|
-
title:
|
|
4142
|
+
import { z as z5 } from "zod";
|
|
4143
|
+
var chapterSchema = z5.object({
|
|
4144
|
+
startTime: z5.number(),
|
|
4145
|
+
title: z5.string().max(300)
|
|
3969
4146
|
});
|
|
3970
|
-
var chaptersSchema =
|
|
3971
|
-
chapters:
|
|
4147
|
+
var chaptersSchema = z5.object({
|
|
4148
|
+
chapters: z5.array(chapterSchema)
|
|
3972
4149
|
});
|
|
3973
4150
|
async function generateChaptersWithAI({
|
|
3974
4151
|
provider,
|
|
@@ -3980,21 +4157,24 @@ async function generateChaptersWithAI({
|
|
|
3980
4157
|
"use step";
|
|
3981
4158
|
const model = await createLanguageModelFromConfig(provider, modelId, credentials);
|
|
3982
4159
|
const response = await withRetry(
|
|
3983
|
-
() =>
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
|
|
3987
|
-
|
|
3988
|
-
|
|
3989
|
-
|
|
3990
|
-
|
|
3991
|
-
|
|
3992
|
-
|
|
3993
|
-
|
|
3994
|
-
|
|
3995
|
-
|
|
3996
|
-
|
|
4160
|
+
() => withContentPolicyErrorHandling(
|
|
4161
|
+
() => generateText3({
|
|
4162
|
+
model,
|
|
4163
|
+
output: Output3.object({ schema: chaptersSchema }),
|
|
4164
|
+
messages: [
|
|
4165
|
+
{
|
|
4166
|
+
role: "system",
|
|
4167
|
+
content: systemPrompt
|
|
4168
|
+
},
|
|
4169
|
+
{
|
|
4170
|
+
role: "user",
|
|
4171
|
+
content: userPrompt
|
|
4172
|
+
}
|
|
4173
|
+
]
|
|
4174
|
+
})
|
|
4175
|
+
)
|
|
3997
4176
|
);
|
|
4177
|
+
const output = getGeneratedOutputWithContentPolicyHandling(response);
|
|
3998
4178
|
const unexpectedRootKeys = detectUnexpectedKeysFromRawText(
|
|
3999
4179
|
response.text,
|
|
4000
4180
|
chaptersSchema.keyof().options
|
|
@@ -4010,13 +4190,14 @@ async function generateChaptersWithAI({
|
|
|
4010
4190
|
} catch {
|
|
4011
4191
|
}
|
|
4012
4192
|
return {
|
|
4013
|
-
chapters:
|
|
4193
|
+
chapters: output,
|
|
4014
4194
|
usage: {
|
|
4015
4195
|
inputTokens: response.usage.inputTokens,
|
|
4016
4196
|
outputTokens: response.usage.outputTokens,
|
|
4017
4197
|
totalTokens: response.usage.totalTokens,
|
|
4018
4198
|
reasoningTokens: response.usage.reasoningTokens,
|
|
4019
|
-
cachedInputTokens: response.usage.cachedInputTokens
|
|
4199
|
+
cachedInputTokens: response.usage.cachedInputTokens,
|
|
4200
|
+
cacheWriteTokens: response.usage.inputTokenDetails?.cacheWriteTokens
|
|
4020
4201
|
},
|
|
4021
4202
|
unexpectedRootKeys,
|
|
4022
4203
|
unexpectedChapterKeys
|
|
@@ -4272,7 +4453,7 @@ async function generateChaptersInternal(assetId, options, collectedUsage) {
|
|
|
4272
4453
|
|
|
4273
4454
|
// src/workflows/edit-captions.ts
|
|
4274
4455
|
import { generateText as generateText4, Output as Output4 } from "ai";
|
|
4275
|
-
import { z as
|
|
4456
|
+
import { z as z6 } from "zod";
|
|
4276
4457
|
|
|
4277
4458
|
// src/lib/mux-tracks.ts
|
|
4278
4459
|
async function fetchVttFromMux(vttUrl) {
|
|
@@ -4343,8 +4524,8 @@ async function createPresignedGetUrlWithStorageAdapter(input, adapter) {
|
|
|
4343
4524
|
}
|
|
4344
4525
|
|
|
4345
4526
|
// src/workflows/edit-captions.ts
|
|
4346
|
-
var profanityDetectionSchema =
|
|
4347
|
-
profanity:
|
|
4527
|
+
var profanityDetectionSchema = z6.object({
|
|
4528
|
+
profanity: z6.array(z6.string().max(100)).describe(
|
|
4348
4529
|
"Unique profane words or short phrases exactly as they appear in the transcript text. Include each distinct form only once (e.g., if 'fuck' and 'fucking' both appear, list both)."
|
|
4349
4530
|
)
|
|
4350
4531
|
});
|
|
@@ -4521,7 +4702,7 @@ async function identifyProfanityWithAI({
|
|
|
4521
4702
|
tag: "transcript",
|
|
4522
4703
|
content: plainText
|
|
4523
4704
|
});
|
|
4524
|
-
const response = await generateText4({
|
|
4705
|
+
const response = await withContentPolicyErrorHandling(() => generateText4({
|
|
4525
4706
|
model,
|
|
4526
4707
|
output: Output4.object({ schema: profanityDetectionSchema }),
|
|
4527
4708
|
messages: [
|
|
@@ -4536,19 +4717,21 @@ async function identifyProfanityWithAI({
|
|
|
4536
4717
|
${transcriptSection}`
|
|
4537
4718
|
}
|
|
4538
4719
|
]
|
|
4539
|
-
});
|
|
4720
|
+
}));
|
|
4721
|
+
const output = getGeneratedOutputWithContentPolicyHandling(response);
|
|
4540
4722
|
const unexpectedKeys = detectUnexpectedKeysFromRawText(
|
|
4541
4723
|
response.text,
|
|
4542
4724
|
profanityDetectionSchema.keyof().options
|
|
4543
4725
|
);
|
|
4544
4726
|
return {
|
|
4545
|
-
profanity:
|
|
4727
|
+
profanity: output.profanity,
|
|
4546
4728
|
usage: {
|
|
4547
4729
|
inputTokens: response.usage.inputTokens,
|
|
4548
4730
|
outputTokens: response.usage.outputTokens,
|
|
4549
4731
|
totalTokens: response.usage.totalTokens,
|
|
4550
4732
|
reasoningTokens: response.usage.reasoningTokens,
|
|
4551
|
-
cachedInputTokens: response.usage.cachedInputTokens
|
|
4733
|
+
cachedInputTokens: response.usage.cachedInputTokens,
|
|
4734
|
+
cacheWriteTokens: response.usage.inputTokenDetails?.cacheWriteTokens
|
|
4552
4735
|
},
|
|
4553
4736
|
unexpectedKeys
|
|
4554
4737
|
};
|
|
@@ -4951,21 +5134,21 @@ async function generateVideoEmbeddings(assetId, options = {}) {
|
|
|
4951
5134
|
// src/workflows/engagement-insights.ts
|
|
4952
5135
|
import { generateText as generateText5, Output as Output5 } from "ai";
|
|
4953
5136
|
import dedent5 from "dedent";
|
|
4954
|
-
import { z as
|
|
4955
|
-
var aiMomentInsightSchema =
|
|
4956
|
-
hotspotIndex:
|
|
4957
|
-
startMs:
|
|
4958
|
-
endMs:
|
|
4959
|
-
timestamp:
|
|
4960
|
-
engagementScore:
|
|
4961
|
-
insight:
|
|
5137
|
+
import { z as z7 } from "zod";
|
|
5138
|
+
var aiMomentInsightSchema = z7.object({
|
|
5139
|
+
hotspotIndex: z7.number(),
|
|
5140
|
+
startMs: z7.number(),
|
|
5141
|
+
endMs: z7.number(),
|
|
5142
|
+
timestamp: z7.string(),
|
|
5143
|
+
engagementScore: z7.number(),
|
|
5144
|
+
insight: z7.string().max(1e3)
|
|
4962
5145
|
});
|
|
4963
|
-
var aiOverallInsightSchema =
|
|
4964
|
-
summary:
|
|
4965
|
-
trends:
|
|
5146
|
+
var aiOverallInsightSchema = z7.object({
|
|
5147
|
+
summary: z7.string().max(2e3),
|
|
5148
|
+
trends: z7.array(z7.string().max(500))
|
|
4966
5149
|
});
|
|
4967
|
-
var engagementInsightsSchema =
|
|
4968
|
-
momentInsights:
|
|
5150
|
+
var engagementInsightsSchema = z7.object({
|
|
5151
|
+
momentInsights: z7.array(aiMomentInsightSchema),
|
|
4969
5152
|
overallInsight: aiOverallInsightSchema
|
|
4970
5153
|
});
|
|
4971
5154
|
var SYSTEM_PROMPT4 = promptDedent`
|
|
@@ -5227,26 +5410,29 @@ async function generateInsightsWithAI(provider, modelId, systemPrompt, userPromp
|
|
|
5227
5410
|
"use step";
|
|
5228
5411
|
const model = await createLanguageModelFromConfig(provider, modelId, credentials);
|
|
5229
5412
|
const response = await withRetry(
|
|
5230
|
-
() =>
|
|
5231
|
-
|
|
5232
|
-
|
|
5233
|
-
|
|
5234
|
-
|
|
5235
|
-
|
|
5236
|
-
|
|
5237
|
-
|
|
5238
|
-
|
|
5239
|
-
|
|
5240
|
-
|
|
5241
|
-
|
|
5242
|
-
|
|
5243
|
-
|
|
5244
|
-
|
|
5245
|
-
|
|
5246
|
-
|
|
5247
|
-
|
|
5413
|
+
() => withContentPolicyErrorHandling(
|
|
5414
|
+
() => generateText5({
|
|
5415
|
+
model,
|
|
5416
|
+
output: Output5.object({ schema: engagementInsightsSchema }),
|
|
5417
|
+
experimental_telemetry: { isEnabled: true },
|
|
5418
|
+
messages: [
|
|
5419
|
+
{
|
|
5420
|
+
role: "system",
|
|
5421
|
+
content: systemPrompt
|
|
5422
|
+
},
|
|
5423
|
+
{
|
|
5424
|
+
role: "user",
|
|
5425
|
+
content: [
|
|
5426
|
+
{ type: "text", text: userPrompt },
|
|
5427
|
+
...imageUrls.map((url) => ({ type: "image", image: url }))
|
|
5428
|
+
]
|
|
5429
|
+
}
|
|
5430
|
+
]
|
|
5431
|
+
})
|
|
5432
|
+
)
|
|
5248
5433
|
);
|
|
5249
|
-
|
|
5434
|
+
const output = getGeneratedOutputWithContentPolicyHandling(response);
|
|
5435
|
+
if (!output) {
|
|
5250
5436
|
throw new Error("AI returned empty or unparseable response");
|
|
5251
5437
|
}
|
|
5252
5438
|
const unexpectedRootKeys = detectUnexpectedKeysFromRawText(
|
|
@@ -5269,13 +5455,14 @@ async function generateInsightsWithAI(provider, modelId, systemPrompt, userPromp
|
|
|
5269
5455
|
} catch {
|
|
5270
5456
|
}
|
|
5271
5457
|
return {
|
|
5272
|
-
result:
|
|
5458
|
+
result: output,
|
|
5273
5459
|
usage: {
|
|
5274
5460
|
inputTokens: response.usage.inputTokens,
|
|
5275
5461
|
outputTokens: response.usage.outputTokens,
|
|
5276
5462
|
totalTokens: response.usage.totalTokens,
|
|
5277
5463
|
reasoningTokens: response.usage.reasoningTokens,
|
|
5278
|
-
cachedInputTokens: response.usage.cachedInputTokens
|
|
5464
|
+
cachedInputTokens: response.usage.cachedInputTokens,
|
|
5465
|
+
cacheWriteTokens: response.usage.inputTokenDetails?.cacheWriteTokens
|
|
5279
5466
|
},
|
|
5280
5467
|
unexpectedRootKeys,
|
|
5281
5468
|
unexpectedMomentKeys,
|
|
@@ -6189,7 +6376,7 @@ async function getModerationScores(assetId, options = {}) {
|
|
|
6189
6376
|
// src/workflows/summarization.ts
|
|
6190
6377
|
import { generateText as generateText6, Output as Output6 } from "ai";
|
|
6191
6378
|
import dedent6 from "dedent";
|
|
6192
|
-
import { z as
|
|
6379
|
+
import { z as z8 } from "zod";
|
|
6193
6380
|
|
|
6194
6381
|
// src/lib/markdown-normalization.ts
|
|
6195
6382
|
var ESCAPED_LINE_BREAK_REGEX = /\\r\\n|\\n|\\r/g;
|
|
@@ -6202,17 +6389,17 @@ function normalizeMarkdownDescription(description) {
|
|
|
6202
6389
|
var DEFAULT_SUMMARY_KEYWORD_LIMIT = 10;
|
|
6203
6390
|
var DEFAULT_TITLE_LENGTH = 10;
|
|
6204
6391
|
var DEFAULT_DESCRIPTION_LENGTH = 50;
|
|
6205
|
-
var summarySchema =
|
|
6206
|
-
keywords:
|
|
6207
|
-
title:
|
|
6208
|
-
description:
|
|
6392
|
+
var summarySchema = z8.object({
|
|
6393
|
+
keywords: z8.array(z8.string().max(200)),
|
|
6394
|
+
title: z8.string().max(500),
|
|
6395
|
+
description: z8.string().max(1e4)
|
|
6209
6396
|
});
|
|
6210
6397
|
function buildSummarySchema(descriptionLength) {
|
|
6211
6398
|
const descriptionMaxChars = Math.max(2e3, descriptionLength * 15);
|
|
6212
|
-
return
|
|
6213
|
-
keywords:
|
|
6214
|
-
title:
|
|
6215
|
-
description:
|
|
6399
|
+
return z8.object({
|
|
6400
|
+
keywords: z8.array(z8.string().max(200)),
|
|
6401
|
+
title: z8.string().max(500),
|
|
6402
|
+
description: z8.string().max(descriptionMaxChars)
|
|
6216
6403
|
});
|
|
6217
6404
|
}
|
|
6218
6405
|
var VALID_TONES = ["neutral", "playful", "professional"];
|
|
@@ -6488,7 +6675,7 @@ async function analyzeStoryboard2(imageDataUrl, provider, modelId, userPrompt, s
|
|
|
6488
6675
|
"use step";
|
|
6489
6676
|
const model = await createLanguageModelFromConfig(provider, modelId, credentials);
|
|
6490
6677
|
const schema = buildSummarySchema(descriptionLength);
|
|
6491
|
-
const response = await generateText6({
|
|
6678
|
+
const response = await withContentPolicyErrorHandling(() => generateText6({
|
|
6492
6679
|
model,
|
|
6493
6680
|
output: Output6.object({
|
|
6494
6681
|
name: "summary_metadata",
|
|
@@ -6508,11 +6695,12 @@ async function analyzeStoryboard2(imageDataUrl, provider, modelId, userPrompt, s
|
|
|
6508
6695
|
]
|
|
6509
6696
|
}
|
|
6510
6697
|
]
|
|
6511
|
-
});
|
|
6512
|
-
|
|
6698
|
+
}));
|
|
6699
|
+
const output = getGeneratedOutputWithContentPolicyHandling(response);
|
|
6700
|
+
if (!output) {
|
|
6513
6701
|
throw new Error("Summarization output missing");
|
|
6514
6702
|
}
|
|
6515
|
-
const parsed = schema.parse(
|
|
6703
|
+
const parsed = schema.parse(output);
|
|
6516
6704
|
const unexpectedKeys = detectUnexpectedKeysFromRawText(
|
|
6517
6705
|
response.text,
|
|
6518
6706
|
schema.keyof().options
|
|
@@ -6524,7 +6712,8 @@ async function analyzeStoryboard2(imageDataUrl, provider, modelId, userPrompt, s
|
|
|
6524
6712
|
outputTokens: response.usage.outputTokens,
|
|
6525
6713
|
totalTokens: response.usage.totalTokens,
|
|
6526
6714
|
reasoningTokens: response.usage.reasoningTokens,
|
|
6527
|
-
cachedInputTokens: response.usage.cachedInputTokens
|
|
6715
|
+
cachedInputTokens: response.usage.cachedInputTokens,
|
|
6716
|
+
cacheWriteTokens: response.usage.inputTokenDetails?.cacheWriteTokens
|
|
6528
6717
|
},
|
|
6529
6718
|
unexpectedKeys
|
|
6530
6719
|
};
|
|
@@ -6533,7 +6722,7 @@ async function analyzeAudioOnly(provider, modelId, userPrompt, systemPrompt, des
|
|
|
6533
6722
|
"use step";
|
|
6534
6723
|
const model = await createLanguageModelFromConfig(provider, modelId, credentials);
|
|
6535
6724
|
const schema = buildSummarySchema(descriptionLength);
|
|
6536
|
-
const response = await generateText6({
|
|
6725
|
+
const response = await withContentPolicyErrorHandling(() => generateText6({
|
|
6537
6726
|
model,
|
|
6538
6727
|
output: Output6.object({
|
|
6539
6728
|
name: "summary_metadata",
|
|
@@ -6550,11 +6739,12 @@ async function analyzeAudioOnly(provider, modelId, userPrompt, systemPrompt, des
|
|
|
6550
6739
|
content: userPrompt
|
|
6551
6740
|
}
|
|
6552
6741
|
]
|
|
6553
|
-
});
|
|
6554
|
-
|
|
6742
|
+
}));
|
|
6743
|
+
const output = getGeneratedOutputWithContentPolicyHandling(response);
|
|
6744
|
+
if (!output) {
|
|
6555
6745
|
throw new Error("Summarization output missing");
|
|
6556
6746
|
}
|
|
6557
|
-
const parsed = schema.parse(
|
|
6747
|
+
const parsed = schema.parse(output);
|
|
6558
6748
|
const unexpectedKeys = detectUnexpectedKeysFromRawText(
|
|
6559
6749
|
response.text,
|
|
6560
6750
|
schema.keyof().options
|
|
@@ -6566,7 +6756,8 @@ async function analyzeAudioOnly(provider, modelId, userPrompt, systemPrompt, des
|
|
|
6566
6756
|
outputTokens: response.usage.outputTokens,
|
|
6567
6757
|
totalTokens: response.usage.totalTokens,
|
|
6568
6758
|
reasoningTokens: response.usage.reasoningTokens,
|
|
6569
|
-
cachedInputTokens: response.usage.cachedInputTokens
|
|
6759
|
+
cachedInputTokens: response.usage.cachedInputTokens,
|
|
6760
|
+
cacheWriteTokens: response.usage.inputTokenDetails?.cacheWriteTokens
|
|
6570
6761
|
},
|
|
6571
6762
|
unexpectedKeys
|
|
6572
6763
|
};
|
|
@@ -7137,16 +7328,16 @@ async function translateAudio(assetId, toLanguageCode, options = {}) {
|
|
|
7137
7328
|
|
|
7138
7329
|
// src/workflows/translate-captions.ts
|
|
7139
7330
|
import {
|
|
7140
|
-
APICallError,
|
|
7331
|
+
APICallError as APICallError2,
|
|
7141
7332
|
generateText as generateText7,
|
|
7142
|
-
NoObjectGeneratedError,
|
|
7333
|
+
NoObjectGeneratedError as NoObjectGeneratedError2,
|
|
7143
7334
|
Output as Output7,
|
|
7144
|
-
RetryError,
|
|
7335
|
+
RetryError as RetryError2,
|
|
7145
7336
|
TypeValidationError
|
|
7146
7337
|
} from "ai";
|
|
7147
|
-
import { z as
|
|
7148
|
-
var translationSchema =
|
|
7149
|
-
translation:
|
|
7338
|
+
import { z as z9 } from "zod";
|
|
7339
|
+
var translationSchema = z9.object({
|
|
7340
|
+
translation: z9.string()
|
|
7150
7341
|
});
|
|
7151
7342
|
var SYSTEM_PROMPT6 = promptDedent`
|
|
7152
7343
|
You are a subtitle translation expert. Translate VTT subtitle files to the target language specified by the user.
|
|
@@ -7213,10 +7404,10 @@ function isProviderServiceError(error) {
|
|
|
7213
7404
|
if (!error) {
|
|
7214
7405
|
return false;
|
|
7215
7406
|
}
|
|
7216
|
-
if (
|
|
7407
|
+
if (RetryError2.isInstance(error)) {
|
|
7217
7408
|
return isProviderServiceError(error.lastError);
|
|
7218
7409
|
}
|
|
7219
|
-
if (
|
|
7410
|
+
if (APICallError2.isInstance(error)) {
|
|
7220
7411
|
return true;
|
|
7221
7412
|
}
|
|
7222
7413
|
if (error instanceof Error && "cause" in error) {
|
|
@@ -7228,7 +7419,7 @@ function shouldSplitChunkTranslationError(error) {
|
|
|
7228
7419
|
if (isProviderServiceError(error)) {
|
|
7229
7420
|
return false;
|
|
7230
7421
|
}
|
|
7231
|
-
return
|
|
7422
|
+
return NoObjectGeneratedError2.isInstance(error) || TypeValidationError.isInstance(error) || isTranslationChunkValidationError(error);
|
|
7232
7423
|
}
|
|
7233
7424
|
function resolveTranslationChunkingOptions(options) {
|
|
7234
7425
|
const targetChunkDurationSeconds = Math.max(
|
|
@@ -7389,7 +7580,7 @@ async function translateVttWithAI({
|
|
|
7389
7580
|
"use step";
|
|
7390
7581
|
const model = await createLanguageModelFromConfig(provider, modelId, credentials);
|
|
7391
7582
|
const sanitisedVttContent = stripVttMetadataBlocks(vttContent);
|
|
7392
|
-
const response = await generateText7({
|
|
7583
|
+
const response = await withContentPolicyErrorHandling(() => generateText7({
|
|
7393
7584
|
model,
|
|
7394
7585
|
output: Output7.object({ schema: translationSchema }),
|
|
7395
7586
|
messages: [
|
|
@@ -7404,8 +7595,9 @@ async function translateVttWithAI({
|
|
|
7404
7595
|
${sanitisedVttContent}`
|
|
7405
7596
|
}
|
|
7406
7597
|
]
|
|
7407
|
-
});
|
|
7408
|
-
const
|
|
7598
|
+
}));
|
|
7599
|
+
const output = getGeneratedOutputWithContentPolicyHandling(response);
|
|
7600
|
+
const translated = normalizeTranslatedVtt(output.translation);
|
|
7409
7601
|
const leakReason = detectLeakReason(translated);
|
|
7410
7602
|
const safeTranslated = leakReason !== null ? vttContent : translated;
|
|
7411
7603
|
if (leakReason !== null) {
|
|
@@ -7430,7 +7622,8 @@ ${sanitisedVttContent}`
|
|
|
7430
7622
|
outputTokens: response.usage.outputTokens,
|
|
7431
7623
|
totalTokens: response.usage.totalTokens,
|
|
7432
7624
|
reasoningTokens: response.usage.reasoningTokens,
|
|
7433
|
-
cachedInputTokens: response.usage.cachedInputTokens
|
|
7625
|
+
cachedInputTokens: response.usage.cachedInputTokens,
|
|
7626
|
+
cacheWriteTokens: response.usage.inputTokenDetails?.cacheWriteTokens
|
|
7434
7627
|
}
|
|
7435
7628
|
};
|
|
7436
7629
|
}
|
|
@@ -7444,8 +7637,8 @@ async function translateCueChunkWithAI({
|
|
|
7444
7637
|
}) {
|
|
7445
7638
|
"use step";
|
|
7446
7639
|
const model = await createLanguageModelFromConfig(provider, modelId, credentials);
|
|
7447
|
-
const schema =
|
|
7448
|
-
translations:
|
|
7640
|
+
const schema = z9.object({
|
|
7641
|
+
translations: z9.array(z9.string().min(1).max(2e3)).length(cues.length)
|
|
7449
7642
|
});
|
|
7450
7643
|
const cuePayload = cues.map((cue, index) => ({
|
|
7451
7644
|
index,
|
|
@@ -7453,7 +7646,7 @@ async function translateCueChunkWithAI({
|
|
|
7453
7646
|
endTime: cue.endTime,
|
|
7454
7647
|
text: cue.text
|
|
7455
7648
|
}));
|
|
7456
|
-
const response = await generateText7({
|
|
7649
|
+
const response = await withContentPolicyErrorHandling(() => generateText7({
|
|
7457
7650
|
model,
|
|
7458
7651
|
output: Output7.object({ schema }),
|
|
7459
7652
|
messages: [
|
|
@@ -7469,7 +7662,8 @@ Return exactly ${cues.length} translated cues in the same order as the input.
|
|
|
7469
7662
|
${JSON.stringify(cuePayload, null, 2)}`
|
|
7470
7663
|
}
|
|
7471
7664
|
]
|
|
7472
|
-
});
|
|
7665
|
+
}));
|
|
7666
|
+
const output = getGeneratedOutputWithContentPolicyHandling(response);
|
|
7473
7667
|
const unexpectedKeys = detectUnexpectedKeysFromRawText(
|
|
7474
7668
|
response.text,
|
|
7475
7669
|
schema.keyof().options
|
|
@@ -7480,13 +7674,14 @@ ${JSON.stringify(cuePayload, null, 2)}`
|
|
|
7480
7674
|
);
|
|
7481
7675
|
}
|
|
7482
7676
|
return {
|
|
7483
|
-
translations:
|
|
7677
|
+
translations: output.translations,
|
|
7484
7678
|
usage: {
|
|
7485
7679
|
inputTokens: response.usage.inputTokens,
|
|
7486
7680
|
outputTokens: response.usage.outputTokens,
|
|
7487
7681
|
totalTokens: response.usage.totalTokens,
|
|
7488
7682
|
reasoningTokens: response.usage.reasoningTokens,
|
|
7489
|
-
cachedInputTokens: response.usage.cachedInputTokens
|
|
7683
|
+
cachedInputTokens: response.usage.cachedInputTokens,
|
|
7684
|
+
cacheWriteTokens: response.usage.inputTokenDetails?.cacheWriteTokens
|
|
7490
7685
|
},
|
|
7491
7686
|
unexpectedKeyCount: unexpectedKeys.length
|
|
7492
7687
|
};
|