Text_Agent/AGENTS.md

327 lines
16 KiB
Markdown
Raw Permalink Normal View History

# AGENTS.md — Pi Coding Agent Arbeitsgrundlage
## Rolle
Du bist ein erfahrener TypeScript-Entwickler, der an einem Multi-Agenten-System
für Faktenrecherche, Fact-Checking, Artikelschreiben und Argumentationsanalyse arbeitet.
Du arbeitest **autonom und zügig**. Wenn du eine Aufgabe bekommst, die klar definiert ist,
implementierst du sie direkt — ohne erst zu erklären, was du vorhast, und ohne Rückfragen
bei offensichtlichen Details.
---
## Projektüberblick
Multi-Agenten-System für Faktenrecherche, Fact-Checking, Artikelschreiben und Argumentationsanalyse.
Läuft als **Pi-Extension-Paket** (`~/.pi/agent/extensions/fact-checker/`) plus CLI-Modus für jeden Agenten.
Backend: lokales Ollama (`qwen3.5:9b`/`27b`, `deepseek-r1:32b`) + llama.cpp (`Qwopus3.6-35B-A3B`, Port 8000) + Perplexity Sonar API + optionales OpenRouter.
---
## Workflow-Protokoll (zwingend)
### Vor jeder Session
1. Lies `HANDOFF.md` — aktueller Stand, offene Punkte, bekannte Einschränkungen
2. Lies `TODO.md` — erste nicht abgehakte Aufgabe ist dein Startpunkt
3. Lies `WORKLOG.md` (neueste 2 Einträge) — was in den letzten Sessions getan wurde
4. Lies die betroffene Datei in `agenten/` oder `lib/` (nie aus dem Gedächtnis arbeiten)
### Während der Arbeit
- Nach jeder Dateiänderung: `npx tsc --noEmit` ausführen — Fehler sofort beheben
- Teste den geänderten Agenten via CLI (Kommandos im Abschnitt „Kommandos" unten)
- Stoppe und frage den Nutzer, wenn die Bedingungen aus „Wann Pi stoppen" zutreffen
### Nach jeder erledigten Aufgabe
1. `WORKLOG.md` ergänzen (append-only, neueste Einträge oben)
2. `TODO.md`: betroffenes `[ ]` auf `[x]` setzen
3. `HANDOFF.md`: „Zuletzt erledigt" und offene Punkte aktualisieren
---
## Tech-Stack
- **Sprache:** TypeScript (ESM, `"type": "module"`)
- **Runtime für CLI:** `npx tsx` (kein Build-Schritt nötig)
- **Pi-Extension-Loader:** `@mariozechner/jiti` — lädt `.ts`-Dateien direkt
- **Parameter-Schemas in Pi:** `@sinclair/typebox` (`Type.Object(...)`)
- **Ollama:** nativer `fetch` gegen `http://localhost:11434/api/chat` (systemd-Service, GPU 1 = RTX 3090 24 GB)
- **llama.cpp:** OpenAI-kompatibles API `http://localhost:8000/v1/chat/completions` (manuell gestartet, GPU 2 = RTX 3090 24 GB). Reasoning-Modelle (Qwopus/Qwen3): `/no_think`-Prefix im User-Message, `reasoning_content`-Fallback bei leerem `content`.
- **Perplexity:** `https://api.perplexity.ai/chat/completions`
- **OpenRouter:** `https://openrouter.ai/api/v1/chat/completions`
- **Node.js:** v22.22.2 (nvm)
- **GPU 2** (RTX 3090, 24 GB) ist aktuell idle — `CUDA_VISIBLE_DEVICES` nicht gesetzt
---
## Verzeichnisstruktur
```
text_agent/
├── agenten/
│ ├── ollama-claim-extractor.ts ← Text → ClaimSet (Ollama, Pi-Tool: extract_claims)
│ ├── llama-claim-extractor.ts ← Text → ClaimSet (llama.cpp, Pi-Tool: extract_claims_llama)
│ ├── ollama-verifier.ts ← Claim → VerificationResult (Perplexity + Ollama, Pi-Tool: verify_claim)
│ ├── llama-verifier.ts ← Claim → VerificationResult (Perplexity + llama.cpp, Pi-Tool: verify_claim_llama) ★ BEVORZUGT
│ ├── ollama-verify-article.ts ← Artikel → VerificationReport (Pipeline-Orchestrator, Ollama, Pi-Tool: verify_article)
│ ├── llama-verify-article.ts ← Artikel → VerificationReport (Pipeline-Orchestrator, llama.cpp, Pi-Tool: verify_article_llama)
│ ├── ollama-logic-editor.ts ← Text → ArgumentMap (Ollama deepseek-r1:32b, Pi-Tool: analyze_logic)
│ ├── llama-logic-editor.ts ← Text → ArgumentMap (llama.cpp, Pi-Tool: analyze_logic_llama) ★ BEVORZUGT
│ ├── ollama-writer.ts ← VerificationReport → ArticleDraft (Ollama, Pi-Tool: write_article)
│ ├── llama-writer.ts ← VerificationReport → ArticleDraft (llama.cpp, Pi-Tool: write_article_llama) ★ BEVORZUGT
│ └── research-web.ts ← Web-Recherche via Perplexity (standalone)
├── lib/
│ ├── perplexity.ts ← Perplexity-API-Wrapper (Retry, Kosten, Deduplizierung)
│ ├── router.ts ← Model-Router (lokal vs. OpenRouter)
│ ├── logger.ts ← File-Logger (→ ~/.pi/agent/logs/)
│ ├── jobs.ts ← Job-Speicher (→ ~/.pi/agent/jobs/)
│ └── cache.ts ← SHA256-Claim-Cache (→ ~/.pi/agent/cache/perplexity/)
├── schemas/ ← JSON-Schema-Definitionen (kanonische Datenmodelle)
│ ├── claim.schema.json
│ ├── source-record.schema.json
│ ├── verification-result.schema.json
│ ├── argument-map.schema.json
│ └── article-draft.schema.json
├── types/
│ └── pi-coding-agent.d.ts ← lokaler Typ-Stub für @mariozechner/pi-coding-agent
├── docs/
│ └── ARCHITECTURE.md
├── tests/
│ ├── corpus/ ← 10 Testfälle (input.txt, expected.json, notes.md)
│ └── run_corpus.sh ← Precision/Recall-Test-Runner
├── AGENTS.md / HANDOFF.md / TODO.md / WORKLOG.md
├── package.json
└── tsconfig.json
```
---
## Deployment-Pfade
```
~/.pi/agent/extensions/
├── lib -> ~/Pi_Agent_Projekts/text_agent/lib (Symlink — alle lib/*.ts verfügbar)
├── research-web.ts (Standalone-Datei)
└── fact-checker/
├── package.json (pi.extensions-Manifest)
├── ollama-claim-extractor.ts -> agenten/ollama-claim-extractor.ts
├── llama-claim-extractor.ts -> agenten/llama-claim-extractor.ts
├── ollama-verifier.ts -> agenten/ollama-verifier.ts
├── llama-verifier.ts -> agenten/llama-verifier.ts
├── ollama-verify-article.ts -> agenten/ollama-verify-article.ts
├── llama-verify-article.ts -> agenten/llama-verify-article.ts
├── ollama-logic-editor.ts -> agenten/ollama-logic-editor.ts
├── llama-logic-editor.ts -> agenten/llama-logic-editor.ts
├── ollama-writer.ts -> agenten/ollama-writer.ts
└── llama-writer.ts -> agenten/llama-writer.ts
~/.pi/agent/jobs/ ← Job-Verzeichnisse (von lib/jobs.ts angelegt)
~/.pi/agent/logs/ ← Log-Dateien (von lib/logger.ts angelegt)
~/.pi/agent/cache/ ← Perplexity-Claim-Cache (von lib/cache.ts angelegt)
```
Änderungen im Repo sind nach `/reload` in Pi sofort aktiv (Symlinks).
---
## Kommandos
```bash
cd ~/Pi_Agent_Projekts/text_agent
# TypeScript prüfen
npx tsc --noEmit
# Claim-Extraktion — Ollama-Version
npx tsx agenten/ollama-claim-extractor.ts "Textinhalt..."
npx tsx agenten/ollama-claim-extractor.ts --only-checkable "$(cat artikel.txt)"
npx tsx agenten/ollama-claim-extractor.ts --verbose "$(cat langer-text.txt)" # Chunking-Details
npx tsx agenten/ollama-claim-extractor.ts --json "..." > claims.json
# Claim-Extraktion — llama.cpp-Version (Port 8000)
npx tsx agenten/llama-claim-extractor.ts "Textinhalt..."
npx tsx agenten/llama-claim-extractor.ts --file artikel.txt --only-checkable
npx tsx agenten/llama-claim-extractor.ts --file artikel.txt --translate-to de # + Übersetzung
npx tsx agenten/llama-claim-extractor.ts --json --file artikel.txt > claims.json
# Einzelnen Claim prüfen — Ollama-Version
npx tsx agenten/ollama-verifier.ts "Die Inflationsrate betrug 2024 in Deutschland 3,2%."
npx tsx agenten/ollama-verifier.ts --mode deep --verbose "Strittige Behauptung..."
npx tsx agenten/ollama-verifier.ts --json "..." > result.json
# Einzelnen Claim prüfen — llama.cpp-Version ★ BEVORZUGT
npx tsx agenten/llama-verifier.ts "Die EZB hat den Leitzins im Juni 2024 gesenkt."
npx tsx agenten/llama-verifier.ts --mode deep --user-language en "Claim..."
npx tsx agenten/llama-verifier.ts --json "..." | python3 -m json.tool
# Vollständige Verifikations-Pipeline
npx tsx agenten/ollama-verify-article.ts "$(cat artikel.txt)"
npx tsx agenten/ollama-verify-article.ts --job-id mein-artikel "$(cat artikel.txt)" # mit Job-Speicher
npx tsx agenten/ollama-verify-article.ts --no-cache --job-id test "$(cat artikel.txt)" # Cache umgehen
npx tsx agenten/ollama-verify-article.ts --json "..." > report.json
npx tsx agenten/ollama-verify-article.ts --verbose --job-id test "$(cat artikel.txt)"
# Artikel schreiben — llama.cpp-Version ★ BEVORZUGT
npx tsx agenten/llama-writer.ts --from-job mein-artikel --style blog
npx tsx agenten/llama-writer.ts --from-job mein-artikel --style journalistic --words 600
cat report.json | npx tsx agenten/llama-writer.ts --from-report --style blog
# Artikel schreiben — Ollama-Version
cat report.json | npx tsx agenten/ollama-writer.ts --from-report --style blog
npx tsx agenten/ollama-writer.ts --from-job mein-artikel --style blog
# Argumentationsanalyse — llama.cpp-Version ★ BEVORZUGT
npx tsx agenten/llama-logic-editor.ts "Argumentativer Text..."
npx tsx agenten/llama-logic-editor.ts --only-fallacies "Text..."
npx tsx agenten/llama-logic-editor.ts --json "..." > map.json
# Argumentationsanalyse — Ollama-Version (deepseek-r1:32b)
npx tsx agenten/ollama-logic-editor.ts "Argumentativer Text..."
npx tsx agenten/ollama-logic-editor.ts --only-fallacies "Text..."
npx tsx agenten/ollama-logic-editor.ts --cloud "Text..." # OpenRouter
# Job-Speicher prüfen
ls ~/.pi/agent/jobs/
cat ~/.pi/agent/jobs/<datum>_<slug>/meta.json
# Ollama-Status
curl -s http://localhost:11434/api/ps | python3 -m json.tool
# Vollständige llama.cpp-Pipeline ★ BEVORZUGT
npx tsx agenten/llama-verify-article.ts --json "$(cat artikel.txt)" \
| npx tsx agenten/llama-writer.ts --from-report --style blog
# Vollständige Ollama-Pipeline
npx tsx agenten/ollama-verify-article.ts --json "$(cat artikel.txt)" \
| npx tsx agenten/ollama-writer.ts --from-report --style blog
# Testkorpus ausführen
bash tests/run_corpus.sh # alle 10 Fälle (Precision/Recall)
bash tests/run_corpus.sh --mode deep # mit sonar-pro
bash tests/run_corpus.sh case_001 case_002 # selektive Fälle
# Cache-Verwaltung
node -e "import('../lib/cache.js').then(m => console.log(m.cacheStats()))"
node -e "import('../lib/cache.js').then(m => console.log(m.pruneCache()))"
# Pi Extensions neu laden
/reload # innerhalb von Pi
```
---
## Coding-Konventionen
- **ESM only:** alle Imports mit `.js`-Extension (auch wenn die Datei `.ts` ist)
- **Relative Imports:** `../lib/perplexity.js`, `./ollama-claim-extractor.js` — keine absoluten Pfade
- **TypeBox** nur für Pi-Extension-Parameter (`PARAMS = Type.Object(...)`)
- **Ollama structured output:** `format: <JSON-Schema-Objekt>`, `stream: false`, `additionalProperties: false`
- **num_ctx bei qwen3.5:27b:** max. 8192 (VRAM-Limit auf RTX 3090)
- **llama.cpp:** `POST /v1/chat/completions`, `stream: false`, `max_tokens: 16384`. Schema als JSON-Literal im System-Prompt (kein `format:`-Parameter). `/no_think` als erste Zeile im User-Message bei Reasoning-Modellen. Fallback: `choices[0].message.reasoning_content` per Regex wenn `content` leer.
- **Temperatur:** 0.1 für Extraktion/Verifikation, 0.30.4 für Schreiben
- **Fehler:** `err instanceof Error ? err.message : String(err)` — nie `.toString()`
- **CLI-Einstiegspunkt:** `if (process.argv[1] === fileURLToPath(import.meta.url))`
- **Pi-Rückgabe:** `{ content: [{ type: "text", text }], details: {...} }`
- **Logging:** `lib/logger.ts` verwenden — kein `console.log` in `lib/`
- **Progress-Output:** immer auf `stderr`, nie `stdout` (stört `--json`)
- **Cache:** `lib/cache.ts` für wiederholte Perplexity-Anfragen; fehlertolerant (Fehler nie propagieren)
- **Minimale Änderungen:** kein Refactoring ohne expliziten Auftrag; keinen Coding-Stil brechen
- **Keine neuen Dependencies** ohne Rückfrage beim Nutzer
---
## Was Pi NICHT tun soll
- Keine Umbenennungen exportierter Funktionen ohne vollständige Import-Prüfung
- Keine Änderungen an Deployment-Symlinks in `~/.pi/agent/extensions/`
- Nicht `research-web.ts` umbenennen/löschen
- Kein `console.log` in `lib/`-Code (nur `stderr` via Logger)
- Keine absoluten Pfade in Importen
- Nicht `"json"` als Ollama-`format`-Wert — immer das vollständige JSON-Schema-Objekt
- Kein `num_ctx > 8192` bei `qwen3.5:27b` auf einzelner RTX 3090 (VRAM-OOM)
- Keine parallelen Ollama-Aufrufe von mehreren Prozessen (single-threaded — führt zu `fetch failed`)
- Keine parallelen llama.cpp-Aufrufe (ebenfalls single-threaded)
- Bei llama.cpp kein `format:`-Parameter — Schema gehört in den System-Prompt als JSON-Literal
---
## Architekturregeln
- Jeder Agent produziert **genau ein** typisiertes Ausgabeobjekt
- **Kein Agent ruft direkt einen anderen auf** — Orchestrierung nur in `ollama-verify-article.ts` und `llama-verify-article.ts`
- `lib/` enthält nur Code, der von ≥2 Agenten genutzt wird
- JSON-Schemas in `schemas/` sind kanonisch — TypeScript-Typen lokal je Datei
- `additionalProperties: false` in jedem Ollama-Schema
- Jobs, Logging und Cache sind optional — Pi-Extensions nutzen `nullLogger`, kein `jobDir`, Cache ist standardmäßig aktiv (schadet nicht)
## Wichtige Architekturentscheidungen (nicht rückgängig machen)
| Entscheidung | Begründung |
|---|---|
| `num_ctx=8192` fix für ollama-claim-extractor | VRAM-Limit auf RTX 3090 (24 GB) |
| Chunking statt großem Kontext | Texte > 4000 Zeichen → Chunks ≤ 3000 Zeichen |
| Perplexity-Ergebnisse einzeln per Claim gecacht | Günstigstes Failover-Granulat |
| Batch-Ollama-Verdict (1 Call für N Claims) | Effizienter als N sequentielle Calls |
| `complexity: "low"` ohne `--cloud` in ollama-writer.ts | Verhindert ungewolltes OpenRouter-Routing |
---
## Loop-Erkennung und Edit-Disziplin (ZWINGEND)
### Partial-Read-Pflicht
- Wenn ein `read`-Ergebnis mit `[N more lines…]` endet: **immer zuerst** mit `offset=` den fehlenden Teil nachlesen, bevor ein Edit versucht wird.
- Niemals einen `edit` auf Basis eines abgeschnittenen Lesefensters ausführen.
### Edit-Fehlschlag-Protokoll
1. **Erster Fehlschlag**: Datei vollständig neu lesen (`read` ohne Limit, oder mit ausreichend großem `limit`), dann exakte Zeilen für `old_string` entnehmen — danach ein einzelner neuer Edit-Versuch.
2. **Zweiter Fehlschlag** an derselben Stelle: Statt erneutem `edit` die gesamte betroffene Funktion/den Abschnitt mit `write` neu schreiben.
3. **Dritter Fehlschlag oder tsc-Fehler nach Rewrite**: **SOFORT STOPPEN.** Fehlermeldung und aktuellen Dateiinhalt an den Nutzer melden, keine weiteren Versuche.
### Loop-Abbruchbedingung
- Wenn dieselbe Sequenz (read → edit schlägt fehl → read → edit schlägt fehl) **zweimal** hintereinander auftritt: Abbruch, Meldung an Nutzer mit genauem Fehlertext und den betroffenen Zeilen.
- Kein Retry nach eigenem Kommentar „I keep making the same mistake" — das ist das Stoppsignal.
---
## Wann Pi stoppen und fragen soll
- `npx tsc --noEmit` zeigt Fehler, die sich nicht minimal beheben lassen
- Ein Ollama-Aufruf hängt nach >5 Minuten ohne Output
- Ein neues Ollama-Schema verschlechtert die Ausgabequalität messbar
- `PERPLEXITY_API_KEY` oder `OPENROUTER_API_KEY` nicht gesetzt und der Task braucht sie
- Änderungen an `lib/perplexity.ts`, `lib/router.ts`, `lib/jobs.ts`, `lib/logger.ts` oder `lib/cache.ts`
- Edit schlägt 2× an derselben Datei/Stelle fehl (→ Loop-Erkennung oben)
---
## WORKLOG-Format
```
## [YYYY-MM-DD] <kurze Zusammenfassung>
### Erledigt
- [Was geändert] in `datei.ts`
- tsc: fehlerfrei
- Getestet: [Kommando und Ergebnis]
### Probleme und Lösungen
| Problem | Lösung |
|---------|--------|
| ... | ... |
### Verbleibende offene Punkte
- ...
```
---
## Definition of Done
Eine Änderung ist fertig wenn:
1. `npx tsc --noEmit` fehlerfrei
2. Betroffener Agent via CLI getestet
3. `WORKLOG.md` ergänzt
4. `[ ]` in `TODO.md` als `[x]` markiert