Arbeitsnotiz mit Stand, den beiden nächsten Schritten (Export/Snapshots, Papierkorb) und dem zurückgestellten Cron-Entwurf. Dazu die Fallstricke dieser Sitzung, damit sie nicht zweimal Zeit kosten — vor allem das falsche gh-Remote, Ollamas effektives Kontextfenster und die Reihenfolge von onStats und onDone. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015AUP4R3rgq4XwVs4bVf7uh
5.6 KiB
Handoff
Stand: 28.08.2026. Arbeitsnotiz für die nächste Sitzung — kein Teil der Projektdokumentation, die steht im README.
Wo wir stehen
Auf main:
| Commit | Inhalt |
|---|---|
8a489df |
Werkzeug-Bestätigung, DNS-Pinning, Statistik-Leiste, Produktionsbetrieb (Squash aus PR #1) |
a36e366 |
Mic-/Anhang-Icons als SVG, blinkender Warte-Cursor |
Arbeitsverzeichnis sauber, npm run typecheck und vite build grün.
Als Nächstes
1. Export und Snapshots
Anlass: Am 28.08. waren die vier Chats des Nutzers plötzlich weg. Rettbar waren sie nur, weil die Löschungen noch im SQLite-WAL standen und der Hauptfile den Stand des letzten Checkpoints hielt. Das war Glück, keine Vorkehrung.
- Export eines Chats als Markdown (Nachrichten, Anhänge als Dateinamen,
Werkzeugaufrufe optional). Naheliegender Ort: Button im Sidebar-Kontext
oder
GET /api/sessions/:id/export. - Snapshot der Datenbank: beim Serverstart und danach täglich eine Kopie
nach
server/backups/data-JJJJ-MM-TT.sqlite, die letzten ~7 behalten. Wichtig:VACUUM INTOstattcp— das schreibt einen konsistenten Stand ohne WAL-Abhängigkeit. Verzeichnis in.gitignoreaufnehmen.
2. Papierkorb statt Sofortlöschung
Der ✕-Button in web/src/components/Sidebar.tsx:38 ruft onDelete ohne
jede Rückfrage. Am 28.08. sind so vier Chats mit 34 Nachrichten in 1,1
Sekunden verschwunden (vier Klicks, je ~250 ms auseinander, jeweils auf den
obersten Eintrag, der nach dem Löschen nachrückt).
- Spalte
deleted_atinsessions; ✕ setzt sie, statt zu löschen - Listenabfragen filtern
deleted_at IS NULL - Endgültiges Löschen nach 30 Tagen oder manuell im Papierkorb
- Optional zusätzlich: kurzes „Rückgängig" nach dem Klick
Eine reine Bestätigungsabfrage wäre billiger, aber schwächer — sie schützt nicht vor dem schnellen Durchklicken, das hier genau passiert ist.
3. Datenbankpfad konfigurierbar machen (klein, aber Voraussetzung)
server/src/db.ts:5 hat den Pfad fest verdrahtet. Jeder Testlauf schreibt
damit in die echte Datenbank des Nutzers — genau das hat am 28.08. Testchats
in seiner Historie hinterlassen. Eine Variable DB_PATH (Default wie
bisher) erlaubt Tests gegen eine Wegwerf-Datei und gehört vor allem, was
automatisiert testet.
Später: geplante Aufgaben (Cron)
Idee des Nutzers, bewusst zurückgestellt. Passt gut — Werkzeug-Loop,
Gedächtnis und TTS liegen bereit, und mit dreamTimers (index.ts:71)
existiert schon ein kleiner Scheduler. Zwei Punkte entscheiden das Design:
Bestätigungspflicht. read_webpage und remember laufen nur nach
Freigabe, und ohne Rückkanal gilt „abgelehnt" (tools/index.ts:107). Ein
Job um 8 Uhr hat niemanden zum Fragen — ausgerechnet der nützlichste Job
würde zuverlässig scheitern. Auflösung: Freigabe wandert vom Ausführungs-
zum Anlegezeitpunkt. Beim Erstellen hakt der Nutzer die erlaubten
Werkzeuge an und sieht sie zusammen mit dem Prompt; der Job trägt diese
Allowlist als ToolContext.confirm. Das ist Einwilligung, nicht ihre
Umgehung.
Dabei eng bleiben: remember nicht in die Standard-Allowlist. Ein
unbeaufsichtigter Job, der Fremdinhalt liest und daraus dauerhafte „Fakten
über den Nutzer" ableitet, ist genau die Kette, die der Security-Review
geschlossen hat. Jeder Job schreibt in einen eigenen Chat.
Laufzeit. Cron feuert nur, solange der Server läuft; gestartet wird er heute von Hand. Statt launchd lieber Verpasstes beim nächsten Start nachholen — deutlich weniger Systemeingriff.
Offen beim Nutzer
- Die vier wiederhergestellten Chats: unklar, ob die Löschung am 28.08. um
15:02 Absicht war. Falls ja, gehören sie wieder raus. Sicherungen liegen
in
~/agenttwo-backups/(vor-wal.sqlite= 8 Sessions inkl. vier Testchats,geloeschter-stand.sqlite*= leerer Stand). - Static-Serving im Entwicklungsbetrieb: seit
8a489dfliefert:8788auchweb/distaus, sobald ein Build existiert — ein Standbild neben dem lebenden Vite auf:5174. Abschaltbar überNODE_ENVimdev-Script, bisher nicht gemacht.
Fallstricke, teuer gelernt
ghzielt auf das falsche Repo. Es löst aufJeuners/agenttwo(dasupstream-Remote) auf, nicht aufagenttwo-tools. Ohne--repo Jeuners/agenttwo-toolsscheitertgh pr createmit einem irreführenden „No commits between". Dauerhaft:gh repo set-default Jeuners/agenttwo-tools.- Ollamas Kontextfenster ist nicht das deklarierte. qwen3.5 meldet
262144, geladen läuft es mit 4096. Der wahre Wert steht in
GET /api/ps, nicht in/api/show. - Emoji lassen sich nicht einfärben.
🎙und📎sind in den Fonts fest grau. Zustandsfarben in CSS verpuffen an ihnen — deshalb jetzt SVG mitcurrentColor. .caretist belegt (Aufklapp-Dreieck des Denkprozesses). Der Warte-Cursor heißt.stream-caret.onStatsmuss voronDoneabgewartet werden. Der/api/ps-Lookup ist asynchron; ohneawaitgeht die Stats-Nachricht hinter demdoneraus und der Client verwirft sie. Fiel nur auf, weil der erste (ungecachte) Lauf leer blieb und der zweite nicht.- OpenRouters
usagekommt nachfinish_reason. Ein früher Return verschluckt die Tokenzahlen. Es brauchtstream_options.include_usage. - Werkzeuge ohne Rückkanal werden abgelehnt. Skripte und Tests, die
runTooldirekt aufrufen, bekommen bei bestätigungspflichtigen Werkzeugen „abgelehnt". Das ist Absicht — beim Testen einconfirmmitgeben.