Codex commited on
Commit
6553273
·
1 Parent(s): 7e5ba8c

Bridge HF auth into Music Forge

Browse files
champion_continuum/deck/continuum_music_forge.py CHANGED
@@ -2,6 +2,7 @@ from __future__ import annotations
2
 
3
  import base64
4
  from hashlib import sha256
 
5
  import json
6
  import os
7
  import re
@@ -56,6 +57,41 @@ def _optional_gradio_client():
56
  return Client, ""
57
 
58
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  def _slug(value: str, fallback: str = "song") -> str:
60
  value = re.sub(r"[^A-Za-z0-9_.-]+", "-", (value or "").strip()).strip("-._")
61
  return (value or fallback)[:80]
@@ -77,6 +113,7 @@ def _write_failure_receipt(
77
  prompt: str = "",
78
  payload: Any = None,
79
  started: float | None = None,
 
80
  ) -> dict[str, Any]:
81
  """Make failed generation attempts inspectable instead of leaving empty dirs."""
82
  run_dir.mkdir(parents=True, exist_ok=True)
@@ -91,6 +128,7 @@ def _write_failure_receipt(
91
  "api_name": api_name,
92
  "title": title,
93
  "prompt_sha256": sha256((prompt or "").encode("utf-8")).hexdigest(),
 
94
  "payload_preview": _json_preview(payload),
95
  "error_type": type(error).__name__ if isinstance(error, Exception) else "GenerationError",
96
  "error": detail,
@@ -106,6 +144,7 @@ def _write_failure_receipt(
106
  "run_dir": str(run_dir),
107
  "failure_path": str(failure_path),
108
  "saved_files": [],
 
109
  }
110
 
111
 
@@ -291,6 +330,7 @@ def music_forge_state() -> dict[str, Any]:
291
  "output_dir": str(OUTPUT_ROOT),
292
  "gradio_client_available": Client is not None,
293
  "gradio_client_error": import_error,
 
294
  "public_backends": PUBLIC_MUSIC_BACKENDS,
295
  "call_order": [
296
  "continuum_music_compose_packet",
@@ -356,12 +396,12 @@ def hf_space_schema(space_id: str) -> dict[str, Any]:
356
  "detail": import_error,
357
  "install": "pip install gradio_client",
358
  }
359
- client = Client(space_id)
360
  try:
361
  api = client.view_api(return_format="dict")
362
  except TypeError:
363
  api = client.view_api()
364
- return {"status": "ok", "space_id": space_id, "api": api}
365
 
366
 
367
  def _ace_step_v15_generation_kwargs(prompt: str, lyrics: str, duration: float, seed: int) -> dict[str, Any]:
@@ -538,8 +578,9 @@ def generate_hf_space_song(
538
  payload=payload,
539
  started=started,
540
  ) | {"install": "pip install gradio_client"}
 
541
  try:
542
- client = Client(space_id)
543
  attempts = 0
544
  while True:
545
  attempts += 1
@@ -564,6 +605,7 @@ def generate_hf_space_song(
564
  prompt=prompt,
565
  payload=failure_payload,
566
  started=started,
 
567
  )
568
 
569
  saved_files = _hash_saved_files(_collect_audio_outputs(result, run_dir, name_hint=_slug(run_title, "song")))
@@ -573,6 +615,7 @@ def generate_hf_space_song(
573
  "title": run_title,
574
  "prompt_sha256": sha256((prompt or "").encode("utf-8")).hexdigest(),
575
  "artifact_sha256": [item.get("sha256") for item in saved_files if item.get("sha256")],
 
576
  }
577
  manifest = {
578
  "schema": "champion-continuum/music-generation/v1",
@@ -587,6 +630,7 @@ def generate_hf_space_song(
587
  "title": run_title,
588
  "prompt": prompt,
589
  "payload_json": payload,
 
590
  "duration_sec": round(time.time() - started, 3),
591
  "saved_files": saved_files,
592
  "result_preview": _json_preview(result),
@@ -598,5 +642,6 @@ def generate_hf_space_song(
598
  "run_dir": str(run_dir),
599
  "manifest_path": str(manifest_path),
600
  "saved_files": saved_files,
 
601
  "result_preview": manifest["result_preview"],
602
  }
 
2
 
3
  import base64
4
  from hashlib import sha256
5
+ import inspect
6
  import json
7
  import os
8
  import re
 
57
  return Client, ""
58
 
59
 
60
+ def _hf_token() -> str:
61
+ for name in ("HF_TOKEN", "HUGGINGFACE_HUB_TOKEN", "HUGGINGFACEHUB_API_TOKEN"):
62
+ token = os.environ.get(name)
63
+ if token and token.strip():
64
+ return token.strip()
65
+ return ""
66
+
67
+
68
+ def _client_auth_kwargs(Client: Any) -> dict[str, str]:
69
+ token = _hf_token()
70
+ if not token:
71
+ return {}
72
+ try:
73
+ parameters = inspect.signature(Client).parameters
74
+ except (TypeError, ValueError): # pragma: no cover - signature can be opaque in wrappers
75
+ return {"token": token}
76
+ if "token" in parameters:
77
+ return {"token": token}
78
+ if "hf_token" in parameters:
79
+ return {"hf_token": token}
80
+ if any(param.kind == inspect.Parameter.VAR_KEYWORD for param in parameters.values()):
81
+ return {"token": token}
82
+ return {}
83
+
84
+
85
+ def _space_client(Client: Any, space_id: str) -> tuple[Any, bool]:
86
+ auth_kwargs = _client_auth_kwargs(Client)
87
+ if not auth_kwargs:
88
+ return Client(space_id), False
89
+ try:
90
+ return Client(space_id, **auth_kwargs), True
91
+ except TypeError:
92
+ return Client(space_id), False
93
+
94
+
95
  def _slug(value: str, fallback: str = "song") -> str:
96
  value = re.sub(r"[^A-Za-z0-9_.-]+", "-", (value or "").strip()).strip("-._")
97
  return (value or fallback)[:80]
 
113
  prompt: str = "",
114
  payload: Any = None,
115
  started: float | None = None,
116
+ hf_token_used: bool = False,
117
  ) -> dict[str, Any]:
118
  """Make failed generation attempts inspectable instead of leaving empty dirs."""
119
  run_dir.mkdir(parents=True, exist_ok=True)
 
128
  "api_name": api_name,
129
  "title": title,
130
  "prompt_sha256": sha256((prompt or "").encode("utf-8")).hexdigest(),
131
+ "hf_token_used": bool(hf_token_used),
132
  "payload_preview": _json_preview(payload),
133
  "error_type": type(error).__name__ if isinstance(error, Exception) else "GenerationError",
134
  "error": detail,
 
144
  "run_dir": str(run_dir),
145
  "failure_path": str(failure_path),
146
  "saved_files": [],
147
+ "hf_token_used": bool(hf_token_used),
148
  }
149
 
150
 
 
330
  "output_dir": str(OUTPUT_ROOT),
331
  "gradio_client_available": Client is not None,
332
  "gradio_client_error": import_error,
333
+ "hf_token_configured": bool(_hf_token()),
334
  "public_backends": PUBLIC_MUSIC_BACKENDS,
335
  "call_order": [
336
  "continuum_music_compose_packet",
 
396
  "detail": import_error,
397
  "install": "pip install gradio_client",
398
  }
399
+ client, hf_token_used = _space_client(Client, space_id)
400
  try:
401
  api = client.view_api(return_format="dict")
402
  except TypeError:
403
  api = client.view_api()
404
+ return {"status": "ok", "space_id": space_id, "hf_token_used": hf_token_used, "api": api}
405
 
406
 
407
  def _ace_step_v15_generation_kwargs(prompt: str, lyrics: str, duration: float, seed: int) -> dict[str, Any]:
 
578
  payload=payload,
579
  started=started,
580
  ) | {"install": "pip install gradio_client"}
