- Add IPFSHLSOutput class that uploads segments to IPFS as they're created
- Update streaming task to use IPFS HLS output for distributed streaming
- Add /ipfs-stream endpoint to get IPFS playlist URL
- Update /stream endpoint to redirect to IPFS when available
- Add GPU persistence mode (STREAMING_GPU_PERSIST=1) to keep frames on GPU
- Add hardware video decoding (NVDEC) support for faster video processing
- Add GPU-accelerated primitive libraries: blending_gpu, color_ops_gpu, geometry_gpu
- Add streaming_gpu module with GPUFrame class for tracking CPU/GPU data location
- Add Dockerfile.gpu for building GPU-enabled worker image
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Update save_run_cache to also update actor_id, recipe, inputs on conflict
- Add logging for actor_id when saving runs to run_cache
- Add admin endpoint DELETE /runs/admin/purge-failed to delete all failed runs
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add /runs/stream POST endpoint for streaming recipes
- Accepts recipe_sexp, sources_sexp, audio_sexp
- Submits to run_stream Celery task
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove legacy_tasks.py, hybrid_state.py, render.py
- Remove old task modules (analyze, execute, execute_sexp, orchestrate)
- Add streaming interpreter from test repo
- Add sexp_effects with primitives and video effects
- Add streaming Celery task with CID-based asset resolution
- Support both CID and friendly name references for assets
- Add .dockerignore to prevent local clones from conflicting
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Use dedicated thread with new event loop for database operations
- Create new database connection per operation to avoid pool conflicts
- Handles both async and sync calling contexts correctly
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Database is the ONLY source of truth for cache_id -> ipfs_cid
- Removed Redis caching layer entirely
- Failures will raise exceptions instead of warning and continuing
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Database (cache_items table) is now source of truth
- Redis used as fast cache on top
- Mapping persists across restarts
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Files in /data/cache/nodes/ are now stored by IPFS CID only
- cache_id parameter creates index from cache_id -> IPFS CID
- Removed deprecated node_id parameter behavior
- get_by_cid(cache_id) still works via index lookup
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
IPFS CIDs are the primary identifiers. If IPFS upload fails,
the operation must fail rather than silently using local hashes.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add plan_cid column to pending_runs table schema
- Add update_pending_run_plan() function to save plan_cid
- Update get_pending_run() to return plan_cid
- Save plan_cid right after storing plan to IPFS (before execution)
- Plan is now available even if run fails
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Upload final output to IPFS after execution completes
- Return success=False if IPFS upload fails
- Previously the run would succeed with output_ipfs_cid=None
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
All callers were passing str(path) but the function expected Path objects,
causing 'str' object has no attribute 'parent' errors when fetching from IPFS.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove effect:identity shortcut executor so effects load from IPFS by CID
- COMPOUND nodes now fall back to generic EFFECT executor for dynamic effects
- EFFECT nodes also fall back to generic executor when specific not found
- Update test assertions to match current implementation
- Raise error instead of silently skipping when effect executor not found
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- EFFECT nodes now handled explicitly like SOURCE, COMPOUND, SEQUENCE
- Case-insensitive node type matching throughout
- Fallback executor lookup tries both upper and original case
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Uses FFmpeg concat demuxer. Falls back to re-encoding if
stream copy fails (different codecs/formats).
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Celery task "succeeds" (no exception) but may return {"success": False}.
Now we check the task result's success field AND output_cid before
marking run as completed.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Failed runs were not showing in UI/CLI because list_runs only
included runs with status "pending" or "running", excluding "failed".
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The dog effect was updated to use process() but DogExecutor
was still importing the old effect_dog() function.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Bug: S-expression plans produce lowercase node types (source, compound)
but code was checking uppercase (SOURCE, COMPOUND).
Fix: Use .upper() for node type comparisons.
Add TestNodeTypeCaseSensitivity tests to catch this regression.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- execute_recipe now returns success=False if output_cid is None
- Add TestRecipeOutputRequired tests to catch missing output
- Recipe must produce valid output to be considered successful
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Tests cover:
- SOURCE node resolution (fixed CID vs user input)
- COMPOUND node filter chain handling
- Cache lookup by code-addressed cache_id vs IPFS CID
- All plan step types (SOURCE, EFFECT, COMPOUND, SEQUENCE)
- Error handling for missing inputs
These tests would have caught the bugs:
- "No executor for node type: SOURCE"
- "No executor for node type: COMPOUND"
- Cache lookup failures by code-addressed hash
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>