fffiloni commited on
Commit
ba8b6e7
·
verified ·
1 Parent(s): bdf80ad

Upload 4 files

Browse files
Files changed (2) hide show
  1. README.md +1 -1
  2. app.py +100 -21
README.md CHANGED
@@ -133,7 +133,7 @@ See `CHANGELOG_V194.md` for the Model Pre-scan Decision Card UI pass.
133
  See `CHANGELOG_V195.md` for the Runtime CSS Cleanup with Legacy Safety Net pass.
134
 
135
 
136
- Current release: Agentic Space Factory v198.26.89.
137
 
138
  ## v198.26.87 — Runs Explorer Badge Rail Alignment
139
 
 
133
  See `CHANGELOG_V195.md` for the Runtime CSS Cleanup with Legacy Safety Net pass.
134
 
135
 
136
+ Current release: Agentic Space Factory v198.26.94.
137
 
138
  ## v198.26.87 — Runs Explorer Badge Rail Alignment
139
 
app.py CHANGED
@@ -11,7 +11,7 @@ from fastapi import FastAPI, HTTPException, Request
11
  from fastapi.responses import HTMLResponse, JSONResponse, FileResponse, RedirectResponse
12
  from huggingface_hub import HfApi, attach_huggingface_oauth
13
 
14
- from src.bucket import RunPaths, check_user_bucket, create_user_bucket, delete_run_folder, read_run_bundle, list_recent_runs, read_json, write_json, write_launch_metadata
15
  from src.config import settings, user_bucket_source
16
  from src.eval_config import activate_eval_archive_config, disable_eval_archive_config, flush_eval_archive_records, public_eval_config
17
  from src.eval_archive import maybe_publish_eval_record
@@ -144,6 +144,53 @@ def _auth_recovery_payload(reason: str = "not_authenticated", detail: str | None
144
  },
145
  }
146
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147
  def _json_error(exc: Exception) -> HTTPException:
148
  if isinstance(exc, HTTPException):
149
  return exc
@@ -707,28 +754,38 @@ def register_custom_routes(fastapi_app: FastAPI) -> None:
707
  payload = _auth_recovery_payload(str(exc.detail), str(exc.detail))
708
  payload["anonymous_eval"] = public_eval_config(None)
709
  return JSONResponse(payload, status_code=401)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
710
  return JSONResponse(
711
  {
712
- "authenticated": True,
713
- "username": ctx["username"],
714
- "profile": {
715
- "name": ctx["profile"].get("name"),
716
- "preferred_username": ctx["profile"].get("preferred_username"),
717
- "picture": ctx["profile"].get("picture"),
718
- "is_pro": ctx.get("is_pro"),
719
- "can_pay": ctx.get("can_pay"),
720
  },
721
- "scopes": ctx.get("scopes", []),
722
- "missing_scopes": ctx.get("missing_scopes", []),
723
- "warnings": ctx.get("warnings", []),
724
- "auth_lifetime": ctx.get("auth_lifetime"),
725
- "anonymous_eval": public_eval_config(ctx["username"] if ctx else None),
726
- "expires_at": ctx.get("expires_at"),
727
- "login_url": "/oauth/huggingface/login",
728
- "refresh_login_url": "/auth/refresh-login",
729
- "reset_url": "/auth/logout-local",
730
- "logout_url": "/auth/logout-local",
731
- }
732
  )
733
 
734
 
@@ -1173,6 +1230,7 @@ def register_custom_routes(fastapi_app: FastAPI) -> None:
1173
  write_json(paths.state, cancelled_state, token=ctx["token"])
1174
  write_json(f"{paths.root}/summary.json", cancelled_summary, token=ctx["token"])
1175
  write_json(f"{paths.root}/cancel.json", cancel_meta, token=ctx["token"])
 
