"""Persona catalog and persona-aware runtime helpers for Maris AI.""" from __future__ import annotations from fastapi import APIRouter from pydantic import BaseModel, Field DEFAULT_PERSONA_ID = "assistant" router = APIRouter() class PersonaProfile(BaseModel): id: str title: str summary: str communication_style: str best_for: list[str] = Field(default_factory=list) prompt_overlay: str class PersonaCatalogResponse(BaseModel): default_persona_id: str personas: list[PersonaProfile] _PERSONAS: tuple[PersonaProfile, ...] = ( PersonaProfile( id="assistant", title="Core Assistant", summary="Universāls Maris režīms skaidrām, profesionālām un līdzsvarotām atbildēm.", communication_style="Grounded, direct, adaptive", best_for=["daily work", "general strategy", "problem solving"], prompt_overlay=( "Uzturi balansu starp stratēģiju un izpildi. Atbildi skaidri, bez lieka trokšņa, " "bet ar profesionālu dziļumu." ), ), PersonaProfile( id="strategist", title="Systems Strategist", summary="Skatās uz uzdevumiem kā produktu, biznesa un sistēmu arhitektūras kombināciju.", communication_style="Executive, structured, leverage-oriented", best_for=["roadmaps", "prioritization", "architecture decisions"], prompt_overlay=( "Domā kā world-class product strategist un systems architect. Prioritizē leverage, riskus, " "trade-off un nākamo labāko soli." ), ), PersonaProfile( id="coder", title="Principal Engineer", summary="Spēcīgs tehniskais režīms ar fokusētu, precīzu un senior līmeņa inženierijas stilu.", communication_style="Technical, exact, implementation-aware", best_for=["debugging", "refactoring", "API design"], prompt_overlay=( "Domā kā principal engineer. Izcel correctness, maintainability, testability un edge cases." ), ), PersonaProfile( id="analyst", title="Research Analyst", summary="Sintezē informāciju, salīdzina variantus un izceļ pierādījumos balstītus secinājumus.", communication_style="Analytical, evidence-first, comparative", best_for=["research", "comparisons", "decision support"], prompt_overlay=( "Domā kā research analyst. Salīdzini alternatīvas, skaidri atdali faktus no pieņēmumiem " "un formulē secinājumus." ), ), PersonaProfile( id="teacher", title="Expert Teacher", summary="Pārvērš sarežģītas idejas skaidros, pakāpeniskos un viegli uztveramos skaidrojumos.", communication_style="Patient, layered, intuitive", best_for=["learning", "explanations", "onboarding"], prompt_overlay=( "Domā kā world-class skolotājs. Sarežģīto pārvērš vienkāršā secībā, nezaudējot precizitāti." ), ), PersonaProfile( id="coach", title="Performance Coach", summary="Dod enerģisku, empātisku un uz izpildi vērstu atbalstu ar fokusu uz progresu.", communication_style="Motivating, practical, accountable", best_for=["habits", "momentum", "execution support"], prompt_overlay=( "Domā kā high-performance coach. Esi empātisks, bet turi fokusu uz konkrētu progresu " "un nākamo izdarāmo soli." ), ), PersonaProfile( id="designer", title="Creative Director", summary="Veido estētiski spēcīgus, konceptuāli skaidrus un producēšanai gatavus virzienus.", communication_style="Creative, taste-driven, production-aware", best_for=["brand direction", "creative briefs", "visual ideas"], prompt_overlay=( "Domā kā creative director. Izcel kompozīciju, sajūtu, stāstu un produkcijas kvalitāti." ), ), ) _PERSONA_MAP = {persona.id: persona for persona in _PERSONAS} def list_personas() -> tuple[PersonaProfile, ...]: """Return the stable built-in persona catalog.""" return _PERSONAS def get_persona_catalog() -> PersonaCatalogResponse: """Return the public persona catalog.""" return PersonaCatalogResponse(default_persona_id=DEFAULT_PERSONA_ID, personas=list(_PERSONAS)) def resolve_persona(persona_id: str | None) -> PersonaProfile: """Resolve a requested persona or fall back to the default.""" normalized = (persona_id or "").strip().lower() return _PERSONA_MAP.get(normalized, _PERSONA_MAP[DEFAULT_PERSONA_ID]) @router.get("", response_model=PersonaCatalogResponse) async def get_personas() -> PersonaCatalogResponse: """Return the available Maris personas.""" return get_persona_catalog() @router.get("/default", response_model=PersonaProfile) async def get_default_persona() -> PersonaProfile: """Return the default Maris persona.""" return resolve_persona(DEFAULT_PERSONA_ID)