@mux/ai 0.6.0 → 0.7.2

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.
@@ -1,3 +1,3 @@
1
- export { D as DEFAULT_STORYBOARD_WIDTH, T as ThumbnailOptions, f as TranscriptFetchOptions, h as TranscriptResult, V as VTTCue, n as buildTranscriptUrl, c as chunkByTokens, b as chunkText, a as chunkVTTCues, e as estimateTokenCount, l as extractTextFromVTT, m as extractTimestampedTranscript, o as fetchTranscriptForAsset, k as findCaptionTrack, j as getReadyTextTracks, g as getStoryboardUrl, d as getThumbnailUrls, p as parseVTTCues, s as secondsToTimestamp, v as vttTimestampToSeconds } from '../index-DAlX4SNJ.js';
2
- import '../types-CqjLMB84.js';
1
+ export { D as DEFAULT_STORYBOARD_WIDTH, H as HeatmapOptions, a as HeatmapResponse, b as Hotspot, c as HotspotOptions, d as HotspotResponse, T as ThumbnailOptions, e as TranscriptFetchOptions, f as TranscriptResult, V as VTTCue, g as buildTranscriptUrl, h as chunkByTokens, j as chunkText, k as chunkVTTCues, l as estimateTokenCount, m as extractTextFromVTT, n as extractTimestampedTranscript, o as fetchTranscriptForAsset, p as findCaptionTrack, q as getHeatmapForAsset, r as getHeatmapForPlaybackId, s as getHeatmapForVideo, t as getHotspotsForAsset, u as getHotspotsForPlaybackId, v as getHotspotsForVideo, w as getReadyTextTracks, x as getStoryboardUrl, y as getThumbnailUrls, z as parseVTTCues, A as secondsToTimestamp, B as vttTimestampToSeconds } from '../index-DZlygsvb.js';
2
+ import '../types-BQVi_wnh.js';
3
3
  import '@mux/mux-node';
@@ -1,5 +1,7 @@
1
- // src/lib/url-signing.ts
2
- import Mux from "@mux/mux-node";
1
+ // src/lib/providers.ts
2
+ import { createAnthropic } from "@ai-sdk/anthropic";
3
+ import { createGoogleGenerativeAI } from "@ai-sdk/google";
4
+ import { createOpenAI } from "@ai-sdk/openai";
3
5
 
4
6
  // src/env.ts
5
7
  import { z } from "zod";
