diff --git a/server.py b/server.py index dca9a50..d00fa6e 100644 --- a/server.py +++ b/server.py @@ -34,7 +34,8 @@ from auth import ( # Configuration DOMAIN = os.environ.get("ARTDAG_DOMAIN", "artdag.rose-ash.com") DATA_DIR = Path(os.environ.get("ARTDAG_DATA", str(Path.home() / ".artdag" / "l2"))) -# Note: L1_SERVER is no longer needed - L1 URL comes with each request +L1_PUBLIC_URL = os.environ.get("L1_PUBLIC_URL", "https://celery-artdag.rose-ash.com") +EFFECTS_REPO_URL = os.environ.get("EFFECTS_REPO_URL", "https://git.rose-ash.com/art-dag/effects") # Ensure data directory exists DATA_DIR.mkdir(parents=True, exist_ok=True) @@ -642,7 +643,7 @@ async def ui_users_page(request: Request): @app.get("/ui/asset/{name}", response_class=HTMLResponse) async def ui_asset_detail(name: str, request: Request): - """Asset detail page.""" + """Asset detail page with content preview and provenance.""" username = get_user_from_cookie(request) registry = load_registry() assets = registry.get("assets", {}) @@ -662,12 +663,56 @@ async def ui_asset_detail(name: str, request: Request): tags = asset.get("tags", []) description = asset.get("description", "") origin = asset.get("origin", {}) + provenance = asset.get("provenance", {}) + metadata = asset.get("metadata", {}) created_at = asset.get("created_at", "")[:10] type_color = "bg-blue-600" if asset_type == "image" else "bg-purple-600" if asset_type == "video" else "bg-gray-600" + # Determine L1 server URL for content + l1_server = provenance.get("l1_server", L1_PUBLIC_URL).rstrip("/") + + # Content display - image or video from L1 + if asset_type == "video": + # Use iOS-compatible MP4 endpoint + content_html = f''' +
+ +
+ + Download Original + +
+
+ ''' + elif asset_type == "image": + content_html = f''' +
+ {name} +
+ + Download + +
+
+ ''' + else: + content_html = f''' +
+

Content type: {asset_type}

+ + Download + +
+ ''' + # Origin display - origin_html = "" + origin_html = 'Not specified' if origin: origin_type = origin.get("type", "unknown") if origin_type == "self": @@ -675,18 +720,69 @@ async def ui_asset_detail(name: str, request: Request): elif origin_type == "external": origin_url = origin.get("url", "") origin_note = origin.get("note", "") - origin_html = f''' - {origin_url} - ''' + origin_html = f'{origin_url}' if origin_note: origin_html += f'

{origin_note}

' # Tags display - tags_html = "" + tags_html = 'No tags' if tags: tags_html = " ".join([f'{t}' for t in tags]) - else: - tags_html = 'No tags' + + # Provenance section - for rendered outputs + provenance_html = "" + if provenance: + recipe = provenance.get("recipe", "") + inputs = provenance.get("inputs", []) + l1_run_id = provenance.get("l1_run_id", "") + rendered_at = provenance.get("rendered_at", "")[:10] if provenance.get("rendered_at") else "" + + # Build effect link + effect_url = f"{EFFECTS_REPO_URL}/src/branch/main/{recipe}" + + # Build inputs display + inputs_html = "" + for inp in inputs: + inp_hash = inp.get("content_hash", "") if isinstance(inp, dict) else inp + if inp_hash: + inputs_html += f''' +
+ {inp_hash[:24]}... +
+ ''' + + provenance_html = f''' +
+

Provenance

+

This asset was created by applying an effect to input content.

+
+ +
+

Input(s)

+ {inputs_html if inputs_html else 'No inputs recorded'} +
+
+

L1 Run

+ {l1_run_id[:16]}... +
+
+

Rendered

+ {rendered_at if rendered_at else 'Unknown'} +
+
+
+ ''' content = f'''

← Back to Registry

@@ -696,6 +792,8 @@ async def ui_asset_detail(name: str, request: Request): {asset_type} + {content_html} +
@@ -703,6 +801,18 @@ async def ui_asset_detail(name: str, request: Request): {owner}
+
+

Description

+

{description if description else 'No description'}

+
+ +
+

Origin

+ {origin_html} +
+
+ +

Content Hash

{content_hash} @@ -712,18 +822,6 @@ async def ui_asset_detail(name: str, request: Request):

Created

{created_at}
-
- -
-
-

Description

-

{description if description else 'No description'}

-
- -
-

Origin

- {origin_html if origin_html else 'Not specified'} -

Tags

@@ -732,11 +830,20 @@ async def ui_asset_detail(name: str, request: Request):
-
-

ActivityPub

-

- Object URL: https://{DOMAIN}/objects/{content_hash} -

+ {provenance_html} + +
+

ActivityPub

+
+

+ Object URL: + https://{DOMAIN}/objects/{content_hash} +

+

+ Owner Actor: + https://{DOMAIN}/users/{owner} +

+
''' return HTMLResponse(base_html(f"Asset: {name}", content, username))