Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
100 commits
Select commit Hold shift + click to select a range
c054fb2
feat: add remotion shell files
CREDO23 Feb 26, 2026
9645a5f
feat: add the remotion player for preview
CREDO23 Feb 26, 2026
d60d066
add video tool prompts
CREDO23 Feb 26, 2026
b22864e
add generate_video tool
CREDO23 Feb 26, 2026
525b611
add video tool __init__
CREDO23 Feb 26, 2026
9ced17a
register generate_video tool
CREDO23 Feb 26, 2026
bf90635
improve video prompts with layout, structure and output rules
CREDO23 Feb 26, 2026
0fe89d8
add generate_video to agent system prompt
CREDO23 Feb 26, 2026
a57a6fd
fix generate_video prompt wording
CREDO23 Feb 26, 2026
29b1d89
add generate_video SSE handling and export
CREDO23 Feb 26, 2026
1bc5324
add generate_video tool UI and register in chat pages
CREDO23 Feb 26, 2026
d7cb087
update chat_deepagent docstring to include generate_video
CREDO23 Feb 26, 2026
38a6e5d
apply formatter fixes
CREDO23 Feb 26, 2026
a6e9d04
rewrite remotion prompt aligned with official template SYSTEM_PROMPT
CREDO23 Feb 26, 2026
311beb8
wire duration_frames from backend result through to Player
CREDO23 Feb 26, 2026
84467ed
add missing type declarations for @babel/standalone and three
CREDO23 Feb 26, 2026
9b8d7b4
fix video-preview error handling: styled states, stable errorFallback…
CREDO23 Feb 26, 2026
ccc142f
refactor video tool and improve remotion prompt
CREDO23 Feb 27, 2026
0d3dc8d
update video tool SSE handler for prompt_ready status
CREDO23 Feb 27, 2026
0e40bf2
add video/generate-code endpoint and register router
CREDO23 Feb 27, 2026
d10ff33
implement client-driven video generation with retry loop
CREDO23 Feb 27, 2026
db815e0
fix permission bug and strengthen remotion prompt rules
CREDO23 Feb 27, 2026
65c5ebf
refactor generate-video into folder with hooks and SRP components
CREDO23 Feb 27, 2026
b803429
harden video lifecycle: single retry loop, AbortController, fix runti…
CREDO23 Feb 27, 2026
a24fdf1
replace component.toString() key with stable generationId counter
CREDO23 Feb 27, 2026
fea68d2
add video_llm_id field and VIDEO role to llm service
CREDO23 Feb 27, 2026
94c6b9b
add video_llm_id to llm preferences schema and routes
CREDO23 Feb 27, 2026
444122a
add skills system and restructure video prompts
CREDO23 Feb 27, 2026
896454b
extract video business logic into service, restructure prompts
CREDO23 Feb 27, 2026
596b393
add video LLM role to frontend contract and settings UI
CREDO23 Feb 27, 2026
f467eea
extract strip_code_fences to shared utility
CREDO23 Feb 27, 2026
816f63f
persist validated video code to DB, fix reload regeneration
CREDO23 Feb 27, 2026
9634a27
improve remotion prompt
CREDO23 Feb 27, 2026
8052175
add reasoning_effort todo for video llm config
CREDO23 Feb 27, 2026
c13a8fe
feat(video): add 9 Remotion example skill files from official template
CREDO23 Feb 28, 2026
78ad9a2
feat(video): expand SKILL_NAMES to include 9 example skill entries
CREDO23 Feb 28, 2026
7faad57
feat(video): add example skill categories to skill detection prompt
CREDO23 Feb 28, 2026
7d63214
refine comments in useVideoLifecycle to be concise and context-only
CREDO23 Feb 28, 2026
f32d7e3
fix duration mismatch by removing MIN_DURATION clamp in extractDuration
CREDO23 Feb 28, 2026
2ec8c8d
add error boundary around Remotion Player to prevent UI crashes
CREDO23 Feb 28, 2026
dd8ecf9
enable reasoning_effort=high for video code generation
CREDO23 Feb 28, 2026
2c03956
add TODO comments for LLM timeout and TOTAL_DURATION validation
CREDO23 Feb 28, 2026
1b791b0
enable drop_params to safely handle models that don't support reasoni…
CREDO23 Feb 28, 2026
5e6c6e9
add official Remotion skills for video agent
CREDO23 Mar 2, 2026
eec73db
add video agent system prompt
CREDO23 Mar 2, 2026
dc18e05
add video agent sandbox and package init
CREDO23 Mar 2, 2026
5a663aa
add video agent tools
CREDO23 Mar 2, 2026
ecff076
move skills to snapshot, clean up sandbox and deepagent
CREDO23 Mar 2, 2026
b3970e5
add structured output schema with success/error fields to video agent
CREDO23 Mar 2, 2026
fd4281d
add video agent API endpoint and MP4 serve route
CREDO23 Mar 2, 2026
2b2bf27
add agent video path with toggle between JIT and rendered MP4
CREDO23 Mar 2, 2026
e572efe
add Daytona snapshot scripts and fix project paths
CREDO23 Mar 2, 2026
d66f4de
fix: correct Daytona base image and snapshot param for Remotion agent
CREDO23 Mar 2, 2026
9677a02
feat: bake official @remotion/skills into snapshot and fix ToolStrategy
CREDO23 Mar 2, 2026
8cbccba
add video pipeline constants module
CREDO23 Mar 3, 2026
ee6c266
add video LLM interaction module
CREDO23 Mar 3, 2026
337f8cd
add video sandbox renderer module
CREDO23 Mar 3, 2026
32ac0b2
add video pipeline orchestrator
CREDO23 Mar 3, 2026
f7901c6
add Remotion skill files to video package
CREDO23 Mar 3, 2026
7d6fdd9
update video package init, prompts, and sandbox
CREDO23 Mar 3, 2026
3a7d49c
rewire chat tool to call backend video pipeline
CREDO23 Mar 3, 2026
82a06c7
simplify video routes and fix stream handler status
CREDO23 Mar 3, 2026
83f2ece
fix snapshot skill description and model list config
CREDO23 Mar 3, 2026
8e867c5
delete old DeepAgent and JIT video backend files
CREDO23 Mar 3, 2026
d70658d
delete old chat tool prompts and skills directories
CREDO23 Mar 3, 2026
8024d21
clean up frontend: remove JIT path and dead Remotion deps
CREDO23 Mar 3, 2026
1643f27
add TS6192 to ignorable TypeScript diagnostics
CREDO23 Mar 4, 2026
433650e
harden sandbox cleanup with retries and stop-before-delete
CREDO23 Mar 4, 2026
838ca87
improve generate_video tool docstring with scene-structured examples
CREDO23 Mar 4, 2026
98e56bc
add detailed user prompt builder for video generation
CREDO23 Mar 4, 2026
1fde6c6
add v2 system prompt with toolkit, patterns, and quality bar
CREDO23 Mar 4, 2026
ed09a8d
add v3 prompt system (experimental, not active)
CREDO23 Mar 4, 2026
d379bae
add v2 annotated example skill files
CREDO23 Mar 4, 2026
3c3d85b
add v3 skill files (AI revolution example + toolkit showcase)
CREDO23 Mar 4, 2026
1f9e13c
wire pipeline to v2 prompts and curated skill files
CREDO23 Mar 4, 2026
4ea4ec2
add snapshot creation and verification scripts
CREDO23 Mar 4, 2026
7f7b6f0
add surfsense_video project scaffold
CREDO23 Mar 5, 2026
20940ea
add grid scene types and VideoInput schema
CREDO23 Mar 5, 2026
bbc3ddc
add grid scene with components extracted from lab
CREDO23 Mar 5, 2026
da09c0e
add category-specific card renderers
CREDO23 Mar 5, 2026
8437bdf
update surfsense_video dependencies
CREDO23 Mar 5, 2026
9c18bae
add theme color system for grid scene
CREDO23 Mar 5, 2026
7e8fcfb
delete obsolete DrawingReveal and ItemScale components
CREDO23 Mar 5, 2026
2e9bcc3
add CardReveal with 5 SVG stroke reveal variants
CREDO23 Mar 5, 2026
30ed7eb
document grid scene timing constants
CREDO23 Mar 5, 2026
376d500
clean variant: remove dead borderShape, document reveal and bg types
CREDO23 Mar 5, 2026
48feec5
refactor GridScene to Element3D cards with Step camera waypoints
CREDO23 Mar 5, 2026
0e5b9bf
refactor ContentItem with CardReveal integration and card bg variants
CREDO23 Mar 5, 2026
39a9d7d
clean category renderers: remove unused props, add doc comments, cent…
CREDO23 Mar 5, 2026
6499068
remove list/keyvalue/step/ranking/comparison from grid, add preview c…
CREDO23 Mar 5, 2026
14700c0
feat: add hierarchy tree scene
CREDO23 Mar 5, 2026
6ad21b1
feat: add list scene
CREDO23 Mar 6, 2026
481be9c
feat: add sequence scene, diversify card styles
CREDO23 Mar 6, 2026
2b326cb
feat: add chart scene with bar, column, pie, donut, line layouts
CREDO23 Mar 6, 2026
e43fbe1
feat: add relation scene with circle, network, dagre layouts
CREDO23 Mar 6, 2026
4d9eb08
feat: add comparison scene with binary, table layouts
CREDO23 Mar 6, 2026
2a313b1
feat: replace grid scene with spotlight, register all scene types
CREDO23 Mar 6, 2026
18b6296
feat: add intro/outro scenes, video compositor, and 2-min demo
CREDO23 Mar 6, 2026
0b87803
refactor: remove old sandbox video pipeline, rename to script_generator
CREDO23 Mar 6, 2026
32aae0e
refactor: use lambda function in teh video ui tool
CREDO23 Mar 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
159 changes: 159 additions & 0 deletions scripts/create_remotion_snapshot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
"""
One-time script to build and register the Remotion Daytona snapshot.

Run from the repo root:
cd surfsense_backend
uv run python ../scripts/create_remotion_snapshot.py

Prerequisites:
- DAYTONA_API_KEY set in surfsense_backend/.env (or exported in shell)
- DAYTONA_API_URL=https://app.daytona.io/api
- DAYTONA_TARGET=us (or eu)

After this script succeeds, add to surfsense_backend/.env:
DAYTONA_REMOTION_SNAPSHOT_ID=remotion-surfsense
"""

