diff --git a/backend/apps/agents/manager/run/handle_run_error.py b/backend/apps/agents/manager/run/handle_run_error.py index 7e0185f9..0f7cf3cf 100644 --- a/backend/apps/agents/manager/run/handle_run_error.py +++ b/backend/apps/agents/manager/run/handle_run_error.py @@ -78,6 +78,7 @@ async def handle_run_error(e: Exception, session: AgentSession, session_id: str, submit_diagnostic({ "kind": "context_overflow", "where": "manager.run.handle_run_error", + "flight": flight_recorder.build_envelope(session_id, "context_overflow", "overflow", session.model, "stream" if turn.current_turn_emitted else "spawn", -1), "session_id": session_id, "model": session.model, "provider": session.provider, @@ -221,6 +222,18 @@ async def handle_run_error(e: Exception, session: AgentSession, session_id: str, reason = "anthropic_auth_invalid" error_msg = Message(role="system", content=friendly_msg, branch_id=session.active_branch_id) session.messages.append(error_msg) + try: + from backend.apps.service.client import submit_diagnostic + submit_diagnostic({ + "kind": "model_error", + "subkind": "auth", + "model": session.model, + "provider": session.provider, + "error_preview": redact_for_telemetry(str(e), limit=400), + "flight": flight_recorder.build_envelope(session_id, "model_error", reason, session.model, "stream" if turn.current_turn_emitted else "spawn", -1), + }) + except Exception: + logger.debug("submit_diagnostic auth failed", exc_info=True) await ws_manager.send_to_session(session_id, "agent:auth_error", { "session_id": session_id, "reason": reason, diff --git a/backend/apps/nine_router/process.py b/backend/apps/nine_router/process.py index 5a54718c..ded135ba 100644 --- a/backend/apps/nine_router/process.py +++ b/backend/apps/nine_router/process.py @@ -463,6 +463,12 @@ async def death_watch(proc_handle: "subprocess.Popen[Any]") -> None: logger.warning("9Router died 3x in 60s; leaving revival to the backed-off watchdog") return logger.warning("9Router process died; instant revive") + # The revive IS a safety net firing; the near-miss ledger counts it so router flap rates are queryable. + try: + from backend.apps.service.client import submit_diagnostic + submit_diagnostic({"kind": "recovered", "subkind": "router-revive"}) + except Exception: + pass p_is_running_last_ok = 0.0 await ensure_running()