@scenar/cli 0.9.1 → 0.11.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.
Files changed (175) hide show
  1. package/example-bundle/assets/index-DxmqjG-8.js +388 -0
  2. package/example-bundle/assets/style-B2sxnVVZ.css +1 -0
  3. package/example-bundle/embed.js +1 -1
  4. package/example-bundle/index.html +2 -2
  5. package/example-bundle/logo.png +0 -0
  6. package/example-bundle/pack-manifest.json +33 -9
  7. package/example-bundle/soundtrack/music.mp3 +0 -0
  8. package/example-bundle/soundtrack/sfx/click.mp3 +0 -0
  9. package/example-bundle/soundtrack/sfx/keystroke.mp3 +0 -0
  10. package/package.json +4 -4
  11. package/src/__tests__/collect-pack-shots.test.ts +27 -1
  12. package/src/__tests__/elevenlabs-provider.test.ts +187 -0
  13. package/src/__tests__/embed-snippet.test.ts +5 -0
  14. package/src/__tests__/find-authored-soundtrack.test.ts +54 -0
  15. package/src/__tests__/find-authored-title-cards.test.ts +65 -0
  16. package/src/__tests__/find-authored-viewport.test.ts +58 -0
  17. package/src/__tests__/load-bundle.test.ts +67 -0
  18. package/src/__tests__/narrate-command.test.ts +65 -1
  19. package/src/__tests__/narration-cache.test.ts +134 -0
  20. package/src/__tests__/pack-bundle-contract.test.ts +2 -0
  21. package/src/__tests__/pack-generate-embed-entry.test.ts +99 -16
  22. package/src/__tests__/presenter-command.test.ts +366 -0
  23. package/src/__tests__/render-command.test.ts +11 -0
  24. package/src/__tests__/render-generate-entry.test.ts +102 -0
  25. package/src/__tests__/resolve-pack-viewport.test.ts +46 -0
  26. package/src/__tests__/resolve-provider.test.ts +32 -3
  27. package/src/__tests__/scenario-validator.test.ts +174 -0
  28. package/src/__tests__/stage-assets.test.ts +269 -0
  29. package/src/commands/narrate.js +1 -1
  30. package/src/commands/narrate.js.map +1 -1
  31. package/src/commands/narrate.ts +1 -1
  32. package/src/commands/pack.d.ts.map +1 -1
  33. package/src/commands/pack.js +23 -4
  34. package/src/commands/pack.js.map +1 -1
  35. package/src/commands/pack.ts +26 -5
  36. package/src/commands/presenter.d.ts +3 -0
  37. package/src/commands/presenter.d.ts.map +1 -0
  38. package/src/commands/presenter.js +89 -0
  39. package/src/commands/presenter.js.map +1 -0
  40. package/src/commands/presenter.ts +107 -0
  41. package/src/commands/render.d.ts.map +1 -1
  42. package/src/commands/render.js +2 -0
  43. package/src/commands/render.js.map +1 -1
  44. package/src/commands/render.ts +6 -0
  45. package/src/embed/embed-snippet.d.ts +5 -0
  46. package/src/embed/embed-snippet.d.ts.map +1 -1
  47. package/src/embed/embed-snippet.js +6 -1
  48. package/src/embed/embed-snippet.js.map +1 -1
  49. package/src/embed/embed-snippet.ts +6 -1
  50. package/src/index.d.ts.map +1 -1
  51. package/src/index.js +2 -0
  52. package/src/index.js.map +1 -1
  53. package/src/index.ts +2 -0
  54. package/src/narrate/run-narrate.d.ts +15 -1
  55. package/src/narrate/run-narrate.d.ts.map +1 -1
  56. package/src/narrate/run-narrate.js +11 -4
  57. package/src/narrate/run-narrate.js.map +1 -1
  58. package/src/narrate/run-narrate.ts +15 -6
  59. package/src/pack/bundle-contract.d.ts +1 -0
  60. package/src/pack/bundle-contract.d.ts.map +1 -1
  61. package/src/pack/bundle-contract.js +3 -0
  62. package/src/pack/bundle-contract.js.map +1 -1
  63. package/src/pack/bundle-contract.ts +3 -0
  64. package/src/pack/collect-pack-shots.d.ts +16 -5
  65. package/src/pack/collect-pack-shots.d.ts.map +1 -1
  66. package/src/pack/collect-pack-shots.js +13 -4
  67. package/src/pack/collect-pack-shots.js.map +1 -1
  68. package/src/pack/collect-pack-shots.ts +35 -8
  69. package/src/pack/generate-embed-entry.d.ts +7 -0
  70. package/src/pack/generate-embed-entry.d.ts.map +1 -1
  71. package/src/pack/generate-embed-entry.js +105 -7
  72. package/src/pack/generate-embed-entry.js.map +1 -1
  73. package/src/pack/generate-embed-entry.ts +110 -7
  74. package/src/pack/run-pack.d.ts +8 -2
  75. package/src/pack/run-pack.d.ts.map +1 -1
  76. package/src/pack/run-pack.js +120 -17
  77. package/src/pack/run-pack.js.map +1 -1
  78. package/src/pack/run-pack.ts +164 -19
  79. package/src/pack/viewport.d.ts +17 -0
  80. package/src/pack/viewport.d.ts.map +1 -1
  81. package/src/pack/viewport.js +19 -0
  82. package/src/pack/viewport.js.map +1 -1
  83. package/src/pack/viewport.ts +29 -0
  84. package/src/presenter/heygen-client.d.ts +69 -0
  85. package/src/presenter/heygen-client.d.ts.map +1 -0
  86. package/src/presenter/heygen-client.js +154 -0
  87. package/src/presenter/heygen-client.js.map +1 -0
  88. package/src/presenter/heygen-client.ts +224 -0
  89. package/src/presenter/run-presenter.d.ts +67 -0
  90. package/src/presenter/run-presenter.d.ts.map +1 -0
  91. package/src/presenter/run-presenter.js +348 -0
  92. package/src/presenter/run-presenter.js.map +1 -0
  93. package/src/presenter/run-presenter.ts +536 -0
  94. package/src/render/generate-entry.d.ts +4 -0
  95. package/src/render/generate-entry.d.ts.map +1 -1
  96. package/src/render/generate-entry.js +75 -7
  97. package/src/render/generate-entry.js.map +1 -1
  98. package/src/render/generate-entry.ts +84 -7
  99. package/src/render/run-render.d.ts +6 -0
  100. package/src/render/run-render.d.ts.map +1 -1
  101. package/src/render/run-render.js +58 -0
  102. package/src/render/run-render.js.map +1 -1
  103. package/src/render/run-render.ts +72 -0
  104. package/src/render/stage-assets.d.ts +44 -0
  105. package/src/render/stage-assets.d.ts.map +1 -0
  106. package/src/render/stage-assets.js +91 -0
  107. package/src/render/stage-assets.js.map +1 -0
  108. package/src/render/stage-assets.ts +130 -0
  109. package/src/tts/echogarden.d.ts.map +1 -1
  110. package/src/tts/echogarden.js +4 -2
  111. package/src/tts/echogarden.js.map +1 -1
  112. package/src/tts/echogarden.ts +5 -2
  113. package/src/tts/edge-tts.d.ts.map +1 -1
  114. package/src/tts/edge-tts.js +2 -1
  115. package/src/tts/edge-tts.js.map +1 -1
  116. package/src/tts/edge-tts.ts +2 -1
  117. package/src/tts/elevenlabs.d.ts +15 -0
  118. package/src/tts/elevenlabs.d.ts.map +1 -0
  119. package/src/tts/elevenlabs.js +73 -0
  120. package/src/tts/elevenlabs.js.map +1 -0
  121. package/src/tts/elevenlabs.ts +105 -0
  122. package/src/tts/openai.d.ts.map +1 -1
  123. package/src/tts/openai.js +2 -1
  124. package/src/tts/openai.js.map +1 -1
  125. package/src/tts/openai.ts +2 -1
  126. package/src/tts/resolve-provider.d.ts +1 -1
  127. package/src/tts/resolve-provider.d.ts.map +1 -1
  128. package/src/tts/resolve-provider.js +10 -3
  129. package/src/tts/resolve-provider.js.map +1 -1
  130. package/src/tts/resolve-provider.ts +12 -4
  131. package/src/tts/types.d.ts +9 -0
  132. package/src/tts/types.d.ts.map +1 -1
  133. package/src/tts/types.ts +10 -0
  134. package/src/util/confirm.d.ts +11 -0
  135. package/src/util/confirm.d.ts.map +1 -0
  136. package/src/util/confirm.js +24 -0
  137. package/src/util/confirm.js.map +1 -0
  138. package/src/util/confirm.ts +23 -0
  139. package/src/util/load-bundle.d.ts +17 -1
  140. package/src/util/load-bundle.d.ts.map +1 -1
  141. package/src/util/load-bundle.js +19 -11
  142. package/src/util/load-bundle.js.map +1 -1
  143. package/src/util/load-bundle.ts +38 -12
  144. package/src/util/load-ts.d.ts +100 -0
  145. package/src/util/load-ts.d.ts.map +1 -1
  146. package/src/util/load-ts.js +176 -0
  147. package/src/util/load-ts.js.map +1 -1
  148. package/src/util/load-ts.ts +227 -0
  149. package/src/util/narration-cache.d.ts +13 -5
  150. package/src/util/narration-cache.d.ts.map +1 -1
  151. package/src/util/narration-cache.js +10 -8
  152. package/src/util/narration-cache.js.map +1 -1
  153. package/src/util/narration-cache.ts +22 -6
  154. package/src/util/presenter-cache.d.ts +44 -0
  155. package/src/util/presenter-cache.d.ts.map +1 -0
  156. package/src/util/presenter-cache.js +43 -0
  157. package/src/util/presenter-cache.js.map +1 -0
  158. package/src/util/presenter-cache.ts +101 -0
  159. package/src/util/scenario-assets.d.ts +47 -0
  160. package/src/util/scenario-assets.d.ts.map +1 -0
  161. package/src/util/scenario-assets.js +71 -0
  162. package/src/util/scenario-assets.js.map +1 -0
  163. package/src/util/scenario-assets.ts +111 -0
  164. package/src/util/soundtrack-assets.d.ts +34 -0
  165. package/src/util/soundtrack-assets.d.ts.map +1 -0
  166. package/src/util/soundtrack-assets.js +48 -0
  167. package/src/util/soundtrack-assets.js.map +1 -0
  168. package/src/util/soundtrack-assets.ts +69 -0
  169. package/src/validate/scenario-validator.d.ts.map +1 -1
  170. package/src/validate/scenario-validator.js +82 -0
  171. package/src/validate/scenario-validator.js.map +1 -1
  172. package/src/validate/scenario-validator.ts +110 -0
  173. package/tsconfig.tsbuildinfo +1 -1
  174. package/example-bundle/assets/index-DlmG1Uh7.js +0 -388
  175. package/example-bundle/assets/style-BjquDnTE.css +0 -1