581
+ hf_token_used = False
582
  try:
583
+ client, hf_token_used = _space_client(Client, space_id)
584
  attempts = 0
585
  while True:
586
  attempts += 1
 
605
  prompt=prompt,
606
  payload=failure_payload,
607
  started=started,
608
+ hf_token_used=hf_token_used,
609
  )
610
 
611
  saved_files = _hash_saved_files(_collect_audio_outputs(result, run_dir, name_hint=_slug(run_title, "song")))
 
615
  "title": run_title,
616
  "prompt_sha256": sha256((prompt or "").encode("utf-8")).hexdigest(),
617
  "artifact_sha256": [item.get("sha256") for item in saved_files if item.get("sha256")],
618
+ "hf_token_used": hf_token_used,
619
  }
620
  manifest = {
621
  "schema": "champion-continuum/music-generation/v1",
 
630
  "title": run_title,
631
  "prompt": prompt,
632
  "payload_json": payload,
633
+ "hf_token_used": hf_token_used,
634
  "duration_sec": round(time.time() - started, 3),
635
  "saved_files": saved_files,
636
  "result_preview": _json_preview(result),
 
642
  "run_dir": str(run_dir),
643
  "manifest_path": str(manifest_path),
644
  "saved_files": saved_files,
645
+ "hf_token_used": hf_token_used,
646
  "result_preview": manifest["result_preview"],
647
  }
