"""Steering API — methods, profiles and context (AP1.1 / AP2.0).""" from __future__ import annotations from typing import Optional from capabilities import require_capability from fastapi import APIRouter, Depends, HTTPException, Query from pydantic import BaseModel, Field from method_profiles.registry import list_method_profiles from services import initiatives as initiative_service from services import steering_context as sc_service from steering.context import get_steering_context_dto from steering.methods.registry import list_methods from tenant_context import TenantContext router = APIRouter(prefix="/api/steering", tags=["steering"]) class SteeringContextUpdateRequest(BaseModel): method_key: Optional[str] = Field(default=None, min_length=1) method_profile_key: Optional[str] = Field(default=None, min_length=1) clear_method_profile: bool = False @router.get("/methods") def list_steering_methods( ctx: TenantContext = Depends(require_capability("kairo.initiative.read")), ): _ = ctx return [ { "key": m.key, "version": m.version, "label": m.label, "description": m.description, "next_action_strategy_key": m.next_action_strategy_key, } for m in list_methods() ] @router.get("/method-profiles") def list_steering_method_profiles( initiative_archetype_key: Optional[str] = Query(default=None), ctx: TenantContext = Depends(require_capability("kairo.initiative.read")), ): _ = ctx return [ { "key": p["key"], "label": p["label"], "description": p["description"], "initiative_archetype_key": p["initiative_archetype_key"], "method_key": p["method_key"], } for p in list_method_profiles(initiative_archetype_key=initiative_archetype_key) ] @router.patch("/initiatives/{initiative_id}/context") def patch_initiative_steering_context( initiative_id: str, body: SteeringContextUpdateRequest, ctx: TenantContext = Depends(require_capability("kairo.initiative.manage")), ): initiative = initiative_service.get_initiative( tenant_id=ctx.tenant_id, initiative_id=initiative_id ) if not initiative: raise HTTPException(status_code=404, detail="Vorhaben nicht gefunden") if not body.method_key and not body.method_profile_key and not body.clear_method_profile: raise HTTPException( status_code=400, detail="method_key, method_profile_key oder clear_method_profile erforderlich", ) try: if body.clear_method_profile: sc_service.update_method_profile_key( tenant_id=ctx.tenant_id, initiative_id=initiative_id, method_profile_key=None, user_id=ctx.user_id, ) elif body.method_profile_key: sc_service.update_method_profile_key( tenant_id=ctx.tenant_id, initiative_id=initiative_id, method_profile_key=body.method_profile_key, user_id=ctx.user_id, ) elif body.method_key: sc_service.update_method_key( tenant_id=ctx.tenant_id, initiative_id=initiative_id, method_key=body.method_key, user_id=ctx.user_id, ) except ValueError as exc: raise HTTPException(status_code=400, detail=str(exc)) from exc return get_steering_context_dto(ctx, initiative_id=initiative_id)