Commits vergleichen

..

2 Commits

Autor SHA1 Nachricht Datum
Claude Dev
08aad935c9 refactor: Quellen-Merge vom KI-Prompt in Python-Code verlagern
Claude liefert bei der Analyse nur noch neue Quellen statt alle bisherigen
zu wiederholen. Der Merge mit bestehenden Quellen passiert deterministisch
im Code. Spart Tokens und verhindert das versehentliche Vergessen von Quellen.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 19:08:13 +01:00
Claude Dev
2c73b1c8f0 chore: Domain auf monitor.aegis-sight.de migrieren und Claude-Pfad aktualisieren
CORS-Origin und Magic-Link-URL von osint.intelsight.de auf monitor.aegis-sight.de
umgestellt. Claude CLI Pfad auf /usr/bin/claude aktualisiert.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 19:08:08 +01:00
3 geänderte Dateien mit 31 neuen und 13 gelöschten Zeilen

Datei anzeigen

@@ -135,12 +135,11 @@ REGELN:
- KEINE Gedankenstriche (—, –) verwenden — stattdessen Kommas, Doppelpunkte oder neue Saetze
- Bei widersprüchlichen Angaben beide Seiten erwähnen
- Quellen immer mit [Nr] referenzieren
- Das sources-Array muss ALLE Quellen enthalten (bisherige + neue)
- Ältere Quellen zeitlich einordnen
Antworte AUSSCHLIESSLICH als JSON-Objekt mit diesen Feldern:
- "summary": Aktualisierte Zusammenfassung mit Quellenverweisen [1], [2] etc.
- "sources": VOLLSTÄNDIGES Array aller Quellen (alte + neue), je: {{"nr": 1, "name": "Quellenname", "url": "https://..."}}
- "sources": Array mit NUR den NEUEN Quellen aus den neuen Meldungen, je: {{"nr": <fortlaufend>, "name": "Quellenname", "url": "https://..."}}. Alte Quellen werden automatisch gemerged.
- "key_facts": Array aller aktuellen Kernfakten (in Ausgabesprache)
- "translations": Array von Objekten mit "article_id", "headline_de", "content_de" (nur für neue fremdsprachige Artikel)
@@ -180,12 +179,11 @@ REGELN:
- Neue Erkenntnisse einarbeiten
- Veraltete Informationen aktualisieren
- Quellen immer mit [Nr] referenzieren
- Das sources-Array muss ALLE Quellen enthalten (bisherige + neue)
- Markdown-Überschriften (##) für die Abschnitte verwenden
Antworte AUSSCHLIESSLICH als JSON-Objekt mit diesen Feldern:
- "summary": Das aktualisierte Briefing als Markdown-Text mit Quellenverweisen
- "sources": VOLLSTÄNDIGES Array aller Quellen (alte + neue), je: {{"nr": 1, "name": "Quellenname", "url": "https://..."}}
- "sources": Array mit NUR den NEUEN Quellen aus den neuen Meldungen, je: {{"nr": <fortlaufend>, "name": "Quellenname", "url": "https://..."}}. Alte Quellen werden automatisch gemerged.
- "key_facts": Array aller gesicherten Kernfakten (in Ausgabesprache)
- "translations": Array von Objekten mit "article_id", "headline_de", "content_de" (nur für neue fremdsprachige Artikel)
@@ -263,13 +261,21 @@ class AnalyzerAgent:
new_articles_text = self._format_articles_text(new_articles, max_articles=20)
previous_sources_text = "Keine bisherigen Quellen"
self._all_previous_sources = []
if previous_sources_json:
try:
sources = json.loads(previous_sources_json)
lines = []
for s in sources:
lines.append(f"[{s.get('nr', '?')}] {s.get('name', '?')}{s.get('url', '?')}")
previous_sources_text = "\n".join(lines)
self._all_previous_sources = json.loads(previous_sources_json)
total = len(self._all_previous_sources)
recent = self._all_previous_sources[-100:] if total > 100 else self._all_previous_sources
src_lines = []
if total > 100:
highest_nr = self._all_previous_sources[-1].get("nr", "?")
src_lines.append(f"(... {total - 100} aeltere Quellen ausgelassen, hoechste Nr: {highest_nr})")
for s in recent:
nr = s.get("nr", "?")
name = s.get("name", "?")
src_lines.append(f"[{nr}] {name}")
previous_sources_text = chr(10).join(src_lines)
except (json.JSONDecodeError, TypeError):
previous_sources_text = "Fehler beim Laden der bisherigen Quellen"
@@ -290,7 +296,19 @@ class AnalyzerAgent:
try:
result, usage = await call_claude(prompt)
analysis = self._parse_response(result)
if analysis:
if analysis and self._all_previous_sources:
# Merge: alte Quellen beibehalten, neue hinzufuegen
returned_sources = analysis.get("sources", [])
returned_nrs = {s.get("nr") for s in returned_sources}
merged = [s for s in self._all_previous_sources if s.get("nr") not in returned_nrs]
merged.extend(returned_sources)
merged.sort(key=lambda s: s.get("nr", 0) if isinstance(s.get("nr"), int) else 9999)
analysis["sources"] = merged
logger.info(
f"Inkrementelle Analyse abgeschlossen: {len(new_articles)} neue Artikel, "
f"{len(analysis.get('sources', []))} Quellen gesamt (merged)"
)
elif analysis:
logger.info(
f"Inkrementelle Analyse abgeschlossen: {len(new_articles)} neue Artikel, "
f"{len(analysis.get('sources', []))} Quellen gesamt"

Datei anzeigen

@@ -20,7 +20,7 @@ JWT_ALGORITHM = "HS256"
JWT_EXPIRE_HOURS = 24
# Claude CLI
CLAUDE_PATH = os.environ.get("CLAUDE_PATH", "/home/claude-dev/.claude/local/claude")
CLAUDE_PATH = os.environ.get("CLAUDE_PATH", "/usr/bin/claude")
CLAUDE_TIMEOUT = 1800 # Sekunden (30 Min - Lage-Updates mit vielen Artikeln brauchen mehr Zeit)
# Claude Modelle
CLAUDE_MODEL_FAST = "claude-haiku-4-5-20251001" # Für einfache Aufgaben (Feed-Selektion)
@@ -75,4 +75,4 @@ MAX_ARTICLES_PER_DOMAIN_RSS = 10 # Max. Artikel pro Domain nach RSS-Fetch
# Magic Link
MAGIC_LINK_EXPIRE_MINUTES = 10
MAGIC_LINK_BASE_URL = os.environ.get("MAGIC_LINK_BASE_URL", "https://osint.intelsight.de")
MAGIC_LINK_BASE_URL = os.environ.get("MAGIC_LINK_BASE_URL", "https://monitor.aegis-sight.de")

Datei anzeigen

@@ -318,7 +318,7 @@ if DEV_MODE:
# CORS
app.add_middleware(
CORSMiddleware,
allow_origins=["https://osint.intelsight.de"],
allow_origins=["https://monitor.aegis-sight.de"],
allow_credentials=True,
allow_methods=["GET", "POST", "PUT", "DELETE"],
allow_headers=["Authorization", "Content-Type"],