continuum_music_forge.py CHANGED
@@ -2,6 +2,7 @@ from __future__ import annotations
2
 
3
  import base64
4
  from hashlib import sha256
 
5
  import json
6
  import os
7
  import re
@@ -56,6 +57,41 @@ def _optional_gradio_client():
56
  return Client, ""
57
 
58
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  def _slug(value: str, fallback: str = "song") -> str:
60
  value = re.sub(r"[^A-Za-z0-9_.-]+", "-", (value or "").strip()).strip("-._")
61
  return (value or fallback)[:80]
@@ -77,6 +113,7 @@ def _write_failure_receipt(
77
  prompt: str = "",
78
  payload: Any = None,
79
  started: float | None = None,
 
80
  ) -> dict[str, Any]:
81
  """Make failed generation attempts inspectable instead of leaving empty dirs."""
82
  run_dir.mkdir(parents=True, exist_ok=True)
@@ -91,6 +128,7 @@ def _write_failure_receipt(
91
  "api_name": api_name,
92
  "title": title,
93
  "prompt_sha256": sha256((prompt or "").encode("utf-8")).hexdigest(),
 
94
  "payload_preview": _json_preview(payload),
95
  "error_type": type(error).__name__ if isinstance(error, Exception) else "GenerationError",
96
  "error": detail,
@@ -106,6 +144,7 @@ def _write_failure_receipt(
106
  "run_dir": str(run_dir),
107
  "failure_path": str(failure_path),
108
  "saved_files": [],
 
109
  }
110
 
111
 
@@ -291,6 +330,7 @@ def music_forge_state() -> dict[str, Any]:
291
  "output_dir": str(OUTPUT_ROOT),
292
  "gradio_client_available": Client is not None,
293
  "gradio_client_error": import_error,
 
294
  "public_backends": PUBLIC_MUSIC_BACKENDS,
295
  "call_order": [
296
  "continuum_music_compose_packet",
@@ -356,12 +396,12 @@ def hf_space_schema(space_id: str) -> dict[str, Any]:
356
  "detail": import_error,
357
  "install": "pip install gradio_client",
358
  }
359
- client = Client(space_id)
360
  try:
361
  api = client.view_api(return_format="dict")
362
  except TypeError:
363
  api = client.view_api()
364
- return {"status": "ok", "space_id": space_id, "api": api}
365
 
366
 
367
  def _ace_step_v15_generation_kwargs(prompt: str, lyrics: str, duration: float, seed: int) -> dict[str, Any]:
@@ -538,8 +578,9 @@ def generate_hf_space_song(
538
  payload=payload,
539
  started=started,
540
  ) | {"install": "pip install gradio_client"}
 
541
  try:
542
- client = Client(space_id)
543
  attempts = 0
544
  while True:
545
  attempts += 1
@@ -564,6 +605,7 @@ def generate_hf_space_song(
564
  prompt=prompt,
565
  payload=failure_payload,
566
  started=started,
 
567
  )
568
 
569
  saved_files = _hash_saved_files(_collect_audio_outputs(result, run_dir, name_hint=_slug(run_title, "song")))
@@ -573,6 +615,7 @@ def generate_hf_space_song(
573
  "title": run_title,
574
  "prompt_sha256": sha256((prompt or "").encode("utf-8")).hexdigest(),
575
  "artifact_sha256": [item.get("sha256") for item in saved_files if item.get("sha256")],
 
576
  }
577
  manifest = {
578
  "schema": "champion-continuum/music-generation/v1",
@@ -587,6 +630,7 @@ def generate_hf_space_song(
587
  "title": run_title,
588
  "prompt": prompt,
589
  "payload_json": payload,
 
590
  "duration_sec": round(time.time() - started, 3),
591
  "saved_files": saved_files,
592
  "result_preview": _json_preview(result),
@@ -598,5 +642,6 @@ def generate_hf_space_song(
598
  "run_dir": str(run_dir),
599
  "manifest_path": str(manifest_path),
600
  "saved_files": saved_files,
 
601
  "result_preview": manifest["result_preview"],
602
  }
 
2
 
3
  import base64
4
  from hashlib import sha256
5
+ import inspect
6
  import json
7
  import os
8
  import re
 
57
  return Client, ""
58
 
59
 
60
+ def _hf_token() -> str:
61
+ for name in ("HF_TOKEN", "HUGGINGFACE_HUB_TOKEN", "HUGGINGFACEHUB_API_TOKEN"):
62
+ token = os.environ.get(name)
63
+ if token and token.strip():
64
+ return token.strip()
65
+ return ""
66
+
67
+
68
+ def _client_auth_kwargs(Client: Any) -> dict[str, str]:
69
+ token = _hf_token()
70
+ if not token:
71
+ return {}
72
+ try:
73
+ parameters = inspect.signature(Client).parameters
74
+ except (TypeError, ValueError): # pragma: no cover - signature can be opaque in wrappers
75
+ return {"token": token}
76
+ if "token" in parameters:
77
+ return {"token": token}
78
+ if "hf_token" in parameters:
79
+ return {"hf_token": token}
80
+ if any(param.kind == inspect.Parameter.VAR_KEYWORD for param in parameters.values()):
81
+ return {"token": token}
82
+ return {}
83
+
84
+
85
+ def _space_client(Client: Any, space_id: str) -> tuple[Any, bool]:
86
+ auth_kwargs = _client_auth_kwargs(Client)
87
+ if not auth_kwargs:
88
+ return Client(space_id), False
89
+ try:
90
+ return Client(space_id, **auth_kwargs), True
91
+ except TypeError:
92
+ return Client(space_id), False
93
+
94
+
95
  def _slug(value: str, fallback: str = "song") -> str:
96
  value = re.sub(r"[^A-Za-z0-9_.-]+", "-", (value or "").strip()).strip("-._")
97
  return (value or fallback)[:80]
 
113
  prompt: str = "",
114
  payload: Any = None,
115
  started: float | None = None,
116
+ hf_token_used: bool = False,
117
  ) -> dict[str, Any]:
118
  """Make failed generation attempts inspectable instead of leaving empty dirs."""
119
  run_dir.mkdir(parents=True, exist_ok=True)
 
128
  "api_name": api_name,
129
  "title": title,
130
  "prompt_sha256": sha256((prompt or "").encode("utf-8")).hexdigest(),
131
+ "hf_token_used": bool(hf_token_used),
132
  "payload_preview": _json_preview(payload),
133
  "error_type": type(error).__name__ if isinstance(error, Exception) else "GenerationError",
134
  "error": detail,
 
144
  "run_dir": str(run_dir),
145
  "failure_path": str(failure_path),
146
  "saved_files": [],
147
+ "hf_token_used": bool(hf_token_used),
148
  }
149
 
150
 
 
330
  "output_dir": str(OUTPUT_ROOT),
331
  "gradio_client_available": Client is not None,
332
  "gradio_client_error": import_error,
333
+ "hf_token_configured": bool(_hf_token()),
334
  "public_backends": PUBLIC_MUSIC_BACKENDS,
335
  "call_order": [
336
  "continuum_music_compose_packet",
 
396
  "detail": import_error,
397
  "install": "pip install gradio_client",
398
  }
399
+ client, hf_token_used = _space_client(Client, space_id)
400
  try:
401
  api = client.view_api(return_format="dict")
402
  except TypeError:
403
  api = client.view_api()
404
+ return {"status": "ok", "space_id": space_id, "hf_token_used": hf_token_used, "api": api}
405
 
406
 
407
  def _ace_step_v15_generation_kwargs(prompt: str, lyrics: str, duration: float, seed: int) -> dict[str, Any]:
 
578
  payload=payload,
579
  started=started,
580
  ) | {"install": "pip install gradio_client"}
