diff --git a/.gitignore b/.gitignore index d1e415cb4c..d88bfa24fd 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,7 @@ UAT/ # Local release notes testing release-notes-*.md + +# Supabase local data +supabase/volumes/ +supabase/.temp/ diff --git a/INFRASTRUCTURE.md b/INFRASTRUCTURE.md new file mode 100644 index 0000000000..277372876c --- /dev/null +++ b/INFRASTRUCTURE.md @@ -0,0 +1,544 @@ +# Archon Infrastructure Setup + +> Dokumentation der lokalen Entwicklungsumgebung mit Supabase und Archon +> +> **Erstellt**: 20. November 2025 +> **Status**: ✅ Produktiv +> **Letzte Aktualisierung**: 20. November 2025 + +--- + +## 📋 Übersicht + +Diese Dokumentation beschreibt die vollständige lokale Entwicklungsumgebung für Archon mit Supabase als Backend-Datenbank. + +### Komponenten + +- **Supabase** (lokal): PostgreSQL 17.6 mit allen Services +- **Archon**: KI-gestütztes Knowledge Management System + - Backend Server (FastAPI) + - MCP Server (Model Context Protocol) + - Frontend (React) + +--- + +## 🏗️ Architektur + +``` +┌─────────────────────────────────────────────────────────┐ +│ Docker Desktop │ +├─────────────────────────────────────────────────────────┤ +│ │ +│ ┌──────────────────────────────────────────────────┐ │ +│ │ Supabase Stack │ │ +│ │ (verwaltet durch supabase CLI) │ │ +│ ├──────────────────────────────────────────────────┤ │ +│ │ - PostgreSQL 17.6 (Port 54322) │ │ +│ │ - Kong API Gateway (Port 54321) │ │ +│ │ - Supabase Studio (Port 54323) │ │ +│ │ - GoTrue Auth (intern) │ │ +│ │ - Storage API (intern) │ │ +│ │ - Realtime (intern) │ │ +│ │ - Edge Functions (intern) │ │ +│ │ - Vector/Analytics (intern) │ │ +│ └──────────────────────────────────────────────────┘ │ +│ │ +│ ┌──────────────────────────────────────────────────┐ │ +│ │ Archon Stack │ │ +│ │ (verwaltet durch docker compose) │ │ +│ ├──────────────────────────────────────────────────┤ │ +│ │ - archon-server (Port 8181) │ │ +│ │ - archon-mcp (Port 8051) │ │ +│ │ - archon-ui (Port 3737) │ │ +│ └──────────────────────────────────────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────┘ +``` + +--- + +## 🚀 Installation & Konfiguration + +### Voraussetzungen + +- Docker Desktop für Mac (läuft bereits) +- Homebrew (installiert) +- Git (installiert) + +### 1. Supabase CLI Installation + +```bash +brew install supabase/tap/supabase +# Version: 2.58.5 +``` + +### 2. Supabase Initialisierung + +```bash +cd /Volumes/DATEN/Coding/archon/supabase +supabase start +``` + +**Wichtig**: Dies erstellt Container mit dem Suffix `_supabase` (z.B. `supabase_db_supabase`) + +### 3. Datenbank-Schema anwenden + +```bash +cd /Volumes/DATEN/Coding/archon +docker exec -i supabase_db_supabase psql -U postgres -d postgres < migration/complete_setup.sql +``` + +Erstellt folgende Tabellen: +- `archon_code_examples` +- `archon_crawled_pages` +- `archon_document_versions` +- `archon_migrations` +- `archon_page_metadata` +- `archon_project_sources` +- `archon_projects` +- `archon_prompts` +- `archon_settings` +- `archon_sources` +- `archon_tasks` + +### 4. Umgebungsvariablen konfigurieren + +**Datei**: `/Volumes/DATEN/Coding/archon/.env` + +```bash +# Supabase Connection (für Docker Container) +SUPABASE_URL=http://host.docker.internal:54321 + +# JWT Service Role Key (generiert mit lokalem JWT_SECRET) +SUPABASE_SERVICE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoic2VydmljZV9yb2xlIiwiaXNzIjoic3VwYWJhc2UiLCJpYXQiOjE3NjM2NTg1MDYsImV4cCI6MjA3OTAxODUwNn0.HVH5TgwW70JZtiGdnjU4RGexDDVbGnI3mXt-diQhVy8 + +# Service Ports +ARCHON_SERVER_PORT=8181 +ARCHON_MCP_PORT=8051 +ARCHON_AGENTS_PORT=8052 +ARCHON_UI_PORT=3737 +ARCHON_DOCS_PORT=3838 +``` + +### 5. Archon Services starten + +```bash +cd /Volumes/DATEN/Coding/archon +docker compose up -d +``` + +--- + +## 🔑 Wichtige Authentifizierung-Details + +### JWT-Token-Problem und Lösung + +**Problem**: Die Standard-JWT-Tokens aus `supabase/.env` funktionieren nicht mit der laufenden Supabase-Instanz. + +**Ursache**: Supabase CLI generiert beim Start ein neues JWT_SECRET (`super-secret-jwt-token-with-at-least-32-characters-long`), das nicht mit den vordefinierten Tokens übereinstimmt. + +**Lösung**: JWT-Token mit dem korrekten Secret generieren: + +```python +import jwt +from datetime import datetime, timedelta + +secret = "super-secret-jwt-token-with-at-least-32-characters-long" + +service_role_payload = { + "role": "service_role", + "iss": "supabase", + "iat": int(datetime.now().timestamp()), + "exp": int((datetime.now() + timedelta(days=365*10)).timestamp()) +} + +token = jwt.encode(service_role_payload, secret, algorithm="HS256") +print(token) +``` + +**Wichtig**: Supabase Python Client (v2.15.1) benötigt JWT-Format, NICHT das neue `sb_secret_*` Format! + +--- + +## 📍 Zugriffspunkte + +### Supabase + +| Service | URL | Credentials | +|---------|-----|-------------| +| **Studio UI** | http://localhost:54323 | - | +| **API Gateway** | http://localhost:54321 | Service Key (siehe .env) | +| **PostgreSQL** | `postgresql://postgres:postgres@localhost:54322/postgres` | postgres/postgres | + +### Archon + +| Service | URL | Beschreibung | +|---------|-----|--------------| +| **UI** | http://localhost:3737 | Hauptanwendung | +| **API Server** | http://localhost:8181 | Backend API | +| **MCP Server** | http://localhost:8051 | Model Context Protocol | +| **Health Check** | http://localhost:8181/health | Server-Status | + +--- + +## 🛠️ Wartung & Verwaltung + +### Supabase Status prüfen + +```bash +cd /Volumes/DATEN/Coding/archon/supabase +supabase status +``` + +Zeigt: +- API URL +- Database URL +- Studio URL +- Publishable/Secret Keys +- Gestoppte Services + +### Container Status + +```bash +# Alle Container anzeigen +docker ps --format "table {{.Names}}\t{{.Status}}" + +# Nur Archon +docker ps --format "table {{.Names}}\t{{.Status}}" | grep archon + +# Nur Supabase +docker ps --format "table {{.Names}}\t{{.Status}}" | grep supabase +``` + +### Services neu starten + +**Supabase**: +```bash +cd /Volumes/DATEN/Coding/archon/supabase +supabase stop +supabase start +``` + +**Archon**: +```bash +cd /Volumes/DATEN/Coding/archon +docker compose restart +# oder für kompletten Neustart: +docker compose down && docker compose up -d +``` + +### Logs einsehen + +**Supabase**: +```bash +docker logs supabase_db_supabase -f +docker logs supabase_kong_supabase -f +``` + +**Archon**: +```bash +docker logs archon-server -f +docker logs archon-mcp -f +docker logs archon-ui -f +``` + +--- + +## 🐛 Troubleshooting + +### Problem: Container mit Status "Created" oder "Restarting" + +**Symptom**: Container ohne `_supabase` Suffix existieren und starten nicht. + +**Ursache**: Docker Compose hat versehentlich Supabase-Container erstellt (sollte nur Archon verwalten). + +**Lösung**: +```bash +# Fehlerhafte Container entfernen +docker rm -f supabase-db supabase-kong supabase-auth supabase-storage \ + supabase-studio supabase-rest supabase-analytics supabase-meta \ + supabase-edge-functions supabase-pooler supabase-vector \ + supabase-imgproxy realtime-dev.supabase-realtime + +# Überflüssiges Netzwerk entfernen +docker network rm supabase_default +``` + +### Problem: "Invalid API key" Fehler + +**Symptom**: `SupabaseException: Invalid API key` beim Start von archon-server. + +**Ursache**: Falsches JWT-Token-Format oder falsches Secret. + +**Lösung**: JWT-Token mit dem tatsächlichen Secret neu generieren (siehe Abschnitt "JWT-Token-Problem"). + +### Problem: Port-Konflikte + +**Symptom**: "Port already in use" beim Start. + +**Lösung**: +```bash +# Belegte Ports prüfen +lsof -i :54321 # Supabase API +lsof -i :8181 # Archon Server +lsof -i :3737 # Archon UI + +# Container stoppen +supabase stop +docker compose down +``` + +### Problem: Container "unhealthy" + +**Symptom**: Container läuft, aber Status zeigt "unhealthy". + +**Diagnose**: +```bash +# Logs prüfen +docker logs --tail 50 + +# Healthcheck-Details +docker inspect | grep -A 10 Health +``` + +**Häufige Ursachen**: +- Datenbankverbindung fehlgeschlagen → JWT-Token prüfen +- Port nicht erreichbar → Netzwerk-Konfiguration prüfen +- Service noch nicht bereit → Warten und Status erneut prüfen + +--- + +## 🗄️ Datenbank-Management + +### Direkter Zugriff + +```bash +# Via Docker +docker exec -it supabase_db_supabase psql -U postgres -d postgres + +# Via lokaler psql (wenn installiert) +psql -h localhost -p 54322 -U postgres -d postgres +``` + +### Backup erstellen + +```bash +# Vollständiges Backup +docker exec supabase_db_supabase pg_dump -U postgres postgres > backup_$(date +%Y%m%d_%H%M%S).sql + +# Nur Schema +docker exec supabase_db_supabase pg_dump -U postgres -s postgres > schema_backup.sql + +# Nur Daten +docker exec supabase_db_supabase pg_dump -U postgres -a postgres > data_backup.sql +``` + +### Backup wiederherstellen + +```bash +docker exec -i supabase_db_supabase psql -U postgres -d postgres < backup.sql +``` + +### Migration hinzufügen + +1. Neue Migration erstellen: +```bash +cd /Volumes/DATEN/Coding/archon/supabase +supabase migration new +``` + +2. SQL-Befehle in generierte Datei einfügen + +3. Migration anwenden: +```bash +docker exec -i supabase_db_supabase psql -U postgres -d postgres < supabase/migrations/_.sql +``` + +--- + +## 🔒 Sicherheit + +### Produktionsumgebung + +**WICHTIG**: Diese Konfiguration ist NUR für lokale Entwicklung geeignet! + +Für Produktion ändern: + +1. **JWT Secret** in `supabase/.env` ändern: +```bash +JWT_SECRET= +``` + +2. **Neue JWT-Tokens** generieren mit neuem Secret + +3. **PostgreSQL Passwort** ändern: +```bash +POSTGRES_PASSWORD= +``` + +4. **Dashboard Credentials** ändern: +```bash +DASHBOARD_USERNAME= +DASHBOARD_PASSWORD= +``` + +5. **Firewall-Regeln** konfigurieren (nur notwendige Ports öffnen) + +### API Keys sicher speichern + +Archon speichert sensible API Keys verschlüsselt in der Datenbank: +- OpenAI API Key +- Google API Key +- Anthropic API Key +- etc. + +Konfiguration über UI: http://localhost:3737/settings + +--- + +## 📊 Ressourcen-Übersicht + +### Docker Images (ca. 15.7 GB) + +**Archon** (5.69 GB): +- `archon-archon-server`: 3.77 GB +- `archon-archon-frontend`: 1.54 GB +- `archon-archon-mcp`: 385 MB + +**Supabase** (~10 GB): +- `public.ecr.aws/supabase/postgres:17.6.1.043`: 4.33 GB +- `public.ecr.aws/supabase/studio`: 1.2 GB +- `public.ecr.aws/supabase/storage-api`: 1.11 GB +- `public.ecr.aws/supabase/edge-runtime`: 1.07 GB +- `public.ecr.aws/supabase/logflare`: 1.02 GB +- `public.ecr.aws/supabase/realtime`: 659 MB +- `public.ecr.aws/supabase/postgrest`: 585 MB +- `public.ecr.aws/supabase/postgres-meta`: 568 MB +- `public.ecr.aws/supabase/kong`: 212 MB +- `public.ecr.aws/supabase/vector`: 160 MB +- `public.ecr.aws/supabase/gotrue`: 74 MB +- `public.ecr.aws/supabase/mailpit`: 43 MB + +### Laufende Container (15) + +**Archon** (3): +- archon-server +- archon-mcp +- archon-ui + +**Supabase** (12): +- supabase_db_supabase +- supabase_kong_supabase +- supabase_studio_supabase +- supabase_auth_supabase +- supabase_storage_supabase +- supabase_realtime_supabase +- supabase_rest_supabase +- supabase_vector_supabase +- supabase_analytics_supabase +- supabase_pg_meta_supabase +- supabase_edge_runtime_supabase +- supabase_inbucket_supabase + +--- + +## 📚 Referenzen + +### Offizielle Dokumentation + +- **Archon**: https://github.com/coleam00/Archon +- **Supabase**: https://supabase.com/docs +- **Supabase CLI**: https://supabase.com/docs/guides/cli + +### Wichtige Konfigurationsdateien + +- `/Volumes/DATEN/Coding/archon/.env` - Archon Umgebungsvariablen +- `/Volumes/DATEN/Coding/archon/docker-compose.yml` - Archon Services +- `/Volumes/DATEN/Coding/archon/supabase/.env` - Supabase Konfiguration +- `/Volumes/DATEN/Coding/archon/supabase/volumes/api/kong.yml` - Kong API Gateway +- `/Volumes/DATEN/Coding/archon/migration/complete_setup.sql` - Datenbank-Schema + +### Nützliche Befehle (Schnellreferenz) + +```bash +# Status prüfen +cd /Volumes/DATEN/Coding/archon +docker ps | grep -E "archon|supabase" +curl http://localhost:8181/health + +# Alles neu starten +cd supabase && supabase stop && supabase start +cd .. && docker compose restart + +# Alles stoppen +docker compose down +cd supabase && supabase stop + +# Logs verfolgen +docker compose logs -f +docker logs archon-server -f + +# Datenbank abfragen +docker exec -it supabase_db_supabase psql -U postgres -d postgres +``` + +--- + +## 🎯 Nächste Schritte + +Nach erfolgreicher Installation: + +1. **API Keys konfigurieren** unter http://localhost:3737/settings + - OpenAI API Key (für Embeddings) + - Optional: Google, Anthropic, etc. + +2. **Knowledge Base befüllen**: + - Dokumente hochladen + - Websites crawlen + +3. **MCP Server mit IDE verbinden**: + - Claude Code: `claude mcp add --transport http archon http://localhost:8051/mcp` + - Cursor/Windsurf: Siehe http://localhost:3737/mcp + +4. **Projekte & Tasks erstellen** (optional, wenn Feature aktiviert) + +--- + +## ✅ Verifizierung + +Alle Services sollten diesen Status zeigen: + +```bash +$ docker ps --format "table {{.Names}}\t{{.Status}}" | grep -E "archon|supabase" + +archon-mcp Up X minutes (healthy) +archon-ui Up X minutes (healthy) +archon-server Up X minutes (healthy) +supabase_studio_supabase Up X minutes (healthy) +supabase_db_supabase Up X minutes (healthy) +supabase_kong_supabase Up X minutes (healthy) +# ... weitere Supabase Services (alle healthy) +``` + +Healthcheck-Endpunkte: +- ✅ http://localhost:8181/health → `{"status":"healthy",...}` +- ✅ http://localhost:3737 → Archon UI lädt +- ✅ http://localhost:54323 → Supabase Studio lädt + +--- + +## 📝 Änderungsprotokoll + +### 2025-11-20 - Initiale Einrichtung +- Supabase CLI 2.58.5 installiert +- PostgreSQL 17.6 mit Archon-Schema konfiguriert +- JWT-Token-Problem identifiziert und gelöst +- Alle Docker Container bereinigt (Duplikate entfernt) +- Playwright-Tests durchgeführt (alle erfolgreich) +- Status: ✅ Produktiv + +--- + +**Maintainer**: Mathias Boni +**Zuletzt getestet**: 20. November 2025 +**Archon Version**: 0.1.0 diff --git a/PLAN.md b/PLAN.md new file mode 100644 index 0000000000..d463798c29 --- /dev/null +++ b/PLAN.md @@ -0,0 +1,344 @@ +# Auth-Token Support für Ollama Chat & Embedding Instanzen - Implementierungsplan + +## Status: ✅ VOLLSTÄNDIG ABGESCHLOSSEN UND DEPLOYED + +## Kontext + +**Aktuelle Situation:** +- Frontend hat ZWEI separate Ollama-Konfigurationen: + - **LLM/Chat**: Gespeichert in `LLM_BASE_URL` (rag_strategy) + - **Embedding**: Gespeichert in `OLLAMA_EMBEDDING_URL` (rag_strategy) +- Backend liest diese URLs und erstellt OpenAI-kompatible Clients +- **PROBLEM GELÖST**: Auth-Token-Unterstützung für geschützte Ollama-Instanzen implementiert + +## Ziel ✅ ERREICHT + +Für BEIDE Ollama-Instanzen (Chat & Embedding) optionale Auth-Token-Felder hinzugefügt: +- ✅ Checkbox "Use Authentication" in jedem Modal +- ✅ Password-Input für Auth-Token (nur sichtbar wenn Checkbox aktiviert) +- ✅ Backend nutzt die korrekten Token basierend auf Operation (Chat vs. Embedding) + +## Implementierte Änderungen + +### ✅ 1. Frontend: RAGSettings.tsx erweitert + +**Datei**: `archon-ui-main/src/components/settings/RAGSettings.tsx` + +**State-Management (Zeile 207-219):** +```typescript +const [llmInstanceConfig, setLLMInstanceConfig] = useState({ + name: '', + url: ragSettings.LLM_BASE_URL || 'http://host.docker.internal:11434/v1', + useAuth: false, + authToken: '' +}); + +const [embeddingInstanceConfig, setEmbeddingInstanceConfig] = useState({ + name: '', + url: ragSettings.OLLAMA_EMBEDDING_URL || 'http://host.docker.internal:11434/v1', + useAuth: false, + authToken: '' +}); +``` + +**useEffect Hooks (Zeile 226-270):** +- ✅ Lädt `OLLAMA_CHAT_AUTH_TOKEN` aus ragSettings +- ✅ Lädt `OLLAMA_EMBEDDING_AUTH_TOKEN` aus ragSettings +- ✅ Setzt `useAuth` Checkbox automatisch basierend auf vorhandenem Token + +**Edit LLM Instance Modal (Zeile 2209-2232):** +- ✅ Checkbox "Use Authentication" +- ✅ Conditional Password-Input für Auth-Token +- ✅ Beim Speichern (Zeile 2244-2250): Speichert `OLLAMA_CHAT_AUTH_TOKEN` in ragSettings + +**Edit Embedding Instance Modal (Zeile 2299-2322):** +- ✅ Checkbox "Use Authentication" +- ✅ Conditional Password-Input für Auth-Token +- ✅ Beim Speichern (Zeile 2334-2340): Speichert `OLLAMA_EMBEDDING_AUTH_TOKEN` in ragSettings + +### ✅ 2. Backend: llm_provider_service.py angepasst + +**Datei**: `python/src/server/services/llm_provider_service.py` + +**Funktion `get_llm_client()` - Hauptimplementierung (Zeile 455-459):** +```python +# Get correct auth token based on operation type +if use_embedding_provider or instance_type == "embedding": + ollama_auth_token = rag_settings.get("OLLAMA_EMBEDDING_AUTH_TOKEN", "ollama") +else: + ollama_auth_token = rag_settings.get("OLLAMA_CHAT_AUTH_TOKEN", "ollama") +``` + +**Fallback-Code (Zeile 422-426):** +```python +# Get correct auth token based on operation type +if use_embedding_provider: + ollama_auth_token = rag_settings.get("OLLAMA_EMBEDDING_AUTH_TOKEN", "ollama") +else: + ollama_auth_token = rag_settings.get("OLLAMA_CHAT_AUTH_TOKEN", "ollama") +``` + +### ✅ 3. Datenbank-Schema + +**KEINE Änderungen nötig!** +- ✅ Nutzt existierende `archon_settings` Tabelle +- ✅ Neue Keys werden automatisch gespeichert: + - `OLLAMA_CHAT_AUTH_TOKEN` (Kategorie: rag_strategy) + - `OLLAMA_EMBEDDING_AUTH_TOKEN` (Kategorie: rag_strategy) + +## Deployment Status + +### ✅ 4. Frontend Build + +```bash +cd archon-ui-main +npm run build +``` + +**Status**: ✅ ABGESCHLOSSEN + +### ✅ 5. Docker Images neu bauen und deployen + +```bash +cd /Volumes/DATEN/Coding/INFRASTRUCTURE_PROJECT/archon-local_supabase/archon +docker compose down +docker compose build --no-cache +docker compose up -d +``` + +**Status**: ✅ ABGESCHLOSSEN + +**Deployment Zeitpunkt**: 2025-11-20 + +**Laufende Services**: +- ✅ `archon-server` (Port 8181) - healthy +- ✅ `archon-mcp` (Port 8051) - running +- ✅ `archon-ui` (Port 3737) - running + +### 🧪 6. Testing + +**Bereit zum Testen!** Das System ist deployed und läuft. + +**Test-Anleitung**: + +1. **UI öffnen**: http://localhost:3737 +2. **Settings öffnen** → RAG Settings Tab +3. **LLM Instance konfigurieren**: + - Klicke auf "Edit" bei der LLM Instance + - Aktiviere "Use Authentication" Checkbox + - Trage dein Ollama Auth-Token ein + - Speichern +4. **Embedding Instance konfigurieren**: + - Klicke auf "Edit" bei der Embedding Instance + - Aktiviere "Use Authentication" Checkbox + - Trage dein Ollama Auth-Token ein (kann unterschiedlich sein) + - Speichern +5. **RAG-Funktionalität testen**: + - Starte einen Crawl oder Search + - Verifiziere, dass die geschützte Ollama-Instanz verwendet wird +6. **Backend-Logs prüfen** (optional): + ```bash + docker compose logs -f archon-server | grep -i "ollama\|auth" + ``` + +**Erwartetes Verhalten**: +- ✅ Auth-Token wird als Bearer Token im Authorization Header gesendet +- ✅ Ollama-Instanz akzeptiert authentifizierte Requests +- ✅ Ohne Auth-Token: Placeholder "required-but-ignored" wird verwendet (abwärtskompatibel) + +## Update: 2025-11-20 - Health-Check & Summary Fixes + +### Problem +Nach dem initialen Deployment wurden zwei Probleme identifiziert: +1. **Health-Check zeigt "Offline"**: Der Health-Check-Endpoint verwendete kein Auth-Token für geschützte Instanzen +2. **Auth-Token nicht sichtbar in Summary**: Die Summary-Tabelle zeigte nicht an, ob ein Auth-Token konfiguriert ist + +### Implementierte Fixes + +#### ✅ Frontend: Auth-Token Status in Summary anzeigen +**Datei**: `archon-ui-main/src/components/settings/RAGSettings.tsx` (Zeile 1723-1750) + +Neue Zeile in der Summary-Tabelle zwischen "Instance URL" und "Status": +```typescript + + Authentication + + {activeSelection === 'chat' ? ( + llmInstanceConfig.authToken ? ( + + + + + Token configured + + ) : ( + No authentication + ) + ) : ( + // Gleiche Logik für Embedding Instance + )} + + +``` + +#### ✅ Backend: Health-Check mit Auth-Token Support + +**Datei 1**: `python/src/server/services/ollama/model_discovery_service.py` (Zeile 958-993) + +Erweiterte `check_instance_health()` Methode um optionalen `auth_token` Parameter: +```python +async def check_instance_health(self, instance_url: str, auth_token: str | None = None) -> InstanceHealthStatus: + # Prepare headers with optional auth token + headers = {} + if auth_token: + headers["Authorization"] = f"Bearer {auth_token}" + + async with httpx.AsyncClient(timeout=httpx.Timeout(10)) as client: + ping_url = f"{instance_url.rstrip('/')}/api/tags" + response = await client.get(ping_url, headers=headers) + # ... +``` + +**Datei 2**: `python/src/server/api_routes/ollama_api.py` (Zeile 142-199) + +Health-Check-Endpoint liest Auth-Tokens aus RAG Settings: +```python +@router.get("/instances/health") +async def health_check_endpoint( + instance_urls: list[str] = Query(...), + include_models: bool = Query(False) +) -> dict[str, Any]: + # Get auth tokens from RAG settings + rag_settings = await credential_service.get_credentials_by_category("rag_strategy") + + llm_base_url = rag_settings.get("LLM_BASE_URL", "").replace("/v1", "").rstrip("/") + embedding_base_url = rag_settings.get("OLLAMA_EMBEDDING_URL", "").replace("/v1", "").rstrip("/") + + chat_auth_token = rag_settings.get("OLLAMA_CHAT_AUTH_TOKEN", "") + embedding_auth_token = rag_settings.get("OLLAMA_EMBEDDING_AUTH_TOKEN", "") + + # Determine which auth token to use based on URL matching + for instance_url in instance_urls: + url = instance_url.rstrip('/') + auth_token = None + if url == llm_base_url and chat_auth_token: + auth_token = chat_auth_token + elif url == embedding_base_url and embedding_auth_token: + auth_token = embedding_auth_token + + health_status = await model_discovery_service.check_instance_health(url, auth_token=auth_token) + # ... +``` + +### ✅ Deployment (2025-11-20 16:00) + +- ✅ Frontend neu gebaut +- ✅ Docker Images neu gebaut (Frontend, Server, MCP) +- ✅ Container neu deployed +- ✅ Alle Services laufen: archon-server (healthy), archon-mcp (healthy), archon-ui (running) + +### Erwartetes Verhalten (nach Fix) + +1. **Summary zeigt Auth-Token Status**: + - ✅ "Token configured" mit Schloss-Icon wenn Token gesetzt + - ✅ "No authentication" wenn kein Token + +2. **Health-Check funktioniert mit Auth**: + - ✅ Backend sendet Bearer Token im Authorization Header + - ✅ Health-Check sollte jetzt "Online" zeigen für geschützte Instanzen + - ✅ Status-Anfrage erfolgt automatisch beim Öffnen der RAG Settings + +### ✅ Final Verification (2025-11-20 22:05) + +**Datenbank-Status**: Alle erforderlichen Settings sind gespeichert: +```sql + key | value | category +-----------------------------+-----------------------------------------+-------------- + LLM_BASE_URL | https://ollama.brusdeylins.info | rag_strategy + OLLAMA_CHAT_AUTH_TOKEN | ollama_13107e338aa16a6a8295592ce050f6cb | rag_strategy + OLLAMA_EMBEDDING_AUTH_TOKEN | ollama_13107e338aa16a6a8295592ce050f6cb | rag_strategy + OLLAMA_EMBEDDING_URL | https://ollama.brusdeylins.info | rag_strategy +``` + +**Health-Check-Test**: Erfolgreiche Authentifizierung mit geschützter Instanz: +```json +{ + "summary": { + "total_instances": 1, + "healthy_instances": 1, + "unhealthy_instances": 0, + "average_response_time_ms": 672.12 + }, + "instance_status": { + "https://ollama.brusdeylins.info": { + "is_healthy": true, + "response_time_ms": 672.12, + "models_available": 5, + "error_message": null + } + } +} +``` + +**Ergebnis**: ✅ **VOLLSTÄNDIG FUNKTIONSFÄHIG** +- Health-Check zeigt "Online" Status +- 5 Modelle erfolgreich erkannt +- Bearer Token-Authentifizierung funktioniert +- Response-Zeit: ~672ms (akzeptabel) + +## Geänderte Dateien (Gesamt) + +1. ✅ `archon-ui-main/src/components/settings/RAGSettings.tsx` (Initial + Summary-Fix) +2. ✅ `python/src/server/services/llm_provider_service.py` (Token-Auswahl) +3. ✅ `python/src/server/services/ollama/model_discovery_service.py` (Health-Check Auth) +4. ✅ `python/src/server/api_routes/ollama_api.py` (Health-Check Endpoint) + +## Technische Details + +### Frontend → Backend Datenfluss + +1. **User füllt Modal aus**: + - URL: `http://my-ollama:11434` + - Checkbox "Use Authentication": ✓ + - Auth Token: `my-secret-token` + +2. **Frontend speichert in archon_settings**: + ```json + { + "LLM_BASE_URL": "http://my-ollama:11434", + "OLLAMA_CHAT_AUTH_TOKEN": "my-secret-token" + } + ``` + +3. **Backend liest und verwendet**: + ```python + # In llm_provider_service.py + ollama_base_url = await _get_optimal_ollama_instance() # → "http://my-ollama:11434/v1" + ollama_auth_token = rag_settings.get("OLLAMA_CHAT_AUTH_TOKEN", "ollama") # → "my-secret-token" + + client = openai.AsyncOpenAI( + api_key=ollama_auth_token, # ← Wird als Bearer Token im HTTP Header verwendet + base_url=ollama_base_url + ) + ``` + +### Sicherheit + +- ✅ Token-Felder sind `type="password"` (versteckte Eingabe) +- ✅ Token wird nur gespeichert wenn Checkbox aktiviert ist +- ✅ Leerer Token = kein Auth-Header (abwärtskompatibel) +- ⚠️ Token wird im Klartext in `archon_settings` gespeichert (Future: Verschlüsselung) + +## Abwärtskompatibilität + +✅ **100% kompatibel mit bestehenden Installationen:** +- Ohne Auth-Token: Standard-Wert `"ollama"` wird verwendet +- Bestehende Instanzen funktionieren weiterhin +- Neue Felder sind optional + +## Lessons Learned + +1. ✅ Keine DB-Schema-Änderungen nötig bei generischen Key-Value-Tabellen +2. ✅ TypeScript `as any` für neue Settings-Keys akzeptabel während Entwicklung +3. ✅ Separate Token für Chat/Embedding ermöglicht flexible Deployment-Szenarien +4. ✅ useEffect Hooks müssen Token in Dependencies aufnehmen für korrektes Laden diff --git a/QUICKSTART.md b/QUICKSTART.md new file mode 100644 index 0000000000..b42dd806d3 --- /dev/null +++ b/QUICKSTART.md @@ -0,0 +1,47 @@ +# Archon + Supabase - Quick Start Guide + +> Schnellstart für die lokale Entwicklungsumgebung + +## ⚡ Schnellstart (für erfahrene Entwickler) + +```bash +# 1. Supabase starten +cd /Volumes/DATEN/Coding/archon/supabase +supabase start + +# 2. Archon starten +cd /Volumes/DATEN/Coding/archon +docker compose up -d + +# 3. Status prüfen +docker ps | grep -E "archon|supabase" +curl http://localhost:8181/health +``` + +## 🌐 Zugriff + +| Service | URL | Beschreibung | +|---------|-----|-------------| +| **Archon UI** | http://localhost:3737 | Hauptanwendung | +| **Supabase Studio** | http://localhost:54323 | Datenbank-UI | +| **API Server** | http://localhost:8181 | Backend API | +| **MCP Server** | http://localhost:8051/mcp | Model Context Protocol | + +## 🛑 Stoppen + +```bash +# Archon stoppen +docker compose down + +# Supabase stoppen +cd supabase && supabase stop +``` + +## 📚 Vollständige Dokumentation + +Siehe **[INFRASTRUCTURE.md](./INFRASTRUCTURE.md)** für: +- Detaillierte Installation +- Troubleshooting +- Datenbank-Management +- Sicherheitshinweise +- Backup/Restore diff --git a/archon-ui-main/package-lock.json b/archon-ui-main/package-lock.json index 37b3e9a745..16740b78ad 100644 --- a/archon-ui-main/package-lock.json +++ b/archon-ui-main/package-lock.json @@ -42,6 +42,7 @@ }, "devDependencies": { "@biomejs/biome": "2.2.2", + "@playwright/test": "^1.56.1", "@tailwindcss/postcss": "4.1.2", "@tailwindcss/vite": "4.1.2", "@testing-library/jest-dom": "^6.4.6", @@ -2389,6 +2390,22 @@ "integrity": "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==", "license": "MIT" }, + "node_modules/@playwright/test": { + "version": "1.56.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.56.1.tgz", + "integrity": "sha512-vSMYtL/zOcFpvJCW71Q/OEGQb7KYBPAdKh35WNSkaZA75JlAO8ED8UN6GUNTm3drWomcbcqRPFqQbLae8yBTdg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright": "1.56.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@polka/url": { "version": "1.0.0-next.29", "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", @@ -9752,6 +9769,53 @@ "dev": true, "license": "MIT" }, + "node_modules/playwright": { + "version": "1.56.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.56.1.tgz", + "integrity": "sha512-aFi5B0WovBHTEvpM3DzXTUaeN6eN0qWnTkKx4NQaH4Wvcmc153PdaY2UBdSYKaGYw+UyWXSVyxDUg5DoPEttjw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.56.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.56.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.56.1.tgz", + "integrity": "sha512-hutraynyn31F+Bifme+Ps9Vq59hKuUCz7H1kDOcBs+2oGguKkWTU50bBWrtz34OUWmIwpBTWDxaRPXrIXkgvmQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/playwright/node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/possible-typed-array-names": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", diff --git a/archon-ui-main/package.json b/archon-ui-main/package.json index 576b78ae2b..4419044216 100644 --- a/archon-ui-main/package.json +++ b/archon-ui-main/package.json @@ -62,6 +62,7 @@ }, "devDependencies": { "@biomejs/biome": "2.2.2", + "@playwright/test": "^1.56.1", "@tailwindcss/postcss": "4.1.2", "@tailwindcss/vite": "4.1.2", "@testing-library/jest-dom": "^6.4.6", diff --git a/archon-ui-main/src/components/settings/OllamaConfigurationPanel.tsx b/archon-ui-main/src/components/settings/OllamaConfigurationPanel.tsx index 4da6f9a0de..a1bba2233e 100644 --- a/archon-ui-main/src/components/settings/OllamaConfigurationPanel.tsx +++ b/archon-ui-main/src/components/settings/OllamaConfigurationPanel.tsx @@ -35,6 +35,8 @@ const OllamaConfigurationPanel: React.FC = ({ const [newInstanceUrl, setNewInstanceUrl] = useState(''); const [newInstanceName, setNewInstanceName] = useState(''); const [newInstanceType, setNewInstanceType] = useState<'chat' | 'embedding'>('chat'); + const [newInstanceUseAuth, setNewInstanceUseAuth] = useState(false); + const [newInstanceAuthToken, setNewInstanceAuthToken] = useState(''); const [showAddInstance, setShowAddInstance] = useState(false); const [discoveringModels, setDiscoveringModels] = useState(false); const [modelDiscoveryResults, setModelDiscoveryResults] = useState(null); @@ -233,7 +235,8 @@ const OllamaConfigurationPanel: React.FC = ({ isEnabled: true, isPrimary: false, loadBalancingWeight: 100, - instanceType: separateHosts ? newInstanceType : 'both' + instanceType: separateHosts ? newInstanceType : 'both', + ...(newInstanceUseAuth && newInstanceAuthToken.trim() && { authToken: newInstanceAuthToken.trim() }) }; try { @@ -246,6 +249,8 @@ const OllamaConfigurationPanel: React.FC = ({ setNewInstanceUrl(''); setNewInstanceName(''); setNewInstanceType('chat'); + setNewInstanceUseAuth(false); + setNewInstanceAuthToken(''); setShowAddInstance(false); showToast(`Added new Ollama instance: ${newInstance.name}`, 'success'); @@ -703,8 +708,8 @@ const OllamaConfigurationPanel: React.FC = ({ size="sm" onClick={() => setNewInstanceType('chat')} className={cn( - newInstanceType === 'chat' - ? 'bg-blue-600 text-white' + newInstanceType === 'chat' + ? 'bg-blue-600 text-white' : 'text-blue-600 border-blue-600' )} > @@ -715,8 +720,8 @@ const OllamaConfigurationPanel: React.FC = ({ size="sm" onClick={() => setNewInstanceType('embedding')} className={cn( - newInstanceType === 'embedding' - ? 'bg-blue-600 text-white' + newInstanceType === 'embedding' + ? 'bg-blue-600 text-white' : 'text-blue-600 border-blue-600' )} > @@ -725,7 +730,29 @@ const OllamaConfigurationPanel: React.FC = ({ )} - + + {/* Authentication Settings */} +
+ + {newInstanceUseAuth && ( + setNewInstanceAuthToken(e.target.value)} + className="text-sm" + /> + )} +
+
+ +
+ + {activeSelection === 'chat' ? ( // Chat Model Configuration
- {llmInstanceConfig.name && llmInstanceConfig.url ? ( + {llmInstanceConfig.url ? ( <>
-
{llmInstanceConfig.name}
+
{llmInstanceConfig.name || 'LLM Instance'}
{llmInstanceConfig.url}
@@ -1600,10 +1732,10 @@ const manualTestConnection = async ( ) : ( // Embedding Model Configuration
- {embeddingInstanceConfig.name && embeddingInstanceConfig.url ? ( + {embeddingInstanceConfig.url ? ( <>
-
{embeddingInstanceConfig.name}
+
{embeddingInstanceConfig.name || 'Embedding Instance'}
{embeddingInstanceConfig.url}
@@ -1710,6 +1842,34 @@ const manualTestConnection = async ( } + + Authentication + + {activeSelection === 'chat' ? ( + llmInstanceConfig.authToken ? ( + + + + + Token configured + + ) : ( + No authentication + ) + ) : ( + embeddingInstanceConfig.authToken ? ( + + + + + Token configured + + ) : ( + No authentication + ) + )} + + Status @@ -1726,11 +1886,16 @@ const manualTestConnection = async ( Selected Model - - {activeSelection === 'chat' - ? (getDisplayedChatModel(ragSettings) || No model selected) - : (getDisplayedEmbeddingModel(ragSettings) || No model selected) - } + + {activeSelection === 'chat' ? ( + + {ragSettings.CHAT_MODEL || Not selected} + + ) : ( + + {ragSettings.EMBEDDING_MODEL || Not selected} + + )} @@ -2183,7 +2348,9 @@ const manualTestConnection = async ( // Sync embedding instance with LLM instance setEmbeddingInstanceConfig({ name: llmInstanceConfig.name || 'Default Ollama', - url: llmInstanceConfig.url + url: llmInstanceConfig.url, + useAuth: embeddingInstanceConfig.useAuth, + authToken: embeddingInstanceConfig.authToken }); } }} @@ -2193,6 +2360,31 @@ const manualTestConnection = async ( Use same host for embedding instance
+ + {/* Authentication Settings */} +
+
+ setLLMInstanceConfig({...llmInstanceConfig, useAuth: e.target.checked})} + className="w-4 h-4 text-green-600 bg-gray-100 border-gray-300 rounded focus:ring-green-500 dark:focus:ring-green-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600" + /> + +
+ {llmInstanceConfig.useAuth && ( + setLLMInstanceConfig({...llmInstanceConfig, authToken: e.target.value})} + className="text-sm" + /> + )} +
@@ -2205,7 +2397,12 @@ const manualTestConnection = async (
@@ -2265,7 +2487,12 @@ const manualTestConnection = async (