fix(agents): nicht maskierte Anfuehrungszeichen in Modell-JSON reparieren
Beobachtet am 31.07.2026 auf Staging: Modelle schliessen deutsche Zitate
gelegentlich mit einem geraden Anfuehrungszeichen, das das JSON an dieser
Stelle bricht. Die Folgen waren still und teuer:
- Lagebild von Lage 47 brach mitten im Satz ab (738 statt ~4000 Zeichen),
weil der Regex-Fallback nur bis zum Stoerzeichen rettete
- ein kompletter Recherche-Durchlauf von Lage 45 ging verloren
- sechs weitere Durchlaeufe fielen auf die verlustbehaftete
Einzelobjekt-Rettung zurueck
Betroffen war vor allem der EU-Weg (Opus 4.6), der CLI-Weg aber ebenfalls.
Neu: src/json_utils.py repariert solche Antworten, indem es beim Durchlauf
mitfuehrt, ob eine Zeichenkette offen ist, und ein Anfuehrungszeichen maskiert,
auf das kein gueltiger JSON-Fortsetzer folgt (Komma nur dann als Ende, wenn
danach wirklich ein Wert oder Schluessel beginnt). Roh eingebettete
Zeilenumbrueche werden ebenfalls maskiert. Repariert wird ausschliesslich als
Rueckfallebene, nachdem der normale Parser gescheitert ist, gueltiges JSON
bleibt unangetastet.
Eingebunden in analyzer, factchecker und researcher. Zusaetzlich meldet der
Analyzer jetzt als ERROR, wenn der letzte Fallback ein erkennbar
abgeschnittenes Lagebild liefert, statt das still hinzunehmen.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Dieser Commit ist enthalten in:
@@ -913,6 +913,20 @@ class ResearcherAgent:
|
||||
if isinstance(obj, dict) and isinstance(obj.get("articles"), list):
|
||||
return obj["articles"]
|
||||
|
||||
# 3b) Nicht maskierte Anfuehrungszeichen im Text reparieren (deutsche
|
||||
# Zitate in content_summary). Ohne diesen Schritt fiel die Auswertung
|
||||
# auf die Einzelobjekt-Rettung zurueck, die Artikel verlieren kann, oder
|
||||
# es ging ein kompletter Recherche-Durchlauf verloren.
|
||||
from json_utils import extract_json_array as _forgiving_array, extract_json_object as _forgiving_object
|
||||
repaired_arr = _forgiving_array(text)
|
||||
if isinstance(repaired_arr, list):
|
||||
logger.info("JSON-Reparatur: %d Artikel gerettet", len(repaired_arr))
|
||||
return repaired_arr
|
||||
repaired_obj = _forgiving_object(text)
|
||||
if isinstance(repaired_obj, dict) and isinstance(repaired_obj.get("articles"), list):
|
||||
logger.info("JSON-Reparatur: %d Artikel gerettet (Objektform)", len(repaired_obj["articles"]))
|
||||
return repaired_obj["articles"]
|
||||
|
||||
# 4) Recovery: einzelne Headline-Objekte aus Fliesstext
|
||||
recovered = []
|
||||
for obj_str in re.findall(r'\{[^{}]*"headline"[^{}]*\}', text, re.DOTALL):
|
||||
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren