e5f546a72f
Sackgasse behoben: ein Worker blockte eine Aufgabe mit einer Frage (kanban block --kind needs_input), aber die Zentrale zeigte nur den roten Status "haengt - braucht dich" - ohne die Frage und ohne Eingabefeld. Der Worker blieb so dauerhaft stehen. Backend (services/ideen.py): - _blocker_frage(): liest die Worker-Frage aus dem juengsten blocked-Event (payload.reason/kind), Fallback: BLOCKED:-Kommentar. - list_queue() reichert blockierte Karten mit frage + frage_kind an (max 6 Extra-show-Aufrufe pro Poll). - answer_task(): unblock --reason schreibt die Antwort als Kommentar und stellt die Karte auf ready -> Dispatcher spawnt den Worker neu, der die Antwort im Kontext vorfindet. Mit ID-/Laengen-Validierung. Router: POST /api/ideen/antwort. Frontend (AuftragsbuchView): blockierte Karten zeigen die Frage (je nach Grund "Die Box hat eine Frage:" / "kam hier nicht weiter:") plus Antwortfeld + "Antworten & weiter". Fallback-Text ohne Grund. Vertraegt sich mit dem Live-Log-Blick (nur triage/running). Verifiziert: E2E gegen die echte Box-Kanban-CLI (Frage auslesen, answer_task entsperrt + protokolliert, Fehlerpfade), py_compile + Frontend-Build gruen, Antwort-UI im Dev-Server gerendert. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
58 lines
1.3 KiB
Python
58 lines
1.3 KiB
Python
"""Ideen-Queue-Endpoints — dünner REST-Layer über services/ideen.py (natives Hermes-Kanban).
|
|
LAN-only wie alle MC2-Endpoints; das Mensch-Gate bleibt die Karte im Auftragsbuch."""
|
|
|
|
from fastapi import APIRouter, HTTPException
|
|
from pydantic import BaseModel
|
|
|
|
from services import ideen
|
|
|
|
router = APIRouter(prefix="/api")
|
|
|
|
|
|
class IdeeIn(BaseModel):
|
|
titel: str
|
|
notiz: str = ""
|
|
|
|
|
|
class TaskIn(BaseModel):
|
|
id: str
|
|
|
|
|
|
class AntwortIn(BaseModel):
|
|
id: str
|
|
antwort: str
|
|
|
|
|
|
@router.get("/ideen")
|
|
def list_queue() -> dict:
|
|
return ideen.list_queue()
|
|
|
|
|
|
@router.post("/ideen")
|
|
def add_idea(body: IdeeIn) -> dict:
|
|
res = ideen.add_idea(body.titel, body.notiz)
|
|
if not res.get("ok"):
|
|
raise HTTPException(400, res.get("error", "Idee konnte nicht angelegt werden."))
|
|
return res
|
|
|
|
|
|
@router.post("/ideen/antwort")
|
|
def answer(body: AntwortIn) -> dict:
|
|
res = ideen.answer_task(body.id, body.antwort)
|
|
if not res.get("ok"):
|
|
raise HTTPException(400, res.get("error", "Antwort konnte nicht gesendet werden."))
|
|
return res
|
|
|
|
|
|
@router.post("/ideen/archivieren")
|
|
def archive(body: TaskIn) -> dict:
|
|
res = ideen.archive_task(body.id)
|
|
if not res.get("ok"):
|
|
raise HTTPException(400, res.get("error", "Archivieren fehlgeschlagen."))
|
|
return res
|
|
|
|
|
|
@router.get("/ideen/{id}/log")
|
|
def get_log(id: str) -> dict:
|
|
return ideen.log_of(id)
|