diff --git a/server.py b/server.py index 1319d4f..7bb8cb0 100644 --- a/server.py +++ b/server.py @@ -1291,6 +1291,42 @@ async def ui_logout(): return response +@app.post("/ui/publish-run/{run_id}", response_class=HTMLResponse) +async def ui_publish_run(run_id: str, request: Request, output_name: str = Form(...)): + """Publish a run to L2 from the web UI.""" + token = request.cookies.get("auth_token") + if not token: + return HTMLResponse('
Not logged in
') + + # Call L2 to publish the run + try: + resp = http_requests.post( + f"{L2_SERVER}/registry/record-run", + json={"run_id": run_id, "output_name": output_name}, + headers={"Authorization": f"Bearer {token}"}, + timeout=10 + ) + if resp.status_code == 400: + error = resp.json().get("detail", "Bad request") + return HTMLResponse(f'
Error: {error}
') + resp.raise_for_status() + result = resp.json() + return HTMLResponse(f''' +
+ Published to L2 as {result["asset"]["name"]} +
+ ''') + except http_requests.exceptions.HTTPError as e: + error_detail = "" + try: + error_detail = e.response.json().get("detail", str(e)) + except Exception: + error_detail = str(e) + return HTMLResponse(f'
Error: {error_detail}
') + except Exception as e: + return HTMLResponse(f'
Error: {e}
') + + @app.get("/ui/runs", response_class=HTMLResponse) async def ui_runs(request: Request): """HTMX partial: list of runs.""" @@ -1557,6 +1593,7 @@ async def ui_detail_page(run_id: str, request: Request): {run.recipe} - {run.run_id[:8]} | Art DAG L1 + @@ -1706,6 +1743,27 @@ async def ui_detail_page(run_id: str, request: Request): html += f'''

Raw JSON

{provenance_json}
+ ''' + + # Add publish section for completed runs + if run.status == "completed" and run.output_hash: + html += f''' +

Publish to L2

+

Register this transformation output on the L2 ActivityPub server.

+
+
+ + +
+ ''' + + html += '''