feat(bookslm): v2.2.0 - BooksLM chat AI contextuel par répertoire + 4 providers AI
CI / lint (push) Failing after 16s
CI / test (push) Skipped
CI / build (push) Skipped
CI / e2e (push) Skipped
CI / security (push) Successful in 21s
Desktop Build / build-windows (push) Canceled after 0s
Desktop Build / build-linux (push) Canceled after 0s

BooksLM (#76):
- Panneau chat slide-in 450px, clic-droit répertoire → 🧠 BooksLM
- Collecte récursive .md avec limites (200 fichiers, 200K chars)
- Cache SHA-256, redaction secrets, priorité README/index
- SSE streaming, badges sources cliquables, historique localStorage
- Commandes palette: BooksLM ouvrir/nouvelle conversation

Providers AI (4 nouveaux):
- NVIDIA (integrate.api.nvidia.com)
- QwenCloud (dashscope.aliyuncs.com)
- Xiaomi (api.xiaomi.com)
- Mistral (api.mistral.ai)
- Tous OpenAI-compatible, auto-listing modèles

Fix: dropdown config-select suit maintenant le thème (option bg/color)
27 tests BooksLM + 466 tests au total
This commit is contained in:
2026-09-06 19:42:40 -04:00
parent 6292bfd9cb
commit 524e6da591
14 changed files with 1595 additions and 11 deletions
+27 -2
View File
@@ -1,6 +1,6 @@
"""ObsiGate AI — Multi-provider AI service for editor enhancement.
Supports: DeepSeek, OpenRouter, Google Gemini.
Supports: DeepSeek, OpenRouter, Google Gemini, Ollama, NVIDIA, QwenCloud, Xiaomi, Mistral.
Configured via environment variables.
"""
@@ -14,7 +14,7 @@ import httpx
logger = logging.getLogger("obsigate.ai")
ProviderName = Literal["deepseek", "openrouter", "gemini", "ollama"]
ProviderName = Literal["deepseek", "openrouter", "gemini", "ollama", "nvidia", "qwencloud", "xiaomi", "mistral"]
# Provider configurations — keys loaded from file or .env
AI_KEYS_FILE = Path("data/api_keys.json")
@@ -61,6 +61,30 @@ def _load_provider_keys():
"model": os.getenv("OLLAMA_MODEL", "qwen2.5-coder:1.5b"),
"auth_header": "Bearer {api_key}",
},
"nvidia": {
"api_key": get_ai_key("NVIDIA_API_KEY"),
"base_url": "https://integrate.api.nvidia.com/v1",
"model": os.getenv("NVIDIA_MODEL", "meta/llama-3.1-405b-instruct"),
"auth_header": "Bearer {api_key}",
},
"qwencloud": {
"api_key": get_ai_key("QWENCLOUD_API_KEY"),
"base_url": "https://dashscope.aliyuncs.com/compatible-mode/v1",
"model": os.getenv("QWENCLOUD_MODEL", "qwen-max"),
"auth_header": "Bearer {api_key}",
},
"xiaomi": {
"api_key": get_ai_key("XIAOMI_API_KEY"),
"base_url": "https://api.xiaomi.com/v1",
"model": os.getenv("XIAOMI_MODEL", "mimo-v2-pro"),
"auth_header": "Bearer {api_key}",
},
"mistral": {
"api_key": get_ai_key("MISTRAL_API_KEY"),
"base_url": "https://api.mistral.ai/v1",
"model": os.getenv("MISTRAL_MODEL", "mistral-large-latest"),
"auth_header": "Bearer {api_key}",
},
}
PROVIDERS = _load_provider_keys()
@@ -139,6 +163,7 @@ async def ai_complete(prompt: str, provider: ProviderName | None = None) -> str:
cfg = _get_provider_config(provider)
if cfg["name"] == "gemini":
return await _call_gemini(prompt, "You are a helpful assistant.")
# All other providers use OpenAI-compatible format
return await _call_deepseek_openrouter(prompt, "You are a helpful assistant.", provider)