Livio Meuli 6f9be8a6c4 Implement ChatManager with API integration, SystemPrompter, and comprehensive test suite
- Add ChatManager class for OpenAI-compatible API communication (silicon.fhgr.ch:7080)
- Add SystemPrompter for intelligent prompt generation with file context
- Integrate ChatManager into frontend chat component
- Add comprehensive pytest tests (40+ tests covering unit and integration scenarios)
- Implement error handling for API failures, timeouts, and connection issues
- Add environment variable-based configuration for API credentials
- Update frontend state initialization to include ChatManager
- All tests passing with mock/patch isolation for API calls
2026-04-09 14:19:57 +02:00

98 lines
3.1 KiB
Python

"""Chat Manager - Handles chat history and AI communication"""
import os
from dotenv import load_dotenv
import requests
import json
load_dotenv()
class ChatManager:
def __init__(self):
self.api_host = os.getenv("HOST")
self.api_port = os.getenv("PORT")
self.api_key = os.getenv("API_KEY")
self.model = os.getenv("MODEL")
# API endpoint URL (OpenAI-compatible format)
self.api_url = f"http://{self.api_host}:{self.api_port}/v1/chat/completions"
# Chat history stored in memory
self.chat_history = []
def add_message(self, role: str, content: str) -> None:
self.chat_history.append({"role": role, "content": content})
def get_history(self) -> list:
return self.chat_history
def clear_history(self) -> None:
self.chat_history = []
def send_message(self, user_message: str) -> str:
# Add user message to history
self.add_message("user", user_message)
try:
# Prepare request to OpenAI-compatible API
headers = {
"Content-Type": "application/json",
}
# Add API key if available
if self.api_key and self.api_key != "EMPTY":
headers["Authorization"] = f"Bearer {self.api_key}"
payload = {
"model": self.model,
"messages": self.chat_history,
"temperature": 0.7,
"max_tokens": 2000,
"stream": False,
}
# Make API request
response = requests.post(
self.api_url, headers=headers, json=payload, timeout=30
)
# Check if request was successful
if response.status_code != 200:
error_msg = f"API Error {response.status_code}: {response.text}"
raise Exception(error_msg)
# Parse response
response_data = response.json()
# Extract AI message
if "choices" in response_data and len(response_data["choices"]) > 0:
ai_message = response_data["choices"][0]["message"]["content"]
# Add AI response to history
self.add_message("assistant", ai_message)
return ai_message
else:
raise Exception("Invalid API response format")
except requests.exceptions.RequestException as e:
error_msg = f"Connection Error: {str(e)}"
# Add error message to history so user sees it
self.add_message("assistant", f"Error: {error_msg}")
raise Exception(error_msg)
except json.JSONDecodeError as e:
error_msg = f"JSON Decode Error: {str(e)}"
self.add_message("assistant", f"Error: {error_msg}")
raise Exception(error_msg)
except Exception as e:
error_msg = f"Error: {str(e)}"
self.add_message("assistant", f"Error: {error_msg}")
raise Exception(error_msg)
def get_chat_display(self) -> list:
return [
{"role": msg["role"], "content": msg["content"]}
for msg in self.chat_history
]