@@ -1,7 +1,14 @@
1
- import { resolve, join, basename } from "node:path";
1
+ import { resolve, join, basename, dirname } from "node:path";
2
2
  import { stat, mkdir, writeFile, rm, readdir, copyFile, access } from "node:fs/promises";
3
3
  import { detectRenderExport } from "../render/detect-render-export.js";
4
4
  import { resolveProvidersPath } from "../render/resolve-providers.js";
5
+ import type { AuthoredSoundtrack, AuthoredTitleCards } from "../util/load-ts.js";
6
+ import {
7
+ SFX_DEST_PATHS,
8
+ resolveMusicAsset,
9
+ resolveSfxAssetPaths,
10
+ } from "../util/soundtrack-assets.js";
11
+ import { resolveLogoAsset } from "../util/scenario-assets.js";
5
12
  import { generateEmbedEntry, generateEmbedHtml } from "./generate-embed-entry.js";
6
13
  import { collectPackShots, type CollectedPackShots } from "./collect-pack-shots.js";
7
14
  import { runViteBuild } from "./build.js";
@@ -13,7 +20,7 @@ import {
13
20
  verifyManifestFilesExist,
14
21
  type PackManifest,
15
22
  } from "./pack-manifest.js";
16
- import { DEFAULT_VIEWPORT } from "./viewport.js";
23
+ import { DEFAULT_VIEWPORT, resolvePackViewport } from "./viewport.js";
17
24
 