import os
import sys
from pathlib import Path

from dotenv import load_dotenv

# Load .env from surfsense_backend (works whether you run from repo root or backend dir)
_here = Path(__file__).parent
for candidate in [_here / "../surfsense_backend/.env", _here / ".env"]:
if candidate.exists():
load_dotenv(candidate)
break

from daytona import CreateSnapshotParams, Daytona, Image, Resources # noqa: E402

SNAPSHOT_NAME = "remotion-surfsense"

# The Daytona sandbox runs as user 'daytona' with home /home/daytona.
# All project files and output must live under this path so they are
# accessible in the running sandbox (files placed outside /home/daytona
# during the Docker build are not visible to the daytona user session).
PROJECT_DIR = "/home/daytona/remotion-project"
OUT_DIR = "/home/daytona/out"
SKILLS_DIR = "/home/daytona/skills"
# Official @remotion/skills package — sparse-cloned during image build.
# Agent reads SKILL.md first (progressive disclosure), then individual rules files.
REMOTION_SKILLS_DIR = f"{SKILLS_DIR}/remotion-best-practices"
REMOTION_SKILLS_REPO = "https://github.com/remotion-dev/remotion.git"
REMOTION_SKILLS_REPO_PATH = "packages/skills/skills/remotion"

# NVM-managed node/npm/npx paths inside daytonaio/sandbox:0.6.0.
# These are stable paths regardless of which Node version NVM has active.
NPM = "/usr/local/share/nvm/current/bin/npm"
NPX = "/usr/local/share/nvm/current/bin/npx"

