Files
hack/tools/scripts/llm-key-hunter/results/_cache/content/aflo59_comparemodelpoc.json
T
OpenCode 68a9071cf1 feat: reconcile local master with origin (exa/hot-platform hunters, leaks ledger, latest results)
Local branch had diverged from origin/master (sibling commits on the same base). Rewrote local history linearly on top of origin/master, folding in all local content: exa/hot-platform discovery hunters, leaks ledger, nightly sweep orchestrator, updated .gitignore and skill docs, plus the latest hunt output and vault state. Remote-only files (vault keys, channel scripts) were restored rather than dropped, so the resulting tree is a full union of both sides.
2026-08-07 12:53:47 +08:00

1 line
30 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{"repo": "aflo59/comparemodelpoc", "files": {".env.example": {"db22d3900cfbc5a5883673130c34b40d9ac9527b": {"t": 1785745160.3250022, "n": 2227, "h": "99bc6e27c2838a09", "c": "# ================================\n# CONFIGURATION API - DnD AI GameMaster\n# ================================\n\n# === OPENAI (Requis pour GPT-4/GPT-4o) ===\nOPENAI_API_KEY=sk-your-openai-api-key-here\n\n# === ALTERNATIVES (Recommandées pour éviter les erreurs de quota) ===\n# Ajoutez au moins une de ces clés pour avoir des alternatives quand OpenAI a des problèmes\nANTHROPIC_API_KEY=sk-ant-your-anthropic-api-key-here\nDEEPSEEK_API_KEY=your-deepseek-api-key-here\n\n# === NOUVELLE FONCTIONNALITÉ : BASCULEMENT AUTOMATIQUE ===\n# Bascule automatiquement vers un modèle alternatif si OpenAI a des problèmes de quota\n# Valeurs : true/false (par défaut: false)\nAI_AUTO_FALLBACK=true\n\n# === BASE DE DONNÉES ===\nDATABASE_PATH=database.db\n\n# === LOGGING ===\nLOG_LEVEL=INFO\n\n# === PORTRAITS (Optionnel) ===\n# Modèle primaire pour les portraits (par défaut: dall-e-3)\nPORTRAIT_PRIMARY_IMAGE_MODEL=dall-e-3\n# Modèle de fallback pour les portraits (par défaut: dall-e-2)\nPORTRAIT_FALLBACK_IMAGE_MODEL=dall-e-2\n\n# === DEEPSEEK CONFIGURATION (Optionnel) ===\n# URL de base pour l'API DeepSeek (par défaut: https://api.deepseek.com/v1)\nDEEPSEEK_BASE_URL=https://api.deepseek.com/v1\n\n# ================================\n# NOTES IMPORTANTES\n# ================================\n# \n# 1. OPENAI_API_KEY est requis pour GPT-4 et GPT-4o\n# \n# 2. Ajoutez ANTHROPIC_API_KEY et/ou DEEPSEEK_API_KEY pour avoir des alternatives\n# économiques en cas de problème avec OpenAI\n# \n# 3. AI_AUTO_FALLBACK=true permet un basculement automatique vers un modèle\n# alternatif en cas d'erreur de quota OpenAI\n# \n# 4. Coûts approximatifs (par 1K tokens) :\n# - GPT-4 : $0.03 entrée, $0.06 sortie\n# - GPT-4o : $0.005 entrée, $0.015 sortie \n# - Claude 3.5 Sonnet : $0.003 entrée, $0.015 sortie\n# - DeepSeek : $0.0001 entrée, $0.0002 sortie (très économique!)\n# \n# 5. Pour obtenir vos clés API :\n# - OpenAI : https://platform.openai.com/api-keys\n# - Anthropic : https://console.anthropic.com/account/keys\n# - DeepSeek : https://platform.deepseek.com/api_keys\n#\n# ================================\n\n# === INFORMATIONS VPS (Optionnel, pour scripts de déploiement) ===\nIPv4=your-server-ip\nIPv6=your-server-ipv6\nNAME=your-username\nPASSWORD=your-new-password\n"}, "56543854cdeb84bfc062596e68ccc27f658681d6": {"t": 1785748304.8484278, "n": 2227, "h": "99bc6e27c2838a09", "c": "# ================================\n# CONFIGURATION API - DnD AI GameMaster\n# ================================\n\n# === OPENAI (Requis pour GPT-4/GPT-4o) ===\nOPENAI_API_KEY=sk-your-openai-api-key-here\n\n# === ALTERNATIVES (Recommandées pour éviter les erreurs de quota) ===\n# Ajoutez au moins une de ces clés pour avoir des alternatives quand OpenAI a des problèmes\nANTHROPIC_API_KEY=sk-ant-your-anthropic-api-key-here\nDEEPSEEK_API_KEY=your-deepseek-api-key-here\n\n# === NOUVELLE FONCTIONNALITÉ : BASCULEMENT AUTOMATIQUE ===\n# Bascule automatiquement vers un modèle alternatif si OpenAI a des problèmes de quota\n# Valeurs : true/false (par défaut: false)\nAI_AUTO_FALLBACK=true\n\n# === BASE DE DONNÉES ===\nDATABASE_PATH=database.db\n\n# === LOGGING ===\nLOG_LEVEL=INFO\n\n# === PORTRAITS (Optionnel) ===\n# Modèle primaire pour les portraits (par défaut: dall-e-3)\nPORTRAIT_PRIMARY_IMAGE_MODEL=dall-e-3\n# Modèle de fallback pour les portraits (par défaut: dall-e-2)\nPORTRAIT_FALLBACK_IMAGE_MODEL=dall-e-2\n\n# === DEEPSEEK CONFIGURATION (Optionnel) ===\n# URL de base pour l'API DeepSeek (par défaut: https://api.deepseek.com/v1)\nDEEPSEEK_BASE_URL=https://api.deepseek.com/v1\n\n# ================================\n# NOTES IMPORTANTES\n# ================================\n# \n# 1. OPENAI_API_KEY est requis pour GPT-4 et GPT-4o\n# \n# 2. Ajoutez ANTHROPIC_API_KEY et/ou DEEPSEEK_API_KEY pour avoir des alternatives\n# économiques en cas de problème avec OpenAI\n# \n# 3. AI_AUTO_FALLBACK=true permet un basculement automatique vers un modèle\n# alternatif en cas d'erreur de quota OpenAI\n# \n# 4. Coûts approximatifs (par 1K tokens) :\n# - GPT-4 : $0.03 entrée, $0.06 sortie\n# - GPT-4o : $0.005 entrée, $0.015 sortie \n# - Claude 3.5 Sonnet : $0.003 entrée, $0.015 sortie\n# - DeepSeek : $0.0001 entrée, $0.0002 sortie (très économique!)\n# \n# 5. Pour obtenir vos clés API :\n# - OpenAI : https://platform.openai.com/api-keys\n# - Anthropic : https://console.anthropic.com/account/keys\n# - DeepSeek : https://platform.deepseek.com/api_keys\n#\n# ================================\n\n# === INFORMATIONS VPS (Optionnel, pour scripts de déploiement) ===\nIPv4=your-server-ip\nIPv6=your-server-ipv6\nNAME=your-username\nPASSWORD=your-new-password\n"}, "a6f2ba46a0d60d2824ab667d4752d8d42bdf113e": {"t": 1785748308.5875182, "n": 2070, "h": "552bfca1ef471f63", "c": "# ================================\n# CONFIGURATION API - DnD AI GameMaster\n# ================================\n\n# === OPENAI (Requis pour GPT-4/GPT-4o) ===\nOPENAI_API_KEY=sk-your-openai-api-key-here\n\n# === ALTERNATIVES (Recommandées pour éviter les erreurs de quota) ===\n# Ajoutez au moins une de ces clés pour avoir des alternatives quand OpenAI a des problèmes\nANTHROPIC_API_KEY=sk-ant-your-anthropic-api-key-here\nDEEPSEEK_API_KEY=your-deepseek-api-key-here\n\n# === NOUVELLE FONCTIONNALITÉ : BASCULEMENT AUTOMATIQUE ===\n# Bascule automatiquement vers un modèle alternatif si OpenAI a des problèmes de quota\n# Valeurs : true/false (par défaut: false)\nAI_AUTO_FALLBACK=true\n\n# === BASE DE DONNÉES ===\nDATABASE_PATH=database.db\n\n# === LOGGING ===\nLOG_LEVEL=INFO\n\n# === PORTRAITS (Optionnel) ===\n# Modèle primaire pour les portraits (par défaut: dall-e-3)\nPORTRAIT_PRIMARY_IMAGE_MODEL=dall-e-3\n# Modèle de fallback pour les portraits (par défaut: dall-e-2)\nPORTRAIT_FALLBACK_IMAGE_MODEL=dall-e-2\n\n# === DEEPSEEK CONFIGURATION (Optionnel) ===\n# URL de base pour l'API DeepSeek (par défaut: https://api.deepseek.com/v1)\nDEEPSEEK_BASE_URL=https://api.deepseek.com/v1\n\n# ================================\n# NOTES IMPORTANTES\n# ================================\n# \n# 1. OPENAI_API_KEY est requis pour GPT-4 et GPT-4o\n# \n# 2. Ajoutez ANTHROPIC_API_KEY et/ou DEEPSEEK_API_KEY pour avoir des alternatives\n# économiques en cas de problème avec OpenAI\n# \n# 3. AI_AUTO_FALLBACK=true permet un basculement automatique vers un modèle\n# alternatif en cas d'erreur de quota OpenAI\n# \n# 4. Coûts approximatifs (par 1K tokens) :\n# - GPT-4 : $0.03 entrée, $0.06 sortie\n# - GPT-4o : $0.005 entrée, $0.015 sortie \n# - Claude 3.5 Sonnet : $0.003 entrée, $0.015 sortie\n# - DeepSeek : $0.0001 entrée, $0.0002 sortie (très économique!)\n# \n# 5. Pour obtenir vos clés API :\n# - OpenAI : https://platform.openai.com/api-keys\n# - Anthropic : https://console.anthropic.com/account/keys\n# - DeepSeek : https://platform.deepseek.com/api_keys\n#\n# ================================\n"}, "35d09eb69eb896ad31994a920f157bb23134f7b8": {"t": 1785748310.154784, "n": 450, "h": "e36ecea8e3686f86", "c": "# Configuration des clés API - Copiez vers .env et remplissez vos vraies clés\n\n# Clé API OpenAI (obligatoire pour GPT-4 et GPT-4o)\nOPENAI_API_KEY=sk-your-openai-api-key-here\n\n# Clé API Anthropic (obligatoire pour Claude 3.5 Sonnet)\nANTHROPIC_API_KEY=sk-ant-your-anthropic-api-key-here\n\n# Clé API DeepSeek (optionnelle)\nDEEPSEEK_API_KEY=your-deepseek-api-key-here\n\n# Base de données (optionnel, par défaut : database.db)\n# DATABASE_PATH=./database.db\n"}}, "src/core/config.py": {"db22d3900cfbc5a5883673130c34b40d9ac9527b": {"t": 1785745449.2200003, "n": 4531, "h": "491652cec066ef50", "c": "\"\"\"\nConfiguration centralisée de l'application.\n\"\"\"\n\nimport os\nfrom pathlib import Path\nfrom typing import Any, Dict\n\nfrom dotenv import load_dotenv\n\n# Charger .env seulement s'il existe (pour le développement local)\nenv_file = Path(\".env\")\nif env_file.exists():\n load_dotenv()\nelse:\n # En production Docker, les variables sont déjà dans l'environnement\n print(\"Fichier .env non trouvé, utilisation des variables d'environnement Docker\")\n\n\nclass Config:\n \"\"\"Configuration de l'application.\"\"\"\n\n # Base de données\n DATABASE_PATH = os.getenv(\"DATABASE_PATH\", \"database.db\")\n\n # APIs\n OPENAI_API_KEY = os.getenv(\"OPENAI_API_KEY\")\n ANTHROPIC_API_KEY = os.getenv(\"ANTHROPIC_API_KEY\")\n DEEPSEEK_API_KEY = os.getenv(\"DEEPSEEK_API_KEY\")\n\n # Modèles supportés - TARIFS ACTUELS 2025\n SUPPORTED_MODELS = {\n \"GPT-4\": {\n \"provider\": \"openai\",\n \"model_name\": \"gpt-4\",\n \"description\": \"🚀 Le plus avancé, créatif et précis\",\n \"cost_per_1k_tokens\": {\"input\": 0.030, \"output\": 0.060}, # $30/$60 per 1M\n \"context_window\": 8192,\n },\n \"GPT-4o\": {\n \"provider\": \"openai\",\n \"model_name\": \"gpt-4o\",\n \"description\": \"⚡ Optimisé, 90% moins cher, contexte 128k\",\n \"cost_per_1k_tokens\": {\"input\": 0.0025, \"output\": 0.010}, # $2.50/$10 per 1M\n \"context_window\": 128000,\n },\n \"Claude 3.5 Sonnet\": {\n \"provider\": \"anthropic\",\n \"model_name\": \"claude-3-5-sonnet-20240620\",\n \"description\": \"🎭 Expert narrateur, contexte 200k tokens\",\n \"cost_per_1k_tokens\": {\"input\": 0.003, \"output\": 0.015}, # $3/$15 per 1M\n \"context_window\": 200000,\n },\n \"DeepSeek V3\": {\n \"provider\": \"deepseek\",\n \"model_name\": \"deepseek-chat\",\n \"description\": \"💰 Ultra-économique, 50x moins cher que GPT-4o\",\n \"cost_per_1k_tokens\": {\"input\": 0.00014, \"output\": 0.00028}, # $0.14/$0.28 per 1M\n \"context_window\": 64000,\n },\n }\n\n # Paramètres de génération d'images\n IMAGE_CONFIG = {\"model\": \"dall-e-3\", \"size\": \"1024x1024\", \"quality\": \"standard\"}\n\n # Paramètres de chat\n CHAT_CONFIG = {\"max_tokens\": 1000, \"temperature\": 0.8, \"max_history_length\": 50}\n\n # Interface utilisateur\n UI_CONFIG = {\n \"page_title\": \"DnD AI GameMaster\",\n \"page_icon\": \"🎲\",\n \"layout\": \"wide\",\n \"themes\": [\"Fantasy\", \"Horreur\", \"Science-Fiction\", \"Mystère\", \"Aventure\", \"Politique\", \"Romance\"],\n \"classes\": [\"Guerrier\", \"Magicien\", \"Voleur\", \"Clerc\", \"Paladin\", \"Rôdeur\", \"Barde\", \"Barbare\", \"Sorcier\", \"Druide\"],\n \"races\": [\"Humain\", \"Elfe\", \"Nain\", \"Orc\", \"Demi-elfe\", \"Halfelin\", \"Tieffelin\", \"Gnome\", \"Dragonide\"],\n \"languages\": [{\"code\": \"fr\", \"name\": \"Français\"}, {\"code\": \"en\", \"name\": \"English\"}],\n }\n\n # Logging\n LOG_LEVEL = os.getenv(\"LOG_LEVEL\", \"INFO\")\n LOG_FORMAT = \"%(asctime)s - %(name)s - %(levelname)s - %(message)s\"\n\n # Sécurité\n SECURITY_CONFIG = {\n \"min_password_length\": 8,\n \"require_uppercase\": True,\n \"require_lowercase\": True,\n \"require_digit\": True,\n \"bcrypt_rounds\": 12,\n }\n\n @classmethod\n def get_model_config(cls, model_name: str) -> Dict[str, Any]:\n \"\"\"Récupère la configuration d'un modèle.\"\"\"\n # Gestion de la rétrocompatibilité pour DeepSeek\n if model_name == \"DeepSeek\":\n model_name = \"DeepSeek V3\"\n return cls.SUPPORTED_MODELS.get(model_name, {})\n\n @classmethod\n def get_all_model_names(cls) -> list:\n \"\"\"Retourne tous les noms de modèles supportés.\"\"\"\n return list(cls.SUPPORTED_MODELS.keys())\n\n @classmethod\n def validate_api_keys(cls) -> Dict[str, bool]:\n \"\"\"Valide la présence des clés API.\"\"\"\n return {\n \"openai\": bool(cls.OPENAI_API_KEY),\n \"anthropic\": bool(cls.ANTHROPIC_API_KEY),\n \"deepseek\": bool(cls.DEEPSEEK_API_KEY),\n }\n\n @classmethod\n def get_available_models(cls) -> list:\n \"\"\"Retourne les modèles disponibles selon les clés API présentes.\"\"\"\n api_status = cls.validate_api_keys()\n available = []\n\n for model_name, config in cls.SUPPORTED_MODELS.items():\n provider = config.get(\"provider\")\n if api_status.get(provider, False):\n available.append(model_name)\n\n return available\n\n\n# Instance globale de configuration\nconfig = Config()\n"}, "c6ae27b155bbd87e2bec35be77d861d44d78b815": {"t": 1785748304.786235, "n": 4531, "h": "491652cec066ef50", "c": "\"\"\"\nConfiguration centralisée de l'application.\n\"\"\"\n\nimport os\nfrom pathlib import Path\nfrom typing import Any, Dict\n\nfrom dotenv import load_dotenv\n\n# Charger .env seulement s'il existe (pour le développement local)\nenv_file = Path(\".env\")\nif env_file.exists():\n load_dotenv()\nelse:\n # En production Docker, les variables sont déjà dans l'environnement\n print(\"Fichier .env non trouvé, utilisation des variables d'environnement Docker\")\n\n\nclass Config:\n \"\"\"Configuration de l'application.\"\"\"\n\n # Base de données\n DATABASE_PATH = os.getenv(\"DATABASE_PATH\", \"database.db\")\n\n # APIs\n OPENAI_API_KEY = os.getenv(\"OPENAI_API_KEY\")\n ANTHROPIC_API_KEY = os.getenv(\"ANTHROPIC_API_KEY\")\n DEEPSEEK_API_KEY = os.getenv(\"DEEPSEEK_API_KEY\")\n\n # Modèles supportés - TARIFS ACTUELS 2025\n SUPPORTED_MODELS = {\n \"GPT-4\": {\n \"provider\": \"openai\",\n \"model_name\": \"gpt-4\",\n \"description\": \"🚀 Le plus avancé, créatif et précis\",\n \"cost_per_1k_tokens\": {\"input\": 0.030, \"output\": 0.060}, # $30/$60 per 1M\n \"context_window\": 8192,\n },\n \"GPT-4o\": {\n \"provider\": \"openai\",\n \"model_name\": \"gpt-4o\",\n \"description\": \"⚡ Optimisé, 90% moins cher, contexte 128k\",\n \"cost_per_1k_tokens\": {\"input\": 0.0025, \"output\": 0.010}, # $2.50/$10 per 1M\n \"context_window\": 128000,\n },\n \"Claude 3.5 Sonnet\": {\n \"provider\": \"anthropic\",\n \"model_name\": \"claude-3-5-sonnet-20240620\",\n \"description\": \"🎭 Expert narrateur, contexte 200k tokens\",\n \"cost_per_1k_tokens\": {\"input\": 0.003, \"output\": 0.015}, # $3/$15 per 1M\n \"context_window\": 200000,\n },\n \"DeepSeek V3\": {\n \"provider\": \"deepseek\",\n \"model_name\": \"deepseek-chat\",\n \"description\": \"💰 Ultra-économique, 50x moins cher que GPT-4o\",\n \"cost_per_1k_tokens\": {\"input\": 0.00014, \"output\": 0.00028}, # $0.14/$0.28 per 1M\n \"context_window\": 64000,\n },\n }\n\n # Paramètres de génération d'images\n IMAGE_CONFIG = {\"model\": \"dall-e-3\", \"size\": \"1024x1024\", \"quality\": \"standard\"}\n\n # Paramètres de chat\n CHAT_CONFIG = {\"max_tokens\": 1000, \"temperature\": 0.8, \"max_history_length\": 50}\n\n # Interface utilisateur\n UI_CONFIG = {\n \"page_title\": \"DnD AI GameMaster\",\n \"page_icon\": \"🎲\",\n \"layout\": \"wide\",\n \"themes\": [\"Fantasy\", \"Horreur\", \"Science-Fiction\", \"Mystère\", \"Aventure\", \"Politique\", \"Romance\"],\n \"classes\": [\"Guerrier\", \"Magicien\", \"Voleur\", \"Clerc\", \"Paladin\", \"Rôdeur\", \"Barde\", \"Barbare\", \"Sorcier\", \"Druide\"],\n \"races\": [\"Humain\", \"Elfe\", \"Nain\", \"Orc\", \"Demi-elfe\", \"Halfelin\", \"Tieffelin\", \"Gnome\", \"Dragonide\"],\n \"languages\": [{\"code\": \"fr\", \"name\": \"Français\"}, {\"code\": \"en\", \"name\": \"English\"}],\n }\n\n # Logging\n LOG_LEVEL = os.getenv(\"LOG_LEVEL\", \"INFO\")\n LOG_FORMAT = \"%(asctime)s - %(name)s - %(levelname)s - %(message)s\"\n\n # Sécurité\n SECURITY_CONFIG = {\n \"min_password_length\": 8,\n \"require_uppercase\": True,\n \"require_lowercase\": True,\n \"require_digit\": True,\n \"bcrypt_rounds\": 12,\n }\n\n @classmethod\n def get_model_config(cls, model_name: str) -> Dict[str, Any]:\n \"\"\"Récupère la configuration d'un modèle.\"\"\"\n # Gestion de la rétrocompatibilité pour DeepSeek\n if model_name == \"DeepSeek\":\n model_name = \"DeepSeek V3\"\n return cls.SUPPORTED_MODELS.get(model_name, {})\n\n @classmethod\n def get_all_model_names(cls) -> list:\n \"\"\"Retourne tous les noms de modèles supportés.\"\"\"\n return list(cls.SUPPORTED_MODELS.keys())\n\n @classmethod\n def validate_api_keys(cls) -> Dict[str, bool]:\n \"\"\"Valide la présence des clés API.\"\"\"\n return {\n \"openai\": bool(cls.OPENAI_API_KEY),\n \"anthropic\": bool(cls.ANTHROPIC_API_KEY),\n \"deepseek\": bool(cls.DEEPSEEK_API_KEY),\n }\n\n @classmethod\n def get_available_models(cls) -> list:\n \"\"\"Retourne les modèles disponibles selon les clés API présentes.\"\"\"\n api_status = cls.validate_api_keys()\n available = []\n\n for model_name, config in cls.SUPPORTED_MODELS.items():\n provider = config.get(\"provider\")\n if api_status.get(provider, False):\n available.append(model_name)\n\n return available\n\n\n# Instance globale de configuration\nconfig = Config()\n"}, "07c5c2eb861d1b4cfab812061af2e427b197d436": {"t": 1785748308.3937032, "n": 4140, "h": "6d98a50f9e77071c", "c": "\"\"\"\nConfiguration centralisée de l'application.\n\"\"\"\n\nimport os\nfrom pathlib import Path\nfrom typing import Any, Dict\n\nfrom dotenv import load_dotenv\n\n# Charger .env seulement s'il existe (pour le développement local)\nenv_file = Path(\".env\")\nif env_file.exists():\n load_dotenv()\nelse:\n # En production Docker, les variables sont déjà dans l'environnement\n print(\"Fichier .env non trouvé, utilisation des variables d'environnement Docker\")\n\n\nclass Config:\n \"\"\"Configuration de l'application.\"\"\"\n\n # Base de données\n DATABASE_PATH = os.getenv(\"DATABASE_PATH\", \"database.db\")\n\n # APIs\n OPENAI_API_KEY = os.getenv(\"OPENAI_API_KEY\")\n ANTHROPIC_API_KEY = os.getenv(\"ANTHROPIC_API_KEY\")\n DEEPSEEK_API_KEY = os.getenv(\"DEEPSEEK_API_KEY\")\n\n # Modèles supportés\n SUPPORTED_MODELS = {\n \"GPT-4\": {\n \"provider\": \"openai\",\n \"model_name\": \"gpt-4\",\n \"description\": \"🚀 Le plus avancé, créatif et précis\",\n \"cost_per_1k_tokens\": {\"input\": 0.03, \"output\": 0.06},\n },\n \"GPT-4o\": {\n \"provider\": \"openai\",\n \"model_name\": \"gpt-4o\",\n \"description\": \"⚡ Optimisé, rapide et économique\",\n \"cost_per_1k_tokens\": {\"input\": 0.005, \"output\": 0.015},\n },\n \"Claude 3.5 Sonnet\": {\n \"provider\": \"anthropic\",\n \"model_name\": \"claude-3-5-sonnet-20240620\",\n \"description\": \"🎭 Excellent pour le roleplay et la narration\",\n \"cost_per_1k_tokens\": {\"input\": 0.003, \"output\": 0.015},\n },\n \"DeepSeek\": {\n \"provider\": \"deepseek\",\n \"model_name\": \"deepseek-chat\",\n \"description\": \"💰 Le plus économique, bon rapport qualité/prix\",\n \"cost_per_1k_tokens\": {\"input\": 0.00014, \"output\": 0.00028},\n },\n }\n\n # Paramètres de génération d'images\n IMAGE_CONFIG = {\"model\": \"dall-e-3\", \"size\": \"1024x1024\", \"quality\": \"standard\"}\n\n # Paramètres de chat\n CHAT_CONFIG = {\"max_tokens\": 1000, \"temperature\": 0.8, \"max_history_length\": 50}\n\n # Interface utilisateur\n UI_CONFIG = {\n \"page_title\": \"DnD AI GameMaster\",\n \"page_icon\": \"🎲\",\n \"layout\": \"wide\",\n \"themes\": [\"Fantasy\", \"Horreur\", \"Science-Fiction\", \"Mystère\", \"Aventure\", \"Politique\", \"Romance\"],\n \"classes\": [\"Guerrier\", \"Magicien\", \"Voleur\", \"Clerc\", \"Paladin\", \"Rôdeur\", \"Barde\", \"Barbare\", \"Sorcier\", \"Druide\"],\n \"races\": [\"Humain\", \"Elfe\", \"Nain\", \"Orc\", \"Demi-elfe\", \"Halfelin\", \"Tieffelin\", \"Gnome\", \"Dragonide\"],\n \"languages\": [{\"code\": \"fr\", \"name\": \"Français\"}, {\"code\": \"en\", \"name\": \"English\"}],\n }\n\n # Logging\n LOG_LEVEL = os.getenv(\"LOG_LEVEL\", \"INFO\")\n LOG_FORMAT = \"%(asctime)s - %(name)s - %(levelname)s - %(message)s\"\n\n # Sécurité\n SECURITY_CONFIG = {\n \"min_password_length\": 8,\n \"require_uppercase\": True,\n \"require_lowercase\": True,\n \"require_digit\": True,\n \"bcrypt_rounds\": 12,\n }\n\n @classmethod\n def get_model_config(cls, model_name: str) -> Dict[str, Any]:\n \"\"\"Récupère la configuration d'un modèle.\"\"\"\n return cls.SUPPORTED_MODELS.get(model_name, {})\n\n @classmethod\n def get_all_model_names(cls) -> list:\n \"\"\"Retourne tous les noms de modèles supportés.\"\"\"\n return list(cls.SUPPORTED_MODELS.keys())\n\n @classmethod\n def validate_api_keys(cls) -> Dict[str, bool]:\n \"\"\"Valide la présence des clés API.\"\"\"\n return {\n \"openai\": bool(cls.OPENAI_API_KEY),\n \"anthropic\": bool(cls.ANTHROPIC_API_KEY),\n \"deepseek\": bool(cls.DEEPSEEK_API_KEY),\n }\n\n @classmethod\n def get_available_models(cls) -> list:\n \"\"\"Retourne les modèles disponibles selon les clés API présentes.\"\"\"\n api_status = cls.validate_api_keys()\n available = []\n\n for model_name, config in cls.SUPPORTED_MODELS.items():\n provider = config.get(\"provider\")\n if api_status.get(provider, False):\n available.append(model_name)\n\n return available\n\n\n# Instance globale de configuration\nconfig = Config()\n"}}, "deploy_ovh_with_db_reset.sh": {"db22d3900cfbc5a5883673130c34b40d9ac9527b": {"t": 1786068353.777316, "n": 7427, "h": "b60d8dff95d9f838", "c": "#!/bin/bash\n# Script de mise à jour VPS OVH avec RESET de la base de données\n# ⚠️ ATTENTION : Ce script supprime complètement la base de données existante\n# Basé sur update_vps.sh mais avec reset complet\n\nset -e # Arrêter en cas d'erreur\n\nVPS_IP=\"51.210.243.134\"\nVPS_USER=\"debian\"\nTIMESTAMP=$(date +%Y%m%d_%H%M%S)\n\necho \"🚀 Mise à jour VPS avec RESET de la base de données - $TIMESTAMP\"\necho \"📍 Serveur: $VPS_IP\"\necho \"👤 Utilisateur: $VPS_USER\"\necho \"\"\necho \"⚠️ ATTENTION : Ce déploiement va SUPPRIMER COMPLÈTEMENT la base de données existante !\"\necho \"⚠️ Tous les utilisateurs, campagnes et personnages seront perdus !\"\necho \"⚠️ Cette opération est IRRÉVERSIBLE !\"\necho \"\"\nread -p \"Voulez-vous vraiment continuer ? (tapez 'RESET' pour confirmer): \" confirm\n\nif [ \"$confirm\" != \"RESET\" ]; then\n echo \"❌ Déploiement annulé\"\n exit 1\nfi\n\necho \"\"\necho \"🔥 Confirmation reçue - Procédure de reset en cours...\"\n\n# 1. Créer le nouveau package localement\necho \"\"\necho \"📦 Création du package de déploiement...\"\npython scripts/deploy.py package\n\n# Trouver le dernier package créé\nPACKAGE_FILE=$(ls -t dist/dnd-gamemaster-*.zip 2>/dev/null | head -n1)\nif [ ! -f \"$PACKAGE_FILE\" ]; then\n echo \"❌ Erreur: Aucun package trouvé dans dist/\"\n echo \"💡 Assurez-vous que 'python scripts/deploy.py package' fonctionne\"\n exit 1\nfi\n\necho \"✅ Package créé: $PACKAGE_FILE\"\nPACKAGE_NAME=$(basename \"$PACKAGE_FILE\")\n\n# 2. Copier le package sur le serveur\necho \"\"\necho \"📤 Copie du package sur le serveur...\"\nif ! scp \"$PACKAGE_FILE\" ${VPS_USER}@${VPS_IP}:~/; then\n echo \"❌ Erreur lors de la copie du package\"\n echo \"💡 Vérifiez votre connexion SSH\"\n exit 1\nfi\n\necho \"✅ Package copié: $PACKAGE_NAME\"\n\n# 3. Mise à jour sur le serveur avec RESET\necho \"\"\necho \"🔥 Mise à jour sur le serveur avec RESET COMPLET des données...\"\n\nssh ${VPS_USER}@${VPS_IP} << REMOTE_SCRIPT\n\nset -e\n\necho \"\"\necho \"🔥 === ARRÊT ET NETTOYAGE COMPLET ===\"\n\n# Arrêter l'application en supprimant TOUS les volumes\nif [ -d ~/docker ]; then\n cd ~/docker\n if [ -f docker-compose.yml ]; then\n echo \"🛑 Arrêt de l'application avec suppression des volumes...\"\n docker-compose down -v --remove-orphans\n echo \"✅ Application arrêtée et volumes supprimés\"\n else\n echo \"⚠️ docker-compose.yml non trouvé dans ~/docker\"\n fi\nelse\n echo \"⚠️ Dossier ~/docker non trouvé\"\nfi\n\n# Supprimer complètement les volumes Docker persistants (nettoyage approfondi)\necho \"🗑️ Suppression des volumes Docker existants...\"\ndocker volume ls -q | grep -E \"(docker_app|comparemodel)\" | xargs -r docker volume rm || echo \"ℹ️ Aucun volume à supprimer\"\necho \"✅ Volumes Docker nettoyés\"\n\n# Supprimer l'ancienne base de données et portraits\necho \"🗑️ Suppression complète de l'ancienne base de données et portraits...\"\nrm -f ~/database.db\nrm -rf ~/static/portraits\nrm -rf ~/data # Supprimer aussi le dossier data s'il existe\necho \"✅ Ancienne base de données et portraits supprimés\"\n\n# Créer un log de reset pour traçabilité\nmkdir -p ~/backups\necho \"$(date): Reset complet effectué par deploy_ovh_with_db_reset.sh - TIMESTAMP=${TIMESTAMP}\" >> ~/backups/reset_log.txt\n\necho \"\"\necho \"📦 === DÉPLOIEMENT DE LA NOUVELLE VERSION ===\"\n\ncd ~/\necho \"📂 Décompression du nouveau package...\"\nif unzip -o \"$PACKAGE_NAME\"; then\n echo \"✅ Package décompressé\"\nelse\n echo \"❌ Erreur lors de la décompression\"\n exit 1\nfi\n\necho \"\"\necho \"⚙️ === CONFIGURATION ENVIRONNEMENT ===\"\n\n# S'assurer que le fichier .env est présent et configuré\nif [ -f ~/.env ]; then\n cp ~/.env ~/docker/.env\n echo \"✅ Fichier .env copié depuis ~/.env\"\nelif [ -f ~/docker/.env ]; then\n echo \"✅ Fichier .env déjà présent dans ~/docker\"\nelse\n echo \"⚠️ ATTENTION: Fichier .env non trouvé !\"\n echo \"💡 Vous devrez configurer manuellement les variables d'environnement\"\n echo \"📋 Variables requises: OPENAI_API_KEY, ANTHROPIC_API_KEY, DEEPSEEK_API_KEY\"\nfi\n\n# Créer les dossiers nécessaires pour les portraits avec permissions correctes\necho \"📁 Création de la structure des dossiers pour les portraits...\"\nmkdir -p ./static/portraits/gm\nmkdir -p ./static/portraits/characters\nchmod -R 755 ./static/portraits\necho \"✅ Structure des dossiers créée avec permissions correctes\"\n\necho \"\"\necho \"🚀 === REDÉMARRAGE DE L'APPLICATION AVEC BASE VIERGE ===\"\n\ncd ~/docker\nif [ -f docker-compose.yml ]; then\n echo \"🔨 Construction et démarrage de l'application (base vierge)...\"\n docker-compose up --build -d\n echo \"✅ Application redémarrée avec base de données vierge\"\nelse\n echo \"❌ docker-compose.yml non trouvé dans ~/docker\"\n exit 1\nfi\n\necho \"\"\necho \"🔍 === VÉRIFICATION DU DÉPLOIEMENT ===\"\n\n# Attendre que l'application démarre\necho \"⏳ Attente du démarrage de l'application (30 secondes)...\"\nsleep 30\n\n# Vérifier que l'application fonctionne\nif docker ps | grep -q docker_app_1; then\n echo \"✅ Conteneur démarré avec succès\"\n \n # Test de santé\n if curl -f -s http://localhost:8501/_stcore/health > /dev/null 2>&1; then\n echo \"✅ Health check réussi - Application fonctionnelle\"\n else\n echo \"⚠️ Health check échoué - Application en cours de démarrage\"\n echo \"💡 Attendez quelques minutes et vérifiez http://${VPS_IP}:8501\"\n fi\n \n # Afficher le statut des conteneurs\n echo \"🔍 Statut des conteneurs:\"\n docker-compose ps\n \nelse\n echo \"❌ Erreur: Conteneur non démarré\"\n echo \"📋 Logs du conteneur:\"\n docker logs docker_app_1 --tail 20 2>/dev/null || echo \"Impossible d'accéder aux logs\"\nfi\n\necho \"\"\necho \"📊 === RÉSUMÉ DU RESET ===\"\necho \"🕐 Timestamp: ${TIMESTAMP}\"\necho \"📦 Package: $PACKAGE_NAME\"\necho \"🔥 Action: RESET COMPLET (base de données + portraits + volumes)\"\necho \"💾 Sauvegarde: AUCUNE (reset intentionnel)\"\necho \"🎨 Portraits: Structure créée et prête pour stockage local\"\necho \"🌐 URL: http://${VPS_IP}:8501\"\necho \"\"\necho \"🎉 === RESET ET DÉPLOIEMENT TERMINÉS AVEC SUCCÈS ! ===\"\necho \"✅ Base de données : NEUVE (complètement réinitialisée)\"\necho \"✅ Portraits : Dossiers créés et configurés pour stockage local\"\necho \"✅ Volumes Docker : Recréés à neuf\"\necho \"✅ Application : Démarrée avec configuration propre\"\necho \"\"\necho \"📝 Notes importantes :\"\necho \" • La base de données est complètement vierge\"\necho \" • Tous les anciens comptes utilisateurs ont été supprimés\"\necho \" • Les nouveaux portraits seront automatiquement stockés localement\"\necho \" • Le fix de stockage local des portraits est actif\"\necho \" • Aucune donnée précédente n'a été préservée\"\n\nREMOTE_SCRIPT\n\necho \"\"\necho \"🎉 === MISE À JOUR VPS AVEC RESET TERMINÉE ===\"\necho \"🌐 Votre application est accessible à: http://${VPS_IP}:8501\"\necho \"✅ Base de données complètement réinitialisée\"\necho \"✅ Système de portraits configuré pour stockage local\"\necho \"\"\necho \"🔍 Pour vérifier que tout fonctionne:\"\necho \" curl -f http://${VPS_IP}:8501/\"\necho \"\"\necho \"📋 Prochaines étapes recommandées :\"\necho \" 1. Accédez à l'application et créez un nouveau compte utilisateur\"\necho \" 2. Testez la création d'une campagne pour vérifier la génération du portrait MJ\"\necho \" 3. Testez la création d'un personnage pour vérifier la génération du portrait\"\necho \" 4. Vérifiez dans les logs que les portraits sont bien téléchargés et stockés localement\"\necho \"\"\necho \"📋 Pour voir les logs en temps réel:\"\necho \" ssh ${VPS_USER}@${VPS_IP} 'cd ~/docker && docker-compose logs -f'\"\n\n# Nettoyer le package local\nrm -f \"$PACKAGE_FILE\"\necho \"🧹 Package local nettoyé\"\n"}}}}