Presentation Video UI Update Implementation Log
Created: 2026-05-20 07:06 UTC Updated: 2026-05-21 02:49 UTC
Status
Implemented. The setup flow now generates a VO Script Preview through the Mastra narrative path,
suspends at narrative-review, and resumes downstream scene-detail generation from Go To Scene
Details.
flowchart LR
setup["Setup fields"] --> preview["generatePresentationNarrativePreview"]
preview --> suspend["narrative-review suspended"]
suspend --> review["VO Script Preview"]
review --> resume["continuePresentationFromNarrative"]
resume --> editor["Scene Editor"]
Decisions
- Kept Payload schema unchanged and stored narrative review state in
presentationStatusJson.setup.narrativeReview. - Made Set/Bot optional until after
narrativeWorkflow; selected Set, Bot, and default Brand Kit are persisted on resume. - Kept
generatePresentationVideoScenesWithWorkflowas a compatibility path by auto-resuming the new narrative review boundary for older callers. - Removed setup-stage Visuals from the UI and generation payload, while leaving scene-level upload, library selection, replacement, and removal paths intact.
- Implemented the VO Script assistant as setup guidance editing plus narrative preview regeneration; it does not introduce a separate LLM refinement action before rerunning narrative.
- Aligned the OpenAI web search tool key with the native Responses API tool name so Web Sources can be ingested during VO Script Preview generation without being serialized as a function tool choice.
- Made the
Go To Scene Detailsgate use the effective first available Set/Bot when content-store options have loaded but the auto-select state has not settled yet. - Preserved workflow metadata through
narrativeWorkflowand added resume-step fallbacks fromprepare-presentation-run, sonarrative-reviewcan persist selected identity after approval. - Changed web research ingestion to build RAG documents from native web-search text and citations instead of requiring structured model output, and surfaced failed workflow starts with their real error message.
- Guarded Scene Editor background server-action polling so generation-status or RAG-status transport failures render as page errors instead of crashing the client after scenes are created.
- Aligned the app-action presentation compiler with the Mastra compiler by using
genericas the public configpresentation.useCaseIdfallback when no video use case is selected. - Updated the video detail dynamic route to await Next.js 15
paramsbefore readingid. - Fixed deep-linked Presentation Creation hydration so React Strict Mode cleanup does not cancel the first project load and then skip the retry for Step 2 or Step 3 links.
- Fixed the video detail page hydration mismatch by replacing locale-dependent created/updated date rendering with a deterministic UTC formatter.
- Hardened Presentation Creation and Scene Editor server-action calls so transport failures such as
Failed to fetchrender as page/panel errors instead of crashing through the Next.js overlay. - Surfaced persisted scene generation failures from
compilerIssuesas scene-level errors, including visual generation failures that previously only appeared as the generic job message. - Reduced Recent Videos and video detail Payload reads to direct relation hydration (
depth: 1) to avoid walking nested presentation-compilation/media/source relationship graphs during server render. - Moved
projectIddeep-link hydration for Presentation Creation Step 2/3 into the server route so opening/app/create/presentation?projectId=...&step=3no longer depends on an initial browserfetchServerActioncall. - Added use case and content-store options to the server hydration payload and suppressed automatic selected-source status polling for the server-hydrated source set, reducing initial deep-link client server-action POSTs.
- Routed Gemini/Imagen image generation models through the AI SDK Google image provider and aligned metering, queued visual-generation metadata, and regenerate-image action metadata to record the resolved image provider.
- Switched the configured Google image model from the unsupported Gemini preview string to
imagen-4.0-generate-001, because the AI SDK image provider uses Google's imagepredictendpoint rather than Gemini nativegenerateContentimage output. - Narrowed Presentation Creation deep-link hydration and RAG status refreshes to fetch only the
presentation's selected RAG source IDs, and reduced setup-page relation depth for
getPresentation, to avoid pulling the entire workspace source library during Step 2/3 loads. - Added a Google image-model fallback so stale runtime references to unsupported Gemini image-preview
models retry with
imagen-4.0-generate-001instead of failing Scene Editor image regeneration. - Switched shared image generation back to OpenAI GPT Image after the hosted Google account rejected Imagen usage on the current plan.
- Changed
Go To Scene Detailsfor existing presentations without an active suspended narrative run to start a fresh workflow-backed scene generation + compilation pass, replacing prior scene values instead of only recompiling the existing snapshot. - Stopped
getPresentationGenerationStatuspolling from rewriting scenes, compilation snapshots, and presentation records on every 2.5s client poll; it now returns derived scene/job state as a read-only status response.
Files Changed
- Code:
src/app/(frontend)/app/presentation/actions.tssrc/app/(frontend)/app/videos/[id]/page.tsxsrc/lib/ai/generate-image.tssrc/lib/ai/model-config.tssrc/lib/coins/metering.tssrc/components/anuvax/presentation-video/presentation-video-page.tsxsrc/mastra/schemas/config.schema.tssrc/mastra/workflows/presentationvideo.workflow.tssrc/mastra/workflows/sub/narrative.workflow.tssrc/mastra/workflows/sub/rag.workflow.tssrc/mastra/tools/presentation/index.tssrc/mastra/tools/web/index.ts- Tests:
tests/integration/helpers/mock-runtime.tstests/integration/helpers/presentation-harness.tstests/integration/presentation-compile.integration.test.tstests/unit/generate-image-provider.test.tstests/unit/mastra-web-search-tool.test.tstests/e2e/presentation-video.e2e.spec.ts- Docs:
docs/core/PresentationVideoWorkflow.mddocs/state/CurrentImplementationMap.mddocs/state/ServerActionsMap.mddocs/state/WorkflowMap.mddocs/changes/2026-05-20-0706-presentation-video-ui-update/ImplementationPlan.mddocs/changes/2026-05-20-0706-presentation-video-ui-update/ImplementationLog.md
Verification
pnpm exec biome check --write ...on touched code/test files: passed.pnpm typecheck: passed.pnpm exec vitest run --config ./vitest.config.mts tests/unit/mastra-web-search-tool.test.ts: passed, 4 tests.pnpm exec biome check src/mastra/tools/web/index.ts tests/unit/mastra-web-search-tool.test.ts src/app/(frontend)/app/presentation/actions.ts: passed.pnpm exec biome check src/components/anuvax/presentation-video/presentation-video-page.tsx: passed.pnpm typecheckafter Scene Editor polling guard: passed.pnpm exec biome check src/components/anuvax/presentation-video/presentation-video-page.tsxafter Scene Editor polling guard: passed.pnpm exec biome check src/mastra/workflows/presentationvideo.workflow.ts src/mastra/workflows/sub/narrative.workflow.ts: passed.pnpm exec vitest run --config ./vitest.config.mts tests/integration/presentation-compile.integration.test.ts: passed, 8 tests.pnpm exec vitest run --config ./vitest.config.mts tests/integration/presentation-compile.integration.test.tsafter generic use-case polling regression: passed, 9 tests.pnpm typecheckafter generic use-case fallback: passed.pnpm exec biome check src/app/(frontend)/app/presentation/actions.ts tests/integration/presentation-compile.integration.test.ts: passed.pnpm exec biome check 'src/app/(frontend)/app/videos/[id]/page.tsx': passed.pnpm typecheckafter video detail route params fix: passed.pnpm exec biome check src/components/anuvax/presentation-video/presentation-video-page.tsxafter deep-link hydration fix: passed.pnpm typecheckafter deep-link hydration fix: passed.pnpm exec biome check src/components/anuvax/videos/video-project-detail-page.tsxafter video detail timestamp hydration fix: passed.pnpm typecheckafter video detail timestamp hydration fix: passed.pnpm exec biome check 'src/app/(frontend)/app/presentation/actions.ts' 'src/components/anuvax/presentation-video/presentation-video-page.tsx' tests/integration/presentation-compile.integration.test.tsafter server-action transport guards and scene error mapping: passed.pnpm exec vitest run --config ./vitest.config.mts tests/integration/presentation-compile.integration.test.tsafter scene error mapping regression: passed, 9 tests.pnpm typecheckafter server-action transport guards and scene error mapping: passed.pnpm exec biome check 'src/app/(frontend)/app/videos/actions.ts' 'src/app/(frontend)/app/videos/[id]/page.tsx' 'src/components/anuvax/videos/video-project-detail-page.tsx'after video detail Payload depth reduction: passed.pnpm typecheckafter video detail Payload depth reduction: passed.pnpm exec biome check 'src/app/(frontend)/app/create/presentation/page.tsx' 'src/components/anuvax/presentation-video/presentation-video-page.tsx' 'src/app/(frontend)/app/presentation/actions.ts'after server-side create-page deep-link hydration: passed.pnpm exec vitest run --config ./vitest.config.mts tests/integration/presentation-compile.integration.test.tsafter server-side create-page deep-link hydration: passed, 9 tests.pnpm typecheckafter server-side create-page deep-link hydration: passed.pnpm exec biome check 'src/app/(frontend)/app/create/presentation/page.tsx' 'src/components/anuvax/presentation-video/presentation-video-page.tsx'after expanded create-page server hydration: passed.pnpm exec vitest run --config ./vitest.config.mts tests/integration/presentation-compile.integration.test.tsafter expanded create-page server hydration: passed, 9 tests.pnpm typecheckafter expanded create-page server hydration: passed.pnpm exec biome check --write src/lib/ai/generate-image.ts src/lib/ai/model-config.ts src/lib/coins/metering.ts src/mastra/tools/presentation/index.ts 'src/app/(frontend)/app/presentation/actions.ts' tests/unit/generate-image-provider.test.tsafter Gemini image provider routing: passed.pnpm exec vitest run --config ./vitest.config.mts tests/unit/generate-image-provider.test.ts: passed, 1 test.pnpm exec vitest run --config ./vitest.config.mts tests/unit/ai-coin-metering.test.ts: passed, 8 tests.pnpm typecheckafter Gemini image provider routing: passed.pnpm exec biome check --write src/lib/ai/model-config.ts tests/unit/generate-image-provider.test.ts docs/changes/2026-05-20-0706-presentation-video-ui-update/ImplementationLog.mdafter switching to Imagen model id: passed.pnpm exec vitest run --config ./vitest.config.mts tests/unit/generate-image-provider.test.tsafter switching to Imagen model id: passed, 1 test.pnpm exec vitest run --config ./vitest.config.mts tests/unit/ai-coin-metering.test.tsafter switching to Imagen model id: passed, 8 tests.pnpm typecheckafter switching to Imagen model id: passed.pnpm exec biome check src/lib/ai/generate-image.ts tests/unit/generate-image-provider.test.tsafter Google image-model fallback: passed.pnpm exec vitest run --config ./vitest.config.mts tests/unit/generate-image-provider.test.tsafter Google image-model fallback: passed, 2 tests.pnpm typecheckafter Google image-model fallback: passed.pnpm exec biome check src/lib/ai/model-config.ts tests/unit/generate-image-provider.test.tsafter switching back to OpenAI GPT Image: passed.pnpm exec vitest run --config ./vitest.config.mts tests/unit/generate-image-provider.test.tsafter switching back to OpenAI GPT Image: passed, 2 tests.pnpm typecheckafter switching back to OpenAI GPT Image: passed.pnpm exec biome check 'src/app/(frontend)/app/presentation/actions.ts' 'src/components/anuvax/presentation-video/presentation-video-page.tsx' 'tests/integration/presentation-compile.integration.test.ts'after existing-presentation rerun path: passed.pnpm exec vitest run --config ./vitest.config.mts tests/integration/presentation-compile.integration.test.tsafter existing-presentation rerun path: passed, 10 tests.pnpm typecheckafter existing-presentation rerun path: passed.pnpm exec biome check 'src/app/(frontend)/app/presentation/actions.ts'after read-only generation-status polling change: passed.pnpm exec vitest run --config ./vitest.config.mts tests/integration/presentation-compile.integration.test.tsafter read-only generation-status polling change: passed, 10 tests.pnpm typecheckafter read-only generation-status polling change: passed.pnpm test:int: presentation integration tests passed, but the full script failed ontests/unit/anuva-orchestration-service.test.tsat an existing artifact metadata assertion.pnpm exec playwright test tests/e2e/presentation-video.e2e.spec.ts: blocked becauseplaywright.config.tsimports missing packagedotenv.
Remaining Risks
- The full
pnpm lintcommand is still blocked by existing repository-wide Biome issues in docs and generated files outside this change. - Playwright coverage could not run until the local dependency issue for
dotenvis resolved. - The VO Script assistant reruns narrative from updated guidance, but does not yet have a dedicated server-side VO-guidance refinement action.