581
+ hf_token_used = False
582
  try:
583
+ client, hf_token_used = _space_client(Client, space_id)
584
  attempts = 0
585
  while True:
586
  attempts += 1
 
605
  prompt=prompt,
606
  payload=failure_payload,
607
  started=started,
608
+ hf_token_used=hf_token_used,
609
  )
610
 
611
  saved_files = _hash_saved_files(_collect_audio_outputs(result, run_dir, name_hint=_slug(run_title, "song")))
 
615
  "title": run_title,
616
  "prompt_sha256": sha256((prompt or "").encode("utf-8")).hexdigest(),
617
  "artifact_sha256": [item.get("sha256") for item in saved_files if item.get("sha256")],
618
+ "hf_token_used": hf_token_used,
619
  }
620
  manifest = {
621
  "schema": "champion-continuum/music-generation/v1",
 
630
  "title": run_title,
631
  "prompt": prompt,
632
  "payload_json": payload,
633
+ "hf_token_used": hf_token_used,
634
  "duration_sec": round(time.time() - started, 3),
635
  "saved_files": saved_files,
636
  "result_preview": _json_preview(result),
 
642
  "run_dir": str(run_dir),
643
  "manifest_path": str(manifest_path),
644
  "saved_files": saved_files,
645
+ "hf_token_used": hf_token_used,
646
  "result_preview": manifest["result_preview"],
647
  }