# Linux shared library dependencies required by Chrome Headless Shell.
# Source: https://remotion.dev/docs/miscellaneous/linux-dependencies
REMOTION_LINUX_DEPS = (
"libnss3 libdbus-1-3 libatk1.0-0 libgbm-dev libasound2 "
"libxrandr2 libxkbcommon-dev libxfixes3 libxcomposite1 "
"libxdamage1 libatk-bridge2.0-0 libpango-1.0-0 libcairo2 libcups2"
)


def build_image() -> Image:
"""
Declaratively build the Remotion sandbox image.

Base image: daytonaio/sandbox:0.6.0
- The Daytona runtime base. Sandboxes always run as user 'daytona'
in /home/daytona — files placed outside that path during the Docker
build are not accessible to the user session.
- Already ships with git, NVM, Node.js, and Python.

Layers (each cached independently by Daytona):
1. Linux shared libraries required by Chrome Headless Shell
2. Clone remotion-dev/template-helloworld into /home/daytona/remotion-project
3. npm install (via NVM's npm)
4. Pre-download Chrome Headless Shell (via NVM's npx)
5. Sparse-clone official @remotion/skills into /home/daytona/skills/remotion-best-practices
6. Pre-create output directory, set daytona ownership
"""
return (
Image.base("daytonaio/sandbox:0.6.0")
.run_commands(
# daytonaio/sandbox runs as a non-root user, so apt-get needs sudo.
# Chrome Headless Shell needs these shared libs on Debian/Ubuntu.
# Do NOT install 'chromium' — Remotion manages its own pinned Chrome.
f"sudo apt-get update && sudo apt-get install -y {REMOTION_LINUX_DEPS}"
" && sudo rm -rf /var/lib/apt/lists/*",
)
.env({"CI": "true"})
.run_commands(
# Clone the Hello World template into the daytona user's home.
# We use Hello World (not blank) so the agent has working reference
# code to read before overwriting it with the generated video.
f"git clone --depth 1"
f" https://github.com/remotion-dev/template-helloworld.git {PROJECT_DIR}",
# Install npm dependencies using NVM's npm (already in the base image).
f"cd {PROJECT_DIR} && {NPM} install",
# Pre-download Remotion's pinned Chrome Headless Shell.
f"cd {PROJECT_DIR} && {NPX} remotion browser ensure",
# Sparse-clone just the @remotion/skills directory from the monorepo.
# --filter=blob:none + --sparse avoids downloading the entire ~400 MB repo.
f"mkdir -p {REMOTION_SKILLS_DIR} {OUT_DIR}"
f" && git clone --depth 1 --filter=blob:none --sparse"
f" {REMOTION_SKILLS_REPO} /tmp/remotion-skills"
f" && cd /tmp/remotion-skills"
f" && git sparse-checkout set {REMOTION_SKILLS_REPO_PATH}"
f" && cp -r {REMOTION_SKILLS_REPO_PATH}/. {REMOTION_SKILLS_DIR}/"
f" && rm -rf /tmp/remotion-skills",
# Overwrite the cloned SKILL.md description so the agent matches this skill
# for every Remotion video task (the upstream description is too generic).
f"python3 -c \""
f"import re, pathlib; "
f"p = pathlib.Path('{REMOTION_SKILLS_DIR}/SKILL.md'); "
f"txt = p.read_text(); "
f"txt = re.sub(r'description:.*', "
f"'description: Use this skill for ALL Remotion video generation tasks. "
f"Contains critical patterns for Sequence/Series timing, spring-physics animations, "
f"chart and SVG layout, component composition, geometry blocks, and common visual bug fixes. "
f"Always read this before writing any Remotion code.', txt); "
f"p.write_text(txt)"
f"\"",
# Give the daytona user ownership of everything we just created.
f"chown -R daytona:daytona {PROJECT_DIR} {OUT_DIR} {SKILLS_DIR}",
)
.cmd(["sleep", "infinity"])
)