@@ -54,6 +56,9 @@ var EnvSchema = z.object({
54
56
  S3_BUCKET: optionalString("Bucket used for caption and audio uploads.", "S3 bucket"),
55
57
  S3_ACCESS_KEY_ID: optionalString("Access key ID for S3-compatible uploads.", "S3 access key id"),
56
58
  S3_SECRET_ACCESS_KEY: optionalString("Secret access key for S3-compatible uploads.", "S3 secret access key"),
59
+ S3_ALLOWED_ENDPOINT_HOSTS: optionalString(
60
+ "Comma-separated S3 endpoint allowlist (supports exact hosts and *.suffix patterns)."
61
+ ),
57
62
  EVALITE_RESULTS_ENDPOINT: optionalString(
58
63
  "Full URL for posting Evalite results (e.g., https://example.com/api/evalite-results).",
59
64
  "Evalite results endpoint"
@@ -95,11 +100,15 @@ var WORKFLOW_ENCRYPTION_VERSION = 1;
95
100
  var WORKFLOW_ENCRYPTION_ALGORITHM = "aes-256-gcm";
96
101
  var IV_LENGTH_BYTES = 12;
97
102
  var AUTH_TAG_LENGTH_BYTES = 16;
103
+ function normalizeBase64Input(value) {
104
+ const cleaned = value.replace(/\s+/g, "").replace(/-/g, "+").replace(/_/g, "/");
105
+ return cleaned?.length % 4 === 0 ? cleaned : cleaned + "=".repeat(4 - cleaned.length % 4);
106
+ }
98
107
  function base64ToBytes(value, label) {
99
108
  if (!value) {
100
109
  throw new Error(`${label} is missing`);
101
110
  }
102
- const normalized = value.length % 4 === 0 ? value : value + "=".repeat(4 - value.length % 4);
111
+ const normalized = normalizeBase64Input(value);
103
112
  const atobImpl = typeof globalThis.atob === "function" ? globalThis.atob.bind(globalThis) : void 0;
104
113
  if (atobImpl) {
105
114
  let binary;
@@ -117,19 +126,18 @@ function base64ToBytes(value, label) {
117
126
  }
118
127
  return bytes2;
119
128
  }
120
- const cleaned = normalized.replace(/\s+/g, "");
121
- if (cleaned.length % 4 !== 0) {
129
+ if (normalized.length % 4 !== 0) {
122
130
  throw new Error(`${label} is not valid base64`);
123
131
  }
124
- const padding = cleaned.endsWith("==") ? 2 : cleaned.endsWith("=") ? 1 : 0;
125
- const outputLength = cleaned.length / 4 * 3 - padding;
132
+ const padding = normalized.endsWith("==") ? 2 : normalized.endsWith("=") ? 1 : 0;
133
+ const outputLength = normalized.length / 4 * 3 - padding;
126
134
  const bytes = new Uint8Array(outputLength);
127
135
  let offset = 0;
128
- for (let i = 0; i < cleaned.length; i += 4) {
129
- const c0 = cleaned.charCodeAt(i);
130
- const c1 = cleaned.charCodeAt(i + 1);
131
- const c2 = cleaned.charCodeAt(i + 2);
132
- const c3 = cleaned.charCodeAt(i + 3);
136
+ for (let i = 0; i < normalized.length; i += 4) {
137
+ const c0 = normalized.charCodeAt(i);
138
+ const c1 = normalized.charCodeAt(i + 1);
139
+ const c2 = normalized.charCodeAt(i + 2);
140
+ const c3 = normalized.charCodeAt(i + 3);
133
141
  if (c0 === 61 || c1 === 61) {
134
142
  throw new Error(`${label} is not valid base64`);
135
143
  }
@@ -250,7 +258,9 @@ async function shouldEnforceEncryptedCredentials() {
250
258
  function getWorkflowSecretKeyFromEnv() {
251
259
  const key = env_default.MUX_AI_WORKFLOW_SECRET_KEY;
252
260
  if (!key) {
253
- throw new Error("Workflow secret key is required. Set MUX_AI_WORKFLOW_SECRET_KEY environment variable.");
261
+ throw new Error(
262
+ "Workflow secret key is required. Set MUX_AI_WORKFLOW_SECRET_KEY environment variable."
263
+ );
254
264
  }
255
265
  return key;
256
266
  }
@@ -281,30 +291,182 @@ async function resolveWorkflowCredentials(credentials) {
281
291
  );
282
292
  return { ...resolved, ...decrypted };
283
293
  } catch (error) {
284
- const detail = error instanceof Error ? error.message : String(error);
294
+ const detail = error instanceof Error ? error.message : "Unknown error.";
285
295
  throw new Error(`Failed to decrypt workflow credentials. ${detail}`);
286
296
  }
287
297
  }
288
298
  if (await shouldEnforceEncryptedCredentials()) {
289
299
  throw new Error(
290
- "Plaintext workflow credentials are not allowed when using Workflow Dev Kit.Pass encrypted credentials (encryptForWorkflow) or resolve secrets via environment variables."
300
+ "Plaintext workflow credentials are not allowed when using Workflow Dev Kit. Pass encrypted credentials (encryptForWorkflow) or resolve secrets via environment variables."
291
301
  );
292
302
  }
293
303
  return { ...resolved, ...credentials };
294
304
  }
305
+ function readString(record, key) {
306
+ const value = record?.[key];
307
+ return typeof value === "string" && value.length > 0 ? value : void 0;
308
+ }
309
+ function resolveDirectMuxCredentials(record) {
310
+ const tokenId = readString(record, "muxTokenId");
311
+ const tokenSecret = readString(record, "muxTokenSecret");
312
+ const signingKey = readString(record, "muxSigningKey");
313
+ const privateKey = readString(record, "muxPrivateKey");
314
+ if (!tokenId && !tokenSecret && !signingKey && !privateKey) {
315
+ return void 0;
316
+ }
317
+ if (!tokenId || !tokenSecret) {
318
+ throw new Error(
319
+ "Both muxTokenId and muxTokenSecret are required when passing direct Mux workflow credentials."
320
+ );
321
+ }
322
+ return {
323
+ tokenId,
324
+ tokenSecret,
325
+ signingKey,
326
+ privateKey
327
+ };
328
+ }
329
+ function createWorkflowMuxClient(options) {
330
+ return {
331
+ async createClient() {
332
+ const { default: MuxClient } = await import("@mux/mux-node");
333
+ return new MuxClient({
334
+ tokenId: options.tokenId,
335
+ tokenSecret: options.tokenSecret
336
+ });
337
+ },
338
+ getSigningKey() {
339
+ return options.signingKey;
340
+ },
341
+ getPrivateKey() {
342
+ return options.privateKey;
343
+ }
344
+ };
345
+ }
346
+ async function resolveMuxClient(credentials) {
347
+ const resolved = await resolveWorkflowCredentials(credentials);
348
+ const resolvedRecord = resolved;
349
+ const resolvedMuxCredentials = resolveDirectMuxCredentials(resolvedRecord);
350
+ if (resolvedMuxCredentials) {
351
+ return createWorkflowMuxClient(resolvedMuxCredentials);
352
+ }
353
+ const muxTokenId = env_default.MUX_TOKEN_ID;
354
+ const muxTokenSecret = env_default.MUX_TOKEN_SECRET;
355
+ if (!muxTokenId || !muxTokenSecret) {
356
+ throw new Error(
357
+ "Mux credentials are required. Provide muxTokenId/muxTokenSecret via workflow credentials, or set MUX_TOKEN_ID and MUX_TOKEN_SECRET environment variables."
358
+ );
359
+ }
360
+ return createWorkflowMuxClient({
361
+ tokenId: muxTokenId,
362
+ tokenSecret: muxTokenSecret,
363
+ signingKey: env_default.MUX_SIGNING_KEY,
364
+ privateKey: env_default.MUX_PRIVATE_KEY
365
+ });
366
+ }
295
367
  async function resolveMuxSigningContext(credentials) {
296
368
  const resolved = await resolveWorkflowCredentials(credentials);
297
- const keyId = resolved.muxSigningKey ?? env_default.MUX_SIGNING_KEY;
298
- const keySecret = resolved.muxPrivateKey ?? env_default.MUX_PRIVATE_KEY;
369
+ const resolvedRecord = resolved;
370
+ const keyId = readString(resolvedRecord, "muxSigningKey") ?? env_default.MUX_SIGNING_KEY;
371
+ const keySecret = readString(resolvedRecord, "muxPrivateKey") ?? env_default.MUX_PRIVATE_KEY;
299
372
  if (!keyId || !keySecret) {
300
373
  return void 0;
301
374
  }
302
375
  return { keyId, keySecret };
303
376
  }
304
377
 
378
+ // src/lib/client-factory.ts
379
+ async function getMuxClientFromEnv(credentials) {
380
+ return resolveMuxClient(credentials);
381
+ }
382
+
383
+ // src/primitives/heatmap.ts
384
+ async function getHeatmapForAsset(assetId, options = {}) {
385
+ "use step";
386
+ return fetchHeatmap("assets", assetId, options);
387
+ }
388
+ async function getHeatmapForVideo(videoId, options = {}) {
389
+ "use step";
390
+ return fetchHeatmap("videos", videoId, options);
391
+ }
392
+ async function getHeatmapForPlaybackId(playbackId, options = {}) {
393
+ "use step";
394
+ return fetchHeatmap("playback-ids", playbackId, options);
395
+ }
396
+ function transformHeatmapResponse(response) {
397
+ return {
398
+ assetId: response.asset_id,
399
+ videoId: response.video_id,
400
+ playbackId: response.playback_id,
401
+ heatmap: response.heatmap,
402
+ timeframe: response.timeframe
403
+ };
404
+ }
405
+ async function fetchHeatmap(identifierType, id, options) {
406
+ "use step";
407
+ const { timeframe = "[24:hours]", credentials } = options;
408
+ const muxClient = await getMuxClientFromEnv(credentials);
409
+ const mux = await muxClient.createClient();
410
+ const queryParams = new URLSearchParams();
411
+ queryParams.append("timeframe[]", timeframe);
412
+ const path = `/data/v1/engagement/${identifierType}/${id}/heatmap?${queryParams.toString()}`;
413
+ const response = await mux.get(path);
414
+ return transformHeatmapResponse(response);
415
+ }
416
+
417
+ // src/primitives/hotspots.ts
418
+ async function getHotspotsForAsset(assetId, options = {}) {
419
+ "use step";
420
+ const response = await fetchHotspots("assets", assetId, options);
421
+ return response.hotspots;
422
+ }
423
+ async function getHotspotsForVideo(videoId, options = {}) {
424
+ "use step";
425
+ const response = await fetchHotspots("videos", videoId, options);
426
+ return response.hotspots;
427
+ }
428
+ async function getHotspotsForPlaybackId(playbackId, options = {}) {
429
+ "use step";
430
+ const response = await fetchHotspots("playback-ids", playbackId, options);
431
+ return response.hotspots;
432
+ }
433
+ function transformHotspotResponse(response) {
434
+ return {
435
+ assetId: response.data.asset_id,
436
+ videoId: response.data.video_id,
437
+ playbackId: response.data.playback_id,
438
+ hotspots: response.data.hotspots.map((h) => ({
439
+ startMs: h.start_ms,
440
+ endMs: h.end_ms,
441
+ score: h.score
442
+ }))
443
+ };
444
+ }
445
+ async function fetchHotspots(identifierType, id, options) {
446
+ "use step";
447
+ const {
448
+ limit = 5,
449
+ orderDirection = "desc",
450
+ orderBy = "score",
451
+ timeframe = "[24:hours]",
452
+ credentials
453
+ } = options;
454
+ const muxClient = await getMuxClientFromEnv(credentials);
455
+ const mux = await muxClient.createClient();
456
+ const queryParams = new URLSearchParams();
457
+ queryParams.append("limit", String(limit));
458
+ queryParams.append("order_direction", orderDirection);
459
+ queryParams.append("order_by", orderBy);
460
+ queryParams.append("timeframe[]", timeframe);
461
+ const path = `/data/v1/engagement/${identifierType}/${id}/hotspots?${queryParams.toString()}`;
462
+ const response = await mux.get(path);
463
+ return transformHotspotResponse(response);
464
+ }
465
+
305
466
  // src/lib/url-signing.ts
306
- function createSigningClient(context) {
307
- return new Mux({
467
+ async function createSigningClient(context) {
468
+ const { default: MuxClient } = await import("@mux/mux-node");
469
+ return new MuxClient({
308
470
  // These are not needed for signing, but the SDK requires them
309
471
  // Using empty strings as we only need the jwt functionality
310
472
  tokenId: env_default.MUX_TOKEN_ID || "",
@@ -315,7 +477,7 @@ function createSigningClient(context) {
315
477
  }
316
478
  async function signPlaybackId(playbackId, context, type = "video", params) {
317
479
  "use step";
318
- const client = createSigningClient(context);
480
+ const client = await createSigningClient(context);
319
481
  const stringParams = params ? Object.fromEntries(
320
482
  Object.entries(params).map(([key, value]) => [key, String(value)])
321
483
  ) : void 0;
@@ -330,7 +492,7 @@ async function signUrl(url, playbackId, context, type = "video", params, credent
330
492
  const resolvedContext = context ?? await resolveMuxSigningContext(credentials);
331
493
  if (!resolvedContext) {
332
494
  throw new Error(
333
- "Signed playback ID requires signing credentials. Provide muxSigningKey and muxPrivateKey in credentials or set MUX_SIGNING_KEY and MUX_PRIVATE_KEY environment variables."
495
+ "Signed playback ID requires signing credentials. Provide muxSigningKey and muxPrivateKey via workflow credentials or set MUX_SIGNING_KEY and MUX_PRIVATE_KEY environment variables."
334
496
  );
335
497
  }
336
498
  const token = await signPlaybackId(playbackId, resolvedContext, type, params);
@@ -658,6 +820,12 @@ export {
658
820
  extractTimestampedTranscript,
659
821
  fetchTranscriptForAsset,
660
822
  findCaptionTrack,
823
+ getHeatmapForAsset,
824
+ getHeatmapForPlaybackId,
825
+ getHeatmapForVideo,
826
+ getHotspotsForAsset,
827
+ getHotspotsForPlaybackId,
828
+ getHotspotsForVideo,
661
829
  getReadyTextTracks,
662
830
  getStoryboardUrl,
663
831
  getThumbnailUrls,