tests/test_continuum.py CHANGED
@@ -147,6 +147,45 @@ def test_music_generation_retries_transient_remote_failure(tmp_path: Path, monke
147
  assert Path(result["saved_files"][0]["path"]).exists()
148
 
149
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
  def test_resonance_audio_falls_back_when_requested_backend_has_no_audio(tmp_path: Path, monkeypatch) -> None:
151
  import sys
152
  import types
 
147
  assert Path(result["saved_files"][0]["path"]).exists()
148
 
149
 
150
+ def test_music_generation_uses_hf_token_without_persisting_secret(tmp_path: Path, monkeypatch) -> None:
151
+ import base64
152
+
153
+ import continuum_music_forge as forge
154
+
155
+ seen: list[dict[str, object]] = []
156
+
157
+ class TokenClient:
158
+ def __init__(self, space_id: str, token: str | None = None) -> None:
159
+ seen.append({"space_id": space_id, "token": token})
160
+
161
+ def predict(self, *_args, **_kwargs) -> str:
162
+ payload = base64.b64encode(b"RIFF token wav").decode("ascii")
163
+ return f"data:audio/wav;base64,{payload}"
164
+
165
+ monkeypatch.setenv("HF_TOKEN", "hf_test_secret")
166
+ monkeypatch.delenv("HUGGINGFACE_HUB_TOKEN", raising=False)
167
+ monkeypatch.delenv("HUGGINGFACEHUB_API_TOKEN", raising=False)
168
+ monkeypatch.setattr(forge, "OUTPUT_ROOT", tmp_path / "music_outputs")
169
+ monkeypatch.setattr(forge, "_optional_gradio_client", lambda: (TokenClient, ""))
170
+
171
+ result = forge.generate_hf_space_song(
172
+ space_id="example/token-space",
173
+ prompt="test prompt",
174
+ payload_json='{"api_name":"/generate","args":["test prompt"]}',
175
+ api_name="/generate",
176
+ title="Token Song",
177
+ )
178
+
179
+ assert seen == [{"space_id": "example/token-space", "token": "hf_test_secret"}]
180
+ assert result["status"] == "ok"
181
+ assert result["hf_token_used"] is True
182
+ manifest_path = Path(result["manifest_path"])
183
+ manifest_text = manifest_path.read_text(encoding="utf-8")
184
+ manifest = json.loads(manifest_text)
185
+ assert manifest["hf_token_used"] is True
186
+ assert "hf_test_secret" not in manifest_text
187
+
188
+
189
  def test_resonance_audio_falls_back_when_requested_backend_has_no_audio(tmp_path: Path, monkeypatch) -> None:
190
  import sys
191
  import types