- Added /download/client endpoint to serve the CLI client tarball
- Added "Client" link to navigation in base template
- Created build-client.sh script to clone and package the client
- Updated Dockerfile to run build-client.sh during container build
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
SOURCE nodes with config.asset now get content_hash from registry.
EFFECT nodes with config.effect now get effect_hash from registry.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Updated cache detail button from "Publish to IPFS" to "Share to L2"
- Added Share to L2 button on recipe detail page
- Added Share to L2 button on run detail page
- Created /recipes/{id}/publish endpoint
- Created /runs/{id}/publish endpoint (publishes run output)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The template expects recipe.steps and recipe.yaml but the recipe
data has dag.nodes. Convert nodes (list or dict) to steps format
and add YAML dump for source display.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Removed /run/{id} and /recipe/{id} redirect routes
- Updated templates to use /runs/ and /recipes/ paths
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The /run/{id} and /recipe/{id} redirects were calling route handlers
directly without passing the required service dependencies.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Made recipe and inputs optional in RunStatus model
- Convert DAG nodes from list format to dict format when running recipes
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Updated requirements.txt to use art-common@11aa056 with l2_server field
- All routers now import UserContext from artdag_common
- Removed duplicate UserContext from auth_service.py
- dependencies.py sets l2_server from settings on user context
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fixes AttributeError when running recipes - the UserContext was
missing the l2_server field that run_service expects.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Template used recipe.id but service returns recipe.recipe_id
- Add recipe count to home page stats
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The CLI client sends multipart file uploads but the server expected JSON.
Changed the /recipes/upload endpoint to accept UploadFile and return
the additional fields (name, version, variable_inputs, fixed_inputs)
that the client expects.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Detect actual MIME type from file content and store it instead of
generic "media" type. This enables proper media categorization
and filtering in the UI.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Use content_hash instead of hash
- Use type instead of media_type
- Show filename instead of size_bytes
- Detect media type from both type field and filename extension
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
New version defaults actor_id to @username when not in token,
and supports both artdag_session and auth_token cookies.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
list_cache_items doesn't accept actor_id parameter.
Use get_user_items which properly filters by actor_id and item_type.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Process all node_results after DAG execution
- Store each intermediate/effect output in cache_manager
- Upload all node outputs to IPFS (not just final output)
- Track node_hashes and node_ipfs_cids mappings
- Save run result to database with run_id
- Include nodes with content_hash + ipfs_cid in provenance
- Return node_hashes and node_ipfs_cids in task result
All DAG nodes are now content-addressable via /cache/{content_hash}
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Recipes: Now content-addressed only (cache + IPFS), removed Redis storage
- Runs: Completed runs stored in PostgreSQL, Redis only for task_id mapping
- Add list_runs_by_actor() to database.py for paginated run queries
- Add list_by_type() to cache_manager for filtering by node_type
- Fix upload endpoint to return size and filename fields
- Fix recipe run endpoint with proper DAG input binding
- Fix get_run_service() dependency to pass database module
Storage architecture:
- Redis: Ephemeral only (sessions, task mappings with TTL)
- PostgreSQL: Permanent records (completed runs, metadata)
- Cache: Content-addressed files (recipes, media, outputs)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Replace 6847-line monolithic server.py with 26-line entry point
- All routes now in app/routers/ using Jinja2 templates
- Add plan_node.html template for step details
- Add plan node route to runs router with cache_id lookup
- Backup old server as server_legacy.py
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Changed node click to use cache_id in URL instead of step_id
- Updated route to lookup step by cache_id
- Added input media previews showing thumbnails of each input step
- Enhanced output preview with video/image/audio support
- Added parameters section showing step config
- Updated JavaScript to pass cacheId when clicking nodes
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use await directly instead of asyncio.to_thread() since the
function is already async.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Provides /help index and /help/{doc_name} routes to view
L1 server and Common library READMEs in the web UI.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
/docs now correctly points to FastAPI's Swagger API docs.
README files can be viewed directly in the git repository.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add load_plan_for_run_with_fallback() that generates plan from recipe
when not found in cache
- Share this helper between plan page and node detail endpoint
- Removes code duplication
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add load_plan_for_run() helper that tries plan_id first, then matches by inputs
- Fix "plan not found" error when clicking plan nodes
- Add inline DAG visualization to recipe detail page with tabs (DAG View / YAML Source)
- Recipe page now uses render_page_with_cytoscape for proper DAG rendering
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Update README with comprehensive documentation covering IPFS-primary mode,
3-phase execution, storage providers, and all API endpoints
- Add /docs routes to serve markdown documentation as styled HTML
- Include common library documentation in web interface
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements HybridStateManager providing fast local Redis operations
with background IPNS sync for eventual consistency across L1 nodes.
- hybrid_state.py: Centralized state management (cache, claims, analysis, plans, runs)
- Updated execute_cid.py, analyze_cid.py, orchestrate_cid.py to use state manager
- Background IPNS sync (configurable interval, disabled by default)
- Atomic claiming with Redis SETNX for preventing duplicate work
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add /run/{run_id}/plan/node/{step_id} endpoint for node details
- Node click updates URL without full page reload (pushState)
- Browser back/forward works correctly
- Refreshing page preserves selected node via ?node= parameter
- Node details loaded via fetch with partial HTML response
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Reads from environment or .env file.
Must be same on server and workers for consistent cache_ids.
Generate with: openssl rand -hex 32
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>