1176
  append_run_event(
1177
  run_id,
1178
  bucket_source=bucket_source,
@@ -1944,6 +2002,28 @@ def _write_parent_linked_validation_state(parent_run_id: str, linked: list[dict[
1944
  linked_payload["effective_status"] = "validated_after_manual_space_test"
1945
  write_json(f"{paths.root}/linked_validations.json", linked_payload, token=token)
1946
  write_json(f"{paths.root}/manual_validation_status.json", manual_status, token=token)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1947
  return {"linked_validations": linked_payload, "manual_validation_status": manual_status}
1948
 
1949
  def create_app() -> FastAPI:
@@ -1970,4 +2050,3 @@ def create_app() -> FastAPI:
1970
 
1971
 
1972
  app = create_app()
1973
-
 
11
  from fastapi.responses import HTMLResponse, JSONResponse, FileResponse, RedirectResponse
12
  from huggingface_hub import HfApi, attach_huggingface_oauth
13
 
14
+ from src.bucket import RunPaths, check_user_bucket, create_user_bucket, delete_run_folder, read_run_bundle, list_recent_runs, read_json, upsert_run_index_entry, write_json, write_launch_metadata
15
  from src.config import settings, user_bucket_source
16
  from src.eval_config import activate_eval_archive_config, disable_eval_archive_config, flush_eval_archive_records, public_eval_config
17
  from src.eval_archive import maybe_publish_eval_record
 
144
  },
145
  }
146
 
147
+
148
+ def _api_me_payload(ctx: dict[str, Any]) -> dict[str, Any]:
149
+ return {
150
+ "authenticated": True,
151
+ "username": ctx["username"],
152
+ "profile": {
153
+ "name": ctx["profile"].get("name"),
154
+ "preferred_username": ctx["profile"].get("preferred_username"),
155
+ "picture": ctx["profile"].get("picture"),
156
+ "is_pro": ctx.get("is_pro"),
157
+ "can_pay": ctx.get("can_pay"),
158
+ },
159
+ "scopes": ctx.get("scopes", []),
160
+ "missing_scopes": ctx.get("missing_scopes", []),
161
+ "warnings": ctx.get("warnings", []),
162
+ "auth_lifetime": ctx.get("auth_lifetime"),
163
+ "anonymous_eval": public_eval_config(ctx["username"] if ctx else None),
164
+ "expires_at": ctx.get("expires_at"),
165
+ "login_url": "/oauth/huggingface/login",
166
+ "refresh_login_url": "/auth/refresh-login",
167
+ "reset_url": "/auth/logout-local",
168
+ "logout_url": "/auth/logout-local",
169
+ }
170
+
171
+
172
+ def _resumable_payload_from_runs(
173
+ runs: list[dict[str, Any]],
174
+ *,
175
+ bucket_source: str,
176
+ token: str | None,
177
+ ) -> dict[str, Any]:
178
+ resumable = find_latest_resumable_run(runs)
179
+ selected = resumable or (runs[0] if runs else None)
180
+ if not selected:
181
+ return {"run": None, "view": None, "bucket_source": bucket_source, "reason": "no_run"}
182
+ run_id = validate_run_id(str(selected.get("run_id")))
183
+ snapshot = _build_live_run_snapshot(run_id, bucket_source=bucket_source, token=token, include_heavy=False)
184
+ return {
185
+ "run": selected,
186
+ "view": snapshot["view"],
187
+ "summary": snapshot["summary"],
188
+ "state": snapshot["state"],
189
+ "bucket_source": bucket_source,
190
+ "reason": "latest_resumable_run" if resumable else "latest_run",
191
+ }
192
+
193
+
194
  def _json_error(exc: Exception) -> HTTPException:
195
  if isinstance(exc, HTTPException):
196
  return exc
 
754
  payload = _auth_recovery_payload(str(exc.detail), str(exc.detail))
755
  payload["anonymous_eval"] = public_eval_config(None)
756
  return JSONResponse(payload, status_code=401)
757
+ return JSONResponse(_api_me_payload(ctx))
758
+
759
+ @fastapi_app.get("/api/bootstrap")
760
+ async def api_bootstrap(request: Request, bucket_name: str = settings.bucket_name, limit: int = 100): # type: ignore[no-untyped-def]
761
+ try:
762
+ ctx = _oauth_context_from_request(request)
763
+ except HTTPException as exc:
764
+ payload = _auth_recovery_payload(str(exc.detail), str(exc.detail))
765
+ payload["anonymous_eval"] = public_eval_config(None)
766
+ return JSONResponse(payload, status_code=401)
767
+ bucket_source = user_bucket_source(username=ctx["username"], bucket_name=bucket_name)
768
+ bucket_status = check_user_bucket(username=ctx["username"], bucket_name=bucket_name, token=ctx["token"])
769
+ runs: list[dict[str, Any]] = []
770
+ resumable = {"run": None, "view": None, "bucket_source": bucket_source, "reason": "bucket_not_ready"}
771
+ if bucket_status.get("ok"):
772
+ runs = list_recent_runs(bucket_source=bucket_source, token=ctx["token"], limit=limit)
773
+ resumable = _resumable_payload_from_runs(runs, bucket_source=bucket_source, token=ctx["token"])
774
  return JSONResponse(
775
  {
776
+ "schema_version": "asf_bootstrap.v1",
777
+ "me": _api_me_payload(ctx),
778
+ "bucket": bucket_status,
779
+ "runs": {
780
+ "runs": runs,
781
+ "bucket_source": bucket_source,
782
+ "bucket_uri": f"hf://buckets/{bucket_source}",
783
+ "limit": limit,
784
  },
785
+ "resumable": resumable,
786
+ "bucket_source": bucket_source,
787
+ },
788
+ headers={"Cache-Control": "no-store, no-cache, must-revalidate", "Pragma": "no-cache"},
 
 
 
 
 
 
 
789
  )
790
 
791
 
 
1230
  write_json(paths.state, cancelled_state, token=ctx["token"])
1231
  write_json(f"{paths.root}/summary.json", cancelled_summary, token=ctx["token"])
1232
  write_json(f"{paths.root}/cancel.json", cancel_meta, token=ctx["token"])
1233
+ upsert_run_index_entry(run_id, bucket_source=bucket_source, summary=cancelled_summary, token=ctx["token"])
1234
  append_run_event(
1235
  run_id,
1236
  bucket_source=bucket_source,
 
2002
  linked_payload["effective_status"] = "validated_after_manual_space_test"
2003
  write_json(f"{paths.root}/linked_validations.json", linked_payload, token=token)
2004
  write_json(f"{paths.root}/manual_validation_status.json", manual_status, token=token)
2005
+ try:
2006
+ index_summary = {
2007
+ "run_id": parent_run_id,
2008
+ "updated_at": linked_payload.get("updated_at"),
2009
+ "linked_validation_count": len(compact),
2010
+ "linked_validations_count": len(compact),
2011
+ }
2012
+ if manual_status.get("status") == "success":
2013
+ index_summary.update({
2014
+ "manual_validation_passed": True,
2015
+ "post_build_status": linked_payload.get("effective_status") or "validated_after_manual_space_test",
2016
+ "effective_status": linked_payload.get("effective_status") or "validated_after_manual_space_test",
2017
+ "latency_seconds": manual_status.get("latency_seconds"),
2018
+ "observed_latency_seconds": manual_status.get("observed_latency_seconds"),
2019
+ "recommended_zero_gpu_duration_seconds": manual_status.get("recommended_zero_gpu_duration_seconds"),
2020
+ "recommendation_source": manual_status.get("recommendation_source") or "linked_space_test",
2021
+ "recommendation_hardware": manual_status.get("recommendation_hardware"),
2022
+ "hardware_used_for_validation": manual_status.get("hardware_used_for_validation"),
2023
+ })
2024
+ upsert_run_index_entry(parent_run_id, bucket_source=bucket_source, summary=index_summary, token=token)
2025
+ except Exception:
2026
+ pass
2027
  return {"linked_validations": linked_payload, "manual_validation_status": manual_status}
2028
 
2029
  def create_app() -> FastAPI:
 
2050
 
2051
 
2052
  app = create_app()