Fix Lyria silent failures and surface generation status in the player.
Robust candidate-part parsing, quota-aware errors, live composing feedback, and two new desert dub tracks in the library. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -33,6 +33,7 @@ app.add_middleware(
|
||||
_config: Config | None = None
|
||||
_queue: RadioQueue | None = None
|
||||
_generating = False
|
||||
_generation_state: dict = {"busy": False, "phase": None, "error": None, "track_title": None}
|
||||
_chat = ChatStore()
|
||||
|
||||
|
||||
@@ -66,6 +67,7 @@ def _dashboard_stats(cfg: Config) -> dict:
|
||||
"costs": rs.costs.__dict__ | {"per_track_estimate_usd": per_track},
|
||||
"playback": rs.playback.__dict__,
|
||||
"projected_daily_max_usd": round(per_track * rs.limits.max_new_songs_per_day, 2),
|
||||
"generation": dict(_generation_state),
|
||||
}
|
||||
|
||||
|
||||
@@ -87,17 +89,29 @@ def _play_library_entry(q: RadioQueue, cfg: Config, entry: dict) -> dict:
|
||||
return {"status": "ok", "source": "library", "track": np.__dict__ if np else None}
|
||||
|
||||
|
||||
def _set_generation(*, busy: bool, phase: str | None = None, error: str | None = None, title: str | None = None) -> None:
|
||||
global _generation_state
|
||||
_generation_state = {
|
||||
"busy": busy,
|
||||
"phase": phase,
|
||||
"error": error,
|
||||
"track_title": title,
|
||||
}
|
||||
|
||||
|
||||
async def _compose_track(request: str | None = None, *, check_limit: bool = True) -> dict:
|
||||
global _generating
|
||||
if _generating:
|
||||
return {"status": "busy", "message": "Already generating a track"}
|
||||
return {"status": "busy", "message": "Already generating a track", "generation": _generation_state}
|
||||
|
||||
_generating = True
|
||||
_set_generation(busy=True, phase="planning", error=None)
|
||||
try:
|
||||
cfg = _get_config()
|
||||
if check_limit:
|
||||
ok, budget = _can_generate_today(cfg)
|
||||
if not ok:
|
||||
_set_generation(busy=False)
|
||||
return {
|
||||
"status": "limit",
|
||||
"message": f"Daily limit reached ({budget['max_per_day']} new songs)",
|
||||
@@ -110,6 +124,7 @@ async def _compose_track(request: str | None = None, *, check_limit: bool = True
|
||||
plan = await DeepSeekDJ(cfg).plan_next(
|
||||
taste, q.recent_titles, seeds, request=vibe or None
|
||||
)
|
||||
_set_generation(busy=True, phase="composing", title=plan.title)
|
||||
track = LyriaEngine(cfg).generate(plan)
|
||||
q.add(track)
|
||||
rs = load_radio_settings(lyria_model=cfg.lyria_model)
|
||||
@@ -117,6 +132,7 @@ async def _compose_track(request: str | None = None, *, check_limit: bool = True
|
||||
record_generation(cfg.output_dir, cost, track.plan.id, track.plan.title)
|
||||
np = q.now_playing()
|
||||
_, budget = _can_generate_today(cfg)
|
||||
_set_generation(busy=False)
|
||||
return {
|
||||
"status": "ok",
|
||||
"source": "generated",
|
||||
@@ -125,6 +141,10 @@ async def _compose_track(request: str | None = None, *, check_limit: bool = True
|
||||
"cost_usd": cost,
|
||||
"budget": budget,
|
||||
}
|
||||
except Exception as exc:
|
||||
message = str(exc)
|
||||
_set_generation(busy=False, error=message)
|
||||
return {"status": "error", "message": message, "generation": _generation_state}
|
||||
finally:
|
||||
_generating = False
|
||||
|
||||
@@ -285,7 +305,7 @@ async def chat_with_dj(body: ChatRequest, background: BackgroundTasks) -> dict:
|
||||
ok, _ = _can_generate_today(cfg)
|
||||
if ok:
|
||||
result["generating"] = True
|
||||
background.add_task(_compose_track, reply.vibe_hint or None)
|
||||
background.add_task(_background_compose, reply.vibe_hint or None)
|
||||
else:
|
||||
result["reply"] += " (Daily new-song limit reached — playing saved tracks only.)"
|
||||
|
||||
@@ -347,6 +367,13 @@ async def player_page() -> HTMLResponse:
|
||||
return HTMLResponse("<h1>Live Ozan Radio</h1><p>gateway/player.html missing</p>")
|
||||
|
||||
|
||||
async def _background_compose(request: str | None = None) -> None:
|
||||
"""Chat-triggered generation — never raises; errors land in _generation_state."""
|
||||
result = await _compose_track(request)
|
||||
if result.get("status") == "error":
|
||||
_chat.add("dj", f"Couldn't finish that track: {result.get('message', 'unknown error')}")
|
||||
|
||||
|
||||
async def _autofill_queue(target: int = 2) -> None:
|
||||
"""Background: keep a small buffer of generated tracks."""
|
||||
while True:
|
||||
|
||||
Reference in New Issue
Block a user