Kairo-Jinkendo/backend/routers/steering.py
Lars efb45a3ee6
Some checks failed
Test Suite / pytest-backend (push) Failing after 2s
Test Suite / k6 /api/health Baseline (push) Has been skipped
Test Suite / playwright-smoke (push) Has been skipped
Test Suite / lint-backend (push) Successful in 3s
Test Suite / compose-smoke (push) Has been skipped
Deploy Development / deploy (push) Failing after 50s
Erfassen und Transparent: Archetyp, Methode und Auspraegung in der UI sichtbar.
Method-Profiles-API und Auswahl beim Anlegen/Profil; Steuerungs-Meta in Listen und Plan; Projekt-Archetyp-Spiegel, Next-Action-Links und Umlaut-Fix fuer testbare Guidance.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-10 12:36:12 +02:00

105 lines
3.5 KiB
Python

"""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)