All checks were successful
Deploy Development / deploy (push) Successful in 46s
Test Suite / pytest-backend (push) Successful in 39s
Test Suite / lint-backend (push) Successful in 0s
Test Suite / build-frontend (push) Successful in 13s
Test Suite / k6 /health Baseline (push) Successful in 33s
Test Suite / playwright-tests (push) Successful in 1m18s
- Introduced `load_and_render_ai_prompt` and `render_ai_prompt_template_for_row` in `ai_prompt_runtime` to streamline prompt loading and rendering processes. - Added `AiPromptUnavailableError` for better error handling when prompts are inactive or missing. - Created `ai_prompt_job` module with `ExerciseFormAiPromptContext` and `resolve_exercise_form_variables` to support admin preview functionality. - Updated documentation and target architecture to reflect changes in the AI prompt system. - Incremented application version to 0.8.160 and updated changelog accordingly.
59 lines
1.9 KiB
Python
59 lines
1.9 KiB
Python
"""
|
|
KI-Prompt Jobs: validierter Kontext (Pydantic) + Zugriff auf gemeinsame Resolver.
|
|
|
|
Importiert exercise_ai nur fuer Platzhalter-Builder — Router importieren dieses Modul oder exercise_ai,
|
|
nicht umgekehrt von exercise_ai nach ai_prompt_job (Zirkel vermeiden).
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from typing import Dict, List, Optional, Tuple
|
|
|
|
from pydantic import BaseModel, Field
|
|
|
|
from exercise_ai import build_exercise_placeholder_variables
|
|
|
|
|
|
class ExerciseFormAiFocusRow(BaseModel):
|
|
"""Fokusbereich fuer Skill-Retrieval-Kontext (wie ExerciseAiFocusCtx / Admin-Preview)."""
|
|
|
|
focus_area_id: int = Field(..., ge=1)
|
|
is_primary: Optional[bool] = False
|
|
|
|
|
|
class ExerciseFormAiPromptContext(BaseModel):
|
|
"""
|
|
Eingabe fuer Uebungsbezogene Prompts (Kurzfassung / Skill-JSON-Vorschlag).
|
|
Entspricht fachlich dem Preview-Body unter /api/admin/ai-prompts/*/preview.
|
|
"""
|
|
|
|
title: Optional[str] = ""
|
|
goal: Optional[str] = None
|
|
execution: Optional[str] = None
|
|
focus_hint: Optional[str] = None
|
|
focus_areas_context: Optional[List[ExerciseFormAiFocusRow]] = None
|
|
|
|
def focus_area_tuples(self) -> Optional[List[Tuple[int, bool]]]:
|
|
if not self.focus_areas_context:
|
|
return None
|
|
return [(int(x.focus_area_id), bool(x.is_primary)) for x in self.focus_areas_context]
|
|
|
|
|
|
def resolve_exercise_form_variables(cur, slug: str, ctx: ExerciseFormAiPromptContext) -> Dict[str, str]:
|
|
"""Baut die Mustache-Map fuer exercise_summary / exercise_skill_suggestions."""
|
|
return build_exercise_placeholder_variables(
|
|
cur,
|
|
slug=slug,
|
|
title=(ctx.title or "").strip(),
|
|
goal=ctx.goal,
|
|
execution=ctx.execution,
|
|
focus_area_hint=ctx.focus_hint,
|
|
focus_areas_context=ctx.focus_area_tuples(),
|
|
)
|
|
|
|
|
|
__all__ = [
|
|
"ExerciseFormAiFocusRow",
|
|
"ExerciseFormAiPromptContext",
|
|
"resolve_exercise_form_variables",
|
|
]
|