fix: absolute imports and type annotations in app.py

- replace implicit relative imports with absolute ones (from backend.*)
- add type hints for lifespan tasks list and middleware
- fix unused bool return value in task.cancel() call
This commit is contained in:
Hitonabi
2026-07-06 20:06:40 +02:00
parent 3a6e3c5432
commit b95530ee70
7 changed files with 465 additions and 16 deletions
+96
View File
@@ -0,0 +1,96 @@
#!/usr/bin/env bash
# Worker — Ein-Schuss-Arbeitsauftrag an ein bestimmtes Worker-Modell (llama-swap, SERIELL).
# Das Gegenstueck zu fremdblick.sh: fremdblick KRITISIERT, worker ARBEITET. Beide sind eine
# EINZELNE Completion an eine ECHTE llama-swap-Modell-ID (kein Gateway-Alias, kein delegate_task)
# → umgeht Hermes' 64K-Delegations-Floor (MINIMUM_CONTEXT_LENGTH) und das Laden grosser Modelle
# neben dem Warm-Set liegt bewusst in DEINER Hand.
#
# WICHTIG (harte Speicher-Falle): Waehle nur Worker, die KLEIN neben dem Warm-Set laden.
# v1-Palette = Qwen3-Coder-Next (128k, code-stark, laedt klein). NIEMALS "heavy"/gpt-oss-120b
# als Worker: 60 GB stirbt beim Laden neben dem VL-30B-Warm-Set (Health-Check-Timeout) und
# gefaehrdet Lucys ~1-s-Sprech-Latenz.
#
# Der Worker ist ZUSTANDSLOS: kein Gedaechtnis, keine Datei-Haende. Er bekommt GENAU den Kontext,
# den du ihm auf stdin gibst, und liefert TEXT zurueck (Datei-Inhalt / Diff / Plan). Das SCHREIBEN
# in Dateien macht der Manager (Hermes) danach mit seinen eigenen Tools.
#
# Nutzung: printf '%s' "$teiltask_mit_kontext" | WORKER_ROLE=build worker.sh > /tmp/out.py
# printf '%s' "$spec" | WORKER_MODEL=Qwen3-Coder-Next WORKER_ROLE=build worker.sh
#
# Env-Overrides:
# WORKER_MODEL echte llama-swap-ID (Default: Qwen3-Coder-Next). NICHT gpt-oss/heavy (siehe oben).
# WORKER_ROLE build (Default) | refactor | plan | prose — waehlt das System-Raster.
# WORKER_SYS eigenes System-Raster (uebersteuert WORKER_ROLE).
# WORKER_MAXTOK max_tokens (Default 4000 — Code braucht Platz).
# WORKER_TEMP temperature (Default 0.1 — deterministisch fuer Code).
set -uo pipefail
# Achtung: llama-swap listet unter /v1/models die ECHTEN Modell-IDs, nicht die Gateway-Aliase
# (kein "heavy"/"coder"/"scout" hier — die echte ID nehmen).
ENDPOINT="${WORKER_ENDPOINT:-http://127.0.0.1:8080/v1/chat/completions}"
MODEL="${WORKER_MODEL:-Qwen3-Coder-Next}"
ROLE="${WORKER_ROLE:-build}"
MAXTOK="${WORKER_MAXTOK:-4000}"
TEMP="${WORKER_TEMP:-0.1}"
TASK="$(cat)"
if [ -z "${TASK// /}" ]; then
echo "=== WORKER: nichts zu tun (leere Eingabe) ===" >&2
exit 2
fi
# Aufruf-Protokoll: Nachweis, dass wirklich delegiert wurde (der Manager kann sich das nicht
# ausdenken) + Beobachtbarkeit eines Orchestrator-Laufs. Best-effort, blockiert nie.
LOGF="${WORKER_LOG:-$HOME/.hermes/logs/worker.log}"
mkdir -p "$(dirname "$LOGF")" 2>/dev/null || true
printf '%s\tmodel=%s\trole=%s\tbytes=%s\tfirst=%s\n' \
"$(date +%Y-%m-%dT%H:%M:%S)" "$MODEL" "$ROLE" "${#TASK}" \
"$(printf '%s' "$TASK" | tr '\n\t' ' ' | cut -c1-90)" >> "$LOGF" 2>/dev/null || true
# Bau-Raster: liefert NUR das Artefakt, keine Prosa, kein Markdown-Zaun (Manager schreibt es 1:1 in eine Datei).
BUILD_SYS='Du bist ein fokussierter Umsetzungs-Worker in einem Fliessband. Du bekommst EINEN abgegrenzten Teil-Auftrag mit allem noetigen Kontext. Erledige GENAU diesen Teil — nicht mehr, nicht weniger. Du bist ZUSTANDSLOS: nutze NUR den mitgelieferten Kontext, erfinde keine Datei-Inhalte, keine Pfade und keine APIs dazu; fehlt dir etwas Entscheidendes, schreibe als EINZIGE Ausgabe eine Zeile "FEHLT: <was genau>" statt zu raten. Uebernimm den Stil des umgebenden Codes (Sprache der Kommentare, bestehende Muster, Einrueckung). Gib NUR das geforderte Artefakt aus (den vollstaendigen Datei-Inhalt bzw. den unified Diff), OHNE Vorrede, OHNE ```-Codezaun, OHNE Erklaerung danach.'
# Refactor: wie build, aber betont Verhalten-erhalten.
REFACTOR_SYS='Du bist ein fokussierter Refactor-Worker. Du bekommst bestehenden Code und einen klaren Umbau-Auftrag. Erhalte das beobachtbare Verhalten exakt; aendere nur, was der Auftrag verlangt. Du bist ZUSTANDSLOS: nutze NUR den mitgelieferten Kontext; fehlt Entscheidendes, gib nur "FEHLT: <was>" aus. Gib NUR den vollstaendigen neuen Datei-Inhalt bzw. den Diff aus, OHNE Prosa, OHNE ```-Codezaun.'
# Plan-Raster: knappe, umsetzbare Schrittliste (kein Code). In v1 plant meist der Manager selbst; optional.
PLAN_SYS='Du bist ein knapper Umsetzungs-Planer. Zerlege den Auftrag in eine kurze, nummerierte Liste konkreter Schritte — je 1 Zeile: welche Datei, was passiert. Keine Prosa drumherum, KEIN Code, keine Alternativen-Diskussion.'
# Prosa-Raster: Text-/Recherche-Teiltask.
PROSE_SYS='Du bist ein fokussierter Text-Worker. Erledige den Schreib-/Recherche-Teilauftrag knapp und sachlich auf Deutsch, ausschliesslich mit dem mitgelieferten Kontext. Keine Ausschmueckung, keine erfundenen Fakten.'
case "$ROLE" in
build) SYS="${WORKER_SYS:-$BUILD_SYS}" ;;
refactor) SYS="${WORKER_SYS:-$REFACTOR_SYS}" ;;
plan) SYS="${WORKER_SYS:-$PLAN_SYS}" ;;
prose) SYS="${WORKER_SYS:-$PROSE_SYS}" ;;
*) SYS="${WORKER_SYS:-$BUILD_SYS}" ;;
esac
RESP="$(jq -n --arg m "$MODEL" --arg s "$SYS" --arg u "$TASK" --argjson t "$MAXTOK" --argjson temp "$TEMP" \
'{model:$m, temperature:$temp, max_tokens:$t, messages:[{role:"system",content:$s},{role:"user",content:$u}]}' \
| curl -s --max-time 300 "$ENDPOINT" -H 'Content-Type: application/json' -d @- 2>/dev/null)"
OUT="$(printf '%s' "$RESP" | jq -r '.choices[0].message.content // empty' 2>/dev/null)"
FIN="$(printf '%s' "$RESP" | jq -r '.choices[0].finish_reason // empty' 2>/dev/null)"
# Code-Modelle wickeln die Ausgabe trotz Anweisung gern in einen ```-Codezaun. stdout soll aber ein
# DIREKT schreibbares Artefakt sein → einen umschliessenden Zaun entfernen (nur wenn die erste UND
# die letzte nicht-leere Zeile ein Zaun ist — der uebliche Wrap-Fall; interne Zaeune bleiben unberuehrt).
OUT="$(printf '%s' "$OUT" | awk '
{ l[NR]=$0 }
END {
f=0; last=0
for (i=1;i<=NR;i++) if (l[i] ~ /[^[:space:]]/) { if (!f) f=i; last=i }
if (f && l[f] ~ /^[[:space:]]*```/ && l[last] ~ /^[[:space:]]*```[[:space:]]*$/ && f!=last)
{ for (i=f+1;i<last;i++) print l[i] }
else
{ for (i=1;i<=NR;i++) print l[i] }
}')"
if [ -n "$OUT" ]; then
printf '%s\n' "$OUT"
# Abschneide-Warnung auf stderr (stdout bleibt sauberes Artefakt).
[ "$FIN" = "length" ] && echo "=== WORKER-HINWEIS: Ausgabe bei max_tokens ($MAXTOK) ABGESCHNITTEN — WORKER_MAXTOK erhoehen ODER den Teil-Task kleiner schneiden. ===" >&2
exit 0
else
echo "=== WORKER FEHLGESCHLAGEN (Modell $MODEL, finish=${FIN:-keins}) — kein Ergebnis. Endpoint/Modell-ID pruefen (echte /v1/models-ID, kein Alias). ===" >&2
exit 1
fi