def main() -> None:
api_key = os.environ.get("DAYTONA_API_KEY")
if not api_key:
print("ERROR: DAYTONA_API_KEY is not set.", file=sys.stderr)
print("Add it to surfsense_backend/.env or export it in your shell.", file=sys.stderr)
sys.exit(1)

print(f"Building snapshot '{SNAPSHOT_NAME}' …")
print("This takes 5–10 minutes (Chrome Headless Shell download included). Logs stream below:\n")

daytona = Daytona()

daytona.snapshot.create(
CreateSnapshotParams(
name=SNAPSHOT_NAME,
image=build_image(),
resources=Resources(
cpu=2, # 2 vCPU — Remotion renders frames in parallel
memory=4, # 4 GiB — Chrome Headless Shell + Node can use 2 GiB under load
disk=8, # 8 GiB — image + node_modules (~800 MB with Chrome) + MP4 output
),
),
on_logs=lambda chunk: print(chunk, end="", flush=True),
)

print(f"\n\n✅ Snapshot '{SNAPSHOT_NAME}' is ready.")
print("\nAdd this to surfsense_backend/.env:")
print(f" DAYTONA_REMOTION_SNAPSHOT_ID={SNAPSHOT_NAME}")


if __name__ == "__main__":
main()
148 changes: 148 additions & 0 deletions scripts/create_remotion_snapshot_v2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
"""
One-time script to build and register the Remotion Daytona snapshot (V2).

Extends V1 by installing additional npm packages required by prompts_v2:
remotion-bits, culori, lucide-react,
@remotion/paths, @remotion/shapes,
@remotion/layout-utils, @remotion/animation-utils

Run from the repo root:
cd surfsense_backend
uv run python ../scripts/create_remotion_snapshot_v2.py

Prerequisites:
- DAYTONA_API_KEY set in surfsense_backend/.env (or exported in shell)
- DAYTONA_API_URL=https://app.daytona.io/api
- DAYTONA_TARGET=us (or eu)

After this script succeeds, add to surfsense_backend/.env:
DAYTONA_REMOTION_SNAPSHOT_ID=remotion-surfsense-v2
"""

