@t3lnet/sceneforge 1.0.7 → 1.0.8

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 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../../shared/src/yaml-parser.ts","../../shared/src/schema.ts","../../shared/src/target-resolver.ts","../../shared/src/action-helpers.ts","../../playwright/src/demo-runner.ts","../../generation/src/voice-synthesis.ts","../../generation/src/script-generator.ts","../../playwright/src/cursor-overlay.ts"],"sourcesContent":["/**\n * @t3lnet/sceneforge\n *\n * SceneForge public API: demo runner + generation utilities.\n */\n\n// Shared types\nexport type {\n DemoDefinition,\n DemoStep,\n DemoAction,\n ActionType,\n StepTarget,\n WaitCondition,\n DragConfig,\n ElementInfo,\n RecordedInteraction,\n SelectorStrategy,\n SelectorCandidate,\n PrivacyConfig,\n SelectorConfig,\n RecordingState,\n PickerResult,\n TestSelectorResponse,\n} from \"../../shared/src/types\";\n\n// YAML parsing and serialization\nexport {\n parseFromYAML,\n serializeToYAML,\n validateDemoDefinition,\n createEmptyDemo,\n createEmptyStep,\n} from \"../../shared/src/yaml-parser\";\n\n// Schema validation\nexport {\n DEMO_SCHEMA_VERSION,\n demoDefinitionSchema,\n parseDemoDefinition,\n safeParseDemoDefinition,\n formatValidationError,\n} from \"../../shared/src/schema\";\n\n// Target resolution\nexport {\n resolveTarget,\n resolvePath,\n} from \"../../shared/src/target-resolver\";\n\n// Action helpers\nexport {\n createClickAction,\n createTypeAction,\n createNavigateAction,\n createWaitAction,\n createWaitForAction,\n createUploadAction,\n createHoverAction,\n createScrollAction,\n createScrollToAction,\n createDragAction,\n} from \"../../shared/src/action-helpers\";\n\n// Demo runner\nexport {\n runDemo,\n runDemoFromFile,\n loadDemoDefinition,\n discoverDemos,\n} from \"../../playwright/src/demo-runner\";\n\nexport type {\n DemoContext,\n DemoResult,\n StepTiming,\n RunDemoOptions,\n} from \"../../playwright/src/demo-runner\";\n\n// Cursor overlay helpers\nexport {\n injectCursorOverlay,\n removeCursorOverlay,\n moveCursorTo,\n triggerClickRipple,\n highlightElement,\n demoClick,\n demoHover,\n demoType,\n} from \"../../playwright/src/cursor-overlay\";\n\n// Voice synthesis utilities\nexport {\n VoiceSynthesizer,\n createVoiceSynthesizer,\n generateTimingManifest,\n} from \"../../generation/src/voice-synthesis\";\n\nexport type {\n VoiceSynthesisConfig,\n VoiceSynthesisResult,\n SynthesizedSegment,\n GeneratedScript,\n ScriptSegment as VoiceScriptSegment,\n AudioTimingManifest,\n} from \"../../generation/src/voice-synthesis\";\n\n// Script generation utilities\nexport {\n ScriptGenerator,\n createScriptGenerator,\n} from \"../../generation/src/script-generator\";\n\nexport type {\n ScriptSegment,\n ScriptOutput,\n StepBoundary,\n} from \"../../generation/src/script-generator\";\n","/**\n * YAML parsing and serialization for demo definitions.\n * Shared between CLI and extension.\n */\n\nimport { parse, stringify } from \"yaml\";\nimport type {\n DemoDefinition,\n DemoStep,\n DemoAction,\n StepTarget,\n WaitCondition,\n} from \"./types\";\nimport {\n DEMO_SCHEMA_VERSION,\n formatValidationError,\n parseDemoDefinition,\n safeParseDemoDefinition,\n} from \"./schema\";\n\n/**\n * Parses a YAML string into a DemoDefinition.\n */\nexport function parseFromYAML(\n yamlString: string,\n options?: { resolveSecrets?: (key: string) => string | undefined }\n): DemoDefinition {\n const parsed = parse(yamlString);\n\n if (!parsed || typeof parsed !== \"object\") {\n throw new Error(\"Invalid YAML: expected an object\");\n }\n const resolved = options?.resolveSecrets\n ? resolveSecrets(parsed, options.resolveSecrets)\n : parsed;\n try {\n return parseDemoDefinition(resolved);\n } catch (error) {\n throw new Error(formatValidationError(error));\n }\n}\n\n/**\n * Serializes a DemoDefinition to a YAML string.\n */\nexport function serializeToYAML(demo: DemoDefinition): string {\n const cleanDemo = {\n version: demo.version ?? DEMO_SCHEMA_VERSION,\n name: demo.name,\n title: demo.title,\n ...(demo.description && { description: demo.description }),\n steps: demo.steps.map(serializeStep),\n };\n\n return stringify(cleanDemo, {\n indent: 2,\n lineWidth: 100,\n defaultStringType: \"QUOTE_DOUBLE\",\n defaultKeyType: \"PLAIN\",\n });\n}\n\nfunction serializeStep(step: DemoStep): object {\n return {\n id: step.id,\n script: step.script,\n actions: step.actions.map(serializeAction),\n };\n}\n\nfunction serializeAction(action: DemoAction): object {\n const result: Record<string, unknown> = {\n action: action.action,\n };\n\n if (action.path !== undefined) {\n result.path = action.path;\n }\n\n if (action.target !== undefined) {\n result.target = serializeTarget(action.target);\n }\n\n if (action.text !== undefined) {\n result.text = action.text;\n }\n\n if (action.file !== undefined) {\n result.file = action.file;\n }\n\n if (action.duration !== undefined) {\n result.duration = action.duration;\n }\n\n if (action.highlight === true) {\n result.highlight = true;\n }\n\n if (action.waitFor !== undefined) {\n result.waitFor = serializeWaitCondition(action.waitFor);\n }\n\n if (action.drag !== undefined) {\n result.drag = {\n deltaX: action.drag.deltaX,\n deltaY: action.drag.deltaY,\n ...(action.drag.steps !== undefined && { steps: action.drag.steps }),\n };\n }\n\n return result;\n}\n\nfunction serializeTarget(target: StepTarget): object {\n const result: Record<string, unknown> = {\n type: target.type,\n };\n\n if (target.text !== undefined) {\n result.text = target.text;\n }\n\n if (target.selector !== undefined) {\n result.selector = target.selector;\n }\n\n if (target.name !== undefined) {\n result.name = target.name;\n }\n\n return result;\n}\n\nfunction serializeWaitCondition(waitFor: WaitCondition): object {\n const result: Record<string, unknown> = {\n type: waitFor.type,\n };\n\n if (waitFor.value !== undefined) {\n result.value = waitFor.value;\n }\n\n if (waitFor.timeout !== undefined) {\n result.timeout = waitFor.timeout;\n }\n\n return result;\n}\n\n/**\n * Validates a demo definition, throwing on errors.\n */\nexport function validateDemoDefinition(definition: DemoDefinition): void {\n const result = safeParseDemoDefinition(definition);\n if (!result.success) {\n throw new Error(formatValidationError(result.error));\n }\n}\n\n/**\n * Creates a default empty demo definition.\n */\nexport function createEmptyDemo(): DemoDefinition {\n return {\n version: DEMO_SCHEMA_VERSION,\n name: \"new-demo\",\n title: \"New Demo\",\n description: \"\",\n steps: [],\n };\n}\n\n/**\n * Creates a default empty step.\n */\nexport function createEmptyStep(id?: string): DemoStep {\n const stepId = id || `step-${Date.now()}`;\n return {\n id: stepId,\n script: \"\",\n actions: [],\n };\n}\n\nconst SECRET_PATTERN = /\\$\\{(ENV|SECRET):([A-Za-z0-9_]+)\\}/g;\n\nfunction resolveSecrets(\n value: unknown,\n resolver: (key: string) => string | undefined,\n path = \"root\"\n): unknown {\n if (typeof value === \"string\") {\n if (!SECRET_PATTERN.test(value)) {\n return value;\n }\n SECRET_PATTERN.lastIndex = 0;\n return value.replace(SECRET_PATTERN, (_match, _type, key: string) => {\n const resolved = resolver(key);\n if (resolved === undefined) {\n throw new Error(`Missing secret for ${key} at ${path}`);\n }\n return resolved;\n });\n }\n\n if (Array.isArray(value)) {\n return value.map((entry, index) =>\n resolveSecrets(entry, resolver, `${path}[${index}]`)\n );\n }\n\n if (value && typeof value === \"object\") {\n const result: Record<string, unknown> = {};\n for (const [key, entry] of Object.entries(value)) {\n result[key] = resolveSecrets(entry, resolver, `${path}.${key}`);\n }\n return result;\n }\n\n return value;\n}\n","import { z } from \"zod\";\nimport type {\n BackgroundMusic,\n DemoAction,\n DemoDefinition,\n DemoStep,\n DragConfig,\n MediaConfig,\n MusicEndPoint,\n MusicStartPoint,\n StepTarget,\n VideoSegment,\n WaitCondition,\n} from \"./types\";\n\nexport const DEMO_SCHEMA_VERSION = 1;\n\ntype DemoDefinitionInput = Omit<DemoDefinition, \"version\"> & { version?: number };\n\nconst stepTargetSchema: z.ZodType<StepTarget> = z\n .object({\n type: z.enum([\"button\", \"link\", \"input\", \"text\", \"selector\"]),\n text: z.string().optional(),\n selector: z.string().optional(),\n name: z.string().optional(),\n })\n .strict()\n .superRefine((target, ctx) => {\n switch (target.type) {\n case \"selector\":\n if (!target.selector) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: \"selector target requires selector\",\n });\n }\n break;\n case \"text\":\n if (!target.text) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: \"text target requires text\",\n });\n }\n break;\n case \"button\":\n case \"link\":\n case \"input\":\n if (!target.text && !target.name && !target.selector) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: \"target requires text, name, or selector\",\n });\n }\n break;\n }\n });\n\nconst waitConditionSchema: z.ZodType<WaitCondition> = z\n .object({\n type: z.enum([\"text\", \"selector\", \"navigation\", \"idle\", \"selectorHidden\", \"textHidden\"]),\n value: z.string().optional(),\n timeout: z.coerce.number().int().positive().optional(),\n })\n .strict()\n .superRefine((condition, ctx) => {\n if ([\"text\", \"selector\", \"selectorHidden\", \"textHidden\"].includes(condition.type)) {\n if (!condition.value) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `wait condition '${condition.type}' requires value`,\n });\n }\n }\n });\n\nconst dragConfigSchema: z.ZodType<DragConfig> = z\n .object({\n deltaX: z.coerce.number(),\n deltaY: z.coerce.number(),\n steps: z.coerce.number().int().positive().optional(),\n })\n .strict();\n\nconst waitActionSchema: z.ZodType<DemoAction> = z\n .object({\n action: z.literal(\"wait\"),\n duration: z.coerce.number().nonnegative().optional(),\n waitFor: waitConditionSchema.optional(),\n })\n .strict()\n .superRefine((action, ctx) => {\n if (action.duration === undefined && action.waitFor === undefined) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: \"wait action requires duration or waitFor\",\n });\n }\n });\n\nconst navigateActionSchema: z.ZodType<DemoAction> = z\n .object({\n action: z.literal(\"navigate\"),\n path: z.string().min(1),\n waitFor: waitConditionSchema.optional(),\n })\n .strict();\n\nconst clickActionSchema: z.ZodType<DemoAction> = z\n .object({\n action: z.literal(\"click\"),\n target: stepTargetSchema,\n highlight: z.boolean().optional(),\n waitFor: waitConditionSchema.optional(),\n })\n .strict();\n\nconst typeActionSchema: z.ZodType<DemoAction> = z\n .object({\n action: z.literal(\"type\"),\n target: stepTargetSchema,\n text: z.string(),\n waitFor: waitConditionSchema.optional(),\n })\n .strict();\n\nconst uploadActionSchema: z.ZodType<DemoAction> = z\n .object({\n action: z.literal(\"upload\"),\n file: z.string().min(1),\n target: stepTargetSchema.optional(),\n waitFor: waitConditionSchema.optional(),\n })\n .strict();\n\nconst hoverActionSchema: z.ZodType<DemoAction> = z\n .object({\n action: z.literal(\"hover\"),\n target: stepTargetSchema,\n waitFor: waitConditionSchema.optional(),\n })\n .strict();\n\nconst scrollActionSchema: z.ZodType<DemoAction> = z\n .object({\n action: z.literal(\"scroll\"),\n duration: z.coerce.number().optional(),\n waitFor: waitConditionSchema.optional(),\n })\n .strict();\n\nconst scrollToActionSchema: z.ZodType<DemoAction> = z\n .object({\n action: z.literal(\"scrollTo\"),\n target: stepTargetSchema,\n waitFor: waitConditionSchema.optional(),\n })\n .strict();\n\nconst dragActionSchema: z.ZodType<DemoAction> = z\n .object({\n action: z.literal(\"drag\"),\n target: stepTargetSchema,\n drag: dragConfigSchema,\n waitFor: waitConditionSchema.optional(),\n })\n .strict();\n\nconst actionSchema: z.ZodType<DemoAction> = z.union([\n navigateActionSchema,\n clickActionSchema,\n typeActionSchema,\n uploadActionSchema,\n waitActionSchema,\n hoverActionSchema,\n scrollActionSchema,\n scrollToActionSchema,\n dragActionSchema,\n]);\n\nconst demoStepSchema: z.ZodType<DemoStep> = z\n .object({\n id: z.string().min(1),\n script: z.string(),\n actions: z.array(actionSchema),\n })\n .strict();\n\nconst videoSegmentSchema: z.ZodType<VideoSegment> = z\n .object({\n file: z.string().min(1),\n duration: z.coerce.number().positive().optional(),\n fade: z.boolean().optional(),\n fadeDuration: z.coerce.number().positive().optional(),\n })\n .strict();\n\nconst musicStartPointSchema: z.ZodType<MusicStartPoint> = z.union([\n z.object({ type: z.literal(\"beginning\") }).strict(),\n z.object({ type: z.literal(\"afterIntro\") }).strict(),\n z.object({ type: z.literal(\"step\"), stepId: z.string().min(1) }).strict(),\n z.object({ type: z.literal(\"time\"), seconds: z.coerce.number().nonnegative() }).strict(),\n]);\n\nconst musicEndPointSchema: z.ZodType<MusicEndPoint> = z.union([\n z.object({ type: z.literal(\"end\") }).strict(),\n z.object({ type: z.literal(\"beforeOutro\") }).strict(),\n z.object({ type: z.literal(\"step\"), stepId: z.string().min(1) }).strict(),\n z.object({ type: z.literal(\"time\"), seconds: z.coerce.number().nonnegative() }).strict(),\n]);\n\nconst backgroundMusicSchema: z.ZodType<BackgroundMusic> = z\n .object({\n file: z.string().min(1),\n volume: z.coerce.number().min(0).max(1).optional(),\n startAt: musicStartPointSchema.optional(),\n endAt: musicEndPointSchema.optional(),\n loop: z.boolean().optional(),\n fadeIn: z.coerce.number().nonnegative().optional(),\n fadeOut: z.coerce.number().nonnegative().optional(),\n })\n .strict();\n\nconst mediaConfigSchema: z.ZodType<MediaConfig> = z\n .object({\n intro: videoSegmentSchema.optional(),\n outro: videoSegmentSchema.optional(),\n backgroundMusic: backgroundMusicSchema.optional(),\n })\n .strict();\n\nexport const demoDefinitionSchema: z.ZodType<\n DemoDefinition,\n z.ZodTypeDef,\n DemoDefinitionInput\n> = z\n .object({\n version: z.coerce.number().int().positive().default(DEMO_SCHEMA_VERSION),\n name: z.string().min(1),\n title: z.string().min(1),\n description: z.string().optional(),\n steps: z.array(demoStepSchema),\n media: mediaConfigSchema.optional(),\n })\n .strict();\n\nexport function formatValidationError(error: unknown): string {\n if (!error || typeof error !== \"object\" || !(\"issues\" in error)) {\n return \"Invalid demo definition\";\n }\n const issues = (error as z.ZodError).issues;\n return issues\n .map((issue) => {\n const path = issue.path.length ? issue.path.join(\".\") : \"root\";\n return `${path}: ${issue.message}`;\n })\n .join(\"; \");\n}\n\nexport function parseDemoDefinition(input: unknown) {\n return demoDefinitionSchema.parse(input);\n}\n\nexport function safeParseDemoDefinition(input: unknown) {\n return demoDefinitionSchema.safeParse(input);\n}\n","/**\n * Target resolution utilities.\n * Converts StepTarget configurations to CSS/Playwright selectors.\n */\n\nimport type { StepTarget } from \"./types\";\n\n/**\n * Resolves a target configuration to a selector string.\n * Works with both Playwright locators and standard CSS selectors.\n */\nexport function resolveTarget(target: StepTarget): string {\n // If explicit selector is provided, use it directly\n if (target.selector) {\n return target.selector;\n }\n\n switch (target.type) {\n case \"button\":\n if (target.text) {\n return `button:has-text(\"${target.text}\"), [role=\"button\"]:has-text(\"${target.text}\")`;\n }\n if (target.name) {\n return `button[name=\"${target.name}\"], [role=\"button\"][name=\"${target.name}\"]`;\n }\n break;\n\n case \"link\":\n if (target.text) {\n return `a:has-text(\"${target.text}\")`;\n }\n if (target.name) {\n return `a[name=\"${target.name}\"]`;\n }\n break;\n\n case \"input\":\n if (target.name) {\n return `input[name=\"${target.name}\"], textarea[name=\"${target.name}\"]`;\n }\n if (target.text) {\n // Input with associated label\n return `label:has-text(\"${target.text}\") + input, label:has-text(\"${target.text}\") input`;\n }\n break;\n\n case \"text\":\n if (target.text) {\n return `text=\"${target.text}\"`;\n }\n break;\n\n case \"selector\":\n // Selector type but no selector provided\n break;\n }\n\n throw new Error(`Unable to resolve target: ${JSON.stringify(target)}`);\n}\n\n/**\n * Replaces template variables in paths.\n * Supports: {baseURL}.\n */\nexport function resolvePath(\n pathTemplate: string,\n variables: Record<string, string | undefined>\n): string {\n let result = pathTemplate;\n for (const [key, value] of Object.entries(variables)) {\n if (value === undefined) {\n continue;\n }\n result = result.replace(new RegExp(`\\\\{${key}\\\\}`, \"g\"), value);\n }\n return result;\n}\n","/**\n * Helper functions for creating common actions.\n */\n\nimport type { DemoAction, WaitCondition } from \"./types\";\n\n/**\n * Creates a click action.\n */\nexport function createClickAction(selector: string, highlight = false): DemoAction {\n return {\n action: \"click\",\n target: {\n type: \"selector\",\n selector,\n },\n highlight,\n };\n}\n\n/**\n * Creates a type/input action.\n */\nexport function createTypeAction(selector: string, text: string): DemoAction {\n return {\n action: \"type\",\n target: {\n type: \"selector\",\n selector,\n },\n text,\n };\n}\n\n/**\n * Creates a navigate action.\n */\nexport function createNavigateAction(path: string): DemoAction {\n return {\n action: \"navigate\",\n path,\n };\n}\n\n/**\n * Creates a wait action with a fixed duration.\n */\nexport function createWaitAction(duration: number): DemoAction {\n return {\n action: \"wait\",\n duration,\n };\n}\n\n/**\n * Creates a wait action with a condition.\n */\nexport function createWaitForAction(\n type: WaitCondition[\"type\"],\n value?: string,\n timeout = 15000\n): DemoAction {\n return {\n action: \"wait\",\n waitFor: {\n type,\n value,\n timeout,\n },\n };\n}\n\n/**\n * Creates an upload action.\n * Note: selector is optional - defaults to first file input on page.\n */\nexport function createUploadAction(file: string, selector?: string): DemoAction {\n const action: DemoAction = {\n action: \"upload\",\n file,\n };\n if (selector) {\n action.target = {\n type: \"selector\",\n selector,\n };\n }\n return action;\n}\n\n/**\n * Creates a hover action.\n */\nexport function createHoverAction(selector: string): DemoAction {\n return {\n action: \"hover\",\n target: {\n type: \"selector\",\n selector,\n },\n };\n}\n\n/**\n * Creates a scroll action.\n */\nexport function createScrollAction(duration = 500): DemoAction {\n return {\n action: \"scroll\",\n duration,\n };\n}\n\n/**\n * Creates a scroll-to action.\n */\nexport function createScrollToAction(selector: string): DemoAction {\n return {\n action: \"scrollTo\",\n target: {\n type: \"selector\",\n selector,\n },\n };\n}\n\n/**\n * Creates a drag action.\n */\nexport function createDragAction(\n selector: string,\n deltaX: number,\n deltaY: number,\n steps = 20\n): DemoAction {\n return {\n action: \"drag\",\n target: {\n type: \"selector\",\n selector,\n },\n drag: {\n deltaX,\n deltaY,\n steps,\n },\n };\n}\n","/**\n * Demo runner for Playwright.\n * Executes demo definitions using Playwright for video recording.\n */\n\nimport { Page, expect } from \"@playwright/test\";\nimport * as fs from \"fs/promises\";\nimport * as path from \"path\";\nimport type {\n DemoDefinition,\n DemoStep,\n DemoAction,\n WaitCondition,\n} from \"@t3lnet/sceneforge-shared\";\nimport {\n parseFromYAML,\n validateDemoDefinition,\n resolveTarget,\n resolvePath,\n} from \"@t3lnet/sceneforge-shared\";\nimport {\n ScriptGenerator,\n createScriptGenerator,\n} from \"@t3lnet/sceneforge-generation\";\nimport {\n injectCursorOverlay,\n removeCursorOverlay,\n demoClick,\n moveCursorTo,\n} from \"./cursor-overlay\";\n\nconst DEFAULT_ACTION_TIMEOUT_MS = 15000;\nconst NAVIGATION_TIMEOUT_MS = 45000;\nconst UPLOAD_TIMEOUT_MS = 30000;\nconst ACTION_TIMEOUT_BUFFER_MS = 2000;\nconst DEFAULT_WAIT_TIMEOUT_MS = Number(process.env.DEMO_WAIT_TIMEOUT_MS ?? 15000);\nconst WAIT_RETRY_ATTEMPTS = Math.max(\n 1,\n Number(process.env.DEMO_WAIT_RETRY_ATTEMPTS ?? 2)\n);\nconst WAIT_RETRY_BASE_DELAY_MS = Number(process.env.DEMO_WAIT_RETRY_DELAY_MS ?? 500);\n\nfunction sanitizeDiagnosticsSegment(value: string, fallback: string): string {\n const raw = String(value ?? \"\").trim();\n if (!raw) {\n return fallback;\n }\n const cleaned = raw.replace(/[^a-zA-Z0-9._-]+/g, \"_\");\n const collapsed = cleaned.replace(/_{2,}/g, \"_\").replace(/^_+|_+$/g, \"\");\n const safe = collapsed || fallback;\n const trimmed = safe.length > 80 ? safe.slice(0, 80) : safe;\n return trimmed === \".\" || trimmed === \"..\" ? fallback : trimmed;\n}\n\nfunction logEvent(\n level: \"info\" | \"warn\" | \"error\",\n event: string,\n data: Record<string, unknown>\n): void {\n const payload = {\n ts: new Date().toISOString(),\n level,\n event,\n ...data,\n };\n const line = JSON.stringify(payload);\n if (level === \"error\") {\n console.error(line);\n } else if (level === \"warn\") {\n console.warn(line);\n } else {\n console.log(line);\n }\n}\n\nfunction getActionTimeoutMs(action: DemoAction): number {\n if (action.action === \"navigate\") {\n return NAVIGATION_TIMEOUT_MS;\n }\n if (action.action === \"upload\") {\n return UPLOAD_TIMEOUT_MS;\n }\n if (action.action === \"wait\") {\n if (action.duration !== undefined) {\n return Math.max(DEFAULT_ACTION_TIMEOUT_MS, action.duration + ACTION_TIMEOUT_BUFFER_MS);\n }\n if (action.waitFor?.timeout) {\n return action.waitFor.timeout + ACTION_TIMEOUT_BUFFER_MS;\n }\n }\n if (action.waitFor?.timeout) {\n return action.waitFor.timeout + ACTION_TIMEOUT_BUFFER_MS;\n }\n return DEFAULT_ACTION_TIMEOUT_MS;\n}\n\nasync function withActionTimeout<T>(\n timeoutMs: number,\n label: string,\n fn: () => Promise<T>\n): Promise<T> {\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeoutId = setTimeout(() => {\n reject(new Error(`${label} timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n });\n\n try {\n return await Promise.race([fn(), timeoutPromise]);\n } finally {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n }\n}\n\nasync function captureDiagnostics(params: {\n context: DemoContext;\n stepId?: string;\n stepIndex?: number;\n actionIndex?: number;\n action?: DemoAction;\n error: unknown;\n runId: string;\n}): Promise<void> {\n const { context, stepId, stepIndex, actionIndex, action, error, runId } = params;\n const diagnosticsDir = path.join(context.outputDir, \"diagnostics\");\n const timestamp = new Date().toISOString().replace(/[:.]/g, \"-\");\n const stepLabel = sanitizeDiagnosticsSegment(stepId ?? \"unknown-step\", \"unknown-step\");\n const actionLabel = actionIndex !== undefined ? `action-${actionIndex + 1}` : \"action\";\n const baseName = `${timestamp}-${runId}-${stepLabel}-${actionLabel}`;\n\n try {\n await fs.mkdir(diagnosticsDir, { recursive: true });\n } catch {\n // Ignore failures creating diagnostics dir.\n }\n\n const metadata = {\n runId,\n stepId,\n stepIndex,\n actionIndex,\n action,\n error: error instanceof Error ? error.message : String(error),\n url: context.page.url(),\n capturedAt: new Date().toISOString(),\n };\n\n try {\n const screenshotPath = path.join(diagnosticsDir, `${baseName}.png`);\n await context.page.screenshot({ path: screenshotPath, fullPage: true });\n } catch {\n // Ignore screenshot failures.\n }\n\n try {\n const domContent = await context.page.content();\n const maxChars = 20000;\n const snippet =\n domContent.length > maxChars\n ? `${domContent.slice(0, maxChars)}\\n<!-- truncated -->`\n : domContent;\n const domPath = path.join(diagnosticsDir, `${baseName}.dom.html`);\n await fs.writeFile(domPath, snippet, \"utf-8\");\n } catch {\n // Ignore DOM capture failures.\n }\n\n try {\n const metaPath = path.join(diagnosticsDir, `${baseName}.json`);\n await fs.writeFile(metaPath, JSON.stringify(metadata, null, 2), \"utf-8\");\n } catch {\n // Ignore metadata write failures.\n }\n}\n\n/**\n * Context passed to the demo runner.\n */\nexport interface DemoContext {\n page: Page;\n baseURL: string;\n outputDir: string;\n videoPath?: string;\n videoRecordingStartTime?: number;\n assetBaseDir?: string;\n}\n\n/**\n * Result of running a demo.\n */\nexport interface DemoResult {\n success: boolean;\n demoName: string;\n videoPath?: string;\n scriptPath?: string;\n error?: Error;\n duration: number;\n}\n\nexport interface RunDemoOptions {\n generateScripts?: boolean;\n scriptOutputDir?: string;\n}\n\n/**\n * Step timing info for video splitting.\n */\nexport interface StepTiming {\n id: string;\n script: string;\n startTime: number;\n endTime?: number;\n}\n\ninterface ActionContext {\n stepId: string;\n stepIndex: number;\n actionIndex: number;\n runId: string;\n demoName: string;\n}\n\n/**\n * Loads and parses a YAML demo definition file.\n */\nexport async function loadDemoDefinition(\n filePath: string,\n options?: { resolveSecrets?: (key: string) => string | undefined }\n): Promise<DemoDefinition> {\n const content = await fs.readFile(filePath, \"utf-8\");\n const definition = parseFromYAML(content, options);\n validateDemoDefinition(definition);\n return definition;\n}\n\n/**\n * Waits for org slug to be available after login/redirect.\n */\nfunction resolveFilePath(filePath: string, baseDir?: string): string {\n if (path.isAbsolute(filePath)) {\n return filePath;\n }\n const root = baseDir ?? process.cwd();\n return path.resolve(root, filePath);\n}\n\nfunction resolveNavigatePath(actionPath: string, context: DemoContext): string {\n const resolvedPath = resolvePath(actionPath, { baseURL: context.baseURL });\n if (/\\{[^}]+\\}/.test(resolvedPath)) {\n throw new Error(\n `Navigate action contains unresolved template variables: ${resolvedPath}`\n );\n }\n return resolvedPath;\n}\n\n/**\n * Executes a wait condition.\n * Returns true if the page navigated.\n */\nasync function executeWaitCondition(\n page: Page,\n condition: WaitCondition,\n actionContext?: ActionContext\n): Promise<boolean> {\n const timeout = condition.timeout || DEFAULT_WAIT_TIMEOUT_MS;\n let navigated = false;\n\n const getSelectorContext = async (): Promise<Record<string, unknown>> => {\n if (!condition.value) return {};\n try {\n if (condition.type === \"selector\" || condition.type === \"selectorHidden\") {\n const count = await page.locator(condition.value).count();\n return { selectorCount: count };\n }\n if (condition.type === \"text\" || condition.type === \"textHidden\") {\n const count = await page.getByText(condition.value, { exact: false }).count();\n return { textMatchCount: count };\n }\n } catch (error) {\n return { selectorContextError: error instanceof Error ? error.message : String(error) };\n }\n return {};\n };\n\n for (let attempt = 0; attempt < WAIT_RETRY_ATTEMPTS; attempt += 1) {\n try {\n switch (condition.type) {\n case \"text\":\n if (!condition.value) {\n throw new Error(\"Wait for text requires 'value'\");\n }\n await expect(page.getByText(condition.value, { exact: false }).first()).toBeVisible({\n timeout,\n });\n break;\n\n case \"selector\":\n if (!condition.value) {\n throw new Error(\"Wait for selector requires 'value'\");\n }\n await page.locator(condition.value).first().waitFor({ state: \"visible\", timeout });\n break;\n\n case \"navigation\":\n await page.waitForURL(/.*/, { waitUntil: \"networkidle\", timeout });\n navigated = true;\n break;\n\n case \"idle\":\n await page.waitForLoadState(\"networkidle\", { timeout });\n break;\n\n case \"selectorHidden\":\n if (!condition.value) {\n throw new Error(\"Wait for selectorHidden requires 'value'\");\n }\n await page.locator(condition.value).first().waitFor({ state: \"hidden\", timeout });\n break;\n\n case \"textHidden\":\n if (!condition.value) {\n throw new Error(\"Wait for textHidden requires 'value'\");\n }\n await expect(page.getByText(condition.value, { exact: false }).first()).toBeHidden({\n timeout,\n });\n break;\n }\n\n if (attempt > 0 && actionContext) {\n logEvent(\"info\", \"wait_retry_success\", {\n runId: actionContext.runId,\n demoName: actionContext.demoName,\n stepId: actionContext.stepId,\n actionIndex: actionContext.actionIndex,\n waitType: condition.type,\n attempt: attempt + 1,\n });\n }\n return navigated;\n } catch (error) {\n const selectorContext = await getSelectorContext();\n logEvent(\"warn\", \"wait_retry\", {\n runId: actionContext?.runId,\n demoName: actionContext?.demoName,\n stepId: actionContext?.stepId,\n actionIndex: actionContext?.actionIndex,\n waitType: condition.type,\n waitValue: condition.value,\n timeout,\n attempt: attempt + 1,\n error: error instanceof Error ? error.message : String(error),\n ...selectorContext,\n });\n\n if (attempt >= WAIT_RETRY_ATTEMPTS - 1) {\n throw error;\n }\n const delayMs = WAIT_RETRY_BASE_DELAY_MS * (attempt + 1);\n await page.waitForTimeout(delayMs);\n }\n }\n\n return navigated;\n}\n\n/**\n * Executes a single action within a step.\n * Returns true if the page navigated.\n */\nasync function executeAction(\n action: DemoAction,\n context: DemoContext,\n actionContext: ActionContext\n): Promise<boolean> {\n const { page } = context;\n let navigated = false;\n const timeoutMs = getActionTimeoutMs(action);\n const startedAt = Date.now();\n\n logEvent(\"info\", \"action_start\", {\n runId: actionContext.runId,\n demoName: actionContext.demoName,\n stepId: actionContext.stepId,\n stepIndex: actionContext.stepIndex,\n actionIndex: actionContext.actionIndex,\n actionType: action.action,\n timeoutMs,\n });\n\n try {\n await withActionTimeout(timeoutMs, `${action.action} action`, async () => {\n switch (action.action) {\n case \"navigate\": {\n if (!action.path) {\n throw new Error(\"Navigate action missing 'path'\");\n }\n const resolvedPath = resolveNavigatePath(action.path, context);\n const fullURL = resolvedPath.startsWith(\"http\")\n ? resolvedPath\n : `${context.baseURL}${resolvedPath}`;\n await page.goto(fullURL, { waitUntil: \"networkidle\", timeout: timeoutMs });\n navigated = true;\n await injectCursorOverlay(page);\n break;\n }\n\n case \"click\": {\n if (!action.target) {\n throw new Error(\"Click action missing 'target'\");\n }\n const selector = resolveTarget(action.target);\n await demoClick(page, selector, {\n highlight: action.highlight,\n delayAfter: 500,\n timeoutMs,\n });\n break;\n }\n\n case \"type\": {\n if (!action.target) {\n throw new Error(\"Type action missing 'target'\");\n }\n if (!action.text) {\n throw new Error(\"Type action missing 'text'\");\n }\n const selector = resolveTarget(action.target);\n const element = page.locator(selector).first();\n await element.waitFor({ state: \"visible\", timeout: timeoutMs });\n await element.scrollIntoViewIfNeeded();\n const box = await element.boundingBox();\n if (box) {\n await moveCursorTo(page, box.x + box.width / 2, box.y + box.height / 2);\n }\n await element.click({ timeout: timeoutMs });\n await element.fill(action.text, { timeout: timeoutMs });\n break;\n }\n\n case \"upload\": {\n if (!action.file) {\n throw new Error(\"Upload action missing 'file'\");\n }\n const filePath = resolveFilePath(action.file, context.assetBaseDir);\n // Use target selector if provided, otherwise find first file input\n const fileSelector = action.target?.selector || 'input[type=\"file\"]';\n const fileInput = page.locator(fileSelector).first();\n await fileInput.setInputFiles(filePath, { timeout: timeoutMs });\n break;\n }\n\n case \"wait\": {\n if (action.duration) {\n await page.waitForTimeout(action.duration);\n } else if (action.waitFor) {\n navigated = await executeWaitCondition(page, action.waitFor, actionContext);\n if (navigated) {\n await injectCursorOverlay(page);\n }\n }\n break;\n }\n\n case \"hover\": {\n if (!action.target) {\n throw new Error(\"Hover action missing 'target'\");\n }\n const selector = resolveTarget(action.target);\n const element = page.locator(selector).first();\n await element.waitFor({ state: \"visible\", timeout: timeoutMs });\n await element.scrollIntoViewIfNeeded();\n const box = await element.boundingBox();\n if (box) {\n await moveCursorTo(page, box.x + box.width / 2, box.y + box.height / 2);\n }\n await element.hover({ timeout: timeoutMs });\n break;\n }\n\n case \"scroll\": {\n const scrollAmount = action.duration || 500;\n await page.mouse.wheel(0, scrollAmount);\n await page.waitForTimeout(300);\n break;\n }\n\n case \"scrollTo\": {\n if (!action.target) {\n throw new Error(\"ScrollTo action missing 'target'\");\n }\n const selector = resolveTarget(action.target);\n await page.locator(selector).first().scrollIntoViewIfNeeded({ timeout: timeoutMs });\n await page.waitForTimeout(300);\n break;\n }\n\n case \"drag\": {\n if (!action.target) {\n throw new Error(\"Drag action missing 'target'\");\n }\n if (!action.drag) {\n throw new Error(\"Drag action missing 'drag' configuration\");\n }\n const selector = resolveTarget(action.target);\n const element = page.locator(selector).first();\n await element.waitFor({ state: \"visible\", timeout: timeoutMs });\n await element.scrollIntoViewIfNeeded();\n const box = await element.boundingBox();\n if (!box) {\n throw new Error(`Drag target not found or not visible: ${selector}`);\n }\n\n const startX = box.x + box.width / 2;\n const startY = box.y + box.height / 2;\n const endX = startX + action.drag.deltaX;\n const endY = startY + action.drag.deltaY;\n const dragSteps = action.drag.steps || 20;\n\n await moveCursorTo(page, startX, startY, { steps: 15 });\n await page.waitForTimeout(100);\n\n await page.mouse.move(startX, startY);\n await page.mouse.down();\n await page.waitForTimeout(50);\n\n for (let i = 1; i <= dragSteps; i++) {\n const t = i / dragSteps;\n const easeT = t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2;\n const currentX = startX + (endX - startX) * easeT;\n const currentY = startY + (endY - startY) * easeT;\n\n await page.mouse.move(currentX, currentY);\n await page.evaluate(\n ([x, y, shouldAddTrail]) => {\n const api = (window as Window & { __demoCursor?: { setPosition: (x: number, y: number) => void; addTrail: (x: number, y: number) => void } }).__demoCursor;\n if (api) {\n api.setPosition(x, y);\n if (shouldAddTrail) {\n api.addTrail(x + 4, y + 4);\n }\n }\n },\n [currentX, currentY, i % 3 === 0] as [number, number, boolean]\n );\n await page.waitForTimeout(25);\n }\n\n await page.mouse.up();\n await page.waitForTimeout(200);\n break;\n }\n\n default:\n throw new Error(`Unknown action type: ${action.action}`);\n }\n\n // Wait for any configured condition after action\n if (action.waitFor && action.action !== \"wait\") {\n const waitNavigated = await executeWaitCondition(page, action.waitFor, actionContext);\n if (waitNavigated) {\n await injectCursorOverlay(page);\n navigated = true;\n }\n }\n\n // Small delay between actions for video clarity\n await page.waitForTimeout(200);\n });\n\n logEvent(\"info\", \"action_complete\", {\n runId: actionContext.runId,\n demoName: actionContext.demoName,\n stepId: actionContext.stepId,\n stepIndex: actionContext.stepIndex,\n actionIndex: actionContext.actionIndex,\n actionType: action.action,\n durationMs: Date.now() - startedAt,\n navigated,\n });\n } catch (error) {\n logEvent(\"error\", \"action_failed\", {\n runId: actionContext.runId,\n demoName: actionContext.demoName,\n stepId: actionContext.stepId,\n stepIndex: actionContext.stepIndex,\n actionIndex: actionContext.actionIndex,\n actionType: action.action,\n durationMs: Date.now() - startedAt,\n error: error instanceof Error ? error.message : String(error),\n });\n await captureDiagnostics({\n context,\n stepId: actionContext.stepId,\n stepIndex: actionContext.stepIndex,\n actionIndex: actionContext.actionIndex,\n action,\n error,\n runId: actionContext.runId,\n });\n throw error;\n }\n\n return navigated;\n}\n\n/**\n * Executes a complete step (all actions).\n */\nasync function executeStep(\n step: DemoStep,\n context: DemoContext,\n scriptGenerator: ScriptGenerator | null,\n runId: string,\n demoName: string,\n stepIndex: number\n): Promise<void> {\n console.log(`[demo] Executing step: ${step.id} (${step.actions.length} actions)`);\n logEvent(\"info\", \"step_start\", {\n runId,\n demoName,\n stepId: step.id,\n stepIndex,\n actionCount: step.actions.length,\n });\n\n if (scriptGenerator) {\n scriptGenerator.addSegment(step.id, step.script);\n }\n\n for (let i = 0; i < step.actions.length; i++) {\n const action = step.actions[i];\n console.log(`[demo] Action ${i + 1}/${step.actions.length}: ${action.action}`);\n await executeAction(action, context, {\n stepId: step.id,\n stepIndex,\n actionIndex: i,\n runId,\n demoName,\n });\n }\n\n logEvent(\"info\", \"step_complete\", {\n runId,\n demoName,\n stepId: step.id,\n stepIndex,\n actionCount: step.actions.length,\n });\n}\n\nfunction getStepStartTarget(step: DemoStep): {\n selector: string;\n waitForState: \"visible\" | \"attached\";\n} | null {\n for (const action of step.actions) {\n if (action.action === \"wait\" || action.action === \"navigate\") {\n continue;\n }\n if (!action.target) {\n continue;\n }\n try {\n return {\n selector: resolveTarget(action.target),\n waitForState: action.action === \"upload\" ? \"attached\" : \"visible\",\n };\n } catch {\n return null;\n }\n }\n\n return null;\n}\n\nasync function waitForStepReady(page: Page, step: DemoStep): Promise<void> {\n const target = getStepStartTarget(step);\n if (!target) {\n return;\n }\n\n try {\n await page\n .locator(target.selector)\n .first()\n .waitFor({ state: target.waitForState, timeout: DEFAULT_WAIT_TIMEOUT_MS });\n } catch {\n // If the element never appears, let the step execution surface the error.\n }\n}\n\nfunction getStepEndSelector(step: DemoStep): string | null {\n for (let index = step.actions.length - 1; index >= 0; index -= 1) {\n const action = step.actions[index];\n if (action.action === \"wait\" || action.action === \"navigate\") {\n continue;\n }\n if (!action.target) {\n continue;\n }\n try {\n return resolveTarget(action.target);\n } catch {\n return null;\n }\n }\n\n return null;\n}\n\nasync function waitForStepExit(page: Page, step: DemoStep): Promise<void> {\n const selector = getStepEndSelector(step);\n if (!selector) {\n return;\n }\n\n try {\n await page.locator(selector).first().waitFor({ state: \"hidden\", timeout: 1500 });\n } catch {\n // Allow steps where the last action target remains visible.\n }\n}\n\n/**\n * Runs a complete demo from a definition.\n */\nexport async function runDemo(\n definition: DemoDefinition,\n context: DemoContext,\n options: RunDemoOptions = {}\n): Promise<DemoResult> {\n const startTime = Date.now();\n const transitionDelayMs = 500;\n const runId = `${definition.name}-${startTime}`;\n let scriptGenerator: ScriptGenerator | null = null;\n\n logEvent(\"info\", \"demo_start\", {\n runId,\n demoName: definition.name,\n stepCount: definition.steps.length,\n baseURL: context.baseURL,\n });\n\n try {\n // Inject cursor overlay\n await injectCursorOverlay(context.page);\n const hadVideoStartTime = context.videoRecordingStartTime !== undefined;\n const syncedVideoStartTimeMs = context.videoRecordingStartTime ?? Date.now();\n if (!hadVideoStartTime) {\n context.videoRecordingStartTime = syncedVideoStartTimeMs;\n }\n logEvent(\"info\", \"video_sync\", {\n runId,\n demoName: definition.name,\n videoStartTimeMs: syncedVideoStartTimeMs,\n providedByCaller: hadVideoStartTime,\n });\n if (options.generateScripts) {\n scriptGenerator = createScriptGenerator(\n definition.name,\n definition.title,\n syncedVideoStartTimeMs\n );\n }\n\n // Execute each step\n for (let stepIndex = 0; stepIndex < definition.steps.length; stepIndex += 1) {\n const step = definition.steps[stepIndex];\n if (scriptGenerator && stepIndex > 0) {\n await waitForStepReady(context.page, step);\n }\n if (scriptGenerator) {\n scriptGenerator.startStep(step.id);\n }\n await executeStep(step, context, scriptGenerator, runId, definition.name, stepIndex);\n if (scriptGenerator && stepIndex < definition.steps.length - 1) {\n await waitForStepExit(context.page, step);\n await context.page.waitForTimeout(transitionDelayMs);\n }\n }\n\n if (scriptGenerator) {\n scriptGenerator.finishAllSteps();\n\n const scriptOutputDir = options.scriptOutputDir ?? path.join(context.outputDir, \"scripts\");\n const scriptBasePath = path.join(scriptOutputDir, definition.name);\n await scriptGenerator.exportJSON(`${scriptBasePath}.json`);\n await scriptGenerator.exportSRT(`${scriptBasePath}.srt`);\n await scriptGenerator.exportMarkdown(`${scriptBasePath}.md`);\n await scriptGenerator.exportAIVoiceScript(`${scriptBasePath}.voice.json`);\n\n // Clean up cursor overlay\n await removeCursorOverlay(context.page);\n\n logEvent(\"info\", \"demo_complete\", {\n runId,\n demoName: definition.name,\n durationMs: Date.now() - startTime,\n });\n\n return {\n success: true,\n demoName: definition.name,\n videoPath: context.videoPath,\n scriptPath: `${scriptBasePath}.json`,\n duration: Date.now() - startTime,\n };\n }\n\n // Clean up cursor overlay\n await removeCursorOverlay(context.page);\n\n logEvent(\"info\", \"demo_complete\", {\n runId,\n demoName: definition.name,\n durationMs: Date.now() - startTime,\n });\n\n return {\n success: true,\n demoName: definition.name,\n videoPath: context.videoPath,\n duration: Date.now() - startTime,\n };\n } catch (error) {\n logEvent(\"error\", \"demo_failed\", {\n runId,\n demoName: definition.name,\n durationMs: Date.now() - startTime,\n error: error instanceof Error ? error.message : String(error),\n });\n await captureDiagnostics({\n context,\n error,\n runId,\n });\n return {\n success: false,\n demoName: definition.name,\n error: error instanceof Error ? error : new Error(String(error)),\n duration: Date.now() - startTime,\n };\n }\n}\n\n/**\n * Runs a demo from a YAML file path.\n */\nexport async function runDemoFromFile(\n definitionPath: string,\n context: DemoContext,\n options?: RunDemoOptions\n): Promise<DemoResult> {\n const definition = await loadDemoDefinition(definitionPath);\n return runDemo(definition, context, options);\n}\n\n/**\n * Discovers all demo definition files in a directory.\n */\nexport async function discoverDemos(demoDir: string): Promise<string[]> {\n const files = await fs.readdir(demoDir);\n return files\n .filter((f) => f.endsWith(\".yaml\") || f.endsWith(\".yml\"))\n .map((f) => path.join(demoDir, f));\n}\n","import { spawn } from \"child_process\";\nimport { ElevenLabsClient } from \"elevenlabs\";\nimport * as fs from \"fs/promises\";\nimport * as path from \"path\";\n\nconst DEFAULT_MAX_OUTPUT_BYTES = 512 * 1024;\nconst DEFAULT_MAX_CONCURRENCY = 2;\nconst DEFAULT_RETRY_OPTIONS = {\n retries: 3,\n minDelayMs: 500,\n maxDelayMs: 8000,\n};\n\nfunction sanitizeFileSegment(value: string, fallback = \"segment\", maxLength = 80): string {\n const raw = String(value ?? \"\").trim();\n if (!raw) {\n return fallback;\n }\n\n const cleaned = raw.replace(/[^a-zA-Z0-9._-]+/g, \"_\");\n const collapsed = cleaned.replace(/_{2,}/g, \"_\").replace(/^_+|_+$/g, \"\");\n const safe = collapsed || fallback;\n const trimmed = safe.length > maxLength ? safe.slice(0, maxLength) : safe;\n\n if (trimmed === \".\" || trimmed === \"..\") {\n return fallback;\n }\n\n return trimmed;\n}\n\nfunction appendWithLimit(buffer: string, chunk: string, limit: number): string {\n const next = buffer + chunk;\n if (next.length <= limit) {\n return next;\n }\n return next.slice(next.length - limit);\n}\n\nfunction runCommand(\n command: string,\n args: string[],\n options: { stdio?: Array<\"ignore\" | \"pipe\">; cwd?: string; maxOutputBytes?: number } = {}\n) {\n const {\n stdio = [\"ignore\", \"pipe\", \"pipe\"],\n cwd,\n maxOutputBytes = DEFAULT_MAX_OUTPUT_BYTES,\n } = options;\n return new Promise<{ stdout: string; stderr: string }>((resolve, reject) => {\n const child = spawn(command, args, { stdio, cwd });\n let stdout = \"\";\n let stderr = \"\";\n\n if (child.stdout) {\n child.stdout.on(\"data\", (chunk) => {\n stdout = appendWithLimit(stdout, chunk.toString(), maxOutputBytes);\n });\n }\n\n if (child.stderr) {\n child.stderr.on(\"data\", (chunk) => {\n stderr = appendWithLimit(stderr, chunk.toString(), maxOutputBytes);\n });\n }\n\n child.on(\"error\", (error) => {\n reject(error);\n });\n\n child.on(\"close\", (code) => {\n if (code === 0) {\n resolve({ stdout, stderr });\n return;\n }\n const error = new Error(`${command} exited with code ${code}`);\n (error as Error & { code?: number; stderr?: string }).code = code ?? undefined;\n (error as Error & { code?: number; stderr?: string }).stderr = stderr;\n reject(error);\n });\n });\n}\n\nasync function probeMediaDurationMs(filePath: string): Promise<number | null> {\n try {\n const { stdout } = await runCommand(\"ffprobe\", [\n \"-v\",\n \"error\",\n \"-show_entries\",\n \"format=duration\",\n \"-of\",\n \"default=noprint_wrappers=1:nokey=1\",\n filePath,\n ]);\n const durationSec = parseFloat(stdout.trim());\n if (Number.isFinite(durationSec)) {\n return Math.round(durationSec * 1000);\n }\n } catch {\n return null;\n }\n return null;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\ninterface RetryOptions {\n retries?: number;\n minDelayMs?: number;\n maxDelayMs?: number;\n}\n\nfunction getStatusCode(error: unknown): number | undefined {\n if (!error || typeof error !== \"object\") return undefined;\n const maybeError = error as {\n status?: number;\n statusCode?: number;\n response?: { status?: number };\n };\n return maybeError.status ?? maybeError.statusCode ?? maybeError.response?.status;\n}\n\nfunction getHeaderValue(headers: unknown, name: string): string | null {\n if (!headers || typeof headers !== \"object\") {\n return null;\n }\n const getter = (headers as { get?: unknown }).get;\n if (typeof getter === \"function\") {\n return getter.call(headers, name);\n }\n const record = headers as Record<string, string>;\n const direct = record[name];\n if (typeof direct === \"string\") {\n return direct;\n }\n const lower = record[name.toLowerCase()];\n if (typeof lower === \"string\") {\n return lower;\n }\n const upper = record[name.toUpperCase()];\n if (typeof upper === \"string\") {\n return upper;\n }\n return null;\n}\n\nfunction getRetryAfterMs(error: unknown): number | null {\n if (!error || typeof error !== \"object\") return null;\n const maybeError = error as {\n retryAfter?: string | number;\n response?: { headers?: Record<string, string> | { get?: (name: string) => string | null } };\n };\n const headerValue = getHeaderValue(maybeError.response?.headers, \"retry-after\");\n const retryAfter = headerValue ?? maybeError.retryAfter;\n if (retryAfter === undefined || retryAfter === null) {\n return null;\n }\n const seconds = Number(retryAfter);\n if (Number.isFinite(seconds)) {\n return Math.max(0, Math.round(seconds * 1000));\n }\n return null;\n}\n\nfunction isRetryableError(error: unknown): boolean {\n const status = getStatusCode(error);\n if (status && [408, 429, 500, 502, 503, 504].includes(status)) {\n return true;\n }\n const message = String((error as Error | undefined)?.message ?? \"\");\n return /(rate limit|timeout|ECONNRESET|ETIMEDOUT|EAI_AGAIN|socket hang up)/i.test(message);\n}\n\nfunction getRetryDelayMs(attempt: number, options: RetryOptions, error: unknown): number {\n const minDelayMs = options.minDelayMs ?? DEFAULT_RETRY_OPTIONS.minDelayMs;\n const maxDelayMs = options.maxDelayMs ?? DEFAULT_RETRY_OPTIONS.maxDelayMs;\n const baseDelay = Math.min(maxDelayMs, minDelayMs * 2 ** attempt);\n const jitter = 0.5 + Math.random();\n const retryAfterMs = getRetryAfterMs(error) ?? 0;\n return Math.max(retryAfterMs, Math.round(baseDelay * jitter));\n}\n\nasync function withRetry<T>(fn: () => Promise<T>, options: RetryOptions = {}): Promise<T> {\n const retries = options.retries ?? DEFAULT_RETRY_OPTIONS.retries;\n let attempt = 0;\n // eslint-disable-next-line no-constant-condition\n while (true) {\n try {\n return await fn();\n } catch (error) {\n if (!isRetryableError(error) || attempt >= retries) {\n throw error;\n }\n const delayMs = getRetryDelayMs(attempt, options, error);\n await sleep(delayMs);\n attempt += 1;\n }\n }\n}\n\n/**\n * Configuration for voice synthesis\n */\nexport interface VoiceSynthesisConfig {\n apiKey: string;\n voiceId: string; // Custom voice ID from ElevenLabs\n modelId?: string; // Default: eleven_multilingual_v2\n outputFormat?: \"mp3_44100_128\" | \"mp3_44100_192\" | \"pcm_16000\" | \"pcm_22050\" | \"pcm_24000\";\n}\n\n/**\n * Script segment from the generated JSON\n */\nexport interface ScriptSegment {\n stepId: string;\n text: string;\n startTimeMs: number;\n endTimeMs: number;\n estimatedDurationMs: number;\n pauseBeforeMs?: number;\n pauseAfterMs?: number;\n}\n\n/**\n * Generated script JSON structure\n */\nexport interface GeneratedScript {\n demoName: string;\n title: string;\n generatedAt: string;\n totalDurationMs: number;\n segments: ScriptSegment[];\n}\n\n/**\n * Result of synthesizing a segment\n */\nexport interface SynthesizedSegment {\n stepId: string;\n audioPath: string;\n durationMs: number;\n text: string;\n}\n\n/**\n * Result of full voice synthesis\n */\nexport interface VoiceSynthesisResult {\n demoName: string;\n segments: SynthesizedSegment[];\n combinedAudioPath?: string;\n soundEffectsPath?: string;\n backgroundMusicPath?: string;\n}\n\n/**\n * ElevenLabs voice synthesizer for demo narration\n */\nexport class VoiceSynthesizer {\n private client: ElevenLabsClient;\n private config: VoiceSynthesisConfig;\n\n constructor(config: VoiceSynthesisConfig) {\n this.config = config;\n this.client = new ElevenLabsClient({\n apiKey: config.apiKey,\n });\n }\n\n /**\n * List available voices (useful for finding voice IDs)\n */\n async listVoices(): Promise<Array<{ voiceId: string; name: string; category: string }>> {\n const response = await this.client.voices.getAll();\n return response.voices.map((voice) => ({\n voiceId: voice.voice_id,\n name: voice.name || \"Unnamed\",\n category: voice.category || \"unknown\",\n }));\n }\n\n /**\n * Synthesize a single text segment to audio\n */\n async synthesizeSegment(\n text: string,\n outputPath: string,\n options?: {\n stability?: number; // 0-1, higher = more consistent\n similarityBoost?: number; // 0-1, higher = more similar to original voice\n style?: number; // 0-1, style exaggeration\n useSpeakerBoost?: boolean;\n }\n ): Promise<{ durationMs: number }> {\n const audio = await this.client.textToSpeech.convert(this.config.voiceId, {\n text,\n model_id: this.config.modelId || \"eleven_multilingual_v2\",\n voice_settings: {\n stability: options?.stability ?? 0.5,\n similarity_boost: options?.similarityBoost ?? 0.75,\n style: options?.style ?? 0.0,\n use_speaker_boost: options?.useSpeakerBoost ?? true,\n },\n });\n\n // Collect audio chunks\n const chunks: Buffer[] = [];\n for await (const chunk of audio) {\n chunks.push(Buffer.from(chunk));\n }\n const audioBuffer = Buffer.concat(chunks);\n\n // Write to file\n await fs.writeFile(outputPath, audioBuffer);\n\n const probedDurationMs = await probeMediaDurationMs(outputPath);\n if (probedDurationMs !== null) {\n return { durationMs: probedDurationMs };\n }\n\n const fileSizeBytes = audioBuffer.length;\n const estimatedDurationMs = Math.round((fileSizeBytes * 8) / 128); // 128kbps\n console.warn(`[voice] ffprobe unavailable, using estimated duration for ${outputPath}`);\n return { durationMs: estimatedDurationMs };\n }\n\n /**\n * Generate a sound effect from text description\n */\n async generateSoundEffect(\n description: string,\n outputPath: string,\n options?: {\n durationSeconds?: number; // 0.5-30\n promptInfluence?: number; // 0-1\n retry?: RetryOptions;\n }\n ): Promise<void> {\n const audio = await withRetry(\n () =>\n this.client.textToSoundEffects.convert({\n text: description,\n duration_seconds: options?.durationSeconds ?? 1.0,\n prompt_influence: options?.promptInfluence ?? 0.3,\n }),\n options?.retry\n );\n\n const chunks: Buffer[] = [];\n for await (const chunk of audio) {\n chunks.push(Buffer.from(chunk));\n }\n await fs.writeFile(outputPath, Buffer.concat(chunks));\n }\n\n /**\n * Synthesize all segments from a script JSON file\n */\n async synthesizeScript(\n scriptPath: string,\n outputDir: string,\n options?: {\n voiceSettings?: {\n stability?: number;\n similarityBoost?: number;\n style?: number;\n };\n generateClickSounds?: boolean;\n onProgress?: (current: number, total: number, stepId: string) => void;\n maxConcurrency?: number;\n retry?: RetryOptions;\n }\n ): Promise<VoiceSynthesisResult> {\n // Read script\n const scriptContent = await fs.readFile(scriptPath, \"utf-8\");\n const script: GeneratedScript = JSON.parse(scriptContent);\n\n // Ensure output directory exists\n const audioDir = path.join(outputDir, \"audio\", script.demoName);\n await fs.mkdir(audioDir, { recursive: true });\n\n const synthesizedSegments: SynthesizedSegment[] = new Array(script.segments.length);\n const maxConcurrency = Math.max(\n 1,\n options?.maxConcurrency ?? DEFAULT_MAX_CONCURRENCY\n );\n let progressCount = 0;\n let nextIndex = 0;\n\n const workers = Array.from({ length: Math.min(maxConcurrency, script.segments.length) }, async () => {\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const index = nextIndex;\n nextIndex += 1;\n if (index >= script.segments.length) {\n break;\n }\n\n const segment = script.segments[index];\n const safeStepId = sanitizeFileSegment(segment.stepId, `step-${index + 1}`);\n const audioFileName = `${String(index + 1).padStart(2, \"0\")}_${safeStepId}.mp3`;\n const audioPath = path.join(audioDir, audioFileName);\n\n progressCount += 1;\n options?.onProgress?.(progressCount, script.segments.length, segment.stepId);\n\n try {\n const result = await withRetry(\n () => this.synthesizeSegment(segment.text, audioPath, options?.voiceSettings),\n options?.retry\n );\n\n synthesizedSegments[index] = {\n stepId: segment.stepId,\n audioPath,\n durationMs: result.durationMs,\n text: segment.text,\n };\n\n console.log(`[voice] Synthesized: ${segment.stepId} (${result.durationMs.toFixed(0)}ms)`);\n } catch (error) {\n console.error(`[voice] Failed to synthesize ${segment.stepId}:`, error);\n throw error;\n }\n }\n });\n\n await Promise.all(workers);\n\n // Generate click sounds if requested\n let soundEffectsPath: string | undefined;\n if (options?.generateClickSounds) {\n soundEffectsPath = path.join(audioDir, \"click.mp3\");\n await this.generateClickSound(soundEffectsPath);\n }\n\n return {\n demoName: script.demoName,\n segments: synthesizedSegments,\n soundEffectsPath,\n };\n }\n\n /**\n * Generate a UI click sound effect\n */\n async generateClickSound(outputPath: string): Promise<void> {\n await this.generateSoundEffect(\n \"soft UI button click, subtle, digital, clean interface sound\",\n outputPath,\n { durationSeconds: 0.5, promptInfluence: 0.5 }\n );\n console.log(\"[voice] Generated click sound effect\");\n }\n\n /**\n * Generate ambient background music\n */\n async generateBackgroundMusic(\n outputPath: string,\n options?: {\n style?: \"corporate\" | \"tech\" | \"calm\" | \"upbeat\";\n durationSeconds?: number;\n }\n ): Promise<void> {\n const styleDescriptions: Record<string, string> = {\n corporate: \"soft corporate background music, professional, minimal, ambient technology sounds\",\n tech: \"modern technology background music, subtle electronic, innovative, clean\",\n calm: \"calm ambient background music, peaceful, soft piano, gentle\",\n upbeat: \"light upbeat background music, positive, motivational, subtle energy\",\n };\n\n const description = styleDescriptions[options?.style || \"tech\"];\n const duration = options?.durationSeconds ?? 30;\n\n // Note: ElevenLabs sound effects max is 30 seconds\n // For longer music, you'd need to loop or use their music generation API\n await this.generateSoundEffect(description, outputPath, {\n durationSeconds: Math.min(duration, 30),\n promptInfluence: 0.4,\n });\n console.log(`[voice] Generated background music (${options?.style || \"tech\"} style)`);\n }\n}\n\n/**\n * Create a timing manifest for video editing\n * Maps audio files to their intended start times in the video\n */\nexport interface AudioTimingManifest {\n demoName: string;\n segments: Array<{\n stepId: string;\n audioFile: string;\n videoStartTimeMs: number;\n audioDurationMs: number;\n text: string;\n }>;\n soundEffects?: {\n clickSound?: string;\n };\n backgroundMusic?: string;\n}\n\n/**\n * Generate a timing manifest from synthesized results and original script\n */\nexport async function generateTimingManifest(\n scriptPath: string,\n synthesisResult: VoiceSynthesisResult,\n outputPath: string\n): Promise<AudioTimingManifest> {\n const scriptContent = await fs.readFile(scriptPath, \"utf-8\");\n const script: GeneratedScript = JSON.parse(scriptContent);\n\n const manifest: AudioTimingManifest = {\n demoName: script.demoName,\n segments: synthesisResult.segments.map((synth) => {\n const originalSegment = script.segments.find((s) => s.stepId === synth.stepId);\n return {\n stepId: synth.stepId,\n audioFile: synth.audioPath,\n videoStartTimeMs: originalSegment?.startTimeMs ?? 0,\n audioDurationMs: synth.durationMs,\n text: synth.text,\n };\n }),\n soundEffects: synthesisResult.soundEffectsPath\n ? { clickSound: synthesisResult.soundEffectsPath }\n : undefined,\n backgroundMusic: synthesisResult.backgroundMusicPath,\n };\n\n await fs.writeFile(outputPath, JSON.stringify(manifest, null, 2));\n return manifest;\n}\n\n/**\n * Default export for easy instantiation\n */\nexport function createVoiceSynthesizer(config: VoiceSynthesisConfig): VoiceSynthesizer {\n return new VoiceSynthesizer(config);\n}\n","import * as fs from \"fs/promises\";\nimport * as path from \"path\";\n\n/**\n * A single segment of narration with timing information.\n */\nexport interface ScriptSegment {\n stepId: string;\n text: string;\n startTimeMs: number;\n endTimeMs: number;\n estimatedDurationMs: number;\n pauseBeforeMs?: number;\n pauseAfterMs?: number;\n}\n\n/**\n * Video step boundary for splitting videos per step.\n */\nexport interface StepBoundary {\n stepId: string;\n stepIndex: number;\n videoStartMs: number;\n videoEndMs: number;\n}\n\n/**\n * Complete script output with metadata.\n */\nexport interface ScriptOutput {\n demoName: string;\n title: string;\n generatedAt: string;\n totalDurationMs: number;\n segments: ScriptSegment[];\n stepBoundaries: StepBoundary[];\n videoMetadata?: {\n videoPath: string;\n durationMs: number;\n alignmentOffsetMs: number;\n recordingStartTimeMs?: number;\n alignedAt?: string;\n };\n}\n\n/**\n * Tracks narration segments during demo execution.\n */\nexport class ScriptGenerator {\n private segments: ScriptSegment[] = [];\n private stepBoundaries: StepBoundary[] = [];\n private currentStepId: string | null = null;\n private currentStepStartMs: number | null = null;\n private demoName: string;\n private title: string;\n private startTime: number;\n\n constructor(demoName: string, title: string, startTimeMs?: number) {\n this.demoName = demoName;\n this.title = title;\n this.startTime = startTimeMs ?? Date.now();\n }\n\n /**\n * Marks the start of a step (for video splitting).\n */\n startStep(stepId: string): void {\n // End previous step if there was one\n if (this.currentStepId && this.currentStepStartMs !== null) {\n this.stepBoundaries.push({\n stepId: this.currentStepId,\n stepIndex: this.stepBoundaries.length,\n videoStartMs: this.currentStepStartMs,\n videoEndMs: Date.now() - this.startTime,\n });\n }\n\n this.currentStepId = stepId;\n this.currentStepStartMs = Date.now() - this.startTime;\n }\n\n /**\n * Marks the end of all steps (call at demo completion).\n */\n finishAllSteps(): void {\n if (this.currentStepId && this.currentStepStartMs !== null) {\n this.stepBoundaries.push({\n stepId: this.currentStepId,\n stepIndex: this.stepBoundaries.length,\n videoStartMs: this.currentStepStartMs,\n videoEndMs: Date.now() - this.startTime,\n });\n this.currentStepId = null;\n this.currentStepStartMs = null;\n }\n }\n\n /**\n * Estimates reading duration for text.\n * Based on ~150 words per minute average speaking rate.\n */\n private estimateReadingDuration(text: string): number {\n const words = text.split(/\\s+/).length;\n const wpm = 150; // Words per minute\n return Math.round((words / wpm) * 60 * 1000);\n }\n\n /**\n * Adds a narration segment with automatic timing.\n */\n addSegment(\n stepId: string,\n text: string,\n options?: {\n timing?: \"on_start\" | \"on_complete\";\n pauseBeforeMs?: number;\n pauseAfterMs?: number;\n }\n ): void {\n const now = Date.now();\n const startTimeMs = now - this.startTime;\n const estimatedDurationMs = this.estimateReadingDuration(text);\n\n this.segments.push({\n stepId,\n text,\n startTimeMs,\n endTimeMs: startTimeMs + estimatedDurationMs,\n estimatedDurationMs,\n pauseBeforeMs: options?.pauseBeforeMs,\n pauseAfterMs: options?.pauseAfterMs,\n });\n }\n\n /**\n * Updates the end time of the last segment.\n * Call this when a step completes to capture actual duration.\n */\n completeLastSegment(): void {\n if (this.segments.length > 0) {\n const lastSegment = this.segments[this.segments.length - 1];\n lastSegment.endTimeMs = Date.now() - this.startTime;\n }\n }\n\n /**\n * Generates the complete script output.\n */\n getOutput(): ScriptOutput {\n const now = Date.now();\n return {\n demoName: this.demoName,\n title: this.title,\n generatedAt: new Date().toISOString(),\n totalDurationMs: now - this.startTime,\n segments: this.segments,\n stepBoundaries: this.stepBoundaries,\n };\n }\n\n /**\n * Exports script as JSON.\n */\n async exportJSON(outputPath: string): Promise<void> {\n const output = this.getOutput();\n await fs.mkdir(path.dirname(outputPath), { recursive: true });\n await fs.writeFile(outputPath, JSON.stringify(output, null, 2));\n }\n\n /**\n * Exports script as SRT subtitle format.\n */\n async exportSRT(outputPath: string): Promise<void> {\n const output = this.getOutput();\n let srt = \"\";\n\n output.segments.forEach((segment, index) => {\n const startTime = formatSRTTime(segment.startTimeMs);\n const endTime = formatSRTTime(segment.endTimeMs);\n\n srt += `${index + 1}\\n`;\n srt += `${startTime} --> ${endTime}\\n`;\n srt += `${segment.text}\\n\\n`;\n });\n\n await fs.mkdir(path.dirname(outputPath), { recursive: true });\n await fs.writeFile(outputPath, srt.trim());\n }\n\n /**\n * Exports script in a format suitable for AI voice generation services.\n * Includes SSML-like pause markers.\n */\n async exportAIVoiceScript(outputPath: string): Promise<void> {\n const output = this.getOutput();\n\n interface AIVoiceSegment {\n index: number;\n stepId: string;\n text: string;\n ssmlHints: string;\n pauseBeforeMs: number;\n pauseAfterMs: number;\n syncPointMs: number;\n }\n\n const voiceScript = {\n demoName: output.demoName,\n title: output.title,\n totalDuration: formatReadableTime(output.totalDurationMs),\n segments: output.segments.map((segment, index) => ({\n index: index + 1,\n stepId: segment.stepId,\n text: segment.text,\n ssmlHints: generateSSMLHints(segment),\n pauseBeforeMs: segment.pauseBeforeMs || 0,\n pauseAfterMs: segment.pauseAfterMs || 500,\n syncPointMs: segment.startTimeMs,\n } satisfies AIVoiceSegment)),\n };\n\n await fs.mkdir(path.dirname(outputPath), { recursive: true });\n await fs.writeFile(outputPath, JSON.stringify(voiceScript, null, 2));\n }\n\n /**\n * Exports script as human-readable markdown for voice actors.\n */\n async exportMarkdown(outputPath: string): Promise<void> {\n const output = this.getOutput();\n\n let markdown = `# ${output.title}\\n\\n`;\n markdown += `**Demo:** ${output.demoName}\\n`;\n markdown += `**Total Duration:** ${formatReadableTime(output.totalDurationMs)}\\n`;\n markdown += `**Generated:** ${output.generatedAt}\\n\\n`;\n markdown += `---\\n\\n`;\n markdown += `## Script\\n\\n`;\n\n output.segments.forEach((segment, index) => {\n markdown += `### ${index + 1}. ${segment.stepId}\\n\\n`;\n markdown += `**Timing:** ${formatReadableTime(segment.startTimeMs)} - ${formatReadableTime(segment.endTimeMs)}\\n\\n`;\n\n if (segment.pauseBeforeMs) {\n markdown += `*[Pause ${segment.pauseBeforeMs}ms before]*\\n\\n`;\n }\n\n markdown += `> ${segment.text}\\n\\n`;\n\n if (segment.pauseAfterMs) {\n markdown += `*[Pause ${segment.pauseAfterMs}ms after]*\\n\\n`;\n }\n\n markdown += `---\\n\\n`;\n });\n\n await fs.mkdir(path.dirname(outputPath), { recursive: true });\n await fs.writeFile(outputPath, markdown);\n }\n}\n\n/**\n * Formats milliseconds to SRT timestamp format (HH:MM:SS,mmm).\n */\nfunction formatSRTTime(ms: number): string {\n const hours = Math.floor(ms / 3600000);\n const minutes = Math.floor((ms % 3600000) / 60000);\n const seconds = Math.floor((ms % 60000) / 1000);\n const milliseconds = ms % 1000;\n\n return `${pad(hours, 2)}:${pad(minutes, 2)}:${pad(seconds, 2)},${pad(milliseconds, 3)}`;\n}\n\n/**\n * Formats milliseconds to human-readable time (M:SS or H:MM:SS).\n */\nfunction formatReadableTime(ms: number): string {\n const totalSeconds = Math.floor(ms / 1000);\n const hours = Math.floor(totalSeconds / 3600);\n const minutes = Math.floor((totalSeconds % 3600) / 60);\n const seconds = totalSeconds % 60;\n\n if (hours > 0) {\n return `${hours}:${pad(minutes, 2)}:${pad(seconds, 2)}`;\n }\n return `${minutes}:${pad(seconds, 2)}`;\n}\n\n/**\n * Pads a number with leading zeros.\n */\nfunction pad(num: number, size: number): string {\n let s = num.toString();\n while (s.length < size) s = \"0\" + s;\n return s;\n}\n\n/**\n * Generates SSML hints for AI voice services.\n */\nfunction generateSSMLHints(segment: ScriptSegment): string {\n let ssml = segment.text;\n\n // Add break before if specified\n if (segment.pauseBeforeMs) {\n ssml = `<break time=\"${segment.pauseBeforeMs}ms\"/> ${ssml}`;\n }\n\n // Add break after if specified\n if (segment.pauseAfterMs) {\n ssml = `${ssml} <break time=\"${segment.pauseAfterMs}ms\"/>`;\n }\n\n return ssml;\n}\n\n/**\n * Creates a new ScriptGenerator instance.\n */\nexport function createScriptGenerator(\n demoName: string,\n title: string,\n startTimeMs?: number\n): ScriptGenerator {\n return new ScriptGenerator(demoName, title, startTimeMs);\n}\n","import type { Page } from \"@playwright/test\";\n\n/**\n * CSS for the custom cursor overlay.\n * Features:\n * - Large red arrow cursor visible on dark and light backgrounds\n * - Click ripple animation\n * - Smooth movement transitions\n * - Element highlight ring\n */\nconst CURSOR_STYLES = `\n /* Hide the real cursor when demo cursor is active */\n html.demo-cursor-active, html.demo-cursor-active * {\n cursor: none !important;\n }\n\n /* Demo cursor container */\n #demo-cursor {\n position: fixed;\n pointer-events: none;\n z-index: 999999;\n will-change: left, top;\n }\n\n /* Cursor arrow SVG - larger for visibility */\n #demo-cursor-arrow {\n width: 32px;\n height: 32px;\n filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.6)) drop-shadow(0 0 2px rgba(0, 0, 0, 0.4));\n }\n\n /* Click ripple effect - larger and more visible */\n .demo-click-ripple {\n position: absolute;\n top: 4px;\n left: 4px;\n width: 60px;\n height: 60px;\n border-radius: 50%;\n background: radial-gradient(circle, rgba(239, 68, 68, 0.7) 0%, rgba(239, 68, 68, 0.3) 40%, rgba(239, 68, 68, 0) 70%);\n transform: translate(-50%, -50%) scale(0);\n animation: demo-ripple 0.5s ease-out forwards;\n pointer-events: none;\n }\n\n @keyframes demo-ripple {\n 0% {\n transform: translate(-50%, -50%) scale(0);\n opacity: 1;\n }\n 100% {\n transform: translate(-50%, -50%) scale(2.5);\n opacity: 0;\n }\n }\n\n /* Highlight ring for elements being clicked - thicker and more visible */\n .demo-highlight-ring {\n position: fixed;\n border: 3px solid rgba(239, 68, 68, 0.9);\n border-radius: 6px;\n pointer-events: none;\n z-index: 999998;\n box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.3), inset 0 0 0 1px rgba(239, 68, 68, 0.2);\n animation: demo-highlight-pulse 0.8s ease-out forwards;\n }\n\n @keyframes demo-highlight-pulse {\n 0% {\n opacity: 1;\n transform: scale(1);\n }\n 50% {\n opacity: 0.9;\n transform: scale(1.03);\n }\n 100% {\n opacity: 0;\n transform: scale(1.08);\n }\n }\n\n /* Trail effect for cursor movement */\n .demo-cursor-trail {\n position: fixed;\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: rgba(239, 68, 68, 0.4);\n pointer-events: none;\n z-index: 999998;\n animation: demo-trail-fade 0.3s ease-out forwards;\n }\n\n @keyframes demo-trail-fade {\n 0% {\n opacity: 0.6;\n transform: scale(1);\n }\n 100% {\n opacity: 0;\n transform: scale(0.5);\n }\n }\n`;\n\n/**\n * SVG cursor arrow (red with white outline for visibility)\n */\nconst CURSOR_SVG = `\n <svg id=\"demo-cursor-arrow\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M3 3L10.5 21L13 13L21 10.5L3 3Z\" fill=\"#ef4444\" stroke=\"white\" stroke-width=\"2\" stroke-linejoin=\"round\"/>\n </svg>\n`;\n\nconst NAME_HELPER_SCRIPT = `\n(() => {\n if (typeof window.__name !== \"function\") {\n window.__name = (target, value) => {\n try {\n Object.defineProperty(target, \"name\", { value, configurable: true });\n } catch {\n // Ignore failures setting function names.\n }\n return target;\n };\n }\n})();\n`;\n\nconst nameHelperInstalled = new WeakSet<Page>();\n\ninterface DemoCursorAPI {\n setPosition: (x: number, y: number) => void;\n click: () => void;\n highlight: (rect: { x: number; y: number; width: number; height: number }) => void;\n addTrail: (x: number, y: number) => void;\n destroy: () => void;\n}\n\nasync function ensureNameHelper(page: Page): Promise<void> {\n if (!nameHelperInstalled.has(page)) {\n await page.addInitScript({ content: NAME_HELPER_SCRIPT });\n nameHelperInstalled.add(page);\n }\n await page.addScriptTag({ content: NAME_HELPER_SCRIPT });\n}\n\n/**\n * Injects the demo cursor overlay into the page.\n * Call this once after page load.\n */\nexport async function injectCursorOverlay(page: Page): Promise<void> {\n await ensureNameHelper(page);\n await page.addStyleTag({ content: CURSOR_STYLES });\n\n await page.evaluate((cursorSvg) => {\n // Create cursor container\n const cursor = document.createElement(\"div\");\n cursor.id = \"demo-cursor\";\n cursor.innerHTML = cursorSvg;\n cursor.style.left = \"-100px\";\n cursor.style.top = \"-100px\";\n document.body.appendChild(cursor);\n\n // Enable demo cursor mode\n document.documentElement.classList.add(\"demo-cursor-active\");\n\n // Expose functions to window for Playwright to call\n (window as Window & { __demoCursor?: DemoCursorAPI }).__demoCursor = {\n setPosition: (x: number, y: number) => {\n cursor.style.left = `${x}px`;\n cursor.style.top = `${y}px`;\n },\n click: () => {\n const ripple = document.createElement(\"div\");\n ripple.className = \"demo-click-ripple\";\n cursor.appendChild(ripple);\n setTimeout(() => ripple.remove(), 500);\n },\n highlight: (rect: { x: number; y: number; width: number; height: number }) => {\n const ring = document.createElement(\"div\");\n ring.className = \"demo-highlight-ring\";\n ring.style.left = `${rect.x}px`;\n ring.style.top = `${rect.y}px`;\n ring.style.width = `${rect.width}px`;\n ring.style.height = `${rect.height}px`;\n document.body.appendChild(ring);\n setTimeout(() => ring.remove(), 800);\n },\n addTrail: (x: number, y: number) => {\n const trail = document.createElement(\"div\");\n trail.className = \"demo-cursor-trail\";\n trail.style.left = `${x}px`;\n trail.style.top = `${y}px`;\n document.body.appendChild(trail);\n setTimeout(() => trail.remove(), 300);\n },\n destroy: () => {\n cursor.remove();\n document.documentElement.classList.remove(\"demo-cursor-active\");\n // Clean up any remaining trails or highlights\n document.querySelectorAll(\".demo-cursor-trail, .demo-highlight-ring, .demo-click-ripple\").forEach(el => el.remove());\n },\n };\n }, CURSOR_SVG);\n}\n\n/**\n * Smoothly moves the demo cursor to specified coordinates using actual mouse movement.\n * This creates a visible animation in the recorded video.\n */\nexport async function moveCursorTo(\n page: Page,\n x: number,\n y: number,\n options?: { steps?: number; trailEnabled?: boolean }\n): Promise<void> {\n const steps = options?.steps ?? 15;\n const trailEnabled = options?.trailEnabled ?? true;\n\n // Get current cursor position\n const currentPos = await page.evaluate(() => {\n const cursor = document.getElementById(\"demo-cursor\");\n if (!cursor) return { x: 0, y: 0 };\n return {\n x: parseFloat(cursor.style.left) || 0,\n y: parseFloat(cursor.style.top) || 0,\n };\n });\n\n // If starting from off-screen, jump to a reasonable starting position\n if (currentPos.x < 0 || currentPos.y < 0) {\n currentPos.x = x > 100 ? x - 100 : 50;\n currentPos.y = y > 100 ? y - 100 : 50;\n await page.evaluate(\n ([startX, startY]) => {\n const api = (window as Window & { __demoCursor?: DemoCursorAPI }).__demoCursor;\n if (api) api.setPosition(startX, startY);\n },\n [currentPos.x, currentPos.y]\n );\n await page.waitForTimeout(50);\n }\n\n // Animate movement in steps with easing\n for (let i = 1; i <= steps; i++) {\n // Ease-out cubic for smooth deceleration\n const t = i / steps;\n const easeT = 1 - Math.pow(1 - t, 3);\n\n const newX = currentPos.x + (x - currentPos.x) * easeT;\n const newY = currentPos.y + (y - currentPos.y) * easeT;\n\n await page.evaluate(\n ({ posX, posY, addTrail }) => {\n const api = (window as Window & { __demoCursor?: DemoCursorAPI }).__demoCursor;\n if (api) {\n api.setPosition(posX, posY);\n // Add trail effect every few steps\n if (addTrail) {\n api.addTrail(posX + 4, posY + 4);\n }\n }\n },\n { posX: newX, posY: newY, addTrail: trailEnabled && i % 3 === 0 }\n );\n\n await page.waitForTimeout(20);\n }\n\n // Ensure final position is exact\n await page.evaluate(\n ([finalX, finalY]) => {\n const api = (window as Window & { __demoCursor?: DemoCursorAPI }).__demoCursor;\n if (api) api.setPosition(finalX, finalY);\n },\n [x, y]\n );\n\n // Also move the actual mouse to ensure hover states work\n await page.mouse.move(x, y);\n\n // Brief pause at destination\n await page.waitForTimeout(100);\n}\n\n/**\n * Triggers the click ripple animation at the current cursor position.\n */\nexport async function triggerClickRipple(page: Page): Promise<void> {\n await page.evaluate(() => {\n const api = (window as Window & { __demoCursor?: DemoCursorAPI }).__demoCursor;\n if (api) {\n api.click();\n }\n });\n // Wait for ripple animation to be visible\n await page.waitForTimeout(150);\n}\n\n/**\n * Highlights an element with a pulsing ring effect.\n */\nexport async function highlightElement(page: Page, selector: string): Promise<void> {\n const boundingBox = await page.locator(selector).first().boundingBox();\n if (boundingBox) {\n await page.evaluate(\n (rect) => {\n const api = (window as Window & { __demoCursor?: DemoCursorAPI }).__demoCursor;\n if (api) {\n api.highlight(rect);\n }\n },\n {\n x: boundingBox.x - 6,\n y: boundingBox.y - 6,\n width: boundingBox.width + 12,\n height: boundingBox.height + 12,\n }\n );\n }\n}\n\n/**\n * Removes the demo cursor overlay.\n */\nexport async function removeCursorOverlay(page: Page): Promise<void> {\n await page.evaluate(() => {\n const api = (window as Window & { __demoCursor?: DemoCursorAPI }).__demoCursor;\n if (api) {\n api.destroy();\n }\n });\n}\n\n/**\n * Performs a demo click action with visible cursor movement:\n * 1. Moves cursor smoothly to element center\n * 2. Optionally highlights element\n * 3. Triggers click ripple\n * 4. Performs actual click\n */\nexport async function demoClick(\n page: Page,\n selector: string,\n options?: {\n highlight?: boolean;\n delayAfter?: number;\n delayBefore?: number;\n timeoutMs?: number;\n }\n): Promise<void> {\n const element = page.locator(selector).first();\n const timeout = options?.timeoutMs ?? 10000;\n await element.scrollIntoViewIfNeeded();\n await element.waitFor({ state: \"visible\", timeout });\n\n const boundingBox = await element.boundingBox();\n if (!boundingBox) {\n throw new Error(`Element not found or not visible: ${selector}`);\n }\n\n // Calculate center of element\n const centerX = boundingBox.x + boundingBox.width / 2;\n const centerY = boundingBox.y + boundingBox.height / 2;\n\n // Optional delay before moving\n if (options?.delayBefore) {\n await page.waitForTimeout(options.delayBefore);\n }\n\n // Move cursor to element with smooth animation\n await moveCursorTo(page, centerX, centerY, { steps: 20 });\n\n // Optional highlight\n if (options?.highlight) {\n await highlightElement(page, selector);\n await page.waitForTimeout(200);\n }\n\n // Trigger click ripple\n await triggerClickRipple(page);\n\n // Perform actual click\n await element.click({ timeout });\n\n // Wait for ripple animation to complete\n await page.waitForTimeout(200);\n\n // Optional delay after click\n if (options?.delayAfter) {\n await page.waitForTimeout(options.delayAfter);\n }\n}\n\n/**\n * Performs a demo hover action with visible cursor movement.\n */\nexport async function demoHover(\n page: Page,\n selector: string,\n options?: { highlight?: boolean; timeoutMs?: number }\n): Promise<void> {\n const element = page.locator(selector).first();\n const timeout = options?.timeoutMs ?? 10000;\n await element.scrollIntoViewIfNeeded();\n await element.waitFor({ state: \"visible\", timeout });\n\n const boundingBox = await element.boundingBox();\n if (!boundingBox) {\n throw new Error(`Element not found or not visible: ${selector}`);\n }\n\n const centerX = boundingBox.x + boundingBox.width / 2;\n const centerY = boundingBox.y + boundingBox.height / 2;\n\n await moveCursorTo(page, centerX, centerY, { steps: 15 });\n\n if (options?.highlight) {\n await highlightElement(page, selector);\n }\n\n await element.hover({ timeout });\n await page.waitForTimeout(300);\n}\n\n/**\n * Types text with visible cursor at the input location.\n */\nexport async function demoType(\n page: Page,\n selector: string,\n text: string,\n options?: { highlight?: boolean; delayBetweenChars?: number }\n): Promise<void> {\n const element = page.locator(selector).first();\n await element.scrollIntoViewIfNeeded();\n await element.waitFor({ state: \"visible\", timeout: 10000 });\n\n const boundingBox = await element.boundingBox();\n if (!boundingBox) {\n throw new Error(`Element not found or not visible: ${selector}`);\n }\n\n const centerX = boundingBox.x + boundingBox.width / 2;\n const centerY = boundingBox.y + boundingBox.height / 2;\n\n await moveCursorTo(page, centerX, centerY);\n\n if (options?.highlight) {\n await highlightElement(page, selector);\n await page.waitForTimeout(150);\n }\n\n await triggerClickRipple(page);\n await element.click();\n await page.waitForTimeout(100);\n\n // Type with optional delay between characters\n await element.fill(text);\n await page.waitForTimeout(200);\n}\n"],"mappings":"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","names":["path","path","path","fs","path","resolve","fs","path"]}
1
+ {"version":3,"sources":["../src/index.ts","../../shared/src/yaml-parser.ts","../../shared/src/schema.ts","../../shared/src/target-resolver.ts","../../shared/src/action-helpers.ts","../../playwright/src/demo-runner.ts","../../generation/src/voice-synthesis.ts","../../generation/src/voice-cache.ts","../../generation/src/script-generator.ts","../../playwright/src/cursor-overlay.ts"],"sourcesContent":["/**\n * @t3lnet/sceneforge\n *\n * SceneForge public API: demo runner + generation utilities.\n */\n\n// Shared types\nexport type {\n DemoDefinition,\n DemoStep,\n DemoAction,\n ActionType,\n StepTarget,\n WaitCondition,\n DragConfig,\n ElementInfo,\n RecordedInteraction,\n SelectorStrategy,\n SelectorCandidate,\n PrivacyConfig,\n SelectorConfig,\n RecordingState,\n PickerResult,\n TestSelectorResponse,\n} from \"../../shared/src/types\";\n\n// YAML parsing and serialization\nexport {\n parseFromYAML,\n serializeToYAML,\n validateDemoDefinition,\n createEmptyDemo,\n createEmptyStep,\n} from \"../../shared/src/yaml-parser\";\n\n// Schema validation\nexport {\n DEMO_SCHEMA_VERSION,\n demoDefinitionSchema,\n parseDemoDefinition,\n safeParseDemoDefinition,\n formatValidationError,\n} from \"../../shared/src/schema\";\n\n// Target resolution\nexport {\n resolveTarget,\n resolvePath,\n} from \"../../shared/src/target-resolver\";\n\n// Action helpers\nexport {\n createClickAction,\n createTypeAction,\n createNavigateAction,\n createWaitAction,\n createWaitForAction,\n createUploadAction,\n createHoverAction,\n createScrollAction,\n createScrollToAction,\n createDragAction,\n} from \"../../shared/src/action-helpers\";\n\n// Demo runner\nexport {\n runDemo,\n runDemoFromFile,\n loadDemoDefinition,\n discoverDemos,\n} from \"../../playwright/src/demo-runner\";\n\nexport type {\n DemoContext,\n DemoResult,\n StepTiming,\n RunDemoOptions,\n} from \"../../playwright/src/demo-runner\";\n\n// Cursor overlay helpers\nexport {\n injectCursorOverlay,\n removeCursorOverlay,\n moveCursorTo,\n triggerClickRipple,\n highlightElement,\n demoClick,\n demoHover,\n demoType,\n} from \"../../playwright/src/cursor-overlay\";\n\n// Voice synthesis utilities\nexport {\n VoiceSynthesizer,\n createVoiceSynthesizer,\n generateTimingManifest,\n} from \"../../generation/src/voice-synthesis\";\n\nexport type {\n VoiceSynthesisConfig,\n VoiceSynthesisResult,\n SynthesizedSegment,\n GeneratedScript,\n ScriptSegment as VoiceScriptSegment,\n AudioTimingManifest,\n} from \"../../generation/src/voice-synthesis\";\n\n// Script generation utilities\nexport {\n ScriptGenerator,\n createScriptGenerator,\n} from \"../../generation/src/script-generator\";\n\nexport type {\n ScriptSegment,\n ScriptOutput,\n StepBoundary,\n} from \"../../generation/src/script-generator\";\n","/**\n * YAML parsing and serialization for demo definitions.\n * Shared between CLI and extension.\n */\n\nimport { parse, stringify } from \"yaml\";\nimport type {\n DemoDefinition,\n DemoStep,\n DemoAction,\n StepTarget,\n WaitCondition,\n} from \"./types\";\nimport {\n DEMO_SCHEMA_VERSION,\n formatValidationError,\n parseDemoDefinition,\n safeParseDemoDefinition,\n} from \"./schema\";\n\n/**\n * Parses a YAML string into a DemoDefinition.\n */\nexport function parseFromYAML(\n yamlString: string,\n options?: { resolveSecrets?: (key: string) => string | undefined }\n): DemoDefinition {\n const parsed = parse(yamlString);\n\n if (!parsed || typeof parsed !== \"object\") {\n throw new Error(\"Invalid YAML: expected an object\");\n }\n const resolved = options?.resolveSecrets\n ? resolveSecrets(parsed, options.resolveSecrets)\n : parsed;\n try {\n return parseDemoDefinition(resolved);\n } catch (error) {\n throw new Error(formatValidationError(error));\n }\n}\n\n/**\n * Serializes a DemoDefinition to a YAML string.\n */\nexport function serializeToYAML(demo: DemoDefinition): string {\n const cleanDemo = {\n version: demo.version ?? DEMO_SCHEMA_VERSION,\n name: demo.name,\n title: demo.title,\n ...(demo.description && { description: demo.description }),\n steps: demo.steps.map(serializeStep),\n };\n\n return stringify(cleanDemo, {\n indent: 2,\n lineWidth: 100,\n defaultStringType: \"QUOTE_DOUBLE\",\n defaultKeyType: \"PLAIN\",\n });\n}\n\nfunction serializeStep(step: DemoStep): object {\n return {\n id: step.id,\n script: step.script,\n actions: step.actions.map(serializeAction),\n };\n}\n\nfunction serializeAction(action: DemoAction): object {\n const result: Record<string, unknown> = {\n action: action.action,\n };\n\n if (action.path !== undefined) {\n result.path = action.path;\n }\n\n if (action.target !== undefined) {\n result.target = serializeTarget(action.target);\n }\n\n if (action.text !== undefined) {\n result.text = action.text;\n }\n\n if (action.file !== undefined) {\n result.file = action.file;\n }\n\n if (action.duration !== undefined) {\n result.duration = action.duration;\n }\n\n if (action.highlight === true) {\n result.highlight = true;\n }\n\n if (action.waitFor !== undefined) {\n result.waitFor = serializeWaitCondition(action.waitFor);\n }\n\n if (action.drag !== undefined) {\n result.drag = {\n deltaX: action.drag.deltaX,\n deltaY: action.drag.deltaY,\n ...(action.drag.steps !== undefined && { steps: action.drag.steps }),\n };\n }\n\n return result;\n}\n\nfunction serializeTarget(target: StepTarget): object {\n const result: Record<string, unknown> = {\n type: target.type,\n };\n\n if (target.text !== undefined) {\n result.text = target.text;\n }\n\n if (target.selector !== undefined) {\n result.selector = target.selector;\n }\n\n if (target.name !== undefined) {\n result.name = target.name;\n }\n\n return result;\n}\n\nfunction serializeWaitCondition(waitFor: WaitCondition): object {\n const result: Record<string, unknown> = {\n type: waitFor.type,\n };\n\n if (waitFor.value !== undefined) {\n result.value = waitFor.value;\n }\n\n if (waitFor.timeout !== undefined) {\n result.timeout = waitFor.timeout;\n }\n\n return result;\n}\n\n/**\n * Validates a demo definition, throwing on errors.\n */\nexport function validateDemoDefinition(definition: DemoDefinition): void {\n const result = safeParseDemoDefinition(definition);\n if (!result.success) {\n throw new Error(formatValidationError(result.error));\n }\n}\n\n/**\n * Creates a default empty demo definition.\n */\nexport function createEmptyDemo(): DemoDefinition {\n return {\n version: DEMO_SCHEMA_VERSION,\n name: \"new-demo\",\n title: \"New Demo\",\n description: \"\",\n steps: [],\n };\n}\n\n/**\n * Creates a default empty step.\n */\nexport function createEmptyStep(id?: string): DemoStep {\n const stepId = id || `step-${Date.now()}`;\n return {\n id: stepId,\n script: \"\",\n actions: [],\n };\n}\n\nconst SECRET_PATTERN = /\\$\\{(ENV|SECRET):([A-Za-z0-9_]+)\\}/g;\n\nfunction resolveSecrets(\n value: unknown,\n resolver: (key: string) => string | undefined,\n path = \"root\"\n): unknown {\n if (typeof value === \"string\") {\n if (!SECRET_PATTERN.test(value)) {\n return value;\n }\n SECRET_PATTERN.lastIndex = 0;\n return value.replace(SECRET_PATTERN, (_match, _type, key: string) => {\n const resolved = resolver(key);\n if (resolved === undefined) {\n throw new Error(`Missing secret for ${key} at ${path}`);\n }\n return resolved;\n });\n }\n\n if (Array.isArray(value)) {\n return value.map((entry, index) =>\n resolveSecrets(entry, resolver, `${path}[${index}]`)\n );\n }\n\n if (value && typeof value === \"object\") {\n const result: Record<string, unknown> = {};\n for (const [key, entry] of Object.entries(value)) {\n result[key] = resolveSecrets(entry, resolver, `${path}.${key}`);\n }\n return result;\n }\n\n return value;\n}\n","import { z } from \"zod\";\nimport type {\n BackgroundMusic,\n DemoAction,\n DemoDefinition,\n DemoStep,\n DragConfig,\n MediaConfig,\n MusicEndPoint,\n MusicStartPoint,\n StepTarget,\n VideoSegment,\n WaitCondition,\n} from \"./types\";\n\nexport const DEMO_SCHEMA_VERSION = 1;\n\ntype DemoDefinitionInput = Omit<DemoDefinition, \"version\"> & { version?: number };\n\nconst stepTargetSchema: z.ZodType<StepTarget> = z\n .object({\n type: z.enum([\"button\", \"link\", \"input\", \"text\", \"selector\"]),\n text: z.string().optional(),\n selector: z.string().optional(),\n name: z.string().optional(),\n })\n .strict()\n .superRefine((target, ctx) => {\n switch (target.type) {\n case \"selector\":\n if (!target.selector) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: \"selector target requires selector\",\n });\n }\n break;\n case \"text\":\n if (!target.text) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: \"text target requires text\",\n });\n }\n break;\n case \"button\":\n case \"link\":\n case \"input\":\n if (!target.text && !target.name && !target.selector) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: \"target requires text, name, or selector\",\n });\n }\n break;\n }\n });\n\nconst waitConditionSchema: z.ZodType<WaitCondition> = z\n .object({\n type: z.enum([\"text\", \"selector\", \"navigation\", \"idle\", \"selectorHidden\", \"textHidden\"]),\n value: z.string().optional(),\n timeout: z.coerce.number().int().positive().optional(),\n })\n .strict()\n .superRefine((condition, ctx) => {\n if ([\"text\", \"selector\", \"selectorHidden\", \"textHidden\"].includes(condition.type)) {\n if (!condition.value) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `wait condition '${condition.type}' requires value`,\n });\n }\n }\n });\n\nconst dragConfigSchema: z.ZodType<DragConfig> = z\n .object({\n deltaX: z.coerce.number(),\n deltaY: z.coerce.number(),\n steps: z.coerce.number().int().positive().optional(),\n })\n .strict();\n\nconst waitActionSchema: z.ZodType<DemoAction> = z\n .object({\n action: z.literal(\"wait\"),\n duration: z.coerce.number().nonnegative().optional(),\n waitFor: waitConditionSchema.optional(),\n })\n .strict()\n .superRefine((action, ctx) => {\n if (action.duration === undefined && action.waitFor === undefined) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: \"wait action requires duration or waitFor\",\n });\n }\n });\n\nconst navigateActionSchema: z.ZodType<DemoAction> = z\n .object({\n action: z.literal(\"navigate\"),\n path: z.string().min(1),\n waitFor: waitConditionSchema.optional(),\n })\n .strict();\n\nconst clickActionSchema: z.ZodType<DemoAction> = z\n .object({\n action: z.literal(\"click\"),\n target: stepTargetSchema,\n highlight: z.boolean().optional(),\n waitFor: waitConditionSchema.optional(),\n })\n .strict();\n\nconst typeActionSchema: z.ZodType<DemoAction> = z\n .object({\n action: z.literal(\"type\"),\n target: stepTargetSchema,\n text: z.string(),\n waitFor: waitConditionSchema.optional(),\n })\n .strict();\n\nconst uploadActionSchema: z.ZodType<DemoAction> = z\n .object({\n action: z.literal(\"upload\"),\n file: z.string().min(1),\n target: stepTargetSchema.optional(),\n waitFor: waitConditionSchema.optional(),\n })\n .strict();\n\nconst hoverActionSchema: z.ZodType<DemoAction> = z\n .object({\n action: z.literal(\"hover\"),\n target: stepTargetSchema,\n waitFor: waitConditionSchema.optional(),\n })\n .strict();\n\nconst scrollActionSchema: z.ZodType<DemoAction> = z\n .object({\n action: z.literal(\"scroll\"),\n duration: z.coerce.number().optional(),\n waitFor: waitConditionSchema.optional(),\n })\n .strict();\n\nconst scrollToActionSchema: z.ZodType<DemoAction> = z\n .object({\n action: z.literal(\"scrollTo\"),\n target: stepTargetSchema,\n waitFor: waitConditionSchema.optional(),\n })\n .strict();\n\nconst dragActionSchema: z.ZodType<DemoAction> = z\n .object({\n action: z.literal(\"drag\"),\n target: stepTargetSchema,\n drag: dragConfigSchema,\n waitFor: waitConditionSchema.optional(),\n })\n .strict();\n\nconst actionSchema: z.ZodType<DemoAction> = z.union([\n navigateActionSchema,\n clickActionSchema,\n typeActionSchema,\n uploadActionSchema,\n waitActionSchema,\n hoverActionSchema,\n scrollActionSchema,\n scrollToActionSchema,\n dragActionSchema,\n]);\n\nconst demoStepSchema: z.ZodType<DemoStep> = z\n .object({\n id: z.string().min(1),\n script: z.string(),\n actions: z.array(actionSchema),\n })\n .strict();\n\nconst videoSegmentSchema: z.ZodType<VideoSegment> = z\n .object({\n file: z.string().min(1),\n duration: z.coerce.number().positive().optional(),\n fade: z.boolean().optional(),\n fadeDuration: z.coerce.number().positive().optional(),\n })\n .strict();\n\nconst musicStartPointSchema: z.ZodType<MusicStartPoint> = z.union([\n z.object({ type: z.literal(\"beginning\") }).strict(),\n z.object({ type: z.literal(\"afterIntro\") }).strict(),\n z.object({ type: z.literal(\"step\"), stepId: z.string().min(1) }).strict(),\n z.object({ type: z.literal(\"time\"), seconds: z.coerce.number().nonnegative() }).strict(),\n]);\n\nconst musicEndPointSchema: z.ZodType<MusicEndPoint> = z.union([\n z.object({ type: z.literal(\"end\") }).strict(),\n z.object({ type: z.literal(\"beforeOutro\") }).strict(),\n z.object({ type: z.literal(\"step\"), stepId: z.string().min(1) }).strict(),\n z.object({ type: z.literal(\"time\"), seconds: z.coerce.number().nonnegative() }).strict(),\n]);\n\nconst backgroundMusicSchema: z.ZodType<BackgroundMusic> = z\n .object({\n file: z.string().min(1),\n volume: z.coerce.number().min(0).max(1).optional(),\n startAt: musicStartPointSchema.optional(),\n endAt: musicEndPointSchema.optional(),\n loop: z.boolean().optional(),\n fadeIn: z.coerce.number().nonnegative().optional(),\n fadeOut: z.coerce.number().nonnegative().optional(),\n })\n .strict();\n\nconst mediaConfigSchema: z.ZodType<MediaConfig> = z\n .object({\n intro: videoSegmentSchema.optional(),\n outro: videoSegmentSchema.optional(),\n backgroundMusic: backgroundMusicSchema.optional(),\n })\n .strict();\n\nexport const demoDefinitionSchema: z.ZodType<\n DemoDefinition,\n z.ZodTypeDef,\n DemoDefinitionInput\n> = z\n .object({\n version: z.coerce.number().int().positive().default(DEMO_SCHEMA_VERSION),\n name: z.string().min(1),\n title: z.string().min(1),\n description: z.string().optional(),\n steps: z.array(demoStepSchema),\n media: mediaConfigSchema.optional(),\n })\n .strict();\n\nexport function formatValidationError(error: unknown): string {\n if (!error || typeof error !== \"object\" || !(\"issues\" in error)) {\n return \"Invalid demo definition\";\n }\n const issues = (error as z.ZodError).issues;\n return issues\n .map((issue) => {\n const path = issue.path.length ? issue.path.join(\".\") : \"root\";\n return `${path}: ${issue.message}`;\n })\n .join(\"; \");\n}\n\nexport function parseDemoDefinition(input: unknown) {\n return demoDefinitionSchema.parse(input);\n}\n\nexport function safeParseDemoDefinition(input: unknown) {\n return demoDefinitionSchema.safeParse(input);\n}\n","/**\n * Target resolution utilities.\n * Converts StepTarget configurations to CSS/Playwright selectors.\n */\n\nimport type { StepTarget } from \"./types\";\n\n/**\n * Resolves a target configuration to a selector string.\n * Works with both Playwright locators and standard CSS selectors.\n */\nexport function resolveTarget(target: StepTarget): string {\n // If explicit selector is provided, use it directly\n if (target.selector) {\n return target.selector;\n }\n\n switch (target.type) {\n case \"button\":\n if (target.text) {\n return `button:has-text(\"${target.text}\"), [role=\"button\"]:has-text(\"${target.text}\")`;\n }\n if (target.name) {\n return `button[name=\"${target.name}\"], [role=\"button\"][name=\"${target.name}\"]`;\n }\n break;\n\n case \"link\":\n if (target.text) {\n return `a:has-text(\"${target.text}\")`;\n }\n if (target.name) {\n return `a[name=\"${target.name}\"]`;\n }\n break;\n\n case \"input\":\n if (target.name) {\n return `input[name=\"${target.name}\"], textarea[name=\"${target.name}\"]`;\n }\n if (target.text) {\n // Input with associated label\n return `label:has-text(\"${target.text}\") + input, label:has-text(\"${target.text}\") input`;\n }\n break;\n\n case \"text\":\n if (target.text) {\n return `text=\"${target.text}\"`;\n }\n break;\n\n case \"selector\":\n // Selector type but no selector provided\n break;\n }\n\n throw new Error(`Unable to resolve target: ${JSON.stringify(target)}`);\n}\n\n/**\n * Replaces template variables in paths.\n * Supports: {baseURL}.\n */\nexport function resolvePath(\n pathTemplate: string,\n variables: Record<string, string | undefined>\n): string {\n let result = pathTemplate;\n for (const [key, value] of Object.entries(variables)) {\n if (value === undefined) {\n continue;\n }\n result = result.replace(new RegExp(`\\\\{${key}\\\\}`, \"g\"), value);\n }\n return result;\n}\n","/**\n * Helper functions for creating common actions.\n */\n\nimport type { DemoAction, WaitCondition } from \"./types\";\n\n/**\n * Creates a click action.\n */\nexport function createClickAction(selector: string, highlight = false): DemoAction {\n return {\n action: \"click\",\n target: {\n type: \"selector\",\n selector,\n },\n highlight,\n };\n}\n\n/**\n * Creates a type/input action.\n */\nexport function createTypeAction(selector: string, text: string): DemoAction {\n return {\n action: \"type\",\n target: {\n type: \"selector\",\n selector,\n },\n text,\n };\n}\n\n/**\n * Creates a navigate action.\n */\nexport function createNavigateAction(path: string): DemoAction {\n return {\n action: \"navigate\",\n path,\n };\n}\n\n/**\n * Creates a wait action with a fixed duration.\n */\nexport function createWaitAction(duration: number): DemoAction {\n return {\n action: \"wait\",\n duration,\n };\n}\n\n/**\n * Creates a wait action with a condition.\n */\nexport function createWaitForAction(\n type: WaitCondition[\"type\"],\n value?: string,\n timeout = 15000\n): DemoAction {\n return {\n action: \"wait\",\n waitFor: {\n type,\n value,\n timeout,\n },\n };\n}\n\n/**\n * Creates an upload action.\n * Note: selector is optional - defaults to first file input on page.\n */\nexport function createUploadAction(file: string, selector?: string): DemoAction {\n const action: DemoAction = {\n action: \"upload\",\n file,\n };\n if (selector) {\n action.target = {\n type: \"selector\",\n selector,\n };\n }\n return action;\n}\n\n/**\n * Creates a hover action.\n */\nexport function createHoverAction(selector: string): DemoAction {\n return {\n action: \"hover\",\n target: {\n type: \"selector\",\n selector,\n },\n };\n}\n\n/**\n * Creates a scroll action.\n */\nexport function createScrollAction(duration = 500): DemoAction {\n return {\n action: \"scroll\",\n duration,\n };\n}\n\n/**\n * Creates a scroll-to action.\n */\nexport function createScrollToAction(selector: string): DemoAction {\n return {\n action: \"scrollTo\",\n target: {\n type: \"selector\",\n selector,\n },\n };\n}\n\n/**\n * Creates a drag action.\n */\nexport function createDragAction(\n selector: string,\n deltaX: number,\n deltaY: number,\n steps = 20\n): DemoAction {\n return {\n action: \"drag\",\n target: {\n type: \"selector\",\n selector,\n },\n drag: {\n deltaX,\n deltaY,\n steps,\n },\n };\n}\n","/**\n * Demo runner for Playwright.\n * Executes demo definitions using Playwright for video recording.\n */\n\nimport { Page, expect } from \"@playwright/test\";\nimport * as fs from \"fs/promises\";\nimport * as path from \"path\";\nimport type {\n DemoDefinition,\n DemoStep,\n DemoAction,\n WaitCondition,\n} from \"@t3lnet/sceneforge-shared\";\nimport {\n parseFromYAML,\n validateDemoDefinition,\n resolveTarget,\n resolvePath,\n} from \"@t3lnet/sceneforge-shared\";\nimport {\n ScriptGenerator,\n createScriptGenerator,\n} from \"@t3lnet/sceneforge-generation\";\nimport {\n injectCursorOverlay,\n removeCursorOverlay,\n demoClick,\n moveCursorTo,\n} from \"./cursor-overlay\";\n\nconst DEFAULT_ACTION_TIMEOUT_MS = 15000;\nconst NAVIGATION_TIMEOUT_MS = 45000;\nconst UPLOAD_TIMEOUT_MS = 30000;\nconst ACTION_TIMEOUT_BUFFER_MS = 2000;\nconst DEFAULT_WAIT_TIMEOUT_MS = Number(process.env.DEMO_WAIT_TIMEOUT_MS ?? 15000);\nconst WAIT_RETRY_ATTEMPTS = Math.max(\n 1,\n Number(process.env.DEMO_WAIT_RETRY_ATTEMPTS ?? 2)\n);\nconst WAIT_RETRY_BASE_DELAY_MS = Number(process.env.DEMO_WAIT_RETRY_DELAY_MS ?? 500);\n\nfunction sanitizeDiagnosticsSegment(value: string, fallback: string): string {\n const raw = String(value ?? \"\").trim();\n if (!raw) {\n return fallback;\n }\n const cleaned = raw.replace(/[^a-zA-Z0-9._-]+/g, \"_\");\n const collapsed = cleaned.replace(/_{2,}/g, \"_\").replace(/^_+|_+$/g, \"\");\n const safe = collapsed || fallback;\n const trimmed = safe.length > 80 ? safe.slice(0, 80) : safe;\n return trimmed === \".\" || trimmed === \"..\" ? fallback : trimmed;\n}\n\nfunction logEvent(\n level: \"info\" | \"warn\" | \"error\",\n event: string,\n data: Record<string, unknown>\n): void {\n const payload = {\n ts: new Date().toISOString(),\n level,\n event,\n ...data,\n };\n const line = JSON.stringify(payload);\n if (level === \"error\") {\n console.error(line);\n } else if (level === \"warn\") {\n console.warn(line);\n } else {\n console.log(line);\n }\n}\n\nfunction getActionTimeoutMs(action: DemoAction): number {\n if (action.action === \"navigate\") {\n return NAVIGATION_TIMEOUT_MS;\n }\n if (action.action === \"upload\") {\n return UPLOAD_TIMEOUT_MS;\n }\n if (action.action === \"wait\") {\n if (action.duration !== undefined) {\n return Math.max(DEFAULT_ACTION_TIMEOUT_MS, action.duration + ACTION_TIMEOUT_BUFFER_MS);\n }\n if (action.waitFor?.timeout) {\n return action.waitFor.timeout + ACTION_TIMEOUT_BUFFER_MS;\n }\n }\n if (action.waitFor?.timeout) {\n return action.waitFor.timeout + ACTION_TIMEOUT_BUFFER_MS;\n }\n return DEFAULT_ACTION_TIMEOUT_MS;\n}\n\nasync function withActionTimeout<T>(\n timeoutMs: number,\n label: string,\n fn: () => Promise<T>\n): Promise<T> {\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeoutId = setTimeout(() => {\n reject(new Error(`${label} timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n });\n\n try {\n return await Promise.race([fn(), timeoutPromise]);\n } finally {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n }\n}\n\nasync function captureDiagnostics(params: {\n context: DemoContext;\n stepId?: string;\n stepIndex?: number;\n actionIndex?: number;\n action?: DemoAction;\n error: unknown;\n runId: string;\n}): Promise<void> {\n const { context, stepId, stepIndex, actionIndex, action, error, runId } = params;\n const diagnosticsDir = path.join(context.outputDir, \"diagnostics\");\n const timestamp = new Date().toISOString().replace(/[:.]/g, \"-\");\n const stepLabel = sanitizeDiagnosticsSegment(stepId ?? \"unknown-step\", \"unknown-step\");\n const actionLabel = actionIndex !== undefined ? `action-${actionIndex + 1}` : \"action\";\n const baseName = `${timestamp}-${runId}-${stepLabel}-${actionLabel}`;\n\n try {\n await fs.mkdir(diagnosticsDir, { recursive: true });\n } catch {\n // Ignore failures creating diagnostics dir.\n }\n\n const metadata = {\n runId,\n stepId,\n stepIndex,\n actionIndex,\n action,\n error: error instanceof Error ? error.message : String(error),\n url: context.page.url(),\n capturedAt: new Date().toISOString(),\n };\n\n try {\n const screenshotPath = path.join(diagnosticsDir, `${baseName}.png`);\n await context.page.screenshot({ path: screenshotPath, fullPage: true });\n } catch {\n // Ignore screenshot failures.\n }\n\n try {\n const domContent = await context.page.content();\n const maxChars = 20000;\n const snippet =\n domContent.length > maxChars\n ? `${domContent.slice(0, maxChars)}\\n<!-- truncated -->`\n : domContent;\n const domPath = path.join(diagnosticsDir, `${baseName}.dom.html`);\n await fs.writeFile(domPath, snippet, \"utf-8\");\n } catch {\n // Ignore DOM capture failures.\n }\n\n try {\n const metaPath = path.join(diagnosticsDir, `${baseName}.json`);\n await fs.writeFile(metaPath, JSON.stringify(metadata, null, 2), \"utf-8\");\n } catch {\n // Ignore metadata write failures.\n }\n}\n\n/**\n * Context passed to the demo runner.\n */\nexport interface DemoContext {\n page: Page;\n baseURL: string;\n outputDir: string;\n videoPath?: string;\n videoRecordingStartTime?: number;\n assetBaseDir?: string;\n}\n\n/**\n * Result of running a demo.\n */\nexport interface DemoResult {\n success: boolean;\n demoName: string;\n videoPath?: string;\n scriptPath?: string;\n error?: Error;\n duration: number;\n}\n\nexport interface RunDemoOptions {\n generateScripts?: boolean;\n scriptOutputDir?: string;\n}\n\n/**\n * Step timing info for video splitting.\n */\nexport interface StepTiming {\n id: string;\n script: string;\n startTime: number;\n endTime?: number;\n}\n\ninterface ActionContext {\n stepId: string;\n stepIndex: number;\n actionIndex: number;\n runId: string;\n demoName: string;\n}\n\n/**\n * Loads and parses a YAML demo definition file.\n */\nexport async function loadDemoDefinition(\n filePath: string,\n options?: { resolveSecrets?: (key: string) => string | undefined }\n): Promise<DemoDefinition> {\n const content = await fs.readFile(filePath, \"utf-8\");\n const definition = parseFromYAML(content, options);\n validateDemoDefinition(definition);\n return definition;\n}\n\n/**\n * Waits for org slug to be available after login/redirect.\n */\nfunction resolveFilePath(filePath: string, baseDir?: string): string {\n if (path.isAbsolute(filePath)) {\n return filePath;\n }\n const root = baseDir ?? process.cwd();\n return path.resolve(root, filePath);\n}\n\nfunction resolveNavigatePath(actionPath: string, context: DemoContext): string {\n const resolvedPath = resolvePath(actionPath, { baseURL: context.baseURL });\n if (/\\{[^}]+\\}/.test(resolvedPath)) {\n throw new Error(\n `Navigate action contains unresolved template variables: ${resolvedPath}`\n );\n }\n return resolvedPath;\n}\n\n/**\n * Executes a wait condition.\n * Returns true if the page navigated.\n */\nasync function executeWaitCondition(\n page: Page,\n condition: WaitCondition,\n actionContext?: ActionContext\n): Promise<boolean> {\n const timeout = condition.timeout || DEFAULT_WAIT_TIMEOUT_MS;\n let navigated = false;\n\n const getSelectorContext = async (): Promise<Record<string, unknown>> => {\n if (!condition.value) return {};\n try {\n if (condition.type === \"selector\" || condition.type === \"selectorHidden\") {\n const count = await page.locator(condition.value).count();\n return { selectorCount: count };\n }\n if (condition.type === \"text\" || condition.type === \"textHidden\") {\n const count = await page.getByText(condition.value, { exact: false }).count();\n return { textMatchCount: count };\n }\n } catch (error) {\n return { selectorContextError: error instanceof Error ? error.message : String(error) };\n }\n return {};\n };\n\n for (let attempt = 0; attempt < WAIT_RETRY_ATTEMPTS; attempt += 1) {\n try {\n switch (condition.type) {\n case \"text\":\n if (!condition.value) {\n throw new Error(\"Wait for text requires 'value'\");\n }\n await expect(page.getByText(condition.value, { exact: false }).first()).toBeVisible({\n timeout,\n });\n break;\n\n case \"selector\":\n if (!condition.value) {\n throw new Error(\"Wait for selector requires 'value'\");\n }\n await page.locator(condition.value).first().waitFor({ state: \"visible\", timeout });\n break;\n\n case \"navigation\":\n await page.waitForURL(/.*/, { waitUntil: \"networkidle\", timeout });\n navigated = true;\n break;\n\n case \"idle\":\n await page.waitForLoadState(\"networkidle\", { timeout });\n break;\n\n case \"selectorHidden\":\n if (!condition.value) {\n throw new Error(\"Wait for selectorHidden requires 'value'\");\n }\n await page.locator(condition.value).first().waitFor({ state: \"hidden\", timeout });\n break;\n\n case \"textHidden\":\n if (!condition.value) {\n throw new Error(\"Wait for textHidden requires 'value'\");\n }\n await expect(page.getByText(condition.value, { exact: false }).first()).toBeHidden({\n timeout,\n });\n break;\n }\n\n if (attempt > 0 && actionContext) {\n logEvent(\"info\", \"wait_retry_success\", {\n runId: actionContext.runId,\n demoName: actionContext.demoName,\n stepId: actionContext.stepId,\n actionIndex: actionContext.actionIndex,\n waitType: condition.type,\n attempt: attempt + 1,\n });\n }\n return navigated;\n } catch (error) {\n const selectorContext = await getSelectorContext();\n logEvent(\"warn\", \"wait_retry\", {\n runId: actionContext?.runId,\n demoName: actionContext?.demoName,\n stepId: actionContext?.stepId,\n actionIndex: actionContext?.actionIndex,\n waitType: condition.type,\n waitValue: condition.value,\n timeout,\n attempt: attempt + 1,\n error: error instanceof Error ? error.message : String(error),\n ...selectorContext,\n });\n\n if (attempt >= WAIT_RETRY_ATTEMPTS - 1) {\n throw error;\n }\n const delayMs = WAIT_RETRY_BASE_DELAY_MS * (attempt + 1);\n await page.waitForTimeout(delayMs);\n }\n }\n\n return navigated;\n}\n\n/**\n * Executes a single action within a step.\n * Returns true if the page navigated.\n */\nasync function executeAction(\n action: DemoAction,\n context: DemoContext,\n actionContext: ActionContext\n): Promise<boolean> {\n const { page } = context;\n let navigated = false;\n const timeoutMs = getActionTimeoutMs(action);\n const startedAt = Date.now();\n\n logEvent(\"info\", \"action_start\", {\n runId: actionContext.runId,\n demoName: actionContext.demoName,\n stepId: actionContext.stepId,\n stepIndex: actionContext.stepIndex,\n actionIndex: actionContext.actionIndex,\n actionType: action.action,\n timeoutMs,\n });\n\n try {\n await withActionTimeout(timeoutMs, `${action.action} action`, async () => {\n switch (action.action) {\n case \"navigate\": {\n if (!action.path) {\n throw new Error(\"Navigate action missing 'path'\");\n }\n const resolvedPath = resolveNavigatePath(action.path, context);\n const fullURL = resolvedPath.startsWith(\"http\")\n ? resolvedPath\n : `${context.baseURL}${resolvedPath}`;\n await page.goto(fullURL, { waitUntil: \"networkidle\", timeout: timeoutMs });\n navigated = true;\n await injectCursorOverlay(page);\n break;\n }\n\n case \"click\": {\n if (!action.target) {\n throw new Error(\"Click action missing 'target'\");\n }\n const selector = resolveTarget(action.target);\n await demoClick(page, selector, {\n highlight: action.highlight,\n delayAfter: 500,\n timeoutMs,\n });\n break;\n }\n\n case \"type\": {\n if (!action.target) {\n throw new Error(\"Type action missing 'target'\");\n }\n if (!action.text) {\n throw new Error(\"Type action missing 'text'\");\n }\n const selector = resolveTarget(action.target);\n const element = page.locator(selector).first();\n await element.waitFor({ state: \"visible\", timeout: timeoutMs });\n await element.scrollIntoViewIfNeeded();\n const box = await element.boundingBox();\n if (box) {\n await moveCursorTo(page, box.x + box.width / 2, box.y + box.height / 2);\n }\n await element.click({ timeout: timeoutMs });\n await element.fill(action.text, { timeout: timeoutMs });\n break;\n }\n\n case \"upload\": {\n if (!action.file) {\n throw new Error(\"Upload action missing 'file'\");\n }\n const filePath = resolveFilePath(action.file, context.assetBaseDir);\n // Use target selector if provided, otherwise find first file input\n const fileSelector = action.target?.selector || 'input[type=\"file\"]';\n const fileInput = page.locator(fileSelector).first();\n await fileInput.setInputFiles(filePath, { timeout: timeoutMs });\n break;\n }\n\n case \"wait\": {\n if (action.duration) {\n await page.waitForTimeout(action.duration);\n } else if (action.waitFor) {\n navigated = await executeWaitCondition(page, action.waitFor, actionContext);\n if (navigated) {\n await injectCursorOverlay(page);\n }\n }\n break;\n }\n\n case \"hover\": {\n if (!action.target) {\n throw new Error(\"Hover action missing 'target'\");\n }\n const selector = resolveTarget(action.target);\n const element = page.locator(selector).first();\n await element.waitFor({ state: \"visible\", timeout: timeoutMs });\n await element.scrollIntoViewIfNeeded();\n const box = await element.boundingBox();\n if (box) {\n await moveCursorTo(page, box.x + box.width / 2, box.y + box.height / 2);\n }\n await element.hover({ timeout: timeoutMs });\n break;\n }\n\n case \"scroll\": {\n const scrollAmount = action.duration || 500;\n await page.mouse.wheel(0, scrollAmount);\n await page.waitForTimeout(300);\n break;\n }\n\n case \"scrollTo\": {\n if (!action.target) {\n throw new Error(\"ScrollTo action missing 'target'\");\n }\n const selector = resolveTarget(action.target);\n await page.locator(selector).first().scrollIntoViewIfNeeded({ timeout: timeoutMs });\n await page.waitForTimeout(300);\n break;\n }\n\n case \"drag\": {\n if (!action.target) {\n throw new Error(\"Drag action missing 'target'\");\n }\n if (!action.drag) {\n throw new Error(\"Drag action missing 'drag' configuration\");\n }\n const selector = resolveTarget(action.target);\n const element = page.locator(selector).first();\n await element.waitFor({ state: \"visible\", timeout: timeoutMs });\n await element.scrollIntoViewIfNeeded();\n const box = await element.boundingBox();\n if (!box) {\n throw new Error(`Drag target not found or not visible: ${selector}`);\n }\n\n const startX = box.x + box.width / 2;\n const startY = box.y + box.height / 2;\n const endX = startX + action.drag.deltaX;\n const endY = startY + action.drag.deltaY;\n const dragSteps = action.drag.steps || 20;\n\n await moveCursorTo(page, startX, startY, { steps: 15 });\n await page.waitForTimeout(100);\n\n await page.mouse.move(startX, startY);\n await page.mouse.down();\n await page.waitForTimeout(50);\n\n for (let i = 1; i <= dragSteps; i++) {\n const t = i / dragSteps;\n const easeT = t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2;\n const currentX = startX + (endX - startX) * easeT;\n const currentY = startY + (endY - startY) * easeT;\n\n await page.mouse.move(currentX, currentY);\n await page.evaluate(\n ([x, y, shouldAddTrail]) => {\n const api = (window as Window & { __demoCursor?: { setPosition: (x: number, y: number) => void; addTrail: (x: number, y: number) => void } }).__demoCursor;\n if (api) {\n api.setPosition(x, y);\n if (shouldAddTrail) {\n api.addTrail(x + 4, y + 4);\n }\n }\n },\n [currentX, currentY, i % 3 === 0] as [number, number, boolean]\n );\n await page.waitForTimeout(25);\n }\n\n await page.mouse.up();\n await page.waitForTimeout(200);\n break;\n }\n\n default:\n throw new Error(`Unknown action type: ${action.action}`);\n }\n\n // Wait for any configured condition after action\n if (action.waitFor && action.action !== \"wait\") {\n const waitNavigated = await executeWaitCondition(page, action.waitFor, actionContext);\n if (waitNavigated) {\n await injectCursorOverlay(page);\n navigated = true;\n }\n }\n\n // Small delay between actions for video clarity\n await page.waitForTimeout(200);\n });\n\n logEvent(\"info\", \"action_complete\", {\n runId: actionContext.runId,\n demoName: actionContext.demoName,\n stepId: actionContext.stepId,\n stepIndex: actionContext.stepIndex,\n actionIndex: actionContext.actionIndex,\n actionType: action.action,\n durationMs: Date.now() - startedAt,\n navigated,\n });\n } catch (error) {\n logEvent(\"error\", \"action_failed\", {\n runId: actionContext.runId,\n demoName: actionContext.demoName,\n stepId: actionContext.stepId,\n stepIndex: actionContext.stepIndex,\n actionIndex: actionContext.actionIndex,\n actionType: action.action,\n durationMs: Date.now() - startedAt,\n error: error instanceof Error ? error.message : String(error),\n });\n await captureDiagnostics({\n context,\n stepId: actionContext.stepId,\n stepIndex: actionContext.stepIndex,\n actionIndex: actionContext.actionIndex,\n action,\n error,\n runId: actionContext.runId,\n });\n throw error;\n }\n\n return navigated;\n}\n\n/**\n * Executes a complete step (all actions).\n */\nasync function executeStep(\n step: DemoStep,\n context: DemoContext,\n scriptGenerator: ScriptGenerator | null,\n runId: string,\n demoName: string,\n stepIndex: number\n): Promise<void> {\n console.log(`[demo] Executing step: ${step.id} (${step.actions.length} actions)`);\n logEvent(\"info\", \"step_start\", {\n runId,\n demoName,\n stepId: step.id,\n stepIndex,\n actionCount: step.actions.length,\n });\n\n if (scriptGenerator) {\n scriptGenerator.addSegment(step.id, step.script);\n }\n\n for (let i = 0; i < step.actions.length; i++) {\n const action = step.actions[i];\n console.log(`[demo] Action ${i + 1}/${step.actions.length}: ${action.action}`);\n await executeAction(action, context, {\n stepId: step.id,\n stepIndex,\n actionIndex: i,\n runId,\n demoName,\n });\n }\n\n logEvent(\"info\", \"step_complete\", {\n runId,\n demoName,\n stepId: step.id,\n stepIndex,\n actionCount: step.actions.length,\n });\n}\n\nfunction getStepStartTarget(step: DemoStep): {\n selector: string;\n waitForState: \"visible\" | \"attached\";\n} | null {\n for (const action of step.actions) {\n if (action.action === \"wait\" || action.action === \"navigate\") {\n continue;\n }\n if (!action.target) {\n continue;\n }\n try {\n return {\n selector: resolveTarget(action.target),\n waitForState: action.action === \"upload\" ? \"attached\" : \"visible\",\n };\n } catch {\n return null;\n }\n }\n\n return null;\n}\n\nasync function waitForStepReady(page: Page, step: DemoStep): Promise<void> {\n const target = getStepStartTarget(step);\n if (!target) {\n return;\n }\n\n try {\n await page\n .locator(target.selector)\n .first()\n .waitFor({ state: target.waitForState, timeout: DEFAULT_WAIT_TIMEOUT_MS });\n } catch {\n // If the element never appears, let the step execution surface the error.\n }\n}\n\nfunction getStepEndSelector(step: DemoStep): string | null {\n for (let index = step.actions.length - 1; index >= 0; index -= 1) {\n const action = step.actions[index];\n if (action.action === \"wait\" || action.action === \"navigate\") {\n continue;\n }\n if (!action.target) {\n continue;\n }\n try {\n return resolveTarget(action.target);\n } catch {\n return null;\n }\n }\n\n return null;\n}\n\nasync function waitForStepExit(page: Page, step: DemoStep): Promise<void> {\n const selector = getStepEndSelector(step);\n if (!selector) {\n return;\n }\n\n try {\n await page.locator(selector).first().waitFor({ state: \"hidden\", timeout: 1500 });\n } catch {\n // Allow steps where the last action target remains visible.\n }\n}\n\n/**\n * Runs a complete demo from a definition.\n */\nexport async function runDemo(\n definition: DemoDefinition,\n context: DemoContext,\n options: RunDemoOptions = {}\n): Promise<DemoResult> {\n const startTime = Date.now();\n const transitionDelayMs = 500;\n const runId = `${definition.name}-${startTime}`;\n let scriptGenerator: ScriptGenerator | null = null;\n\n logEvent(\"info\", \"demo_start\", {\n runId,\n demoName: definition.name,\n stepCount: definition.steps.length,\n baseURL: context.baseURL,\n });\n\n try {\n // Inject cursor overlay\n await injectCursorOverlay(context.page);\n const hadVideoStartTime = context.videoRecordingStartTime !== undefined;\n const syncedVideoStartTimeMs = context.videoRecordingStartTime ?? Date.now();\n if (!hadVideoStartTime) {\n context.videoRecordingStartTime = syncedVideoStartTimeMs;\n }\n logEvent(\"info\", \"video_sync\", {\n runId,\n demoName: definition.name,\n videoStartTimeMs: syncedVideoStartTimeMs,\n providedByCaller: hadVideoStartTime,\n });\n if (options.generateScripts) {\n scriptGenerator = createScriptGenerator(\n definition.name,\n definition.title,\n syncedVideoStartTimeMs\n );\n }\n\n // Execute each step\n for (let stepIndex = 0; stepIndex < definition.steps.length; stepIndex += 1) {\n const step = definition.steps[stepIndex];\n if (scriptGenerator && stepIndex > 0) {\n await waitForStepReady(context.page, step);\n }\n if (scriptGenerator) {\n scriptGenerator.startStep(step.id);\n }\n await executeStep(step, context, scriptGenerator, runId, definition.name, stepIndex);\n if (scriptGenerator && stepIndex < definition.steps.length - 1) {\n await waitForStepExit(context.page, step);\n await context.page.waitForTimeout(transitionDelayMs);\n }\n }\n\n if (scriptGenerator) {\n scriptGenerator.finishAllSteps();\n\n const scriptOutputDir = options.scriptOutputDir ?? path.join(context.outputDir, \"scripts\");\n const scriptBasePath = path.join(scriptOutputDir, definition.name);\n await scriptGenerator.exportJSON(`${scriptBasePath}.json`);\n await scriptGenerator.exportSRT(`${scriptBasePath}.srt`);\n await scriptGenerator.exportMarkdown(`${scriptBasePath}.md`);\n await scriptGenerator.exportAIVoiceScript(`${scriptBasePath}.voice.json`);\n\n // Clean up cursor overlay\n await removeCursorOverlay(context.page);\n\n logEvent(\"info\", \"demo_complete\", {\n runId,\n demoName: definition.name,\n durationMs: Date.now() - startTime,\n });\n\n return {\n success: true,\n demoName: definition.name,\n videoPath: context.videoPath,\n scriptPath: `${scriptBasePath}.json`,\n duration: Date.now() - startTime,\n };\n }\n\n // Clean up cursor overlay\n await removeCursorOverlay(context.page);\n\n logEvent(\"info\", \"demo_complete\", {\n runId,\n demoName: definition.name,\n durationMs: Date.now() - startTime,\n });\n\n return {\n success: true,\n demoName: definition.name,\n videoPath: context.videoPath,\n duration: Date.now() - startTime,\n };\n } catch (error) {\n logEvent(\"error\", \"demo_failed\", {\n runId,\n demoName: definition.name,\n durationMs: Date.now() - startTime,\n error: error instanceof Error ? error.message : String(error),\n });\n await captureDiagnostics({\n context,\n error,\n runId,\n });\n return {\n success: false,\n demoName: definition.name,\n error: error instanceof Error ? error : new Error(String(error)),\n duration: Date.now() - startTime,\n };\n }\n}\n\n/**\n * Runs a demo from a YAML file path.\n */\nexport async function runDemoFromFile(\n definitionPath: string,\n context: DemoContext,\n options?: RunDemoOptions\n): Promise<DemoResult> {\n const definition = await loadDemoDefinition(definitionPath);\n return runDemo(definition, context, options);\n}\n\n/**\n * Discovers all demo definition files in a directory.\n */\nexport async function discoverDemos(demoDir: string): Promise<string[]> {\n const files = await fs.readdir(demoDir);\n return files\n .filter((f) => f.endsWith(\".yaml\") || f.endsWith(\".yml\"))\n .map((f) => path.join(demoDir, f));\n}\n","import { spawn } from \"child_process\";\nimport { ElevenLabsClient } from \"elevenlabs\";\nimport * as fs from \"fs/promises\";\nimport * as path from \"path\";\nimport {\n VoiceCache,\n VoiceCacheConfig,\n normalizeVoiceSettings,\n getDefaultCacheDir,\n} from \"./voice-cache.js\";\n\nconst DEFAULT_MAX_OUTPUT_BYTES = 512 * 1024;\nconst DEFAULT_MAX_CONCURRENCY = 2;\nconst DEFAULT_RETRY_OPTIONS = {\n retries: 3,\n minDelayMs: 500,\n maxDelayMs: 8000,\n};\n\nfunction sanitizeFileSegment(value: string, fallback = \"segment\", maxLength = 80): string {\n const raw = String(value ?? \"\").trim();\n if (!raw) {\n return fallback;\n }\n\n const cleaned = raw.replace(/[^a-zA-Z0-9._-]+/g, \"_\");\n const collapsed = cleaned.replace(/_{2,}/g, \"_\").replace(/^_+|_+$/g, \"\");\n const safe = collapsed || fallback;\n const trimmed = safe.length > maxLength ? safe.slice(0, maxLength) : safe;\n\n if (trimmed === \".\" || trimmed === \"..\") {\n return fallback;\n }\n\n return trimmed;\n}\n\nfunction appendWithLimit(buffer: string, chunk: string, limit: number): string {\n const next = buffer + chunk;\n if (next.length <= limit) {\n return next;\n }\n return next.slice(next.length - limit);\n}\n\nfunction runCommand(\n command: string,\n args: string[],\n options: { stdio?: Array<\"ignore\" | \"pipe\">; cwd?: string; maxOutputBytes?: number } = {}\n) {\n const {\n stdio = [\"ignore\", \"pipe\", \"pipe\"],\n cwd,\n maxOutputBytes = DEFAULT_MAX_OUTPUT_BYTES,\n } = options;\n return new Promise<{ stdout: string; stderr: string }>((resolve, reject) => {\n const child = spawn(command, args, { stdio, cwd });\n let stdout = \"\";\n let stderr = \"\";\n\n if (child.stdout) {\n child.stdout.on(\"data\", (chunk) => {\n stdout = appendWithLimit(stdout, chunk.toString(), maxOutputBytes);\n });\n }\n\n if (child.stderr) {\n child.stderr.on(\"data\", (chunk) => {\n stderr = appendWithLimit(stderr, chunk.toString(), maxOutputBytes);\n });\n }\n\n child.on(\"error\", (error) => {\n reject(error);\n });\n\n child.on(\"close\", (code) => {\n if (code === 0) {\n resolve({ stdout, stderr });\n return;\n }\n const error = new Error(`${command} exited with code ${code}`);\n (error as Error & { code?: number; stderr?: string }).code = code ?? undefined;\n (error as Error & { code?: number; stderr?: string }).stderr = stderr;\n reject(error);\n });\n });\n}\n\nasync function probeMediaDurationMs(filePath: string): Promise<number | null> {\n try {\n const { stdout } = await runCommand(\"ffprobe\", [\n \"-v\",\n \"error\",\n \"-show_entries\",\n \"format=duration\",\n \"-of\",\n \"default=noprint_wrappers=1:nokey=1\",\n filePath,\n ]);\n const durationSec = parseFloat(stdout.trim());\n if (Number.isFinite(durationSec)) {\n return Math.round(durationSec * 1000);\n }\n } catch {\n return null;\n }\n return null;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\ninterface RetryOptions {\n retries?: number;\n minDelayMs?: number;\n maxDelayMs?: number;\n}\n\nfunction getStatusCode(error: unknown): number | undefined {\n if (!error || typeof error !== \"object\") return undefined;\n const maybeError = error as {\n status?: number;\n statusCode?: number;\n response?: { status?: number };\n };\n return maybeError.status ?? maybeError.statusCode ?? maybeError.response?.status;\n}\n\nfunction getHeaderValue(headers: unknown, name: string): string | null {\n if (!headers || typeof headers !== \"object\") {\n return null;\n }\n const getter = (headers as { get?: unknown }).get;\n if (typeof getter === \"function\") {\n return getter.call(headers, name);\n }\n const record = headers as Record<string, string>;\n const direct = record[name];\n if (typeof direct === \"string\") {\n return direct;\n }\n const lower = record[name.toLowerCase()];\n if (typeof lower === \"string\") {\n return lower;\n }\n const upper = record[name.toUpperCase()];\n if (typeof upper === \"string\") {\n return upper;\n }\n return null;\n}\n\nfunction getRetryAfterMs(error: unknown): number | null {\n if (!error || typeof error !== \"object\") return null;\n const maybeError = error as {\n retryAfter?: string | number;\n response?: { headers?: Record<string, string> | { get?: (name: string) => string | null } };\n };\n const headerValue = getHeaderValue(maybeError.response?.headers, \"retry-after\");\n const retryAfter = headerValue ?? maybeError.retryAfter;\n if (retryAfter === undefined || retryAfter === null) {\n return null;\n }\n const seconds = Number(retryAfter);\n if (Number.isFinite(seconds)) {\n return Math.max(0, Math.round(seconds * 1000));\n }\n return null;\n}\n\nfunction isRetryableError(error: unknown): boolean {\n const status = getStatusCode(error);\n if (status && [408, 429, 500, 502, 503, 504].includes(status)) {\n return true;\n }\n const message = String((error as Error | undefined)?.message ?? \"\");\n return /(rate limit|timeout|ECONNRESET|ETIMEDOUT|EAI_AGAIN|socket hang up)/i.test(message);\n}\n\nfunction getRetryDelayMs(attempt: number, options: RetryOptions, error: unknown): number {\n const minDelayMs = options.minDelayMs ?? DEFAULT_RETRY_OPTIONS.minDelayMs;\n const maxDelayMs = options.maxDelayMs ?? DEFAULT_RETRY_OPTIONS.maxDelayMs;\n const baseDelay = Math.min(maxDelayMs, minDelayMs * 2 ** attempt);\n const jitter = 0.5 + Math.random();\n const retryAfterMs = getRetryAfterMs(error) ?? 0;\n return Math.max(retryAfterMs, Math.round(baseDelay * jitter));\n}\n\nasync function withRetry<T>(fn: () => Promise<T>, options: RetryOptions = {}): Promise<T> {\n const retries = options.retries ?? DEFAULT_RETRY_OPTIONS.retries;\n let attempt = 0;\n // eslint-disable-next-line no-constant-condition\n while (true) {\n try {\n return await fn();\n } catch (error) {\n if (!isRetryableError(error) || attempt >= retries) {\n throw error;\n }\n const delayMs = getRetryDelayMs(attempt, options, error);\n await sleep(delayMs);\n attempt += 1;\n }\n }\n}\n\n/**\n * Configuration for voice synthesis\n */\nexport interface VoiceSynthesisConfig {\n apiKey: string;\n voiceId: string; // Custom voice ID from ElevenLabs\n modelId?: string; // Default: eleven_multilingual_v2\n outputFormat?: \"mp3_44100_128\" | \"mp3_44100_192\" | \"pcm_16000\" | \"pcm_22050\" | \"pcm_24000\";\n /** Voice cache configuration. Set to false to disable caching entirely. */\n cache?: VoiceCacheConfig | false;\n}\n\n/**\n * Script segment from the generated JSON\n */\nexport interface ScriptSegment {\n stepId: string;\n text: string;\n startTimeMs: number;\n endTimeMs: number;\n estimatedDurationMs: number;\n pauseBeforeMs?: number;\n pauseAfterMs?: number;\n}\n\n/**\n * Generated script JSON structure\n */\nexport interface GeneratedScript {\n demoName: string;\n title: string;\n generatedAt: string;\n totalDurationMs: number;\n segments: ScriptSegment[];\n}\n\n/**\n * Result of synthesizing a segment\n */\nexport interface SynthesizedSegment {\n stepId: string;\n audioPath: string;\n durationMs: number;\n text: string;\n}\n\n/**\n * Result of full voice synthesis\n */\nexport interface VoiceSynthesisResult {\n demoName: string;\n segments: SynthesizedSegment[];\n combinedAudioPath?: string;\n soundEffectsPath?: string;\n backgroundMusicPath?: string;\n}\n\n/**\n * ElevenLabs voice synthesizer for demo narration\n */\nexport class VoiceSynthesizer {\n private client: ElevenLabsClient;\n private config: VoiceSynthesisConfig;\n private cache: VoiceCache | null = null;\n private cacheInitialized = false;\n\n constructor(config: VoiceSynthesisConfig) {\n this.config = config;\n this.client = new ElevenLabsClient({\n apiKey: config.apiKey,\n });\n\n // Initialize cache if not explicitly disabled\n if (config.cache !== false) {\n const cacheConfig: VoiceCacheConfig = config.cache ?? {\n cacheDir: getDefaultCacheDir(),\n enabled: true,\n };\n this.cache = new VoiceCache(cacheConfig);\n }\n }\n\n /**\n * Ensures the cache is initialized before use\n */\n private async ensureCacheInitialized(): Promise<void> {\n if (this.cache && !this.cacheInitialized) {\n await this.cache.initialize();\n this.cacheInitialized = true;\n }\n }\n\n /**\n * Gets the voice cache instance (if enabled)\n */\n getCache(): VoiceCache | null {\n return this.cache;\n }\n\n /**\n * List available voices (useful for finding voice IDs)\n */\n async listVoices(): Promise<Array<{ voiceId: string; name: string; category: string }>> {\n const response = await this.client.voices.getAll();\n return response.voices.map((voice) => ({\n voiceId: voice.voice_id,\n name: voice.name || \"Unnamed\",\n category: voice.category || \"unknown\",\n }));\n }\n\n /**\n * Synthesize a single text segment to audio\n */\n async synthesizeSegment(\n text: string,\n outputPath: string,\n options?: {\n stability?: number; // 0-1, higher = more consistent\n similarityBoost?: number; // 0-1, higher = more similar to original voice\n style?: number; // 0-1, style exaggeration\n useSpeakerBoost?: boolean;\n /** Skip cache lookup (still stores result in cache) */\n skipCache?: boolean;\n }\n ): Promise<{ durationMs: number; fromCache: boolean }> {\n const modelId = this.config.modelId || \"eleven_multilingual_v2\";\n const voiceSettings = normalizeVoiceSettings(options);\n\n // Check cache first (unless skipCache is true)\n if (this.cache && !options?.skipCache) {\n await this.ensureCacheInitialized();\n\n const cachedEntry = await this.cache.get(\n this.config.voiceId,\n modelId,\n text,\n voiceSettings\n );\n\n if (cachedEntry) {\n // Copy cached file to output path\n const cachedPath = this.cache.getAudioPath(cachedEntry);\n await fs.copyFile(cachedPath, outputPath);\n console.log(`[voice] Cache hit for \"${text.slice(0, 40)}...\" (saved API call)`);\n return { durationMs: cachedEntry.durationMs, fromCache: true };\n }\n }\n\n // Cache miss - call the API\n const audio = await this.client.textToSpeech.convert(this.config.voiceId, {\n text,\n model_id: modelId,\n voice_settings: {\n stability: voiceSettings.stability,\n similarity_boost: voiceSettings.similarityBoost,\n style: voiceSettings.style,\n use_speaker_boost: voiceSettings.useSpeakerBoost,\n },\n });\n\n // Collect audio chunks\n const chunks: Buffer[] = [];\n for await (const chunk of audio) {\n chunks.push(Buffer.from(chunk));\n }\n const audioBuffer = Buffer.concat(chunks);\n\n // Write to file\n await fs.writeFile(outputPath, audioBuffer);\n\n const probedDurationMs = await probeMediaDurationMs(outputPath);\n let durationMs: number;\n\n if (probedDurationMs !== null) {\n durationMs = probedDurationMs;\n } else {\n const fileSizeBytes = audioBuffer.length;\n durationMs = Math.round((fileSizeBytes * 8) / 128); // 128kbps\n console.warn(`[voice] ffprobe unavailable, using estimated duration for ${outputPath}`);\n }\n\n // Store in cache for future use\n if (this.cache) {\n await this.ensureCacheInitialized();\n await this.cache.put(\n this.config.voiceId,\n modelId,\n text,\n voiceSettings,\n audioBuffer,\n durationMs\n );\n await this.cache.saveIndex();\n }\n\n return { durationMs, fromCache: false };\n }\n\n /**\n * Generate a sound effect from text description\n */\n async generateSoundEffect(\n description: string,\n outputPath: string,\n options?: {\n durationSeconds?: number; // 0.5-30\n promptInfluence?: number; // 0-1\n retry?: RetryOptions;\n }\n ): Promise<void> {\n const audio = await withRetry(\n () =>\n this.client.textToSoundEffects.convert({\n text: description,\n duration_seconds: options?.durationSeconds ?? 1.0,\n prompt_influence: options?.promptInfluence ?? 0.3,\n }),\n options?.retry\n );\n\n const chunks: Buffer[] = [];\n for await (const chunk of audio) {\n chunks.push(Buffer.from(chunk));\n }\n await fs.writeFile(outputPath, Buffer.concat(chunks));\n }\n\n /**\n * Synthesize all segments from a script JSON file\n */\n async synthesizeScript(\n scriptPath: string,\n outputDir: string,\n options?: {\n voiceSettings?: {\n stability?: number;\n similarityBoost?: number;\n style?: number;\n };\n generateClickSounds?: boolean;\n onProgress?: (current: number, total: number, stepId: string) => void;\n maxConcurrency?: number;\n retry?: RetryOptions;\n }\n ): Promise<VoiceSynthesisResult> {\n // Read script\n const scriptContent = await fs.readFile(scriptPath, \"utf-8\");\n const script: GeneratedScript = JSON.parse(scriptContent);\n\n // Ensure output directory exists\n const audioDir = path.join(outputDir, \"audio\", script.demoName);\n await fs.mkdir(audioDir, { recursive: true });\n\n const synthesizedSegments: SynthesizedSegment[] = new Array(script.segments.length);\n const maxConcurrency = Math.max(\n 1,\n options?.maxConcurrency ?? DEFAULT_MAX_CONCURRENCY\n );\n let progressCount = 0;\n let nextIndex = 0;\n\n const workers = Array.from({ length: Math.min(maxConcurrency, script.segments.length) }, async () => {\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const index = nextIndex;\n nextIndex += 1;\n if (index >= script.segments.length) {\n break;\n }\n\n const segment = script.segments[index];\n const safeStepId = sanitizeFileSegment(segment.stepId, `step-${index + 1}`);\n const audioFileName = `${String(index + 1).padStart(2, \"0\")}_${safeStepId}.mp3`;\n const audioPath = path.join(audioDir, audioFileName);\n\n progressCount += 1;\n options?.onProgress?.(progressCount, script.segments.length, segment.stepId);\n\n try {\n const result = await withRetry(\n () => this.synthesizeSegment(segment.text, audioPath, options?.voiceSettings),\n options?.retry\n );\n\n synthesizedSegments[index] = {\n stepId: segment.stepId,\n audioPath,\n durationMs: result.durationMs,\n text: segment.text,\n };\n\n const cacheStatus = result.fromCache ? \"[cached]\" : \"[new]\";\n console.log(`[voice] ${cacheStatus} ${segment.stepId} (${result.durationMs.toFixed(0)}ms)`);\n } catch (error) {\n console.error(`[voice] Failed to synthesize ${segment.stepId}:`, error);\n throw error;\n }\n }\n });\n\n await Promise.all(workers);\n\n // Generate click sounds if requested\n let soundEffectsPath: string | undefined;\n if (options?.generateClickSounds) {\n soundEffectsPath = path.join(audioDir, \"click.mp3\");\n await this.generateClickSound(soundEffectsPath);\n }\n\n return {\n demoName: script.demoName,\n segments: synthesizedSegments,\n soundEffectsPath,\n };\n }\n\n /**\n * Generate a UI click sound effect\n */\n async generateClickSound(outputPath: string): Promise<void> {\n await this.generateSoundEffect(\n \"soft UI button click, subtle, digital, clean interface sound\",\n outputPath,\n { durationSeconds: 0.5, promptInfluence: 0.5 }\n );\n console.log(\"[voice] Generated click sound effect\");\n }\n\n /**\n * Generate ambient background music\n */\n async generateBackgroundMusic(\n outputPath: string,\n options?: {\n style?: \"corporate\" | \"tech\" | \"calm\" | \"upbeat\";\n durationSeconds?: number;\n }\n ): Promise<void> {\n const styleDescriptions: Record<string, string> = {\n corporate: \"soft corporate background music, professional, minimal, ambient technology sounds\",\n tech: \"modern technology background music, subtle electronic, innovative, clean\",\n calm: \"calm ambient background music, peaceful, soft piano, gentle\",\n upbeat: \"light upbeat background music, positive, motivational, subtle energy\",\n };\n\n const description = styleDescriptions[options?.style || \"tech\"];\n const duration = options?.durationSeconds ?? 30;\n\n // Note: ElevenLabs sound effects max is 30 seconds\n // For longer music, you'd need to loop or use their music generation API\n await this.generateSoundEffect(description, outputPath, {\n durationSeconds: Math.min(duration, 30),\n promptInfluence: 0.4,\n });\n console.log(`[voice] Generated background music (${options?.style || \"tech\"} style)`);\n }\n}\n\n/**\n * Create a timing manifest for video editing\n * Maps audio files to their intended start times in the video\n */\nexport interface AudioTimingManifest {\n demoName: string;\n segments: Array<{\n stepId: string;\n audioFile: string;\n videoStartTimeMs: number;\n audioDurationMs: number;\n text: string;\n }>;\n soundEffects?: {\n clickSound?: string;\n };\n backgroundMusic?: string;\n}\n\n/**\n * Generate a timing manifest from synthesized results and original script\n */\nexport async function generateTimingManifest(\n scriptPath: string,\n synthesisResult: VoiceSynthesisResult,\n outputPath: string\n): Promise<AudioTimingManifest> {\n const scriptContent = await fs.readFile(scriptPath, \"utf-8\");\n const script: GeneratedScript = JSON.parse(scriptContent);\n\n const manifest: AudioTimingManifest = {\n demoName: script.demoName,\n segments: synthesisResult.segments.map((synth) => {\n const originalSegment = script.segments.find((s) => s.stepId === synth.stepId);\n return {\n stepId: synth.stepId,\n audioFile: synth.audioPath,\n videoStartTimeMs: originalSegment?.startTimeMs ?? 0,\n audioDurationMs: synth.durationMs,\n text: synth.text,\n };\n }),\n soundEffects: synthesisResult.soundEffectsPath\n ? { clickSound: synthesisResult.soundEffectsPath }\n : undefined,\n backgroundMusic: synthesisResult.backgroundMusicPath,\n };\n\n await fs.writeFile(outputPath, JSON.stringify(manifest, null, 2));\n return manifest;\n}\n\n/**\n * Default export for easy instantiation\n */\nexport function createVoiceSynthesizer(config: VoiceSynthesisConfig): VoiceSynthesizer {\n return new VoiceSynthesizer(config);\n}\n","import * as crypto from \"crypto\";\nimport * as fs from \"fs/promises\";\nimport * as path from \"path\";\n\n/**\n * Voice settings that affect the generated audio output\n */\nexport interface VoiceCacheSettings {\n stability: number;\n similarityBoost: number;\n style: number;\n useSpeakerBoost: boolean;\n}\n\n/**\n * A single entry in the voice cache\n */\nexport interface VoiceCacheEntry {\n key: string;\n voiceId: string;\n modelId: string;\n text: string;\n voiceSettings: VoiceCacheSettings;\n audioFileName: string;\n durationMs: number;\n fileSizeBytes: number;\n createdAt: string;\n lastUsedAt: string;\n}\n\n/**\n * The cache index structure stored on disk\n */\nexport interface VoiceCacheIndex {\n version: number;\n entries: Record<string, VoiceCacheEntry>;\n}\n\n/**\n * Configuration for the voice cache\n */\nexport interface VoiceCacheConfig {\n /** Directory where cache files are stored */\n cacheDir: string;\n /** Whether caching is enabled (default: true) */\n enabled?: boolean;\n}\n\n/**\n * Statistics about the voice cache\n */\nexport interface VoiceCacheStats {\n totalEntries: number;\n totalSizeBytes: number;\n oldestEntry: string | null;\n newestEntry: string | null;\n hitCount: number;\n missCount: number;\n}\n\nconst CACHE_VERSION = 1;\nconst INDEX_FILE = \"index.json\";\nconst AUDIO_DIR = \"audio\";\n\n/**\n * Default voice settings used when none are specified\n */\nexport const DEFAULT_VOICE_SETTINGS: VoiceCacheSettings = {\n stability: 0.5,\n similarityBoost: 0.75,\n style: 0.0,\n useSpeakerBoost: true,\n};\n\n/**\n * Normalizes voice settings by applying defaults for missing values\n */\nexport function normalizeVoiceSettings(\n settings?: Partial<VoiceCacheSettings>\n): VoiceCacheSettings {\n return {\n stability: settings?.stability ?? DEFAULT_VOICE_SETTINGS.stability,\n similarityBoost: settings?.similarityBoost ?? DEFAULT_VOICE_SETTINGS.similarityBoost,\n style: settings?.style ?? DEFAULT_VOICE_SETTINGS.style,\n useSpeakerBoost: settings?.useSpeakerBoost ?? DEFAULT_VOICE_SETTINGS.useSpeakerBoost,\n };\n}\n\n/**\n * Generates a deterministic cache key from voice synthesis parameters.\n * The key is a SHA-256 hash of the normalized inputs.\n */\nexport function generateCacheKey(\n voiceId: string,\n modelId: string,\n text: string,\n voiceSettings: VoiceCacheSettings\n): string {\n // Normalize text by trimming whitespace\n const normalizedText = text.trim();\n\n // Create a deterministic string representation of all parameters\n const keyData = JSON.stringify({\n voiceId,\n modelId,\n text: normalizedText,\n voiceSettings: {\n stability: voiceSettings.stability,\n similarityBoost: voiceSettings.similarityBoost,\n style: voiceSettings.style,\n useSpeakerBoost: voiceSettings.useSpeakerBoost,\n },\n });\n\n // Generate SHA-256 hash\n return crypto.createHash(\"sha256\").update(keyData).digest(\"hex\");\n}\n\n/**\n * Voice cache manager for storing and retrieving synthesized audio.\n * This helps avoid duplicate API calls to ElevenLabs for the same text/voice combinations.\n */\nexport class VoiceCache {\n private config: VoiceCacheConfig;\n private index: VoiceCacheIndex | null = null;\n private stats: { hits: number; misses: number } = { hits: 0, misses: 0 };\n private indexDirty = false;\n\n constructor(config: VoiceCacheConfig) {\n this.config = {\n ...config,\n enabled: config.enabled ?? true,\n };\n }\n\n /**\n * Gets the path to the cache index file\n */\n private get indexPath(): string {\n return path.join(this.config.cacheDir, INDEX_FILE);\n }\n\n /**\n * Gets the path to the audio cache directory\n */\n private get audioDir(): string {\n return path.join(this.config.cacheDir, AUDIO_DIR);\n }\n\n /**\n * Whether caching is enabled\n */\n get enabled(): boolean {\n return this.config.enabled ?? true;\n }\n\n /**\n * Initializes the cache directory and loads the index\n */\n async initialize(): Promise<void> {\n if (!this.enabled) {\n return;\n }\n\n // Ensure cache directories exist\n await fs.mkdir(this.config.cacheDir, { recursive: true });\n await fs.mkdir(this.audioDir, { recursive: true });\n\n // Load existing index or create new one\n await this.loadIndex();\n }\n\n /**\n * Loads the cache index from disk\n */\n private async loadIndex(): Promise<void> {\n try {\n const content = await fs.readFile(this.indexPath, \"utf-8\");\n const parsed = JSON.parse(content) as VoiceCacheIndex;\n\n // Handle version migrations if needed\n if (parsed.version !== CACHE_VERSION) {\n console.warn(\n `[voice-cache] Index version mismatch (${parsed.version} vs ${CACHE_VERSION}), rebuilding cache`\n );\n this.index = { version: CACHE_VERSION, entries: {} };\n this.indexDirty = true;\n return;\n }\n\n this.index = parsed;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n // Index doesn't exist, create a new one\n this.index = { version: CACHE_VERSION, entries: {} };\n this.indexDirty = true;\n } else {\n console.warn(`[voice-cache] Failed to load index, creating new one:`, error);\n this.index = { version: CACHE_VERSION, entries: {} };\n this.indexDirty = true;\n }\n }\n }\n\n /**\n * Saves the cache index to disk\n */\n async saveIndex(): Promise<void> {\n if (!this.enabled || !this.index || !this.indexDirty) {\n return;\n }\n\n await fs.writeFile(this.indexPath, JSON.stringify(this.index, null, 2));\n this.indexDirty = false;\n }\n\n /**\n * Looks up a cached audio file by its synthesis parameters.\n * Returns the cache entry if found, null otherwise.\n */\n async get(\n voiceId: string,\n modelId: string,\n text: string,\n voiceSettings: VoiceCacheSettings\n ): Promise<VoiceCacheEntry | null> {\n if (!this.enabled || !this.index) {\n this.stats.misses++;\n return null;\n }\n\n const key = generateCacheKey(voiceId, modelId, text, voiceSettings);\n const entry = this.index.entries[key];\n\n if (!entry) {\n this.stats.misses++;\n return null;\n }\n\n // Verify the cached file still exists\n const audioPath = path.join(this.audioDir, entry.audioFileName);\n try {\n await fs.access(audioPath);\n } catch {\n // File doesn't exist, remove from index\n delete this.index.entries[key];\n this.indexDirty = true;\n this.stats.misses++;\n return null;\n }\n\n // Update last used timestamp\n entry.lastUsedAt = new Date().toISOString();\n this.indexDirty = true;\n this.stats.hits++;\n\n return entry;\n }\n\n /**\n * Gets the full path to a cached audio file\n */\n getAudioPath(entry: VoiceCacheEntry): string {\n return path.join(this.audioDir, entry.audioFileName);\n }\n\n /**\n * Stores a synthesized audio file in the cache.\n * The audio data should be provided as a Buffer.\n */\n async put(\n voiceId: string,\n modelId: string,\n text: string,\n voiceSettings: VoiceCacheSettings,\n audioData: Buffer,\n durationMs: number\n ): Promise<VoiceCacheEntry> {\n if (!this.index) {\n await this.initialize();\n }\n\n const key = generateCacheKey(voiceId, modelId, text, voiceSettings);\n const audioFileName = `${key}.mp3`;\n const audioPath = path.join(this.audioDir, audioFileName);\n\n // Write audio file\n await fs.writeFile(audioPath, audioData);\n\n const now = new Date().toISOString();\n const entry: VoiceCacheEntry = {\n key,\n voiceId,\n modelId,\n text: text.trim(),\n voiceSettings,\n audioFileName,\n durationMs,\n fileSizeBytes: audioData.length,\n createdAt: now,\n lastUsedAt: now,\n };\n\n this.index!.entries[key] = entry;\n this.indexDirty = true;\n\n return entry;\n }\n\n /**\n * Removes a specific entry from the cache\n */\n async remove(key: string): Promise<boolean> {\n if (!this.enabled || !this.index) {\n return false;\n }\n\n const entry = this.index.entries[key];\n if (!entry) {\n return false;\n }\n\n // Delete the audio file\n const audioPath = path.join(this.audioDir, entry.audioFileName);\n try {\n await fs.unlink(audioPath);\n } catch {\n // File might not exist, that's okay\n }\n\n delete this.index.entries[key];\n this.indexDirty = true;\n\n return true;\n }\n\n /**\n * Clears all entries from the cache\n */\n async clear(): Promise<number> {\n if (!this.index) {\n await this.initialize();\n }\n\n const count = Object.keys(this.index!.entries).length;\n\n // Delete all audio files\n try {\n const files = await fs.readdir(this.audioDir);\n await Promise.all(\n files.map((file) => fs.unlink(path.join(this.audioDir, file)).catch(() => {}))\n );\n } catch {\n // Directory might not exist\n }\n\n this.index!.entries = {};\n this.indexDirty = true;\n await this.saveIndex();\n\n return count;\n }\n\n /**\n * Lists all entries in the cache\n */\n async list(): Promise<VoiceCacheEntry[]> {\n if (!this.index) {\n await this.initialize();\n }\n\n return Object.values(this.index!.entries).sort(\n (a, b) => new Date(b.lastUsedAt).getTime() - new Date(a.lastUsedAt).getTime()\n );\n }\n\n /**\n * Gets statistics about the cache\n */\n async getStats(): Promise<VoiceCacheStats> {\n if (!this.index) {\n await this.initialize();\n }\n\n const entries = Object.values(this.index!.entries);\n const totalSizeBytes = entries.reduce((sum, e) => sum + e.fileSizeBytes, 0);\n\n let oldestEntry: string | null = null;\n let newestEntry: string | null = null;\n\n if (entries.length > 0) {\n const sorted = [...entries].sort(\n (a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime()\n );\n oldestEntry = sorted[0].createdAt;\n newestEntry = sorted[sorted.length - 1].createdAt;\n }\n\n return {\n totalEntries: entries.length,\n totalSizeBytes,\n oldestEntry,\n newestEntry,\n hitCount: this.stats.hits,\n missCount: this.stats.misses,\n };\n }\n\n /**\n * Prunes entries older than the specified age (in days)\n */\n async pruneOlderThan(days: number): Promise<number> {\n if (!this.index) {\n await this.initialize();\n }\n\n const cutoff = Date.now() - days * 24 * 60 * 60 * 1000;\n let removed = 0;\n\n for (const [key, entry] of Object.entries(this.index!.entries)) {\n const lastUsed = new Date(entry.lastUsedAt).getTime();\n if (lastUsed < cutoff) {\n await this.remove(key);\n removed++;\n }\n }\n\n await this.saveIndex();\n return removed;\n }\n\n /**\n * Validates the cache by checking that all indexed files exist\n * and removing orphaned entries\n */\n async validate(): Promise<{ valid: number; removed: number }> {\n if (!this.index) {\n await this.initialize();\n }\n\n let valid = 0;\n let removed = 0;\n\n for (const [key, entry] of Object.entries(this.index!.entries)) {\n const audioPath = path.join(this.audioDir, entry.audioFileName);\n try {\n await fs.access(audioPath);\n valid++;\n } catch {\n delete this.index!.entries[key];\n this.indexDirty = true;\n removed++;\n }\n }\n\n if (removed > 0) {\n await this.saveIndex();\n }\n\n return { valid, removed };\n }\n}\n\n/**\n * Creates a new VoiceCache instance with the given configuration\n */\nexport function createVoiceCache(config: VoiceCacheConfig): VoiceCache {\n return new VoiceCache(config);\n}\n\n/**\n * Gets the default cache directory path\n */\nexport function getDefaultCacheDir(projectRoot?: string): string {\n const root = projectRoot || process.cwd();\n return path.join(root, \".voice-cache\");\n}\n","import * as fs from \"fs/promises\";\nimport * as path from \"path\";\n\n/**\n * A single segment of narration with timing information.\n */\nexport interface ScriptSegment {\n stepId: string;\n text: string;\n startTimeMs: number;\n endTimeMs: number;\n estimatedDurationMs: number;\n pauseBeforeMs?: number;\n pauseAfterMs?: number;\n}\n\n/**\n * Video step boundary for splitting videos per step.\n */\nexport interface StepBoundary {\n stepId: string;\n stepIndex: number;\n videoStartMs: number;\n videoEndMs: number;\n}\n\n/**\n * Complete script output with metadata.\n */\nexport interface ScriptOutput {\n demoName: string;\n title: string;\n generatedAt: string;\n totalDurationMs: number;\n segments: ScriptSegment[];\n stepBoundaries: StepBoundary[];\n videoMetadata?: {\n videoPath: string;\n durationMs: number;\n alignmentOffsetMs: number;\n recordingStartTimeMs?: number;\n alignedAt?: string;\n };\n}\n\n/**\n * Tracks narration segments during demo execution.\n */\nexport class ScriptGenerator {\n private segments: ScriptSegment[] = [];\n private stepBoundaries: StepBoundary[] = [];\n private currentStepId: string | null = null;\n private currentStepStartMs: number | null = null;\n private demoName: string;\n private title: string;\n private startTime: number;\n\n constructor(demoName: string, title: string, startTimeMs?: number) {\n this.demoName = demoName;\n this.title = title;\n this.startTime = startTimeMs ?? Date.now();\n }\n\n /**\n * Marks the start of a step (for video splitting).\n */\n startStep(stepId: string): void {\n // End previous step if there was one\n if (this.currentStepId && this.currentStepStartMs !== null) {\n this.stepBoundaries.push({\n stepId: this.currentStepId,\n stepIndex: this.stepBoundaries.length,\n videoStartMs: this.currentStepStartMs,\n videoEndMs: Date.now() - this.startTime,\n });\n }\n\n this.currentStepId = stepId;\n this.currentStepStartMs = Date.now() - this.startTime;\n }\n\n /**\n * Marks the end of all steps (call at demo completion).\n */\n finishAllSteps(): void {\n if (this.currentStepId && this.currentStepStartMs !== null) {\n this.stepBoundaries.push({\n stepId: this.currentStepId,\n stepIndex: this.stepBoundaries.length,\n videoStartMs: this.currentStepStartMs,\n videoEndMs: Date.now() - this.startTime,\n });\n this.currentStepId = null;\n this.currentStepStartMs = null;\n }\n }\n\n /**\n * Estimates reading duration for text.\n * Based on ~150 words per minute average speaking rate.\n */\n private estimateReadingDuration(text: string): number {\n const words = text.split(/\\s+/).length;\n const wpm = 150; // Words per minute\n return Math.round((words / wpm) * 60 * 1000);\n }\n\n /**\n * Adds a narration segment with automatic timing.\n */\n addSegment(\n stepId: string,\n text: string,\n options?: {\n timing?: \"on_start\" | \"on_complete\";\n pauseBeforeMs?: number;\n pauseAfterMs?: number;\n }\n ): void {\n const now = Date.now();\n const startTimeMs = now - this.startTime;\n const estimatedDurationMs = this.estimateReadingDuration(text);\n\n this.segments.push({\n stepId,\n text,\n startTimeMs,\n endTimeMs: startTimeMs + estimatedDurationMs,\n estimatedDurationMs,\n pauseBeforeMs: options?.pauseBeforeMs,\n pauseAfterMs: options?.pauseAfterMs,\n });\n }\n\n /**\n * Updates the end time of the last segment.\n * Call this when a step completes to capture actual duration.\n */\n completeLastSegment(): void {\n if (this.segments.length > 0) {\n const lastSegment = this.segments[this.segments.length - 1];\n lastSegment.endTimeMs = Date.now() - this.startTime;\n }\n }\n\n /**\n * Generates the complete script output.\n */\n getOutput(): ScriptOutput {\n const now = Date.now();\n return {\n demoName: this.demoName,\n title: this.title,\n generatedAt: new Date().toISOString(),\n totalDurationMs: now - this.startTime,\n segments: this.segments,\n stepBoundaries: this.stepBoundaries,\n };\n }\n\n /**\n * Exports script as JSON.\n */\n async exportJSON(outputPath: string): Promise<void> {\n const output = this.getOutput();\n await fs.mkdir(path.dirname(outputPath), { recursive: true });\n await fs.writeFile(outputPath, JSON.stringify(output, null, 2));\n }\n\n /**\n * Exports script as SRT subtitle format.\n */\n async exportSRT(outputPath: string): Promise<void> {\n const output = this.getOutput();\n let srt = \"\";\n\n output.segments.forEach((segment, index) => {\n const startTime = formatSRTTime(segment.startTimeMs);\n const endTime = formatSRTTime(segment.endTimeMs);\n\n srt += `${index + 1}\\n`;\n srt += `${startTime} --> ${endTime}\\n`;\n srt += `${segment.text}\\n\\n`;\n });\n\n await fs.mkdir(path.dirname(outputPath), { recursive: true });\n await fs.writeFile(outputPath, srt.trim());\n }\n\n /**\n * Exports script in a format suitable for AI voice generation services.\n * Includes SSML-like pause markers.\n */\n async exportAIVoiceScript(outputPath: string): Promise<void> {\n const output = this.getOutput();\n\n interface AIVoiceSegment {\n index: number;\n stepId: string;\n text: string;\n ssmlHints: string;\n pauseBeforeMs: number;\n pauseAfterMs: number;\n syncPointMs: number;\n }\n\n const voiceScript = {\n demoName: output.demoName,\n title: output.title,\n totalDuration: formatReadableTime(output.totalDurationMs),\n segments: output.segments.map((segment, index) => ({\n index: index + 1,\n stepId: segment.stepId,\n text: segment.text,\n ssmlHints: generateSSMLHints(segment),\n pauseBeforeMs: segment.pauseBeforeMs || 0,\n pauseAfterMs: segment.pauseAfterMs || 500,\n syncPointMs: segment.startTimeMs,\n } satisfies AIVoiceSegment)),\n };\n\n await fs.mkdir(path.dirname(outputPath), { recursive: true });\n await fs.writeFile(outputPath, JSON.stringify(voiceScript, null, 2));\n }\n\n /**\n * Exports script as human-readable markdown for voice actors.\n */\n async exportMarkdown(outputPath: string): Promise<void> {\n const output = this.getOutput();\n\n let markdown = `# ${output.title}\\n\\n`;\n markdown += `**Demo:** ${output.demoName}\\n`;\n markdown += `**Total Duration:** ${formatReadableTime(output.totalDurationMs)}\\n`;\n markdown += `**Generated:** ${output.generatedAt}\\n\\n`;\n markdown += `---\\n\\n`;\n markdown += `## Script\\n\\n`;\n\n output.segments.forEach((segment, index) => {\n markdown += `### ${index + 1}. ${segment.stepId}\\n\\n`;\n markdown += `**Timing:** ${formatReadableTime(segment.startTimeMs)} - ${formatReadableTime(segment.endTimeMs)}\\n\\n`;\n\n if (segment.pauseBeforeMs) {\n markdown += `*[Pause ${segment.pauseBeforeMs}ms before]*\\n\\n`;\n }\n\n markdown += `> ${segment.text}\\n\\n`;\n\n if (segment.pauseAfterMs) {\n markdown += `*[Pause ${segment.pauseAfterMs}ms after]*\\n\\n`;\n }\n\n markdown += `---\\n\\n`;\n });\n\n await fs.mkdir(path.dirname(outputPath), { recursive: true });\n await fs.writeFile(outputPath, markdown);\n }\n}\n\n/**\n * Formats milliseconds to SRT timestamp format (HH:MM:SS,mmm).\n */\nfunction formatSRTTime(ms: number): string {\n const hours = Math.floor(ms / 3600000);\n const minutes = Math.floor((ms % 3600000) / 60000);\n const seconds = Math.floor((ms % 60000) / 1000);\n const milliseconds = ms % 1000;\n\n return `${pad(hours, 2)}:${pad(minutes, 2)}:${pad(seconds, 2)},${pad(milliseconds, 3)}`;\n}\n\n/**\n * Formats milliseconds to human-readable time (M:SS or H:MM:SS).\n */\nfunction formatReadableTime(ms: number): string {\n const totalSeconds = Math.floor(ms / 1000);\n const hours = Math.floor(totalSeconds / 3600);\n const minutes = Math.floor((totalSeconds % 3600) / 60);\n const seconds = totalSeconds % 60;\n\n if (hours > 0) {\n return `${hours}:${pad(minutes, 2)}:${pad(seconds, 2)}`;\n }\n return `${minutes}:${pad(seconds, 2)}`;\n}\n\n/**\n * Pads a number with leading zeros.\n */\nfunction pad(num: number, size: number): string {\n let s = num.toString();\n while (s.length < size) s = \"0\" + s;\n return s;\n}\n\n/**\n * Generates SSML hints for AI voice services.\n */\nfunction generateSSMLHints(segment: ScriptSegment): string {\n let ssml = segment.text;\n\n // Add break before if specified\n if (segment.pauseBeforeMs) {\n ssml = `<break time=\"${segment.pauseBeforeMs}ms\"/> ${ssml}`;\n }\n\n // Add break after if specified\n if (segment.pauseAfterMs) {\n ssml = `${ssml} <break time=\"${segment.pauseAfterMs}ms\"/>`;\n }\n\n return ssml;\n}\n\n/**\n * Creates a new ScriptGenerator instance.\n */\nexport function createScriptGenerator(\n demoName: string,\n title: string,\n startTimeMs?: number\n): ScriptGenerator {\n return new ScriptGenerator(demoName, title, startTimeMs);\n}\n","import type { Page } from \"@playwright/test\";\n\n/**\n * CSS for the custom cursor overlay.\n * Features:\n * - Large red arrow cursor visible on dark and light backgrounds\n * - Click ripple animation\n * - Smooth movement transitions\n * - Element highlight ring\n */\nconst CURSOR_STYLES = `\n /* Hide the real cursor when demo cursor is active */\n html.demo-cursor-active, html.demo-cursor-active * {\n cursor: none !important;\n }\n\n /* Demo cursor container */\n #demo-cursor {\n position: fixed;\n pointer-events: none;\n z-index: 999999;\n will-change: left, top;\n }\n\n /* Cursor arrow SVG - larger for visibility */\n #demo-cursor-arrow {\n width: 32px;\n height: 32px;\n filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.6)) drop-shadow(0 0 2px rgba(0, 0, 0, 0.4));\n }\n\n /* Click ripple effect - larger and more visible */\n .demo-click-ripple {\n position: absolute;\n top: 4px;\n left: 4px;\n width: 60px;\n height: 60px;\n border-radius: 50%;\n background: radial-gradient(circle, rgba(239, 68, 68, 0.7) 0%, rgba(239, 68, 68, 0.3) 40%, rgba(239, 68, 68, 0) 70%);\n transform: translate(-50%, -50%) scale(0);\n animation: demo-ripple 0.5s ease-out forwards;\n pointer-events: none;\n }\n\n @keyframes demo-ripple {\n 0% {\n transform: translate(-50%, -50%) scale(0);\n opacity: 1;\n }\n 100% {\n transform: translate(-50%, -50%) scale(2.5);\n opacity: 0;\n }\n }\n\n /* Highlight ring for elements being clicked - thicker and more visible */\n .demo-highlight-ring {\n position: fixed;\n border: 3px solid rgba(239, 68, 68, 0.9);\n border-radius: 6px;\n pointer-events: none;\n z-index: 999998;\n box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.3), inset 0 0 0 1px rgba(239, 68, 68, 0.2);\n animation: demo-highlight-pulse 0.8s ease-out forwards;\n }\n\n @keyframes demo-highlight-pulse {\n 0% {\n opacity: 1;\n transform: scale(1);\n }\n 50% {\n opacity: 0.9;\n transform: scale(1.03);\n }\n 100% {\n opacity: 0;\n transform: scale(1.08);\n }\n }\n\n /* Trail effect for cursor movement */\n .demo-cursor-trail {\n position: fixed;\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: rgba(239, 68, 68, 0.4);\n pointer-events: none;\n z-index: 999998;\n animation: demo-trail-fade 0.3s ease-out forwards;\n }\n\n @keyframes demo-trail-fade {\n 0% {\n opacity: 0.6;\n transform: scale(1);\n }\n 100% {\n opacity: 0;\n transform: scale(0.5);\n }\n }\n`;\n\n/**\n * SVG cursor arrow (red with white outline for visibility)\n */\nconst CURSOR_SVG = `\n <svg id=\"demo-cursor-arrow\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M3 3L10.5 21L13 13L21 10.5L3 3Z\" fill=\"#ef4444\" stroke=\"white\" stroke-width=\"2\" stroke-linejoin=\"round\"/>\n </svg>\n`;\n\nconst NAME_HELPER_SCRIPT = `\n(() => {\n if (typeof window.__name !== \"function\") {\n window.__name = (target, value) => {\n try {\n Object.defineProperty(target, \"name\", { value, configurable: true });\n } catch {\n // Ignore failures setting function names.\n }\n return target;\n };\n }\n})();\n`;\n\nconst nameHelperInstalled = new WeakSet<Page>();\n\ninterface DemoCursorAPI {\n setPosition: (x: number, y: number) => void;\n click: () => void;\n highlight: (rect: { x: number; y: number; width: number; height: number }) => void;\n addTrail: (x: number, y: number) => void;\n destroy: () => void;\n}\n\nasync function ensureNameHelper(page: Page): Promise<void> {\n if (!nameHelperInstalled.has(page)) {\n await page.addInitScript({ content: NAME_HELPER_SCRIPT });\n nameHelperInstalled.add(page);\n }\n await page.addScriptTag({ content: NAME_HELPER_SCRIPT });\n}\n\n/**\n * Injects the demo cursor overlay into the page.\n * Call this once after page load.\n */\nexport async function injectCursorOverlay(page: Page): Promise<void> {\n await ensureNameHelper(page);\n await page.addStyleTag({ content: CURSOR_STYLES });\n\n await page.evaluate((cursorSvg) => {\n // Create cursor container\n const cursor = document.createElement(\"div\");\n cursor.id = \"demo-cursor\";\n cursor.innerHTML = cursorSvg;\n cursor.style.left = \"-100px\";\n cursor.style.top = \"-100px\";\n document.body.appendChild(cursor);\n\n // Enable demo cursor mode\n document.documentElement.classList.add(\"demo-cursor-active\");\n\n // Expose functions to window for Playwright to call\n (window as Window & { __demoCursor?: DemoCursorAPI }).__demoCursor = {\n setPosition: (x: number, y: number) => {\n cursor.style.left = `${x}px`;\n cursor.style.top = `${y}px`;\n },\n click: () => {\n const ripple = document.createElement(\"div\");\n ripple.className = \"demo-click-ripple\";\n cursor.appendChild(ripple);\n setTimeout(() => ripple.remove(), 500);\n },\n highlight: (rect: { x: number; y: number; width: number; height: number }) => {\n const ring = document.createElement(\"div\");\n ring.className = \"demo-highlight-ring\";\n ring.style.left = `${rect.x}px`;\n ring.style.top = `${rect.y}px`;\n ring.style.width = `${rect.width}px`;\n ring.style.height = `${rect.height}px`;\n document.body.appendChild(ring);\n setTimeout(() => ring.remove(), 800);\n },\n addTrail: (x: number, y: number) => {\n const trail = document.createElement(\"div\");\n trail.className = \"demo-cursor-trail\";\n trail.style.left = `${x}px`;\n trail.style.top = `${y}px`;\n document.body.appendChild(trail);\n setTimeout(() => trail.remove(), 300);\n },\n destroy: () => {\n cursor.remove();\n document.documentElement.classList.remove(\"demo-cursor-active\");\n // Clean up any remaining trails or highlights\n document.querySelectorAll(\".demo-cursor-trail, .demo-highlight-ring, .demo-click-ripple\").forEach(el => el.remove());\n },\n };\n }, CURSOR_SVG);\n}\n\n/**\n * Smoothly moves the demo cursor to specified coordinates using actual mouse movement.\n * This creates a visible animation in the recorded video.\n */\nexport async function moveCursorTo(\n page: Page,\n x: number,\n y: number,\n options?: { steps?: number; trailEnabled?: boolean }\n): Promise<void> {\n const steps = options?.steps ?? 15;\n const trailEnabled = options?.trailEnabled ?? true;\n\n // Get current cursor position\n const currentPos = await page.evaluate(() => {\n const cursor = document.getElementById(\"demo-cursor\");\n if (!cursor) return { x: 0, y: 0 };\n return {\n x: parseFloat(cursor.style.left) || 0,\n y: parseFloat(cursor.style.top) || 0,\n };\n });\n\n // If starting from off-screen, jump to a reasonable starting position\n if (currentPos.x < 0 || currentPos.y < 0) {\n currentPos.x = x > 100 ? x - 100 : 50;\n currentPos.y = y > 100 ? y - 100 : 50;\n await page.evaluate(\n ([startX, startY]) => {\n const api = (window as Window & { __demoCursor?: DemoCursorAPI }).__demoCursor;\n if (api) api.setPosition(startX, startY);\n },\n [currentPos.x, currentPos.y]\n );\n await page.waitForTimeout(50);\n }\n\n // Animate movement in steps with easing\n for (let i = 1; i <= steps; i++) {\n // Ease-out cubic for smooth deceleration\n const t = i / steps;\n const easeT = 1 - Math.pow(1 - t, 3);\n\n const newX = currentPos.x + (x - currentPos.x) * easeT;\n const newY = currentPos.y + (y - currentPos.y) * easeT;\n\n await page.evaluate(\n ({ posX, posY, addTrail }) => {\n const api = (window as Window & { __demoCursor?: DemoCursorAPI }).__demoCursor;\n if (api) {\n api.setPosition(posX, posY);\n // Add trail effect every few steps\n if (addTrail) {\n api.addTrail(posX + 4, posY + 4);\n }\n }\n },\n { posX: newX, posY: newY, addTrail: trailEnabled && i % 3 === 0 }\n );\n\n await page.waitForTimeout(20);\n }\n\n // Ensure final position is exact\n await page.evaluate(\n ([finalX, finalY]) => {\n const api = (window as Window & { __demoCursor?: DemoCursorAPI }).__demoCursor;\n if (api) api.setPosition(finalX, finalY);\n },\n [x, y]\n );\n\n // Also move the actual mouse to ensure hover states work\n await page.mouse.move(x, y);\n\n // Brief pause at destination\n await page.waitForTimeout(100);\n}\n\n/**\n * Triggers the click ripple animation at the current cursor position.\n */\nexport async function triggerClickRipple(page: Page): Promise<void> {\n await page.evaluate(() => {\n const api = (window as Window & { __demoCursor?: DemoCursorAPI }).__demoCursor;\n if (api) {\n api.click();\n }\n });\n // Wait for ripple animation to be visible\n await page.waitForTimeout(150);\n}\n\n/**\n * Highlights an element with a pulsing ring effect.\n */\nexport async function highlightElement(page: Page, selector: string): Promise<void> {\n const boundingBox = await page.locator(selector).first().boundingBox();\n if (boundingBox) {\n await page.evaluate(\n (rect) => {\n const api = (window as Window & { __demoCursor?: DemoCursorAPI }).__demoCursor;\n if (api) {\n api.highlight(rect);\n }\n },\n {\n x: boundingBox.x - 6,\n y: boundingBox.y - 6,\n width: boundingBox.width + 12,\n height: boundingBox.height + 12,\n }\n );\n }\n}\n\n/**\n * Removes the demo cursor overlay.\n */\nexport async function removeCursorOverlay(page: Page): Promise<void> {\n await page.evaluate(() => {\n const api = (window as Window & { __demoCursor?: DemoCursorAPI }).__demoCursor;\n if (api) {\n api.destroy();\n }\n });\n}\n\n/**\n * Performs a demo click action with visible cursor movement:\n * 1. Moves cursor smoothly to element center\n * 2. Optionally highlights element\n * 3. Triggers click ripple\n * 4. Performs actual click\n */\nexport async function demoClick(\n page: Page,\n selector: string,\n options?: {\n highlight?: boolean;\n delayAfter?: number;\n delayBefore?: number;\n timeoutMs?: number;\n }\n): Promise<void> {\n const element = page.locator(selector).first();\n const timeout = options?.timeoutMs ?? 10000;\n await element.scrollIntoViewIfNeeded();\n await element.waitFor({ state: \"visible\", timeout });\n\n const boundingBox = await element.boundingBox();\n if (!boundingBox) {\n throw new Error(`Element not found or not visible: ${selector}`);\n }\n\n // Calculate center of element\n const centerX = boundingBox.x + boundingBox.width / 2;\n const centerY = boundingBox.y + boundingBox.height / 2;\n\n // Optional delay before moving\n if (options?.delayBefore) {\n await page.waitForTimeout(options.delayBefore);\n }\n\n // Move cursor to element with smooth animation\n await moveCursorTo(page, centerX, centerY, { steps: 20 });\n\n // Optional highlight\n if (options?.highlight) {\n await highlightElement(page, selector);\n await page.waitForTimeout(200);\n }\n\n // Trigger click ripple\n await triggerClickRipple(page);\n\n // Perform actual click\n await element.click({ timeout });\n\n // Wait for ripple animation to complete\n await page.waitForTimeout(200);\n\n // Optional delay after click\n if (options?.delayAfter) {\n await page.waitForTimeout(options.delayAfter);\n }\n}\n\n/**\n * Performs a demo hover action with visible cursor movement.\n */\nexport async function demoHover(\n page: Page,\n selector: string,\n options?: { highlight?: boolean; timeoutMs?: number }\n): Promise<void> {\n const element = page.locator(selector).first();\n const timeout = options?.timeoutMs ?? 10000;\n await element.scrollIntoViewIfNeeded();\n await element.waitFor({ state: \"visible\", timeout });\n\n const boundingBox = await element.boundingBox();\n if (!boundingBox) {\n throw new Error(`Element not found or not visible: ${selector}`);\n }\n\n const centerX = boundingBox.x + boundingBox.width / 2;\n const centerY = boundingBox.y + boundingBox.height / 2;\n\n await moveCursorTo(page, centerX, centerY, { steps: 15 });\n\n if (options?.highlight) {\n await highlightElement(page, selector);\n }\n\n await element.hover({ timeout });\n await page.waitForTimeout(300);\n}\n\n/**\n * Types text with visible cursor at the input location.\n */\nexport async function demoType(\n page: Page,\n selector: string,\n text: string,\n options?: { highlight?: boolean; delayBetweenChars?: number }\n): Promise<void> {\n const element = page.locator(selector).first();\n await element.scrollIntoViewIfNeeded();\n await element.waitFor({ state: \"visible\", timeout: 10000 });\n\n const boundingBox = await element.boundingBox();\n if (!boundingBox) {\n throw new Error(`Element not found or not visible: ${selector}`);\n }\n\n const centerX = boundingBox.x + boundingBox.width / 2;\n const centerY = boundingBox.y + boundingBox.height / 2;\n\n await moveCursorTo(page, centerX, centerY);\n\n if (options?.highlight) {\n await highlightElement(page, selector);\n await page.waitForTimeout(150);\n }\n\n await triggerClickRipple(page);\n await element.click();\n await page.waitForTimeout(100);\n\n // Type with optional delay between characters\n await element.fill(text);\n await page.waitForTimeout(200);\n}\n"],"mappings":"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","names":["path","path","path","fs","path","fs","path","resolve","fs","path"]}