This commit is contained in:
team3
2026-07-13 12:31:25 +02:00
parent 32d7ad9ea1
commit 9cd8e02e22
34 changed files with 747 additions and 606 deletions

View File

@@ -34,6 +34,7 @@ _api_sem = asyncio.Semaphore(MAX_CONCURRENT_API_AGENTS)
_active: dict[str, float] = {} # key → Startzeit (Anzeige)
_prozesse: dict[str, asyncio.subprocess.Process] = {}
_abgebrochen: set[str] = set() # Key-Präfixe abgebrochener Läufe
_pausiert: set[str] = set() # Key-Präfixe sanft pausierter Läufe
# ── Globale 429-Bremse: Backoff pro Call reicht nicht — 28 Parallel-Calls
# kollidieren nach der Wartezeit sofort wieder. Ein 429 drosselt deshalb ALLE:
@@ -108,14 +109,25 @@ def abbrechen(prefix: str) -> None:
_kill(p)
def pausieren(prefix: str) -> None:
"""Sanfte Pause: Wartende + Neue liefern sofort „pausiert", Laufende laufen
aus und ihre Ergebnisse landen noch in der DB (Gegenstück zu abbrechen)."""
_pausiert.add(prefix)
def abbruch_aufheben(prefix: str) -> None:
_abgebrochen.discard(prefix)
_pausiert.discard(prefix)
def _ist_abgebrochen(key: str) -> bool:
return any(key.startswith(p) for p in _abgebrochen)
def _ist_pausiert(key: str) -> bool:
return any(key.startswith(p) for p in _pausiert)
def provider_verfuegbar(provider: str) -> bool:
cfg = PROVIDERS.get(provider)
if not cfg:
@@ -136,6 +148,8 @@ async def run_agent(key: str, prompt: str, timeout: int, *, provider: str,
role: str = "quick", capabilities: str = "none") -> AgentErgebnis:
"""Ein Call. capabilities: none (nur Text) | files (Read/Write/Bash) | full (+Web).
Wirft asyncio.TimeoutError bei Timeout (Infra-Behandlung macht llm.py)."""
if _ist_pausiert(key): # VOR dem Fake-Shortcut — sonst ist Pause untestbar
return AgentErgebnis(1, "", "pausiert")
if os.getenv("CREATOR_FAKE_AGENTS"):
import fake_agents
return await fake_agents.antwort(key, prompt, capabilities)
@@ -154,6 +168,8 @@ async def run_agent(key: str, prompt: str, timeout: int, *, provider: str,
global _api_inflight
warte_start = time.time() # Queue-Zeit getrennt ausweisen (Ledger wait_ms)
async with sem:
if _ist_pausiert(key): # wartete im Semaphor, als die Pause kam
return AgentErgebnis(1, "", "pausiert")
if _ist_abgebrochen(key):
return AgentErgebnis(1, "", "abgebrochen")
_active[key] = time.time()