import os
import sys
import time
from pathlib import Path

from dotenv import load_dotenv

_here = Path(__file__).parent
for candidate in [_here / "../surfsense_backend/.env", _here / ".env"]:
if candidate.exists():
load_dotenv(candidate)
break

from daytona import CreateSnapshotParams, Daytona, Image, Resources # noqa: E402

SNAPSHOT_NAME = "remotion-surfsense-v2"
OLD_SNAPSHOT_NAME = "remotion-surfsense"

PROJECT_DIR = "/home/daytona/remotion-project"
OUT_DIR = "/home/daytona/out"

NPM = "/usr/local/share/nvm/current/bin/npm"
NPX = "/usr/local/share/nvm/current/bin/npx"

REMOTION_LINUX_DEPS = (
"libnss3 libdbus-1-3 libatk1.0-0 libgbm-dev libasound2 "
"libxrandr2 libxkbcommon-dev libxfixes3 libxcomposite1 "
"libxdamage1 libatk-bridge2.0-0 libpango-1.0-0 libcairo2 libcups2"
)

V2_PACKAGES = (
"remotion-bits"
" culori"
" lucide-react"
" @remotion/paths"
" @remotion/shapes"
" @remotion/layout-utils"
" @remotion/animation-utils"
" @remotion/google-fonts"
)


def build_image() -> Image:
"""
Build the V2 Remotion sandbox image.

Layers:
1. Linux shared libraries required by Chrome Headless Shell
2. Clone remotion template into /home/daytona/remotion-project
3. npm install (base + V2 packages)
4. Pre-download Chrome Headless Shell
5. Create output directory, set ownership

Skills are NOT included — they live in the backend repo at
surfsense_backend/app/agents/video/skills/ and are loaded by the
pipeline into the system prompt at runtime.
"""
return (
Image.base("daytonaio/sandbox:0.6.0")
.run_commands(
f"sudo apt-get update && sudo apt-get install -y {REMOTION_LINUX_DEPS}"
" && sudo rm -rf /var/lib/apt/lists/*",
)
.env({"CI": "true"})
.run_commands(
f"git clone --depth 1"
f" https://github.com/remotion-dev/template-helloworld.git {PROJECT_DIR}",
f"cd {PROJECT_DIR} && {NPM} install",
f"cd {PROJECT_DIR} && {NPM} install {V2_PACKAGES}",
f"cd {PROJECT_DIR} && {NPX} remotion browser ensure",
f"mkdir -p {OUT_DIR}",
f"chown -R daytona:daytona {PROJECT_DIR} {OUT_DIR}",
)
.cmd(["sleep", "infinity"])
)


def main() -> None:
api_key = os.environ.get("DAYTONA_API_KEY")
if not api_key:
print("ERROR: DAYTONA_API_KEY is not set.", file=sys.stderr)
print("Add it to surfsense_backend/.env or export it in your shell.", file=sys.stderr)
sys.exit(1)

daytona = Daytona()

for name in [OLD_SNAPSHOT_NAME, SNAPSHOT_NAME]:
try:
old = daytona.snapshot.get(name)
print(f"Deleting existing snapshot '{name}' …")
daytona.snapshot.delete(old)
print(f"Deleted '{name}'. Waiting for removal to propagate …")
for attempt in range(30):
time.sleep(2)
try:
daytona.snapshot.get(name)
except Exception:
print(f"Confirmed '{name}' is gone.\n")
break
else:
print(f"WARNING: '{name}' may still exist after 60s. Proceeding anyway.\n")
except Exception:
pass

print(f"Building snapshot '{SNAPSHOT_NAME}' …")
print("This takes 5–10 minutes (Chrome Headless Shell download included). Logs stream below:\n")

daytona.snapshot.create(
CreateSnapshotParams(
name=SNAPSHOT_NAME,
image=build_image(),
resources=Resources(
cpu=2,
memory=4,
disk=8,
),
),
on_logs=lambda chunk: print(chunk, end="", flush=True),
)

print(f"\n\n✅ Snapshot '{SNAPSHOT_NAME}' is ready.")
print("\nAdd this to surfsense_backend/.env:")
print(f" DAYTONA_REMOTION_SNAPSHOT_ID={SNAPSHOT_NAME}")


if __name__ == "__main__":
main()
Loading
Loading