Commit graph

5 commits

Author SHA1 Message Date
Jeuner
adb57ae6e3 feat: Bilder im Chat (Vision)
qwen3.5 meldet die Fähigkeit "vision", die bisher ungenutzt blieb. Bilder
lassen sich jetzt per Button, Zwischenablage (⌘V) oder Drag & Drop anhängen;
eine Nachricht darf auch nur aus einem Bild bestehen.

- images.ts: Validierung vor dem Speichern — maximal 4 Bilder je Nachricht,
  je 6 MB, Typ per Magic Bytes statt per Dateiendung (PNG/JPEG/GIF/WebP).
  Der WebSocket bekommt dazu ein maxPayload von 32 MB, vorher war er
  unbegrenzt und Bilder machen Nachrichten deutlich größer.
- db.ts: Spalte images samt Migration für bestehende Datenbanken aus agenttwo
- ollama.ts: images-Feld je Message; openrouter.ts: OpenAI-Format mit
  image_url, MIME aus den Magic Bytes statt fest image/png
- Composer: Vorschau mit Entfernen-Button, Fehlermeldung bei zu großen oder
  nicht unterstützten Dateien; ChatMessage zeigt Bilder in der Historie
- Bilder wandern in die Chat-Historie und werden bei Folgefragen erneut
  mitgeschickt, damit Rückfragen zum selben Bild funktionieren

Getestet gegen das laufende Modell: ein rendertes PNG (roter Kreis auf weiß)
wird korrekt als japanische Flagge beschrieben. Validierung geprüft gegen
5 Bilder, Textdatei mit Bildnamen, kaputtes base64 und 7-MB-Blob — alle
abgelehnt.

Nebenbei: Branding in UI, Titel und Serverlog auf agenttwo-tools umgestellt.
Die localStorage-Keys bleiben unverändert, sonst gingen gespeicherte
Einstellungen verloren.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S1NXUpHbxTusqQmsjrFfbU
2026-08-26 17:44:57 +02:00
Jeuner
e48228c570 chore: Fork als agenttwo-tools aufsetzen
Basis für die Tool-Calling- und Vision-Entwicklung. Die Historie von agenttwo
bleibt erhalten, damit sich Fixes aus der Basis per cherry-pick übernehmen
lassen; das Remote upstream zeigt dafür auf Jeuners/agenttwo.

Eigene Ports, damit beide Projekte gleichzeitig laufen können:
- Backend 8787 -> 8788, Vite 5173 -> 5174 samt Proxy-Zielen
- Origin-Allowlist in security.ts entsprechend auf 5174/8788
- OpenRouter-Attribution (HTTP-Referer, X-Title) angepasst

Die SQLite-Datei liegt wie gehabt neben dem Server, beide Instanzen haben
dadurch getrennte Sessions.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S1NXUpHbxTusqQmsjrFfbU
2026-08-26 17:35:51 +02:00
Jeuner
e721540b80 docs: Voraussetzungen korrigieren (Node 22+, piper als Python-Modul)
Beim Testen eines frischen Clones fielen zwei falsche Angaben auf:

- "Node.js 20+" stimmte nicht. db.ts nutzt node:sqlite, das unter Node 20
  gar nicht existiert (ERR_UNKNOWN_BUILTIN_MODULE) — der Server startet dort
  nicht. Ab 22 läuft es, mit ExperimentalWarning; stabil ab Node 24.
  Zusätzlich als engines-Feld in package.json hinterlegt.
- "brew install piper" führte in die Irre: voice.ts ruft `python3 -m piper`
  auf, nicht das Homebrew-Binary. Korrekt ist `pip3 install piper-tts`.

Dazu ein Prüf-Snippet, mit dem sich die Toolchain vor dem ersten Start
verifizieren lässt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S1NXUpHbxTusqQmsjrFfbU
2026-08-26 17:16:17 +02:00
Jeuner
799c9c9394 fix: Origin-Prüfung für HTTP und WebSocket, Härtung von STT/TTS
Der Server lauscht nur auf 127.0.0.1, hatte aber keine Authentifizierung und
mit CORS origin:true jede fremde Origin reflektiert. Da localhost aus jedem
Browser-Tab erreichbar ist, konnte damit jede besuchte Webseite über
/api/sessions und /api/sessions/:id/messages die komplette Chat-Historie
auslesen. Der WebSocket-Upgrade prüfte die Origin ebenfalls nicht — WebSockets
unterliegen nicht der Same-Origin-Policy, wodurch fremde Seiten Chats senden,
Antworten mitlesen und Kosten auf dem OpenRouter-Key erzeugen konnten (CSWSH).

- security.ts: Origin-Allowlist (localhost/127.0.0.1:5173 und :8787, per
  ALLOWED_ORIGINS erweiterbar) und einfacher In-Memory-Rate-Limiter
- CORS auf die Allowlist begrenzt, zusätzlicher onRequest-Hook mit 403
- WebSocket-Handshake weist fremde Origins mit 403 ab
- ffmpeg: Containerformat per Magic Bytes bestimmt statt geraten, dazu
  -protocol_whitelist file — verhindert, dass Demuxer wie concat oder HLS
  auf lokale Pfade und URLs im hochgeladenen Inhalt zugreifen
- Rate-Limits auf /api/stt (10/min) und /api/tts (30/min), Textlänge bei TTS
  begrenzt, bodyLimit und MAX_AUDIO_BYTES auf 8 MB angeglichen
- Fehlerdetails (lokale Pfade, Upstream-Antworten) nur noch ins Server-Log;
  dafür Fastify-Logger aktiviert, sonst wären sie stillschweigend verworfen

Nebenbei: ollama.ts respektiert jetzt OLLAMA_URL statt localhost:11434
hartzukodieren, und ws wandert von devDependencies zu dependencies, da es
zur Laufzeit importiert wird.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S1NXUpHbxTusqQmsjrFfbU
2026-08-26 16:54:31 +02:00
Jeuner
752198c5fa init: oxagenttwo — voice chat with local qwen3 (Ollama) + OpenRouter, Whisper STT, Piper TTS (Thorsten), sessions, thinking mode 2026-08-26 16:37:59 +02:00