Store and display full provenance including effect_url
- record-run now stores effect_url, effects_commit, infrastructure in provenance - Asset detail uses stored effect_url (with fallback for older records) - Shows effects commit hash under effect button - Shows infrastructure info (software/hardware) if available 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -6,6 +6,12 @@ ARTDAG_DOMAIN=artdag.rose-ash.com
|
|||||||
# JWT secret for token signing (generate with: openssl rand -hex 32)
|
# JWT secret for token signing (generate with: openssl rand -hex 32)
|
||||||
JWT_SECRET=your-secret-here-generate-with-openssl-rand-hex-32
|
JWT_SECRET=your-secret-here-generate-with-openssl-rand-hex-32
|
||||||
|
|
||||||
|
# L1 server URL for fetching content (images/videos)
|
||||||
|
L1_PUBLIC_URL=https://celery-artdag.rose-ash.com
|
||||||
|
|
||||||
|
# Effects repository URL for linking to effect source code
|
||||||
|
EFFECTS_REPO_URL=https://git.rose-ash.com/art-dag/effects
|
||||||
|
|
||||||
# Notes:
|
# Notes:
|
||||||
# - ARTDAG_USER removed - now multi-actor, each registered user is their own actor
|
# - ARTDAG_USER removed - now multi-actor, each registered user is their own actor
|
||||||
# - ARTDAG_L1 removed - L1 server URL is sent with each request
|
# - L1 URL can also come from provenance data per-asset
|
||||||
|
|||||||
37
server.py
37
server.py
@@ -736,9 +736,17 @@ async def ui_asset_detail(name: str, request: Request):
|
|||||||
inputs = provenance.get("inputs", [])
|
inputs = provenance.get("inputs", [])
|
||||||
l1_run_id = provenance.get("l1_run_id", "")
|
l1_run_id = provenance.get("l1_run_id", "")
|
||||||
rendered_at = provenance.get("rendered_at", "")[:10] if provenance.get("rendered_at") else ""
|
rendered_at = provenance.get("rendered_at", "")[:10] if provenance.get("rendered_at") else ""
|
||||||
|
effects_commit = provenance.get("effects_commit", "")
|
||||||
|
infrastructure = provenance.get("infrastructure", {})
|
||||||
|
|
||||||
# Build effect link
|
# Use stored effect_url or build fallback
|
||||||
effect_url = f"{EFFECTS_REPO_URL}/src/branch/main/{recipe}"
|
effect_url = provenance.get("effect_url")
|
||||||
|
if not effect_url:
|
||||||
|
# Fallback for older records
|
||||||
|
if effects_commit and effects_commit != "unknown":
|
||||||
|
effect_url = f"{EFFECTS_REPO_URL}/src/commit/{effects_commit}/{recipe}"
|
||||||
|
else:
|
||||||
|
effect_url = f"{EFFECTS_REPO_URL}/src/branch/main/{recipe}"
|
||||||
|
|
||||||
# Build inputs display
|
# Build inputs display
|
||||||
inputs_html = ""
|
inputs_html = ""
|
||||||
@@ -752,6 +760,24 @@ async def ui_asset_detail(name: str, request: Request):
|
|||||||
</div>
|
</div>
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
# Infrastructure display
|
||||||
|
infra_html = ""
|
||||||
|
if infrastructure:
|
||||||
|
software = infrastructure.get("software", {})
|
||||||
|
hardware = infrastructure.get("hardware", {})
|
||||||
|
if software or hardware:
|
||||||
|
infra_html = f'''
|
||||||
|
<div class="bg-dark-600 rounded-lg p-4 sm:col-span-2">
|
||||||
|
<h4 class="text-sm font-medium text-gray-400 mb-2">Infrastructure</h4>
|
||||||
|
<div class="text-sm text-gray-300">
|
||||||
|
{f"Software: {software.get('name', 'unknown')}" if software else ""}
|
||||||
|
{f" ({software.get('content_hash', '')[:16]}...)" if software.get('content_hash') else ""}
|
||||||
|
{" | " if software and hardware else ""}
|
||||||
|
{f"Hardware: {hardware.get('name', 'unknown')}" if hardware else ""}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
'''
|
||||||
|
|
||||||
provenance_html = f'''
|
provenance_html = f'''
|
||||||
<div class="border-t border-dark-500 pt-6 mt-6">
|
<div class="border-t border-dark-500 pt-6 mt-6">
|
||||||
<h3 class="text-lg font-semibold text-white mb-4">Provenance</h3>
|
<h3 class="text-lg font-semibold text-white mb-4">Provenance</h3>
|
||||||
@@ -766,6 +792,7 @@ async def ui_asset_detail(name: str, request: Request):
|
|||||||
</svg>
|
</svg>
|
||||||
{recipe}
|
{recipe}
|
||||||
</a>
|
</a>
|
||||||
|
{f'<div class="mt-2 text-xs text-gray-500">Commit: {effects_commit[:12]}...</div>' if effects_commit else ''}
|
||||||
</div>
|
</div>
|
||||||
<div class="bg-dark-600 rounded-lg p-4">
|
<div class="bg-dark-600 rounded-lg p-4">
|
||||||
<h4 class="text-sm font-medium text-gray-400 mb-2">Input(s)</h4>
|
<h4 class="text-sm font-medium text-gray-400 mb-2">Input(s)</h4>
|
||||||
@@ -780,6 +807,7 @@ async def ui_asset_detail(name: str, request: Request):
|
|||||||
<h4 class="text-sm font-medium text-gray-400 mb-2">Rendered</h4>
|
<h4 class="text-sm font-medium text-gray-400 mb-2">Rendered</h4>
|
||||||
<span class="text-white">{rendered_at if rendered_at else 'Unknown'}</span>
|
<span class="text-white">{rendered_at if rendered_at else 'Unknown'}</span>
|
||||||
</div>
|
</div>
|
||||||
|
{infra_html}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
'''
|
'''
|
||||||
@@ -1339,9 +1367,12 @@ async def record_run(req: RecordRunRequest, user: User = Depends(get_required_us
|
|||||||
provenance = {
|
provenance = {
|
||||||
"inputs": [{"content_hash": h} for h in run.get("inputs", [])],
|
"inputs": [{"content_hash": h} for h in run.get("inputs", [])],
|
||||||
"recipe": run.get("recipe"),
|
"recipe": run.get("recipe"),
|
||||||
|
"effect_url": run.get("effect_url"),
|
||||||
|
"effects_commit": run.get("effects_commit"),
|
||||||
"l1_server": l1_url,
|
"l1_server": l1_url,
|
||||||
"l1_run_id": req.run_id,
|
"l1_run_id": req.run_id,
|
||||||
"rendered_at": run.get("completed_at")
|
"rendered_at": run.get("completed_at"),
|
||||||
|
"infrastructure": run.get("infrastructure")
|
||||||
}
|
}
|
||||||
|
|
||||||
# Register the output under the authenticated user
|
# Register the output under the authenticated user
|
||||||
|
|||||||
Reference in New Issue
Block a user