refactored gateway for scaling
This commit is contained in:
parent
5d5fb4d56f
commit
39f33b0fb8
24 changed files with 843 additions and 420 deletions
439
gwserver/app.py
439
gwserver/app.py
|
|
@ -1,45 +1,38 @@
|
|||
from fastapi import FastAPI, File, UploadFile, HTTPException, Depends, Body, Query, status
|
||||
from fastapi import FastAPI, HTTPException, Depends, Body, status
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi.responses import JSONResponse, Response
|
||||
from fastapi.responses import JSONResponse
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from fastapi.security import OAuth2PasswordRequestForm, OAuth2PasswordBearer
|
||||
from fastapi.security import OAuth2PasswordRequestForm
|
||||
|
||||
import uvicorn
|
||||
from typing import List, Dict, Any, Optional
|
||||
import uuid
|
||||
from typing import Dict, Any
|
||||
import os
|
||||
import json
|
||||
import asyncio
|
||||
import logging
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import timedelta
|
||||
|
||||
# Import interfaces
|
||||
from interface_gateway import get_gateway_interface
|
||||
from interface_lucydom import get_lucydom_interface
|
||||
from interface_agentservice import get_agent_service
|
||||
from modules.gateway_interface import get_gateway_interface
|
||||
from modules.agentservice_interface import get_agent_service
|
||||
|
||||
# Import auth module
|
||||
from auth import (
|
||||
create_access_token,
|
||||
get_current_user,
|
||||
get_current_active_user,
|
||||
get_user_context,
|
||||
ACCESS_TOKEN_EXPIRE_MINUTES
|
||||
)
|
||||
|
||||
# Import models (restructured)
|
||||
from model_gateway import User, UserInDB, Token, Mandate
|
||||
from model_lucydom import (
|
||||
Workspace,
|
||||
Agent,
|
||||
DataObject,
|
||||
Prompt,
|
||||
WorkflowRequest,
|
||||
WorkflowResponse,
|
||||
LogEntry,
|
||||
Result
|
||||
)
|
||||
# Import models - generisch importieren
|
||||
import modules.gateway_model as gateway_model
|
||||
|
||||
# Import router modules
|
||||
from routes.attributes import router as attributes_router
|
||||
from routes.workspace import router as workspace_router
|
||||
from routes.agent import router as agent_router
|
||||
from routes.file import router as file_router
|
||||
from routes.prompt import router as prompt_router
|
||||
from routes.workflow import router as workflow_router
|
||||
from routes.mandate import router as mandate_router
|
||||
|
||||
# Konfiguration des Loggers
|
||||
logging.basicConfig(
|
||||
|
|
@ -60,8 +53,6 @@ app.add_middleware(
|
|||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
# API - ENDPUNKTE
|
||||
|
||||
# Statischer Folder für Frontend
|
||||
os.makedirs(os.path.join(os.getcwd(), "static"), exist_ok=True)
|
||||
app.mount("/static", StaticFiles(directory="static"), name="static")
|
||||
|
|
@ -77,7 +68,7 @@ async def get_test():
|
|||
return "OK 1.0"
|
||||
|
||||
# Token-Endpunkt für Login
|
||||
@app.post("/token", response_model=Token, tags=["General"])
|
||||
@app.post("/token", response_model=gateway_model.Token, tags=["General"])
|
||||
async def login_for_access_token(form_data: OAuth2PasswordRequestForm = Depends()):
|
||||
# Gateway-Interface ohne Kontext initialisieren
|
||||
gateway = get_gateway_interface()
|
||||
|
|
@ -106,7 +97,7 @@ async def login_for_access_token(form_data: OAuth2PasswordRequestForm = Depends(
|
|||
|
||||
|
||||
# Benutzerregistrierung
|
||||
@app.post("/api/users/register", response_model=User, tags=["General"])
|
||||
@app.post("/api/users/register", response_model=gateway_model.User, tags=["General"])
|
||||
async def register_user(user_data: dict = Body(...), current_user: Dict[str, Any] = Depends(get_current_active_user)):
|
||||
"""Neuen Benutzer registrieren"""
|
||||
# Nur Benutzer des gleichen Mandanten dürfen erstellt werden
|
||||
|
|
@ -137,390 +128,14 @@ async def read_users_me(current_user: Dict[str, Any] = Depends(get_current_activ
|
|||
return current_user
|
||||
|
||||
|
||||
# Workspace-Endpunkte
|
||||
@app.get("/api/workspaces", tags=["Workspaces"], response_model=List[Dict[str, Any]])
|
||||
async def get_workspaces(current_user: Dict[str, Any] = Depends(get_current_active_user)):
|
||||
"""Alle verfügbaren Workspaces abrufen"""
|
||||
mandate_id, user_id = await get_user_context(current_user)
|
||||
|
||||
# LucyDOM-Interface mit Benutzerkontext initialisieren
|
||||
lucy_interface = get_lucydom_interface(mandate_id, user_id)
|
||||
|
||||
return lucy_interface.get_all_workspaces()
|
||||
|
||||
|
||||
@app.get("/api/workspaces/{workspace_id}", tags=["Workspaces"], response_model=Dict[str, Any])
|
||||
async def get_workspace(
|
||||
workspace_id: int,
|
||||
current_user: Dict[str, Any] = Depends(get_current_active_user)
|
||||
):
|
||||
"""Einen bestimmten Workspace mit allen Details abrufen"""
|
||||
mandate_id, user_id = await get_user_context(current_user)
|
||||
|
||||
# LucyDOM-Interface mit Benutzerkontext initialisieren
|
||||
lucy_interface = get_lucydom_interface(mandate_id, user_id)
|
||||
|
||||
workspace = lucy_interface.get_workspace(workspace_id)
|
||||
if not workspace:
|
||||
raise HTTPException(status_code=404, detail=f"Workspace mit ID {workspace_id} nicht gefunden")
|
||||
|
||||
return workspace
|
||||
|
||||
|
||||
@app.post("/api/workspaces", tags=["Workspaces"], response_model=Dict[str, Any])
|
||||
async def create_workspace(
|
||||
workspace: Dict[str, Any] = Body(...),
|
||||
current_user: Dict[str, Any] = Depends(get_current_active_user)
|
||||
):
|
||||
"""Einen neuen Workspace erstellen"""
|
||||
mandate_id, user_id = await get_user_context(current_user)
|
||||
|
||||
# LucyDOM-Interface mit Benutzerkontext initialisieren
|
||||
lucy_interface = get_lucydom_interface(mandate_id, user_id)
|
||||
|
||||
new_workspace = lucy_interface.create_workspace(name=workspace.get("name", "Neuer Workspace"))
|
||||
return new_workspace
|
||||
|
||||
|
||||
# Agenten-Endpunkte
|
||||
@app.get("/api/agents", tags=["Agents"], response_model=List[Dict[str, Any]])
|
||||
async def get_agents(
|
||||
workspace_id: Optional[int] = Query(None),
|
||||
current_user: Dict[str, Any] = Depends(get_current_active_user)
|
||||
):
|
||||
"""Alle Agenten oder Agenten eines bestimmten Workspaces abrufen"""
|
||||
mandate_id, user_id = await get_user_context(current_user)
|
||||
|
||||
# LucyDOM-Interface mit Benutzerkontext initialisieren
|
||||
lucy_interface = get_lucydom_interface(mandate_id, user_id)
|
||||
|
||||
if workspace_id:
|
||||
return lucy_interface.get_agents_by_workspace(workspace_id)
|
||||
|
||||
return lucy_interface.get_all_agents()
|
||||
|
||||
|
||||
@app.post("/api/agents", tags=["Agents"], response_model=Dict[str, Any])
|
||||
async def create_agent(
|
||||
agent: Dict[str, Any] = Body(...),
|
||||
current_user: Dict[str, Any] = Depends(get_current_active_user)
|
||||
):
|
||||
"""Einen neuen Agenten erstellen"""
|
||||
mandate_id, user_id = await get_user_context(current_user)
|
||||
|
||||
# LucyDOM-Interface mit Benutzerkontext initialisieren
|
||||
lucy_interface = get_lucydom_interface(mandate_id, user_id)
|
||||
|
||||
workspace_id = agent.get("workspace_id")
|
||||
|
||||
if not workspace_id:
|
||||
raise HTTPException(status_code=400, detail="workspace_id ist erforderlich")
|
||||
|
||||
# Workspace existiert?
|
||||
workspace = lucy_interface.get_workspace(workspace_id)
|
||||
if not workspace:
|
||||
raise HTTPException(status_code=404, detail=f"Workspace mit ID {workspace_id} nicht gefunden")
|
||||
|
||||
new_agent = lucy_interface.create_agent(
|
||||
name=agent.get("name", "Neuer Agent"),
|
||||
agent_type=agent.get("type", "generic"),
|
||||
workspace_id=workspace_id,
|
||||
capabilities=agent.get("capabilities", []),
|
||||
description=agent.get("description", "")
|
||||
)
|
||||
|
||||
return new_agent
|
||||
|
||||
|
||||
# Datei-Endpunkte
|
||||
@app.get("/api/files", tags=["Files"], response_model=List[Dict[str, Any]])
|
||||
async def get_files(current_user: Dict[str, Any] = Depends(get_current_active_user)):
|
||||
"""Alle verfügbaren Dateien abrufen"""
|
||||
mandate_id, user_id = await get_user_context(current_user)
|
||||
|
||||
# LucyDOM-Interface mit Benutzerkontext initialisieren
|
||||
lucy_interface = get_lucydom_interface(mandate_id, user_id)
|
||||
|
||||
return lucy_interface.get_all_files()
|
||||
|
||||
|
||||
@app.post("/api/files/upload", tags=["Files"])
|
||||
async def upload_file(
|
||||
file: UploadFile = File(...),
|
||||
current_user: Dict[str, Any] = Depends(get_current_active_user)
|
||||
):
|
||||
"""Eine Datei hochladen"""
|
||||
mandate_id, user_id = await get_user_context(current_user)
|
||||
|
||||
# LucyDOM-Interface mit Benutzerkontext initialisieren
|
||||
lucy_interface = get_lucydom_interface(mandate_id, user_id)
|
||||
|
||||
try:
|
||||
# Generiere eine eindeutige ID für die Datei
|
||||
file_id = str(uuid.uuid4())
|
||||
file_ext = os.path.splitext(file.filename)[1]
|
||||
file_path = os.path.join(get_agent_service(mandate_id, user_id).upload_dir, f"{file_id}{file_ext}")
|
||||
|
||||
# Datei speichern
|
||||
with open(file_path, "wb") as f:
|
||||
content = await file.read()
|
||||
f.write(content)
|
||||
|
||||
# Dateityp bestimmen
|
||||
file_type = "image" if file.content_type and "image" in file.content_type else "document"
|
||||
|
||||
# In Datenbank speichern
|
||||
new_file = lucy_interface.create_file(
|
||||
name=file.filename,
|
||||
file_type=file_type,
|
||||
content_type=file.content_type,
|
||||
size=os.path.getsize(file_path),
|
||||
path=file_path
|
||||
)
|
||||
|
||||
return {
|
||||
"id": new_file["id"],
|
||||
"name": new_file["name"],
|
||||
"type": new_file["type"],
|
||||
"size": f"{new_file['size'] / (1024 * 1024):.1f} MB",
|
||||
"upload_date": new_file.get("upload_date")
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Fehler beim Hochladen der Datei: {e}")
|
||||
raise HTTPException(status_code=500, detail=f"Fehler beim Hochladen der Datei: {str(e)}")
|
||||
|
||||
|
||||
@app.delete("/api/files/{file_id}", tags=["Files"])
|
||||
async def delete_file(
|
||||
file_id: int,
|
||||
current_user: Dict[str, Any] = Depends(get_current_active_user)
|
||||
):
|
||||
"""Löscht eine Datei"""
|
||||
mandate_id, user_id = await get_user_context(current_user)
|
||||
|
||||
# LucyDOM-Interface mit Benutzerkontext initialisieren
|
||||
lucy_interface = get_lucydom_interface(mandate_id, user_id)
|
||||
|
||||
try:
|
||||
# Hole die Datei aus der Datenbank
|
||||
file = lucy_interface.get_file(file_id)
|
||||
if not file:
|
||||
raise HTTPException(status_code=404, detail=f"Datei mit ID {file_id} nicht gefunden")
|
||||
|
||||
# Prüfe, ob die physische Datei existiert
|
||||
if "path" in file and os.path.exists(file["path"]):
|
||||
try:
|
||||
# Versuche, die physische Datei zu löschen
|
||||
os.remove(file["path"])
|
||||
except Exception as e:
|
||||
logger.warning(f"Konnte physische Datei nicht löschen: {e}")
|
||||
|
||||
# Lösche die Datei aus der Datenbank
|
||||
success = lucy_interface.delete_file(file_id)
|
||||
|
||||
if not success:
|
||||
raise HTTPException(status_code=500, detail="Fehler beim Löschen der Datei aus der Datenbank")
|
||||
|
||||
return {"success": True, "message": f"Datei '{file.get('name', 'unbekannt')}' wurde gelöscht"}
|
||||
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(f"Fehler beim Löschen der Datei: {e}")
|
||||
raise HTTPException(status_code=500, detail=f"Fehler beim Löschen der Datei: {str(e)}")
|
||||
|
||||
|
||||
# Prompt-Endpunkte
|
||||
@app.get("/api/prompts", tags=["Prompts"], response_model=List[Dict[str, Any]])
|
||||
async def get_prompts(
|
||||
workspace_id: Optional[int] = Query(None),
|
||||
current_user: Dict[str, Any] = Depends(get_current_active_user)
|
||||
):
|
||||
"""Alle Prompts oder Prompts eines bestimmten Workspaces abrufen"""
|
||||
mandate_id, user_id = await get_user_context(current_user)
|
||||
|
||||
# LucyDOM-Interface mit Benutzerkontext initialisieren
|
||||
lucy_interface = get_lucydom_interface(mandate_id, user_id)
|
||||
|
||||
if workspace_id:
|
||||
return lucy_interface.get_prompts_by_workspace(workspace_id)
|
||||
|
||||
return lucy_interface.get_all_prompts()
|
||||
|
||||
|
||||
@app.post("/api/prompts", tags=["Prompts"], response_model=Dict[str, Any])
|
||||
async def create_prompt(
|
||||
prompt: Dict[str, Any] = Body(...),
|
||||
current_user: Dict[str, Any] = Depends(get_current_active_user)
|
||||
):
|
||||
"""Einen neuen Prompt erstellen"""
|
||||
mandate_id, user_id = await get_user_context(current_user)
|
||||
|
||||
# LucyDOM-Interface mit Benutzerkontext initialisieren
|
||||
lucy_interface = get_lucydom_interface(mandate_id, user_id)
|
||||
|
||||
workspace_id = prompt.get("workspace_id")
|
||||
|
||||
if not workspace_id:
|
||||
raise HTTPException(status_code=400, detail="workspace_id ist erforderlich")
|
||||
|
||||
# Workspace existiert?
|
||||
workspace = lucy_interface.get_workspace(workspace_id)
|
||||
if not workspace:
|
||||
raise HTTPException(status_code=404, detail=f"Workspace mit ID {workspace_id} nicht gefunden")
|
||||
|
||||
new_prompt = lucy_interface.create_prompt(
|
||||
content=prompt.get("content", ""),
|
||||
workspace_id=workspace_id
|
||||
)
|
||||
|
||||
return new_prompt
|
||||
|
||||
|
||||
# Workflow-Endpunkte
|
||||
@app.post("/api/workflow/run", tags=["Workflow"], response_model=Dict[str, Any])
|
||||
async def run_workflow(
|
||||
workflow_request: WorkflowRequest = Body(...),
|
||||
current_user: Dict[str, Any] = Depends(get_current_active_user)
|
||||
):
|
||||
"""Führt einen Workflow mit den ausgewählten Agenten und Dateien aus"""
|
||||
mandate_id, user_id = await get_user_context(current_user)
|
||||
|
||||
# LucyDOM-Interface mit Benutzerkontext initialisieren
|
||||
lucy_interface = get_lucydom_interface(mandate_id, user_id)
|
||||
|
||||
# AgentService mit Benutzerkontext initialisieren
|
||||
agent_service = get_agent_service(mandate_id, user_id)
|
||||
|
||||
workspace = lucy_interface.get_workspace(workflow_request.workspace_id)
|
||||
if not workspace:
|
||||
raise HTTPException(status_code=404, detail=f"Workspace mit ID {workflow_request.workspace_id} nicht gefunden")
|
||||
|
||||
# Prüfen, ob Dateien existieren
|
||||
files = []
|
||||
for file_id in workflow_request.files:
|
||||
file = lucy_interface.get_file(file_id)
|
||||
if not file:
|
||||
raise HTTPException(status_code=404, detail=f"Datei mit ID {file_id} nicht gefunden")
|
||||
files.append(file)
|
||||
|
||||
# Prüfen, ob Agenten existieren
|
||||
agents = []
|
||||
for agent_id in workflow_request.agents:
|
||||
agent = lucy_interface.get_agent(agent_id)
|
||||
if not agent:
|
||||
raise HTTPException(status_code=404, detail=f"Agent mit ID {agent_id} nicht gefunden")
|
||||
agents.append(agent)
|
||||
|
||||
# Workflow ID generieren
|
||||
workflow_id = str(uuid.uuid4())
|
||||
|
||||
# Workflow starten (asynchron)
|
||||
workflow_task = asyncio.create_task(
|
||||
agent_service.execute_workflow(
|
||||
workflow_id,
|
||||
workflow_request.prompt,
|
||||
agents,
|
||||
files
|
||||
)
|
||||
)
|
||||
|
||||
# Sofort eine Antwort zurückgeben
|
||||
return {
|
||||
"workflow_id": workflow_id,
|
||||
"status": "running",
|
||||
"message": "Workflow wurde gestartet"
|
||||
}
|
||||
|
||||
|
||||
@app.get("/api/workflow/{workflow_id}/status", tags=["Workflow"])
|
||||
async def get_workflow_status(
|
||||
workflow_id: str,
|
||||
current_user: Dict[str, Any] = Depends(get_current_active_user)
|
||||
):
|
||||
"""Status eines laufenden Workflows abrufen"""
|
||||
mandate_id, user_id = await get_user_context(current_user)
|
||||
|
||||
# AgentService mit Benutzerkontext initialisieren
|
||||
agent_service = get_agent_service(mandate_id, user_id)
|
||||
|
||||
status = agent_service.get_workflow_status(workflow_id)
|
||||
if not status:
|
||||
raise HTTPException(status_code=404, detail=f"Workflow mit ID {workflow_id} nicht gefunden")
|
||||
|
||||
return status
|
||||
|
||||
|
||||
@app.get("/api/workflow/{workflow_id}/logs", tags=["Workflow"], response_model=List[Dict[str, Any]])
|
||||
async def get_workflow_logs(
|
||||
workflow_id: str,
|
||||
current_user: Dict[str, Any] = Depends(get_current_active_user)
|
||||
):
|
||||
"""Protokolle eines Workflows abrufen"""
|
||||
mandate_id, user_id = await get_user_context(current_user)
|
||||
|
||||
# AgentService mit Benutzerkontext initialisieren
|
||||
agent_service = get_agent_service(mandate_id, user_id)
|
||||
|
||||
logs = agent_service.get_workflow_logs(workflow_id)
|
||||
if logs is None:
|
||||
raise HTTPException(status_code=404, detail=f"Workflow mit ID {workflow_id} nicht gefunden")
|
||||
|
||||
return logs
|
||||
|
||||
|
||||
@app.get("/api/workflow/{workflow_id}/results", tags=["Workflow"], response_model=List[Dict[str, Any]])
|
||||
async def get_workflow_results(
|
||||
workflow_id: str,
|
||||
current_user: Dict[str, Any] = Depends(get_current_active_user)
|
||||
):
|
||||
"""Ergebnisse eines Workflows abrufen"""
|
||||
mandate_id, user_id = await get_user_context(current_user)
|
||||
|
||||
# AgentService mit Benutzerkontext initialisieren
|
||||
agent_service = get_agent_service(mandate_id, user_id)
|
||||
|
||||
results = agent_service.get_workflow_results(workflow_id)
|
||||
if results is None:
|
||||
raise HTTPException(status_code=404, detail=f"Workflow mit ID {workflow_id} nicht gefunden")
|
||||
|
||||
return results
|
||||
|
||||
|
||||
# Mandanten-Endpunkte (neu)
|
||||
@app.get("/api/mandates", tags=["Mandates"], response_model=List[Dict[str, Any]])
|
||||
async def get_mandates(current_user: Dict[str, Any] = Depends(get_current_active_user)):
|
||||
"""Alle verfügbaren Mandanten abrufen (nur für Admin-Benutzer)"""
|
||||
mandate_id, user_id = await get_user_context(current_user)
|
||||
|
||||
# Gateway-Interface mit Benutzerkontext initialisieren
|
||||
gateway = get_gateway_interface(mandate_id, user_id)
|
||||
|
||||
# TODO: Hier sollte eine Berechtigungsprüfung erfolgen
|
||||
|
||||
return gateway.get_all_mandates()
|
||||
|
||||
|
||||
@app.post("/api/mandates", tags=["Mandates"], response_model=Dict[str, Any])
|
||||
async def create_mandate(
|
||||
mandate: Dict[str, Any] = Body(...),
|
||||
current_user: Dict[str, Any] = Depends(get_current_active_user)
|
||||
):
|
||||
"""Einen neuen Mandanten erstellen (nur für Admin-Benutzer)"""
|
||||
mandate_id, user_id = await get_user_context(current_user)
|
||||
|
||||
# Gateway-Interface mit Benutzerkontext initialisieren
|
||||
gateway = get_gateway_interface(mandate_id, user_id)
|
||||
|
||||
# TODO: Hier sollte eine Berechtigungsprüfung erfolgen
|
||||
|
||||
new_mandate = gateway.create_mandate(
|
||||
name=mandate.get("name", "Neuer Mandant"),
|
||||
language=mandate.get("language", "de")
|
||||
)
|
||||
|
||||
return new_mandate
|
||||
# Alle Router einbinden
|
||||
app.include_router(attributes_router)
|
||||
app.include_router(workspace_router)
|
||||
app.include_router(agent_router)
|
||||
app.include_router(file_router)
|
||||
app.include_router(prompt_router)
|
||||
app.include_router(workflow_router)
|
||||
app.include_router(mandate_router)
|
||||
|
||||
|
||||
# Event handler beim Herunterfahren
|
||||
|
|
|
|||
113
gwserver/attributes.py
Normal file
113
gwserver/attributes.py
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
from pydantic import BaseModel, Field
|
||||
from typing import List, Dict, Any, Optional
|
||||
|
||||
# Definiere das Modell für Attributdefinitionen
|
||||
class AttributeDefinition(BaseModel):
|
||||
name: str
|
||||
label: str
|
||||
type: str
|
||||
required: bool = False
|
||||
placeholder: Optional[str] = None
|
||||
default_value: Optional[Any] = None
|
||||
options: Optional[List[Dict[str, Any]]] = None
|
||||
editable: bool = True
|
||||
visible: bool = True
|
||||
order: int = 0
|
||||
validation: Optional[Dict[str, Any]] = None
|
||||
help_text: Optional[str] = None
|
||||
|
||||
# Hilfsklassen für Typzuordnung
|
||||
type_mappings = {
|
||||
"int": "number",
|
||||
"str": "string",
|
||||
"float": "number",
|
||||
"bool": "boolean",
|
||||
"List[int]": "array",
|
||||
"List[str]": "array",
|
||||
"Dict[str, Any]": "object",
|
||||
"Optional[str]": "string",
|
||||
"Optional[int]": "number",
|
||||
"Optional[Dict[str, Any]]": "object"
|
||||
}
|
||||
|
||||
# Spezielle Feldtypen basierend auf Namenskonventionen
|
||||
special_field_types = {
|
||||
"content": "textarea",
|
||||
"description": "textarea",
|
||||
"instructions": "textarea",
|
||||
"password": "password",
|
||||
"email": "email",
|
||||
"workspace_id": "select",
|
||||
"agent_id": "select",
|
||||
"type": "select"
|
||||
}
|
||||
|
||||
# Funktion zum Konvertieren eines Pydantic-Modells in Attributdefinitionen
|
||||
def get_model_attributes(model_class, user_language="de"):
|
||||
"""
|
||||
Konvertiert ein Pydantic-Modell in eine Liste von AttributeDefinition-Objekten
|
||||
"""
|
||||
attributes = []
|
||||
|
||||
# Gehe alle Felder im Modell durch
|
||||
for i, (field_name, field) in enumerate(model_class.__fields__.items()):
|
||||
# Überspringe interne Felder
|
||||
if field_name.startswith('_') or field_name in ["label", "field_labels"]:
|
||||
continue
|
||||
|
||||
# Bestimme den Feldtyp
|
||||
field_type = type_mappings.get(str(field.type_), "string")
|
||||
|
||||
# Prüfe auf spezielle Feldtypen
|
||||
if field_name in special_field_types:
|
||||
field_type = special_field_types[field_name]
|
||||
|
||||
# Hole das Label (falls vorhanden)
|
||||
field_label = field_name.replace('_', ' ').capitalize()
|
||||
if hasattr(model_class, 'field_labels') and field_name in model_class.field_labels:
|
||||
label_obj = model_class.field_labels[field_name]
|
||||
field_label = label_obj.get_label(user_language)
|
||||
|
||||
# Standardwerte und Required-Status ermitteln
|
||||
required = field.required
|
||||
default_value = field.default if not field.required else None
|
||||
|
||||
# Hinweise auf Validierungsregeln
|
||||
validation = None
|
||||
if field.validators:
|
||||
validation = {"has_validators": True}
|
||||
|
||||
# Platzhaltertext
|
||||
placeholder = f"Bitte {field_label} eingeben"
|
||||
|
||||
# Spezielle Optionen für Select-Felder
|
||||
options = None
|
||||
if field_type == "select":
|
||||
if field_name == "type" and model_class.__name__ == "Agent":
|
||||
options = [
|
||||
{"value": "Analyse", "label": "Analyse"},
|
||||
{"value": "Transformation", "label": "Transformation"},
|
||||
{"value": "Generierung", "label": "Generierung"},
|
||||
{"value": "Klassifikation", "label": "Klassifikation"},
|
||||
{"value": "Benutzerdefiniert", "label": "Benutzerdefiniert"}
|
||||
]
|
||||
|
||||
# Attributdefinition erstellen
|
||||
attr_def = AttributeDefinition(
|
||||
name=field_name,
|
||||
label=field_label,
|
||||
type=field_type,
|
||||
required=required,
|
||||
placeholder=placeholder,
|
||||
default_value=default_value,
|
||||
options=options,
|
||||
editable=field_name not in ["id", "mandate_id", "user_id", "created_at", "upload_date"],
|
||||
visible=field_name not in ["hashed_password", "mandate_id", "user_id"],
|
||||
order=i,
|
||||
validation=validation,
|
||||
help_text=field.description
|
||||
)
|
||||
|
||||
attributes.append(attr_def)
|
||||
|
||||
return attributes
|
||||
|
|
@ -4,8 +4,8 @@ from fastapi import Depends, HTTPException, status
|
|||
from fastapi.security import OAuth2PasswordBearer
|
||||
from jose import JWTError, jwt
|
||||
import logging
|
||||
from interface_gateway import get_gateway_interface
|
||||
from model_gateway import User, Token
|
||||
from modules.gateway_interface import get_gateway_interface
|
||||
from modules.gateway_model import User, Token
|
||||
import configload
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
[Application]
|
||||
DEBUG = True
|
||||
UPLOAD_DIR = ./uploads
|
||||
RESULTS_DIR = ./results
|
||||
UPLOAD_DIR = ./_uploads
|
||||
RESULTS_DIR = ./_results
|
||||
|
||||
[Access]
|
||||
SECRET_KEY = dein-geheimer-schlüssel
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ from typing import Dict, Any, List, Optional, Union
|
|||
import importlib
|
||||
from passlib.context import CryptContext
|
||||
from connector_db_json import JSONDatabaseConnector
|
||||
from model_gateway import User, UserInDB, Token, Mandate
|
||||
from modules.gateway_model import User, UserInDB, Token, Mandate
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
|
@ -33,9 +33,9 @@ class GatewayInterface:
|
|||
self.user_id = user_id if user_id is not None else 1 # Admin-Benutzer als Standard
|
||||
|
||||
# Datenverzeichnis
|
||||
self.data_folder = "data_gateway"
|
||||
self.data_folder = "_database_gateway"
|
||||
os.makedirs(self.data_folder, exist_ok=True)
|
||||
logger.info("db for data_gateway atteached")
|
||||
logger.info("db for data_gateway attached")
|
||||
|
||||
# Datenmodell-Modul importieren
|
||||
try:
|
||||
|
|
@ -26,7 +26,7 @@ class LucyDOMInterface:
|
|||
self.user_id = user_id
|
||||
|
||||
# Datenverzeichnis
|
||||
self.data_folder = "data_lucydom"
|
||||
self.data_folder = "_database_lucydom"
|
||||
os.makedirs(self.data_folder, exist_ok=True)
|
||||
|
||||
# Datenmodell-Modul importieren
|
||||
91
gwserver/routes/agent.py
Normal file
91
gwserver/routes/agent.py
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
from fastapi import APIRouter, HTTPException, Depends, Body, Query, Path
|
||||
from typing import List, Dict, Any, Optional
|
||||
from fastapi import status
|
||||
|
||||
# Import auth module
|
||||
from auth import get_current_active_user, get_user_context
|
||||
|
||||
# Import interfaces
|
||||
from modules.lucydom_interface import get_lucydom_interface
|
||||
|
||||
# Router für Agenten-Endpunkte erstellen
|
||||
router = APIRouter(
|
||||
prefix="/api/agents",
|
||||
tags=["Agents"],
|
||||
responses={404: {"description": "Not found"}}
|
||||
)
|
||||
|
||||
@router.get("", response_model=List[Dict[str, Any]])
|
||||
async def get_agents(
|
||||
workspace_id: Optional[int] = Query(None),
|
||||
current_user: Dict[str, Any] = Depends(get_current_active_user)
|
||||
):
|
||||
"""Alle Agenten oder Agenten eines bestimmten Workspaces abrufen"""
|
||||
mandate_id, user_id = await get_user_context(current_user)
|
||||
|
||||
# LucyDOM-Interface mit Benutzerkontext initialisieren
|
||||
lucy_interface = get_lucydom_interface(mandate_id, user_id)
|
||||
|
||||
if workspace_id:
|
||||
return lucy_interface.get_agents_by_workspace(workspace_id)
|
||||
|
||||
return lucy_interface.get_all_agents()
|
||||
|
||||
|
||||
@router.post("", response_model=Dict[str, Any])
|
||||
async def create_agent(
|
||||
agent: Dict[str, Any] = Body(...),
|
||||
current_user: Dict[str, Any] = Depends(get_current_active_user)
|
||||
):
|
||||
"""Einen neuen Agenten erstellen"""
|
||||
mandate_id, user_id = await get_user_context(current_user)
|
||||
|
||||
# LucyDOM-Interface mit Benutzerkontext initialisieren
|
||||
lucy_interface = get_lucydom_interface(mandate_id, user_id)
|
||||
|
||||
workspace_id = agent.get("workspace_id")
|
||||
|
||||
if not workspace_id:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="workspace_id ist erforderlich"
|
||||
)
|
||||
|
||||
# Workspace existiert?
|
||||
workspace = lucy_interface.get_workspace(workspace_id)
|
||||
if not workspace:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail=f"Workspace mit ID {workspace_id} nicht gefunden"
|
||||
)
|
||||
|
||||
new_agent = lucy_interface.create_agent(
|
||||
name=agent.get("name", "Neuer Agent"),
|
||||
agent_type=agent.get("type", "generic"),
|
||||
workspace_id=workspace_id,
|
||||
capabilities=agent.get("capabilities", []),
|
||||
description=agent.get("description", "")
|
||||
)
|
||||
|
||||
return new_agent
|
||||
|
||||
|
||||
@router.get("/{agent_id}", response_model=Dict[str, Any])
|
||||
async def get_agent(
|
||||
agent_id: int,
|
||||
current_user: Dict[str, Any] = Depends(get_current_active_user)
|
||||
):
|
||||
"""Einen bestimmten Agenten abrufen"""
|
||||
mandate_id, user_id = await get_user_context(current_user)
|
||||
|
||||
# LucyDOM-Interface mit Benutzerkontext initialisieren
|
||||
lucy_interface = get_lucydom_interface(mandate_id, user_id)
|
||||
|
||||
agent = lucy_interface.get_agent(agent_id)
|
||||
if not agent:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail=f"Agent mit ID {agent_id} nicht gefunden"
|
||||
)
|
||||
|
||||
return agent
|
||||
101
gwserver/routes/attributes.py
Normal file
101
gwserver/routes/attributes.py
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
from fastapi import APIRouter, HTTPException, Depends, Path
|
||||
from typing import List, Dict, Any
|
||||
from fastapi import status
|
||||
|
||||
# Import auth module
|
||||
from auth import get_current_active_user, get_user_context
|
||||
|
||||
# Importiere die Attributdefinition und Hilfsfunktionen
|
||||
from attributes import AttributeDefinition, get_model_attributes
|
||||
|
||||
# Importiere die Modellmodule (ohne spezifische Klassen)
|
||||
import modules.gateway_model as gateway_model
|
||||
import modules.lucydom_model as lucydom_model
|
||||
|
||||
# Erstelle ein Dictionary, das die Modellklassen ihren Typen zuordnet
|
||||
model_classes = {
|
||||
"workspace": lucydom_model.Workspace,
|
||||
"agent": lucydom_model.Agent,
|
||||
"file": lucydom_model.DataObject,
|
||||
"prompt": lucydom_model.Prompt,
|
||||
"user": gateway_model.User,
|
||||
"mandate": gateway_model.Mandate,
|
||||
"workflow_request": lucydom_model.WorkflowRequest,
|
||||
"workflow_response": lucydom_model.WorkflowResponse,
|
||||
"log_entry": lucydom_model.LogEntry,
|
||||
"result": lucydom_model.Result
|
||||
}
|
||||
|
||||
# Erstelle einen Router für die Attribute-Endpunkte
|
||||
router = APIRouter(
|
||||
prefix="/api/attributes",
|
||||
tags=["Attributes"],
|
||||
responses={404: {"description": "Not found"}}
|
||||
)
|
||||
|
||||
@router.get("/{entity_type}", response_model=List[AttributeDefinition])
|
||||
async def get_entity_attributes(
|
||||
entity_type: str = Path(..., description="Typ der Entität (z.B. workspace, agent, prompt)"),
|
||||
current_user: Dict[str, Any] = Depends(get_current_active_user)
|
||||
):
|
||||
"""
|
||||
Ruft die Attributdefinitionen für eine bestimmte Entität ab.
|
||||
Dies kann für die dynamische Generierung von Formularen verwendet werden.
|
||||
"""
|
||||
# Authentifizierung und Benutzerkontext
|
||||
mandate_id, user_id = await get_user_context(current_user)
|
||||
|
||||
# Bevorzugte Sprache des Benutzers ermitteln
|
||||
user_language = current_user.get("language", "de")
|
||||
|
||||
# Prüfen, ob Entitätstyp bekannt ist
|
||||
if entity_type not in model_classes:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail=f"Entitätstyp '{entity_type}' nicht gefunden."
|
||||
)
|
||||
|
||||
# Model-Klasse abrufen und Attribute daraus ableiten
|
||||
model_class = model_classes[entity_type]
|
||||
attributes = get_model_attributes(model_class, user_language)
|
||||
|
||||
# Nur bearbeitbare und sichtbare Attribute zurückgeben
|
||||
visible_attributes = [attr for attr in attributes if attr.visible]
|
||||
|
||||
# Wenn es sich um die Workspace-Auswahl handelt, Daten aus der Datenbank laden
|
||||
for attr in visible_attributes:
|
||||
if attr.name == "workspace_id" and attr.type == "select":
|
||||
# LucyDOM-Interface mit Benutzerkontext initialisieren
|
||||
from modules.lucydom_interface import get_lucydom_interface
|
||||
lucy_interface = get_lucydom_interface(mandate_id, user_id)
|
||||
|
||||
# Alle verfügbaren Workspaces abrufen
|
||||
workspaces = lucy_interface.get_all_workspaces()
|
||||
|
||||
# Options-Liste aus Workspaces erstellen
|
||||
attr.options = [
|
||||
{"value": ws["id"], "label": ws["name"]}
|
||||
for ws in workspaces
|
||||
]
|
||||
|
||||
# Wenn es sich um Agent-Auswahl handelt und ein Workspace-Kontext existiert
|
||||
elif attr.name == "agent_id" and attr.type == "select" and "workspace_id" in [a.name for a in visible_attributes]:
|
||||
# Wenn ein aktueller Workspace gesetzt ist
|
||||
workspace_id_attr = next((a for a in visible_attributes if a.name == "workspace_id"), None)
|
||||
if workspace_id_attr and workspace_id_attr.default_value:
|
||||
workspace_id = workspace_id_attr.default_value
|
||||
|
||||
# LucyDOM-Interface mit Benutzerkontext initialisieren
|
||||
from modules.lucydom_interface import get_lucydom_interface
|
||||
lucy_interface = get_lucydom_interface(mandate_id, user_id)
|
||||
|
||||
# Agenten für den Workspace abrufen
|
||||
agents = lucy_interface.get_agents_by_workspace(workspace_id)
|
||||
|
||||
# Options-Liste aus Agenten erstellen
|
||||
attr.options = [
|
||||
{"value": agent["id"], "label": agent["name"]}
|
||||
for agent in agents
|
||||
]
|
||||
|
||||
return visible_attributes
|
||||
132
gwserver/routes/file.py
Normal file
132
gwserver/routes/file.py
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
from fastapi import APIRouter, HTTPException, Depends, File, UploadFile, Path
|
||||
from typing import List, Dict, Any
|
||||
from fastapi import status
|
||||
import uuid
|
||||
import os
|
||||
import logging
|
||||
|
||||
# Import auth module
|
||||
from auth import get_current_active_user, get_user_context
|
||||
|
||||
# Import interfaces
|
||||
from modules.lucydom_interface import get_lucydom_interface
|
||||
from modules.agentservice_interface import get_agent_service
|
||||
|
||||
# Logger konfigurieren
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Router für Datei-Endpunkte erstellen
|
||||
router = APIRouter(
|
||||
prefix="/api/files",
|
||||
tags=["Files"],
|
||||
responses={404: {"description": "Not found"}}
|
||||
)
|
||||
|
||||
@router.get("", response_model=List[Dict[str, Any]])
|
||||
async def get_files(current_user: Dict[str, Any] = Depends(get_current_active_user)):
|
||||
"""Alle verfügbaren Dateien abrufen"""
|
||||
mandate_id, user_id = await get_user_context(current_user)
|
||||
|
||||
# LucyDOM-Interface mit Benutzerkontext initialisieren
|
||||
lucy_interface = get_lucydom_interface(mandate_id, user_id)
|
||||
|
||||
return lucy_interface.get_all_files()
|
||||
|
||||
|
||||
@router.post("/upload")
|
||||
async def upload_file(
|
||||
file: UploadFile = File(...),
|
||||
current_user: Dict[str, Any] = Depends(get_current_active_user)
|
||||
):
|
||||
"""Eine Datei hochladen"""
|
||||
mandate_id, user_id = await get_user_context(current_user)
|
||||
|
||||
# LucyDOM-Interface mit Benutzerkontext initialisieren
|
||||
lucy_interface = get_lucydom_interface(mandate_id, user_id)
|
||||
|
||||
try:
|
||||
# Generiere eine eindeutige ID für die Datei
|
||||
file_id = str(uuid.uuid4())
|
||||
file_ext = os.path.splitext(file.filename)[1]
|
||||
file_path = os.path.join(get_agent_service(mandate_id, user_id).upload_dir, f"{file_id}{file_ext}")
|
||||
|
||||
# Datei speichern
|
||||
with open(file_path, "wb") as f:
|
||||
content = await file.read()
|
||||
f.write(content)
|
||||
|
||||
# Dateityp bestimmen
|
||||
file_type = "image" if file.content_type and "image" in file.content_type else "document"
|
||||
|
||||
# In Datenbank speichern
|
||||
new_file = lucy_interface.create_file(
|
||||
name=file.filename,
|
||||
file_type=file_type,
|
||||
content_type=file.content_type,
|
||||
size=os.path.getsize(file_path),
|
||||
path=file_path
|
||||
)
|
||||
|
||||
return {
|
||||
"id": new_file["id"],
|
||||
"name": new_file["name"],
|
||||
"type": new_file["type"],
|
||||
"size": f"{new_file['size'] / (1024 * 1024):.1f} MB",
|
||||
"upload_date": new_file.get("upload_date")
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Fehler beim Hochladen der Datei: {e}")
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=f"Fehler beim Hochladen der Datei: {str(e)}"
|
||||
)
|
||||
|
||||
|
||||
@router.delete("/{file_id}")
|
||||
async def delete_file(
|
||||
file_id: int,
|
||||
current_user: Dict[str, Any] = Depends(get_current_active_user)
|
||||
):
|
||||
"""Löscht eine Datei"""
|
||||
mandate_id, user_id = await get_user_context(current_user)
|
||||
|
||||
# LucyDOM-Interface mit Benutzerkontext initialisieren
|
||||
lucy_interface = get_lucydom_interface(mandate_id, user_id)
|
||||
|
||||
try:
|
||||
# Hole die Datei aus der Datenbank
|
||||
file = lucy_interface.get_file(file_id)
|
||||
if not file:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail=f"Datei mit ID {file_id} nicht gefunden"
|
||||
)
|
||||
|
||||
# Prüfe, ob die physische Datei existiert
|
||||
if "path" in file and os.path.exists(file["path"]):
|
||||
try:
|
||||
# Versuche, die physische Datei zu löschen
|
||||
os.remove(file["path"])
|
||||
except Exception as e:
|
||||
logger.warning(f"Konnte physische Datei nicht löschen: {e}")
|
||||
|
||||
# Lösche die Datei aus der Datenbank
|
||||
success = lucy_interface.delete_file(file_id)
|
||||
|
||||
if not success:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail="Fehler beim Löschen der Datei aus der Datenbank"
|
||||
)
|
||||
|
||||
return {"success": True, "message": f"Datei '{file.get('name', 'unbekannt')}' wurde gelöscht"}
|
||||
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(f"Fehler beim Löschen der Datei: {e}")
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=f"Fehler beim Löschen der Datei: {str(e)}"
|
||||
)
|
||||
73
gwserver/routes/mandate.py
Normal file
73
gwserver/routes/mandate.py
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
from fastapi import APIRouter, HTTPException, Depends, Body
|
||||
from typing import List, Dict, Any
|
||||
from fastapi import status
|
||||
|
||||
# Import auth module
|
||||
from auth import get_current_active_user, get_user_context
|
||||
|
||||
# Import interfaces
|
||||
from modules.gateway_interface import get_gateway_interface
|
||||
|
||||
# Router für Mandanten-Endpunkte erstellen
|
||||
router = APIRouter(
|
||||
prefix="/api/mandates",
|
||||
tags=["Mandates"],
|
||||
responses={404: {"description": "Not found"}}
|
||||
)
|
||||
|
||||
@router.get("", response_model=List[Dict[str, Any]])
|
||||
async def get_mandates(current_user: Dict[str, Any] = Depends(get_current_active_user)):
|
||||
"""Alle verfügbaren Mandanten abrufen (nur für Admin-Benutzer)"""
|
||||
mandate_id, user_id = await get_user_context(current_user)
|
||||
|
||||
# Gateway-Interface mit Benutzerkontext initialisieren
|
||||
gateway = get_gateway_interface(mandate_id, user_id)
|
||||
|
||||
# TODO: Hier sollte eine Berechtigungsprüfung erfolgen
|
||||
|
||||
return gateway.get_all_mandates()
|
||||
|
||||
|
||||
@router.post("", response_model=Dict[str, Any])
|
||||
async def create_mandate(
|
||||
mandate: Dict[str, Any] = Body(...),
|
||||
current_user: Dict[str, Any] = Depends(get_current_active_user)
|
||||
):
|
||||
"""Einen neuen Mandanten erstellen (nur für Admin-Benutzer)"""
|
||||
mandate_id, user_id = await get_user_context(current_user)
|
||||
|
||||
# Gateway-Interface mit Benutzerkontext initialisieren
|
||||
gateway = get_gateway_interface(mandate_id, user_id)
|
||||
|
||||
# TODO: Hier sollte eine Berechtigungsprüfung erfolgen
|
||||
|
||||
new_mandate = gateway.create_mandate(
|
||||
name=mandate.get("name", "Neuer Mandant"),
|
||||
language=mandate.get("language", "de")
|
||||
)
|
||||
|
||||
return new_mandate
|
||||
|
||||
|
||||
@router.get("/{mandate_id}", response_model=Dict[str, Any])
|
||||
async def get_mandate(
|
||||
mandate_id: int,
|
||||
current_user: Dict[str, Any] = Depends(get_current_active_user)
|
||||
):
|
||||
"""Einen bestimmten Mandanten abrufen"""
|
||||
user_mandate_id, user_id = await get_user_context(current_user)
|
||||
|
||||
# Gateway-Interface mit Benutzerkontext initialisieren
|
||||
gateway = get_gateway_interface(user_mandate_id, user_id)
|
||||
|
||||
# TODO: Hier sollte eine Berechtigungsprüfung erfolgen
|
||||
# Nur Admins oder Benutzer des gleichen Mandanten dürfen den Mandanten sehen
|
||||
|
||||
mandate = gateway.get_mandate(mandate_id)
|
||||
if not mandate:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail=f"Mandant mit ID {mandate_id} nicht gefunden"
|
||||
)
|
||||
|
||||
return mandate
|
||||
88
gwserver/routes/prompt.py
Normal file
88
gwserver/routes/prompt.py
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
from fastapi import APIRouter, HTTPException, Depends, Body, Query, Path
|
||||
from typing import List, Dict, Any, Optional
|
||||
from fastapi import status
|
||||
|
||||
# Import auth module
|
||||
from auth import get_current_active_user, get_user_context
|
||||
|
||||
# Import interfaces
|
||||
from modules.lucydom_interface import get_lucydom_interface
|
||||
|
||||
# Router für Prompt-Endpunkte erstellen
|
||||
router = APIRouter(
|
||||
prefix="/api/prompts",
|
||||
tags=["Prompts"],
|
||||
responses={404: {"description": "Not found"}}
|
||||
)
|
||||
|
||||
@router.get("", response_model=List[Dict[str, Any]])
|
||||
async def get_prompts(
|
||||
workspace_id: Optional[int] = Query(None),
|
||||
current_user: Dict[str, Any] = Depends(get_current_active_user)
|
||||
):
|
||||
"""Alle Prompts oder Prompts eines bestimmten Workspaces abrufen"""
|
||||
mandate_id, user_id = await get_user_context(current_user)
|
||||
|
||||
# LucyDOM-Interface mit Benutzerkontext initialisieren
|
||||
lucy_interface = get_lucydom_interface(mandate_id, user_id)
|
||||
|
||||
if workspace_id:
|
||||
return lucy_interface.get_prompts_by_workspace(workspace_id)
|
||||
|
||||
return lucy_interface.get_all_prompts()
|
||||
|
||||
|
||||
@router.post("", response_model=Dict[str, Any])
|
||||
async def create_prompt(
|
||||
prompt: Dict[str, Any] = Body(...),
|
||||
current_user: Dict[str, Any] = Depends(get_current_active_user)
|
||||
):
|
||||
"""Einen neuen Prompt erstellen"""
|
||||
mandate_id, user_id = await get_user_context(current_user)
|
||||
|
||||
# LucyDOM-Interface mit Benutzerkontext initialisieren
|
||||
lucy_interface = get_lucydom_interface(mandate_id, user_id)
|
||||
|
||||
workspace_id = prompt.get("workspace_id")
|
||||
|
||||
if not workspace_id:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="workspace_id ist erforderlich"
|
||||
)
|
||||
|
||||
# Workspace existiert?
|
||||
workspace = lucy_interface.get_workspace(workspace_id)
|
||||
if not workspace:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail=f"Workspace mit ID {workspace_id} nicht gefunden"
|
||||
)
|
||||
|
||||
new_prompt = lucy_interface.create_prompt(
|
||||
content=prompt.get("content", ""),
|
||||
workspace_id=workspace_id
|
||||
)
|
||||
|
||||
return new_prompt
|
||||
|
||||
|
||||
@router.get("/{prompt_id}", response_model=Dict[str, Any])
|
||||
async def get_prompt(
|
||||
prompt_id: int,
|
||||
current_user: Dict[str, Any] = Depends(get_current_active_user)
|
||||
):
|
||||
"""Einen bestimmten Prompt abrufen"""
|
||||
mandate_id, user_id = await get_user_context(current_user)
|
||||
|
||||
# LucyDOM-Interface mit Benutzerkontext initialisieren
|
||||
lucy_interface = get_lucydom_interface(mandate_id, user_id)
|
||||
|
||||
prompt = lucy_interface.get_prompt(prompt_id)
|
||||
if not prompt:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail=f"Prompt mit ID {prompt_id} nicht gefunden"
|
||||
)
|
||||
|
||||
return prompt
|
||||
148
gwserver/routes/workflow.py
Normal file
148
gwserver/routes/workflow.py
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
from fastapi import APIRouter, HTTPException, Depends, Body, Path
|
||||
from typing import List, Dict, Any
|
||||
from fastapi import status
|
||||
import asyncio
|
||||
import uuid
|
||||
|
||||
# Import auth module
|
||||
from auth import get_current_active_user, get_user_context
|
||||
|
||||
# Import interfaces
|
||||
from modules.lucydom_interface import get_lucydom_interface
|
||||
from modules.agentservice_interface import get_agent_service
|
||||
|
||||
# Import models
|
||||
import modules.lucydom_model as lucydom_model
|
||||
|
||||
# Router für Workflow-Endpunkte erstellen
|
||||
router = APIRouter(
|
||||
prefix="/api/workflow",
|
||||
tags=["Workflow"],
|
||||
responses={404: {"description": "Not found"}}
|
||||
)
|
||||
|
||||
@router.post("/run", response_model=Dict[str, Any])
|
||||
async def run_workflow(
|
||||
workflow_request: lucydom_model.WorkflowRequest = Body(...),
|
||||
current_user: Dict[str, Any] = Depends(get_current_active_user)
|
||||
):
|
||||
"""Führt einen Workflow mit den ausgewählten Agenten und Dateien aus"""
|
||||
mandate_id, user_id = await get_user_context(current_user)
|
||||
|
||||
# LucyDOM-Interface mit Benutzerkontext initialisieren
|
||||
lucy_interface = get_lucydom_interface(mandate_id, user_id)
|
||||
|
||||
# AgentService mit Benutzerkontext initialisieren
|
||||
agent_service = get_agent_service(mandate_id, user_id)
|
||||
|
||||
workspace = lucy_interface.get_workspace(workflow_request.workspace_id)
|
||||
if not workspace:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail=f"Workspace mit ID {workflow_request.workspace_id} nicht gefunden"
|
||||
)
|
||||
|
||||
# Prüfen, ob Dateien existieren
|
||||
files = []
|
||||
for file_id in workflow_request.files:
|
||||
file = lucy_interface.get_file(file_id)
|
||||
if not file:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail=f"Datei mit ID {file_id} nicht gefunden"
|
||||
)
|
||||
files.append(file)
|
||||
|
||||
# Prüfen, ob Agenten existieren
|
||||
agents = []
|
||||
for agent_id in workflow_request.agents:
|
||||
agent = lucy_interface.get_agent(agent_id)
|
||||
if not agent:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail=f"Agent mit ID {agent_id} nicht gefunden"
|
||||
)
|
||||
agents.append(agent)
|
||||
|
||||
# Workflow ID generieren
|
||||
workflow_id = str(uuid.uuid4())
|
||||
|
||||
# Workflow starten (asynchron)
|
||||
workflow_task = asyncio.create_task(
|
||||
agent_service.execute_workflow(
|
||||
workflow_id,
|
||||
workflow_request.prompt,
|
||||
agents,
|
||||
files
|
||||
)
|
||||
)
|
||||
|
||||
# Sofort eine Antwort zurückgeben
|
||||
return {
|
||||
"workflow_id": workflow_id,
|
||||
"status": "running",
|
||||
"message": "Workflow wurde gestartet"
|
||||
}
|
||||
|
||||
|
||||
@router.get("/{workflow_id}/status")
|
||||
async def get_workflow_status(
|
||||
workflow_id: str,
|
||||
current_user: Dict[str, Any] = Depends(get_current_active_user)
|
||||
):
|
||||
"""Status eines laufenden Workflows abrufen"""
|
||||
mandate_id, user_id = await get_user_context(current_user)
|
||||
|
||||
# AgentService mit Benutzerkontext initialisieren
|
||||
agent_service = get_agent_service(mandate_id, user_id)
|
||||
|
||||
status = agent_service.get_workflow_status(workflow_id)
|
||||
if not status:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail=f"Workflow mit ID {workflow_id} nicht gefunden"
|
||||
)
|
||||
|
||||
return status
|
||||
|
||||
|
||||
@router.get("/{workflow_id}/logs", response_model=List[Dict[str, Any]])
|
||||
async def get_workflow_logs(
|
||||
workflow_id: str,
|
||||
current_user: Dict[str, Any] = Depends(get_current_active_user)
|
||||
):
|
||||
"""Protokolle eines Workflows abrufen"""
|
||||
mandate_id, user_id = await get_user_context(current_user)
|
||||
|
||||
# AgentService mit Benutzerkontext initialisieren
|
||||
agent_service = get_agent_service(mandate_id, user_id)
|
||||
|
||||
logs = agent_service.get_workflow_logs(workflow_id)
|
||||
if logs is None:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail=f"Workflow mit ID {workflow_id} nicht gefunden"
|
||||
)
|
||||
|
||||
return logs
|
||||
|
||||
|
||||
@router.get("/{workflow_id}/results", response_model=List[Dict[str, Any]])
|
||||
async def get_workflow_results(
|
||||
workflow_id: str,
|
||||
current_user: Dict[str, Any] = Depends(get_current_active_user)
|
||||
):
|
||||
"""Ergebnisse eines Workflows abrufen"""
|
||||
mandate_id, user_id = await get_user_context(current_user)
|
||||
|
||||
# AgentService mit Benutzerkontext initialisieren
|
||||
agent_service = get_agent_service(mandate_id, user_id)
|
||||
|
||||
results = agent_service.get_workflow_results(workflow_id)
|
||||
if results is None:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail=f"Workflow mit ID {workflow_id} nicht gefunden"
|
||||
)
|
||||
|
||||
return results
|
||||
62
gwserver/routes/workspace.py
Normal file
62
gwserver/routes/workspace.py
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
from fastapi import APIRouter, HTTPException, Depends, Body, Path
|
||||
from typing import List, Dict, Any
|
||||
from fastapi import status
|
||||
|
||||
# Import auth module
|
||||
from auth import get_current_active_user, get_user_context
|
||||
|
||||
# Import interfaces
|
||||
from modules.lucydom_interface import get_lucydom_interface
|
||||
|
||||
# Router für Workspace-Endpunkte erstellen
|
||||
router = APIRouter(
|
||||
prefix="/api/workspaces",
|
||||
tags=["Workspaces"],
|
||||
responses={404: {"description": "Not found"}}
|
||||
)
|
||||
|
||||
@router.get("", response_model=List[Dict[str, Any]])
|
||||
async def get_workspaces(current_user: Dict[str, Any] = Depends(get_current_active_user)):
|
||||
"""Alle verfügbaren Workspaces abrufen"""
|
||||
mandate_id, user_id = await get_user_context(current_user)
|
||||
|
||||
# LucyDOM-Interface mit Benutzerkontext initialisieren
|
||||
lucy_interface = get_lucydom_interface(mandate_id, user_id)
|
||||
|
||||
return lucy_interface.get_all_workspaces()
|
||||
|
||||
|
||||
@router.get("/{workspace_id}", response_model=Dict[str, Any])
|
||||
async def get_workspace(
|
||||
workspace_id: int,
|
||||
current_user: Dict[str, Any] = Depends(get_current_active_user)
|
||||
):
|
||||
"""Einen bestimmten Workspace mit allen Details abrufen"""
|
||||
mandate_id, user_id = await get_user_context(current_user)
|
||||
|
||||
# LucyDOM-Interface mit Benutzerkontext initialisieren
|
||||
lucy_interface = get_lucydom_interface(mandate_id, user_id)
|
||||
|
||||
workspace = lucy_interface.get_workspace(workspace_id)
|
||||
if not workspace:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail=f"Workspace mit ID {workspace_id} nicht gefunden"
|
||||
)
|
||||
|
||||
return workspace
|
||||
|
||||
|
||||
@router.post("", response_model=Dict[str, Any])
|
||||
async def create_workspace(
|
||||
workspace: Dict[str, Any] = Body(...),
|
||||
current_user: Dict[str, Any] = Depends(get_current_active_user)
|
||||
):
|
||||
"""Einen neuen Workspace erstellen"""
|
||||
mandate_id, user_id = await get_user_context(current_user)
|
||||
|
||||
# LucyDOM-Interface mit Benutzerkontext initialisieren
|
||||
lucy_interface = get_lucydom_interface(mandate_id, user_id)
|
||||
|
||||
new_workspace = lucy_interface.create_workspace(name=workspace.get("name", "Neuer Workspace"))
|
||||
return new_workspace
|
||||
Loading…
Reference in a new issue