18
25
  /**
19
26
  * Generator version stamped into scenario.json (kept in sync with the CLI).
@@ -27,9 +34,14 @@ export interface RunPackOptions {
27
34
  readonly scenarioDir: string;
28
35
  /** Output directory for the bundle (default: ./<scenario-id>-bundle). */
29
36
  readonly outDir?: string;
30
- /** Canonical viewport width in px (default: {@link DEFAULT_VIEWPORT}.width). */
37
+ /**
38
+ * Canonical viewport width in px. Omitted -> the scenario's own authored
39
+ * viewport (`createScenario({ viewport })` or an exported `viewport`
40
+ * constant) applies; a scenario that authors none falls back to
41
+ * {@link DEFAULT_VIEWPORT}. Explicit flags always win over both.
42
+ */
31
43
  readonly width?: number;
32
- /** Shell/container height in px (default: {@link DEFAULT_VIEWPORT}.height). */
44
+ /** Shell/container height in px. Same resolution chain as `width`. */
33
45
  readonly shellHeight?: number;
34
46
  /**
35
47
  * Float the scenario on a backdrop with a window shadow (screen-recording
@@ -50,6 +62,7 @@ export interface PackResult {
50
62
  readonly renderFilePath: string;
51
63
  readonly providersPath: string | null;
52
64
  readonly hasNarration: boolean;
65
+ readonly hasPresenter: boolean;
53
66
  /**
54
67
  * The declared shot names recorded in scenario.json (empty = the scenario
55
68
  * authoritatively declares none), or undefined when the steps module could
@@ -83,8 +96,6 @@ export async function runPack(options: RunPackOptions): Promise<PackResult> {
83
96
 
84
97
  const scenarioId = basename(scenarioDir);
85
98
  const outDir = options.outDir ? resolve(options.outDir) : resolve(`./${scenarioId}-bundle`);
86
- const width = options.width ?? DEFAULT_VIEWPORT.width;
87
- const shellHeight = options.shellHeight ?? DEFAULT_VIEWPORT.height;
88
99
 
89
100
  // The entry must live inside the scenario directory so the bundler's
90
101
  // node_modules resolution walks up into the consumer project.
@@ -94,21 +105,41 @@ export async function runPack(options: RunPackOptions): Promise<PackResult> {
94
105
  const renderFilePath = await detectRenderExport(scenarioDir);
95
106
  const providersPath = await resolveProvidersPath(scenarioDir);
96
107
  const hasNarration = await fileExists(join(scenarioDir, "narration", "manifest.json"));
108
+ const hasPresenter = await fileExists(join(scenarioDir, "presenter", "manifest.json"));
97
109
 
98
110
  onLog(`Scenario: ${scenarioId}`);
99
111
  onLog(`Render: ${renderFilePath}`);
100
112
  onLog(`Providers: ${providersPath ?? "none"}`);
101
113
  onLog(`Narration: ${hasNarration ? "yes (manifest found)" : "none"}`);
114
+ onLog(`Presenter: ${hasPresenter ? "yes (manifest found)" : "none"}`);
102
115
  onLog(`Output: ${outDir}`);
103
116
 
104
- // 1. Discover the declared shots by SSR-loading the steps module (same
105
- // Vite resolution as the build below). Before the build on purpose:
106
- // authoring errors bad shot names, no steps array fail fast here,
107
- // without paying for a bundle. An import failure is tolerated: the
108
- // shots are then unknown and scenario.json omits the key.
117
+ // 1. Discover the declared shots and the authored viewport — by
118
+ // SSR-loading the steps module (same Vite resolution as the build
119
+ // below). Before the build on purpose: authoring errorsbad shot
120
+ // names, no steps array fail fast here, without paying for a
121
+ // bundle. An import failure is tolerated: the shots are then unknown
122
+ // and scenario.json omits the key.
109
123
  const collectedShots = await collectPackShots(scenarioDir);
110
124
  onLog(`Shots: ${describeCollectedShots(collectedShots)}`);
111
125
 
126
+ // Canonical viewport: explicit options > the scenario's authored
127
+ // viewport > the packer default. Authored viewports used to be silently
128
+ // ignored (the authoring docs demonstrated `createScenario({ viewport })`
129
+ // while pack only ever read its own options); the source is logged so a
130
+ // surprising size is one log line from its explanation.
131
+ const resolvedViewport = resolvePackViewport(
132
+ options,
133
+ collectedShots.recorded ? collectedShots.authoredViewport : null,
134
+ );
135
+ const { width, height: shellHeight } = resolvedViewport;
136
+ const viewportSourceLabel = {
137
+ explicit: "explicit",
138
+ authored: "authored by the scenario",
139
+ default: "packer default",
140
+ }[resolvedViewport.source];
141
+ onLog(`Viewport: ${width}x${shellHeight} (${viewportSourceLabel})`);
142
+
112
143
  // 2. Generate the browser entry + index.html into the temp dir.
113
144
  const stage = options.stage ?? false;
114
145
  const entrySource = generateEmbedEntry({
@@ -116,6 +147,7 @@ export async function runPack(options: RunPackOptions): Promise<PackResult> {
116
147
  renderFilePath,
117
148
  scenarioId,
118
149
  hasNarration,
150
+ hasPresenter,
119
151
  providersPath,
120
152
  canonicalWidth: width,
121
153
  shellHeight,
@@ -135,7 +167,48 @@ export async function runPack(options: RunPackOptions): Promise<PackResult> {
135
167
  // ./narration/manifest.json at runtime and resolves each clip's
136
168
  // relative src against it, so both must ship in the bundle.
137
169
  if (hasNarration) {
138
- await copyNarration(scenarioDir, outDir);
170
+ await copyClipTrack(scenarioDir, outDir, "narration", ".mp3");
171
+ }
172
+
173
+ // 4a. Copy the presenter manifest + clips — the same runtime contract
174
+ // as narration: the embed fetches ./presenter/manifest.json and
175
+ // resolves each clip's relative src against it. CSP is
176
+ // `media-src 'self'`, so the clips must ship in the bundle.
177
+ if (hasPresenter) {
178
+ await copyClipTrack(scenarioDir, outDir, "presenter", ".mp4");
179
+ }
180
+
181
+ // 4b. Copy the soundtrack's assets: the authored music file (at its
182
+ // scenario-relative path, which is what the embed references) and
183
+ // the built-in SFX set from @scenar/react. Discovery rides the same
184
+ // SSR load as the shots; when the module was not loadable, the
185
+ // soundtrack (if any) cannot ship — warn rather than silently
186
+ // packing an embed whose audio 404s.
187
+ if (collectedShots.recorded) {
188
+ if (collectedShots.authoredSoundtrack) {
189
+ const copied = await copySoundtrack(
190
+ scenarioDir,
191
+ outDir,
192
+ collectedShots.authoredSoundtrack,
193
+ );
194
+ if (copied > 0) onLog(`Soundtrack: ${copied} audio file(s) copied into the bundle`);
195
+ }
196
+ // 4c. Copy title-card logos at their scenario-relative paths (the
197
+ // card component references them by that same path). Discovery
198
+ // rides the same SSR load as the shots and the soundtrack.
199
+ if (collectedShots.authoredTitleCards) {
200
+ const copied = await copyTitleCardLogos(
201
+ scenarioDir,
202
+ outDir,
203
+ collectedShots.authoredTitleCards,
204
+ );
205
+ if (copied > 0) onLog(`Cards: ${copied} logo file(s) copied into the bundle`);
206
+ }
207
+ } else {
208
+ onLog(
209
+ "Warning: steps module not loadable under Node — if this scenario authors a " +
210
+ "soundtrack or title cards, their asset files were NOT copied into the bundle.",
211
+ );
139
212
  }
140
213
 
141
214
  // 5. Write the required scenario.json descriptor, recording the canonical
@@ -170,6 +243,7 @@ export async function runPack(options: RunPackOptions): Promise<PackResult> {
170
243
  renderFilePath,
171
244
  providersPath,
172
245
  hasNarration,
246
+ hasPresenter,
173
247
  shots: collectedShots.recorded ? collectedShots.shots : undefined,
174
248
  manifest,
175
249
  totalBytes,
@@ -182,24 +256,95 @@ export async function runPack(options: RunPackOptions): Promise<PackResult> {
182
256
  }
183
257
 
184
258
  /**
185
- * Copy the narration manifest and every *.mp3 from <scenarioDir>/narration into
186
- * <outDir>/narration. The manifest is the runtime index the embed fetches; the
187
- * mp3s are the clips it references by relative src.
259
+ * Copy one clip track's manifest and media (narration mp3s, presenter
260
+ * mp4s) from <scenarioDir>/<trackDir> into <outDir>/<trackDir>. The
261
+ * manifest is the runtime index the embed fetches; the clips are what it
262
+ * references by relative src. Cache files never ship.
188
263
  */
