fix(admin-scrape): ge=1 on count param + enforce LLM finish_reason (#review-followup)
Some checks failed
CI / changes (push) Has been cancelled
CI / backend-tests (push) Has been cancelled
CI / frontend-tests (push) Has been cancelled
CI / openapi-codegen-check (push) Has been cancelled
CI / backend-tests (pull_request) Has been cancelled
CI / frontend-tests (pull_request) Has been cancelled
CI / openapi-codegen-check (pull_request) Has been cancelled
CI / changes (pull_request) Has been cancelled

- admin_scrape.py /failures limit: ge=0 → ge=1 (returning 0 rows is nonsensical for a list endpoint)
- orchestrator.py: check result.finish_reason after ok=True; 'length'/'content_filter' and any
  other non-stop reason triggers deterministic fallback with reason=finish_reason:<value>
  (LLMResult docstring mandated this but no consumer enforced it)
This commit is contained in:
bot-backend 2026-06-17 21:23:13 +03:00
parent f55e83a150
commit 145dc62e0b
2 changed files with 14 additions and 4 deletions

View file

@ -268,7 +268,7 @@ def revoke_task(
def list_failures(
db: Annotated[Session, Depends(get_db)],
run_id: int | None = None,
limit: int = Query(default=50, ge=0),
limit: int = Query(default=50, ge=1),
) -> list[dict[str, Any]]:
"""Per-request failure log for manual browser verification."""
where = ""
@ -1284,9 +1284,7 @@ _FRESHNESS_SOURCES: list[FreshnessSource] = [
]
def _classify_freshness(
age_days: float | None, fresh_days: float, stale_days: float
) -> str:
def _classify_freshness(age_days: float | None, fresh_days: float, stale_days: float) -> str:
"""fresh / stale / critical / unknown по возрасту последнего успешного прогона."""
if age_days is None:
return "unknown"

View file

@ -165,6 +165,18 @@ def orchestrate_chat(
continue
# Нет tool_calls → финальная проза.
# Проверяем finish_reason: 'length' / 'content_filter' означают обрезанный
# или отфильтрованный ответ — неполная проза клиенту не отдаётся (LLMResult
# docstring §64: «консьюмер ОБЯЗАН проверять даже при ok=True»).
if result.finish_reason not in (None, "stop", "end_turn", "tool_calls"):
logger.warning(
"chat: non-stop finish_reason=%r for cad=%s run=%s → deterministic fallback",
result.finish_reason,
cad_num,
run_id,
)
return _deterministic(report_dict, message, f"finish_reason:{result.finish_reason}")
answer = (result.content or "").strip()
if not answer:
# Модель вернула пустоту — пустой ответ клиенту не отдаём, деградируем.