# Research Agent – Web-Chat-Oberfläche Browser-Chatoberfläche für den Research-Agent: DeepSeek v4 Flash recherchiert per Playwright im Internet, verifiziert alle Links und generiert HTML-Dashboards – ohne dass Opencode lokal laufen muss. ## Funktionen - 💬 Chat-Oberfläche mit Live-Fortschritt (SSE): Suchen, Seitenbesuche, Link-Verifizierung in Echtzeit - 🔎 Volle Research-Funktion: DuckDuckGo-Suche, Seiten lesen, Links verifizieren, HTML-Dashboard generieren - 🔔 Web-Push-Benachrichtigung, wenn die Recherche fertig ist (auch wenn der Browser zu ist) - 📱 PWA: installierbar auf Desktop & Handy (Chrome/Android; iOS 16.4+ für Push) - 👤 Eine gemeinsame Anmeldung (Name + Passwort), Sessions sind dem Namen zugeordnet - 🔗 Sessions als read-only Teil-Link ohne Login teilbar - 📦 SQLite-Speicherung, keine externe Datenbank nötig ## Setup ```bash cd webapp npm install cp .env.example .env # .env editieren: DEEPSEEK_API_KEY und APP_PASSWORD setzen (Pflicht) npx playwright install chromium # falls Chromium fehlt npm start # läuft auf Port 3000 ``` Fehlende Werte wie `SESSION_SECRET` und die VAPID-Keys werden beim ersten Start automatisch erzeugt und in die `.env` geschrieben. ## Konfiguration (.env) | Variable | Pflicht | Beschreibung | |---|---|---| | `DEEPSEEK_API_KEY` | ja | Key von https://platform.deepseek.com/api_keys | | `APP_PASSWORD` | ja | Gemeinsames Login-Passwort | | `PORT` | nein | Standard 3000 | | `MODEL` | nein | Standard `deepseek-v4-flash` | | `THINKING` | nein | `enabled` (Standard) oder `disabled` | | `DEEPSEEK_BASE_URL` | nein | Für Tests/Proxies überschreibbar | ## Deployment mit Docker/Podman (empfohlen) Alles läuft in einem Container (Node + Playwright-Chromium). Auf dem Server reicht: ```bash git clone researchChat cd researchChat cp .env.example .env # .env editieren: DEEPSEEK_API_KEY und APP_PASSWORD setzen ``` **Mit Docker:** ```bash docker compose up -d ``` **Mit Podman (Bazzite/Fedora Atomic):** ```bash podman compose up -d ``` Beim ersten Start wird das Image gebaut (npm install + Chromium-Download, dauert ein paar Minuten). Alternativ ist das fertige Image in der Gitea-Registry gepusht: ```bash podman compose pull # fertiges Image aus der Registry holen podman compose up -d ``` Danach läuft die App auf Port 3000. Daten bleiben über die Volumes erhalten: | Host-Verzeichnis | Inhalt | |---|---| | `./data/` | SQLite-Datenbank (Sessions, Nachrichten, Push-Abos) | | `./dashboards/` | Generierte HTML-Dashboards | | `./.env` | Konfiguration (generierte Secrets werden ergänzt) | Nützliche Befehle: ```bash podman compose logs -f # Logs ansehen podman compose restart # Neustart podman compose pull # neues Image holen (nach Rebuild) ``` ## Alternativ: Direkt mit Node (ohne Container) ```bash npm install npx playwright install --with-deps chromium # Chromium + Systemdeps npm start ``` ## Optional: NGINX davor (Reverse Proxy + IP-Prüfung + HTTPS) ### systemd-Unit (`/etc/systemd/system/research-web.service`, falls ohne Docker) ```ini [Unit] Description=Research Agent WebApp After=network.target [Service] WorkingDirectory=/var/home/nico/dev/researchChat ExecStart=/usr/bin/node server.js Restart=always RestartSec=3 Environment=NODE_ENV=production [Install] WantedBy=multi-user.target ``` ```bash sudo systemctl enable --now research-web ``` **Mit Docker/Podman** entfällt die systemd-Unit — `restart: unless-stopped` in der docker-compose.yaml übernimmt das. Der NGINX-Block bleibt der gleiche: ### NGINX (Reverse Proxy + IP-Prüfung + HTTPS) ```nginx server { listen 443 ssl; server_name research.deinedomain.de; # SSL-Zertifikat (certbot --nginx) ssl_certificate /etc/letsencrypt/live/research.deinedomain.de/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/research.deinedomain.de/privkey.pem; # IP-Prüfung: nur deine IPs kommen rein allow 123.45.67.89; # deine Heim-IP allow 10.0.0.0/8; # ggf. Heimnetz/VPN # deny all; # Kommentar entfernen, wenn IP-Check aktiv sein soll # (für /share/ entfernen, damit Teil-Links extern funktionieren) location / { proxy_pass http://localhost:3000; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Upgrade $http_upgrade; # SSE/EventSource proxy_set_header Connection "upgrade"; proxy_buffering off; # wichtig für Live-Streaming proxy_read_timeout 3600s; proxy_send_timeout 3600s; } } ``` Tipp: Möchte man Teil-Links (`/share/...`) auch für Personen außerhalb der eigenen IP freigeben, kann man die `allow/deny`-Regeln nur für `location /share/` weglassen (und `location /` mit deny schützen) – die Teil-Ansicht ist read-only und benötigt keinen Login. ## Teilen In jeder Session gibt es „🔗 Teilen-Link kopieren“. Der Link zeigt den Chat-Verlauf und das Dashboard read-only, ganz ohne Login. ## Projektstruktur ``` researchChat/ ├── Dockerfile # Node + Playwright-Chromium im Container ├── docker-compose.yaml # Ein-Befehl-Deployment (Docker & Podman) ├── server.js # Express-App: Auth, APIs, SSE, Web Push, statische Dateien ├── lib/ │ ├── config.js # .env-Laden, Secret/VAPID-Autogenerierung │ ├── db.js # SQLite (node:sqlite, keine nativen Module) │ ├── tools.js # Playwright-Tools: search, browse, verify, save_dashboard │ ├── research.js # DeepSeek Tool-Calling-Loop (Agent) │ └── queue.js # FIFO-Job-Queue (1 Recherche gleichzeitig) ├── public/ # Frontend (Vanilla JS + Tailwind CDN) │ ├── index.html # Chat-UI │ ├── login.html # Anmeldung │ ├── share.html # Read-only Teil-Ansicht │ ├── app.js │ ├── sw.js # Service Worker (Push + Notifications) │ └── manifest.json # PWA-Manifest ├── dashboards/ # generierte HTML-Dashboards (Host-Volume) ├── data/research.db # SQLite-Datenbank (Host-Volume) └── scripts/make-icons.js ``` ## Hinweise - Recherchen dauern mehrere Minuten – die Fortschrittsleiste zeigt den aktuellen Schritt - Nur **eine** Recherche läuft gleichzeitig; weitere Anfragen zeigen „Recherche läuft…“ - DuckDuckGo blockiert nach ~4-5 Suchen: Der Agent wechselt automatisch auf Fallback-Suchmaschinen - Der Browser-Context bleibt pro Server-Lauf erhalten (weniger CAPTCHAs durch stabile Session-Cookies) - API-Kosten: DeepSeek v4 Flash kostet ~$0,44/M Input- und ~$0,66/M Output-Token – eine Recherche kostet Cent-Beträge - Auf SELinux-Systemen (Bazzite/Fedora Atomic) sind die Volume-Mounts mit `:Z` markiert – Docker ignoriert das Flag, dort reicht die Compose-Datei unverändert