189
- async function copyNarration(scenarioDir: string, outDir: string): Promise<void> {
190
- const srcDir = join(scenarioDir, "narration");
191
- const destDir = join(outDir, "narration");
264
+ async function copyClipTrack(
265
+ scenarioDir: string,
266
+ outDir: string,
267
+ trackDir: string,
268
+ extension: string,
269
+ ): Promise<void> {
270
+ const srcDir = join(scenarioDir, trackDir);
271
+ const destDir = join(outDir, trackDir);
192
272
  await mkdir(destDir, { recursive: true });
193
273
  const entries = await readdir(srcDir, { withFileTypes: true });
194
274
  for (const entry of entries) {
195
275
  if (!entry.isFile()) continue;
196
276
  const name = entry.name.toLowerCase();
197
- if (name === "manifest.json" || name.endsWith(".mp3")) {
277
+ if (name === "manifest.json" || name.endsWith(extension)) {
198
278
  await copyFile(join(srcDir, entry.name), join(destDir, entry.name));
199
279
  }
200
280
  }
201
281
  }
202
282
 
283
+ /**
284
+ * Copy the soundtrack's audio into the bundle: the authored music file at
285
+ * its scenario-relative path (the embed references it by that same path),
286
+ * and the built-in SFX set from @scenar/react at the shared
287
+ * {@link SFX_DEST_PATHS} locations the generated entry points at. Returns
288
+ * the number of files copied. Remote music URLs copy nothing.
289
+ */
290
+ async function copySoundtrack(
291
+ scenarioDir: string,
292
+ outDir: string,
293
+ soundtrack: AuthoredSoundtrack,
294
+ ): Promise<number> {
295
+ let copied = 0;
296
+
297
+ if (soundtrack.musicSrc) {
298
+ const music = await resolveMusicAsset(scenarioDir, soundtrack.musicSrc);
299
+ if (music) {
300
+ const dest = join(outDir, music.destRelPath);
301
+ await mkdir(dirname(dest), { recursive: true });
302
+ await copyFile(music.sourcePath, dest);
303
+ copied += 1;
304
+ }
305
+ }
306
+
307
+ if (soundtrack.sfx) {
308
+ const sfxPaths = resolveSfxAssetPaths(scenarioDir);
309
+ for (const sound of ["click", "keystroke"] as const) {
310
+ const dest = join(outDir, SFX_DEST_PATHS[sound]);
311
+ await mkdir(dirname(dest), { recursive: true });
312
+ await copyFile(sfxPaths[sound], dest);
313
+ copied += 1;
314
+ }
315
+ }
316
+
317
+ return copied;
318
+ }
319
+
320
+ /**
321
+ * Copy title-card logos into the bundle at their scenario-relative paths.
322
+ * A logo shared by intro and outro copies once; remote URLs copy nothing.
323
+ * Returns the number of files copied.
324
+ */
325
+ async function copyTitleCardLogos(
326
+ scenarioDir: string,
327
+ outDir: string,
328
+ titleCards: AuthoredTitleCards,
329
+ ): Promise<number> {
330
+ let copied = 0;
331
+ const copiedPaths = new Set<string>();
332
+
333
+ for (const side of ["intro", "outro"] as const) {
334
+ const logoSrc = titleCards[side]?.logoSrc;
335
+ if (!logoSrc) continue;
336
+ const logo = await resolveLogoAsset(scenarioDir, logoSrc, `titleCards.${side}.logoSrc`);
337
+ if (!logo || copiedPaths.has(logo.destRelPath)) continue;
338
+ const dest = join(outDir, logo.destRelPath);
339
+ await mkdir(dirname(dest), { recursive: true });
340
+ await copyFile(logo.sourcePath, dest);
341
+ copiedPaths.add(logo.destRelPath);
342
+ copied += 1;
343
+ }
344
+
345
+ return copied;
346
+ }
347
+
203
348
  /** One log-friendly line for the shot discovery outcome. */
204
349
  function describeCollectedShots(collected: CollectedPackShots): string {
205
350
  if (!collected.recorded) {
@@ -33,4 +33,21 @@ export declare const DEFAULT_VIEWPORT: Viewport;
33
33
  * accept a recorded viewport while falling back cleanly for older bundles.
34
34
  */
35
35
  export declare function parseViewport(value: unknown): Viewport | null;
36
+ /** A resolved pack viewport plus where each number came from (for the log). */
37
+ export interface ResolvedPackViewport extends Viewport {
38
+ readonly source: "explicit" | "authored" | "default";
39
+ }
40
+ /**
41
+ * Resolve the canonical viewport a bundle is packed at: explicit options
42
+ * (CLI flags / MCP params) > the scenario's own authored viewport > the
43
+ * packer default. Width and height resolve as a pair — an explicit *partial*
44
+ * override (only `--width`) still counts as explicit, filling the other axis
45
+ * from the authored viewport when present, else the default — and the
46
+ * source names the strongest contributor so the pack log can explain a
47
+ * surprising size in one line.
48
+ */
49
+ export declare function resolvePackViewport(options: {
50
+ readonly width?: number;
51
+ readonly shellHeight?: number;
52
+ }, authored: Viewport | null): ResolvedPackViewport;
36
53
  //# sourceMappingURL=viewport.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"viewport.d.ts","sourceRoot":"","sources":["../../../src/pack/viewport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,QAAQ;IACvB,2DAA2D;IAC3D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,kFAAkF;IAClF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,EAAE,QAAsC,CAAC;AAEtE;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,QAAQ,GAAG,IAAI,CAK7D"}
1
+ {"version":3,"file":"viewport.d.ts","sourceRoot":"","sources":["../../../src/pack/viewport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,QAAQ;IACvB,2DAA2D;IAC3D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,kFAAkF;IAClF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,EAAE,QAAsC,CAAC;AAEtE;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,QAAQ,GAAG,IAAI,CAK7D;AAED,+EAA+E;AAC/E,MAAM,WAAW,oBAAqB,SAAQ,QAAQ;IACpD,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,UAAU,GAAG,SAAS,CAAC;CACtD;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE;IAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,EACnE,QAAQ,EAAE,QAAQ,GAAG,IAAI,GACxB,oBAAoB,CAUtB"}
@@ -19,6 +19,25 @@ export function parseViewport(value) {
19
19
  return null;
20
20
  return { width, height };
21
21
  }
22
+ /**
23
+ * Resolve the canonical viewport a bundle is packed at: explicit options
24
+ * (CLI flags / MCP params) > the scenario's own authored viewport > the
25
+ * packer default. Width and height resolve as a pair — an explicit *partial*
26
+ * override (only `--width`) still counts as explicit, filling the other axis
27
+ * from the authored viewport when present, else the default — and the
28
+ * source names the strongest contributor so the pack log can explain a
29
+ * surprising size in one line.
30
+ */
31
+ export function resolvePackViewport(options, authored) {
32
+ const width = options.width ?? authored?.width ?? DEFAULT_VIEWPORT.width;
33
+ const height = options.shellHeight ?? authored?.height ?? DEFAULT_VIEWPORT.height;
34
+ const source = options.width !== undefined || options.shellHeight !== undefined
35
+ ? "explicit"
36
+ : authored
37
+ ? "authored"
38
+ : "default";
39
+ return { width, height, source };
40
+ }
22
41
  function isPositiveInt(value) {
23
42
  return typeof value === "number" && Number.isInteger(value) && value > 0;
24
43
  }
@@ -1 +1 @@
1
- {"version":3,"file":"viewport.js","sourceRoot":"","sources":["../../../src/pack/viewport.ts"],"names":[],"mappings":"AAsBA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAa,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;AAEtE;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC7D,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,KAAgC,CAAC;IAC3D,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC;IACjE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;AAC3B,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACnC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC;AAC3E,CAAC"}
1
+ {"version":3,"file":"viewport.js","sourceRoot":"","sources":["../../../src/pack/viewport.ts"],"names":[],"mappings":"AAsBA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAa,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;AAEtE;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC7D,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,KAAgC,CAAC;IAC3D,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC;IACjE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;AAC3B,CAAC;AAOD;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CACjC,OAAmE,EACnE,QAAyB;IAEzB,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,QAAQ,EAAE,KAAK,IAAI,gBAAgB,CAAC,KAAK,CAAC;IACzE,MAAM,MAAM,GAAG,OAAO,CAAC,WAAW,IAAI,QAAQ,EAAE,MAAM,IAAI,gBAAgB,CAAC,MAAM,CAAC;IAClF,MAAM,MAAM,GACV,OAAO,CAAC,KAAK,KAAK,SAAS,IAAI,OAAO,CAAC,WAAW,KAAK,SAAS;QAC9D,CAAC,CAAC,UAAU;QACZ,CAAC,CAAC,QAAQ;YACR,CAAC,CAAC,UAAU;YACZ,CAAC,CAAC,SAAS,CAAC;IAClB,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;AACnC,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACnC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC;AAC3E,CAAC"}
@@ -41,6 +41,35 @@ export function parseViewport(value: unknown): Viewport | null {
41
41
  return { width, height };
42
42
  }
43
43
 
44
+ /** A resolved pack viewport plus where each number came from (for the log). */
45
+ export interface ResolvedPackViewport extends Viewport {
46
+ readonly source: "explicit" | "authored" | "default";
47
+ }
48
+
49
+ /**
50
+ * Resolve the canonical viewport a bundle is packed at: explicit options
51
+ * (CLI flags / MCP params) > the scenario's own authored viewport > the
52
+ * packer default. Width and height resolve as a pair — an explicit *partial*
53
+ * override (only `--width`) still counts as explicit, filling the other axis
54
+ * from the authored viewport when present, else the default — and the
55
+ * source names the strongest contributor so the pack log can explain a
56
+ * surprising size in one line.
57
+ */
58
+ export function resolvePackViewport(
59
+ options: { readonly width?: number; readonly shellHeight?: number },
60
+ authored: Viewport | null,
61
+ ): ResolvedPackViewport {
62
+ const width = options.width ?? authored?.width ?? DEFAULT_VIEWPORT.width;
63
+ const height = options.shellHeight ?? authored?.height ?? DEFAULT_VIEWPORT.height;
64
+ const source =
65
+ options.width !== undefined || options.shellHeight !== undefined
66
+ ? "explicit"
67
+ : authored
68
+ ? "authored"
69
+ : "default";
70
+ return { width, height, source };
71
+ }
72
+
44
73
  function isPositiveInt(value: unknown): value is number {
45
74
  return typeof value === "number" && Number.isInteger(value) && value > 0;
46
75
  }
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Minimal HeyGen API client for `scenar presenter` — deliberately an
3
+ * internal module of the CLI, not published API. Shaped so a second
4
+ * avatar provider could slot in behind the same function signatures,
5
+ * but the interface is not exported until a second provider is a
6
+ * concrete need (the TTS-provider precedent).
7
+ *
8
+ * Endpoints and response fields follow the live Gate 0 transcript:
9
+ * `POST /v3/assets` (multipart) → `data.asset_id`;
10
+ * `POST /v3/videos` (`type: "avatar"`, `audio_asset_id`) →
11
+ * `data.video_id`; `GET /v3/videos/{id}` → `data.status`
12
+ * (`completed`/`failed`), `data.video_url`, `data.failure_message`.
13
+ *
14
+ * BYO key, no Scenar-side proxying — identical to the TTS providers.
15
+ * Native fetch, no new runtime dependencies.
16
+ */
17
+ /** Engine flag values → HeyGen's API vocabulary. */
18
+ export declare const HEYGEN_ENGINE_TYPES: {
19
+ readonly iii: "avatar_iii";
20
+ readonly iv: "avatar_iv";
21
+ };
22
+ export type HeygenEngineFlag = keyof typeof HEYGEN_ENGINE_TYPES;
23
+ /**
24
+ * Indicative $/minute of narration audio per engine, from the project
25
+ * cost analysis. The estimate the cost gate prints is indicative —
26
+ * HeyGen bills credits, not dollars.
27
+ */
28
+ export declare const HEYGEN_RATE_PER_MIN: Record<HeygenEngineFlag, number>;
29
+ export interface HeygenRequestContext {
30
+ readonly apiKey: string;
31
+ /** Injectable for tests; defaults to a real timer. */
32
+ readonly sleep?: (ms: number) => Promise<void>;
33
+ /** Rate-limit feedback sink (stderr line per retry). */
34
+ readonly onRetry?: (message: string) => void;
35
+ }
36
+ /** Upload one narration MP3 as a HeyGen asset (free). Returns the asset id. */
37
+ export declare function uploadAudioAsset(ctx: HeygenRequestContext, audio: Buffer, filename: string): Promise<string>;
38
+ export interface CreateAvatarVideoInput {
39
+ readonly avatarId: string;
40
+ readonly audioAssetId: string;
41
+ readonly engine: HeygenEngineFlag;
42
+ readonly resolution: string;
43
+ /**
44
+ * Deterministic title (`scenar <scenarioId> step-<N> <hash8>`) so any
45
+ * duplicate generation is identifiable in the HeyGen dashboard.
46
+ */
47
+ readonly title: string;
48
+ }
49
+ /** Create one avatar video lip-synced to the uploaded audio. Returns the video id. */
50
+ export declare function createAvatarVideo(ctx: HeygenRequestContext, input: CreateAvatarVideoInput): Promise<string>;
51
+ export interface PollOutcome {
52
+ readonly status: "completed" | "failed" | "timeout";
53
+ readonly videoUrl?: string;
54
+ readonly failureMessage?: string;
55
+ }
56
+ export interface PollOptions {
57
+ readonly intervalMs: number;
58
+ readonly timeoutMs: number;
59
+ /** Elapsed-time feedback per tick (drives the progress line). */
60
+ readonly onTick?: (elapsedMs: number) => void;
61
+ }
62
+ /**
63
+ * Poll a generation to completion. Polling is read-only, so transient
64
+ * network errors retry on the next tick inside the step timeout.
65
+ */
66
+ export declare function pollVideo(ctx: HeygenRequestContext, videoId: string, options: PollOptions): Promise<PollOutcome>;
67
+ /** Download a completed clip. Returns the raw bytes. */
68
+ export declare function downloadVideo(url: string): Promise<Buffer>;
69
+ //# sourceMappingURL=heygen-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"heygen-client.d.ts","sourceRoot":"","sources":["../../../src/presenter/heygen-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,oDAAoD;AACpD,eAAO,MAAM,mBAAmB;;;CAGtB,CAAC;AAEX,MAAM,MAAM,gBAAgB,GAAG,MAAM,OAAO,mBAAmB,CAAC;AAEhE;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,gBAAgB,EAAE,MAAM,CAGhE,CAAC;AAKF,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,sDAAsD;IACtD,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,wDAAwD;IACxD,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9C;AA6CD,+EAA+E;AAC/E,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,oBAAoB,EACzB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,CAAC,CAkBjB;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAClC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,sFAAsF;AACtF,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,oBAAoB,EACzB,KAAK,EAAE,sBAAsB,GAC5B,OAAO,CAAC,MAAM,CAAC,CAsBjB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,QAAQ,GAAG,SAAS,CAAC;IACpD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;CAClC;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,iEAAiE;IACjE,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;CAC/C;AAED;;;GAGG;AACH,wBAAsB,SAAS,CAC7B,GAAG,EAAE,oBAAoB,EACzB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,WAAW,CAAC,CAqCtB;AAED,wDAAwD;AACxD,wBAAsB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAMhE"}
@@ -0,0 +1,154 @@
1
+ /**
2
+ * Minimal HeyGen API client for `scenar presenter` — deliberately an
3
+ * internal module of the CLI, not published API. Shaped so a second
4
+ * avatar provider could slot in behind the same function signatures,
5
+ * but the interface is not exported until a second provider is a
6
+ * concrete need (the TTS-provider precedent).
7
+ *
8
+ * Endpoints and response fields follow the live Gate 0 transcript:
9
+ * `POST /v3/assets` (multipart) → `data.asset_id`;
10
+ * `POST /v3/videos` (`type: "avatar"`, `audio_asset_id`) →
11
+ * `data.video_id`; `GET /v3/videos/{id}` → `data.status`
12
+ * (`completed`/`failed`), `data.video_url`, `data.failure_message`.
13
+ *
14
+ * BYO key, no Scenar-side proxying — identical to the TTS providers.
15
+ * Native fetch, no new runtime dependencies.
16
+ */
17
+ const HEYGEN_BASE_URL = "https://api.heygen.com";
18
+ /** Engine flag values → HeyGen's API vocabulary. */
19
+ export const HEYGEN_ENGINE_TYPES = {
20
+ iii: "avatar_iii",
21
+ iv: "avatar_iv",
22
+ };
23
+ /**
24
+ * Indicative $/minute of narration audio per engine, from the project
25
+ * cost analysis. The estimate the cost gate prints is indicative —
26
+ * HeyGen bills credits, not dollars.
27
+ */
28
+ export const HEYGEN_RATE_PER_MIN = {
29
+ iii: 1.0,
30
+ iv: 4.0,
31
+ };
32
+ const MAX_ATTEMPTS_ON_429 = 3;
33
+ const DEFAULT_RETRY_AFTER_S = 30;
34
+ const realSleep = (ms) => new Promise((r) => setTimeout(r, ms));
35
+ /**
36
+ * Run a HeyGen request, honoring 429 rate limits: wait `Retry-After`
37
+ * (default 30 s) and retry the same call, up to 3 attempts total.
38
+ */
39
+ async function heygenFetch(ctx, path, init) {
40
+ const sleep = ctx.sleep ?? realSleep;
41
+ let response;
42
+ for (let attempt = 1;; attempt++) {
43
+ response = await fetch(`${HEYGEN_BASE_URL}${path}`, {
44
+ ...init,
45
+ headers: { "x-api-key": ctx.apiKey, ...(init.headers ?? {}) },
46
+ });
47
+ if (response.status !== 429 || attempt >= MAX_ATTEMPTS_ON_429)
48
+ return response;
49
+ const retryAfterS = Number(response.headers.get("retry-after")) || DEFAULT_RETRY_AFTER_S;
50
+ ctx.onRetry?.(`rate-limited, retrying in ${retryAfterS}s (${attempt}/${MAX_ATTEMPTS_ON_429})`);
51
+ await sleep(retryAfterS * 1000);
52
+ }
53
+ }
54
+ async function readBody(response) {
55
+ try {
56
+ return (await response.json());
57
+ }
58
+ catch {
59
+ return {};
60
+ }
61
+ }
62
+ function apiError(operation, response, body) {
63
+ return new Error(`HeyGen ${operation} failed (${response.status}): ${JSON.stringify(body)}`);
64
+ }
65
+ /** Upload one narration MP3 as a HeyGen asset (free). Returns the asset id. */
66
+ export async function uploadAudioAsset(ctx, audio, filename) {
67
+ const form = new FormData();
68
+ form.append("file", new Blob([new Uint8Array(audio)], { type: "audio/mpeg" }), filename);
69
+ const response = await heygenFetch(ctx, "/v3/assets", {
70
+ method: "POST",
71
+ body: form,
72
+ });
73
+ const body = await readBody(response);
74
+ if (!response.ok)
75
+ throw apiError("asset upload", response, body);
76
+ const assetId = body["data"]?.["asset_id"];
77
+ if (typeof assetId !== "string" || assetId.length === 0) {
78
+ throw new Error(`HeyGen asset upload returned no asset_id: ${JSON.stringify(body)}`);
79
+ }
80
+ return assetId;
81
+ }
82
+ /** Create one avatar video lip-synced to the uploaded audio. Returns the video id. */
83
+ export async function createAvatarVideo(ctx, input) {
84
+ const response = await heygenFetch(ctx, "/v3/videos", {
85
+ method: "POST",
86
+ headers: { "Content-Type": "application/json" },
87
+ body: JSON.stringify({
88
+ type: "avatar",
89
+ avatar_id: input.avatarId,
90
+ audio_asset_id: input.audioAssetId,
91
+ engine: { type: HEYGEN_ENGINE_TYPES[input.engine] },
92
+ output_format: "mp4",
93
+ aspect_ratio: "auto",
94
+ resolution: input.resolution,
95
+ title: input.title,
96
+ }),
97
+ });
98
+ const body = await readBody(response);
99
+ if (!response.ok)
100
+ throw apiError("video create", response, body);
101
+ const videoId = body["data"]?.["video_id"];
102
+ if (typeof videoId !== "string" || videoId.length === 0) {
103
+ throw new Error(`HeyGen video create returned no video_id: ${JSON.stringify(body)}`);
104
+ }
105
+ return videoId;
106
+ }
107
+ /**
108
+ * Poll a generation to completion. Polling is read-only, so transient
109
+ * network errors retry on the next tick inside the step timeout.
110
+ */
111
+ export async function pollVideo(ctx, videoId, options) {
112
+ const sleep = ctx.sleep ?? realSleep;
113
+ const startedAt = Date.now();
114
+ while (Date.now() - startedAt < options.timeoutMs) {
115
+ await sleep(options.intervalMs);
116
+ options.onTick?.(Date.now() - startedAt);
117
+ let body;
118
+ try {
119
+ const response = await heygenFetch(ctx, `/v3/videos/${videoId}`, { method: "GET" });
120
+ body = await readBody(response);
121
+ if (!response.ok)
122
+ continue;
123
+ }
124
+ catch {
125
+ continue;
126
+ }
127
+ const data = (body["data"] ?? {});
128
+ const status = data["status"];
129
+ if (status === "completed") {
130
+ return {
131
+ status: "completed",
132
+ videoUrl: typeof data["video_url"] === "string" ? data["video_url"] : undefined,
133
+ };
134
+ }
135
+ if (status === "failed") {
136
+ return {
137
+ status: "failed",
138
+ failureMessage: typeof data["failure_message"] === "string"
139
+ ? data["failure_message"]
140
+ : JSON.stringify(data["failure_message"] ?? "unknown failure"),
141
+ };
142
+ }
143
+ }
144
+ return { status: "timeout" };
145
+ }
146
+ /** Download a completed clip. Returns the raw bytes. */
147
+ export async function downloadVideo(url) {
148
+ const response = await fetch(url);
149
+ if (!response.ok) {
150
+ throw new Error(`HeyGen clip download failed (${response.status}) for ${url}`);
151
+ }
152
+ return Buffer.from(await response.arrayBuffer());
153
+ }
154
+ //# sourceMappingURL=heygen-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"heygen-client.js","sourceRoot":"","sources":["../../../src/presenter/heygen-client.ts"],"names":[],"mappings":"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"}