# #region AssistantToolLlm [C:2] [TYPE Module] [SEMANTICS assistant, tool, llm, providers, status] # @defgroup AssistantApi Module group. # @BRIEF Handlers for LLM operations — list providers and check LLM status. # @LAYER API # @RELATION DEPENDS_ON -> [AssistantToolRegistry] # @RELATION DEPENDS_ON -> [LLMProviderService] from __future__ import annotations from typing import Any from sqlalchemy.orm import Session from src.core.config_manager import ConfigManager from src.core.logger import belief_scope, logger from src.core.task_manager import TaskManager from src.schemas.auth import User from src.services.llm_provider import LLMProviderService from ._schemas import AssistantAction from ._tool_registry import assistant_tool # #region handle_list_llm_providers [C:2] [TYPE Function] # @ingroup AssistantApi @assistant_tool( operation="list_llm_providers", domain="llm", description="List configured LLM providers with their type, model, and active status", risk_level="safe", requires_confirmation=False, ) @belief_scope("list_llm_providers") async def handle_list_llm_providers( intent: dict[str, Any], current_user: User, task_manager: TaskManager, config_manager: ConfigManager, db: Session, ) -> tuple[str, str | None, list[AssistantAction]]: """List configured LLM providers.""" service = LLMProviderService(db) providers = service.get_all_providers() if not providers: return ("LLM провайдеры не настроены.", None, []) lines = ["**🤖 LLM провайдеры:**"] for p in providers: icon = "🟢" if p.is_active else "⚪" model = p.default_model or "модель не указана" lines.append( f"{icon} **{p.name}** — {p.provider_type}" f"\n └ Модель: {model}" ) return ( "\n".join(lines), None, [ AssistantAction( type="open_route", label="Настройки LLM", target="/settings/llm", ) ], ) # #endregion handle_list_llm_providers # #region handle_get_llm_status [C:2] [TYPE Function] # @ingroup AssistantApi @assistant_tool( operation="get_llm_status", domain="llm", description="Check if LLM is configured and ready for dashboard validation and documentation", risk_level="safe", requires_confirmation=False, ) @belief_scope("get_llm_status") async def handle_get_llm_status( intent: dict[str, Any], current_user: User, task_manager: TaskManager, config_manager: ConfigManager, db: Session, ) -> tuple[str, str | None, list[AssistantAction]]: """Check LLM configuration and readiness status.""" service = LLMProviderService(db) providers = service.get_all_providers() active_provider = next((p for p in providers if p.is_active), None) lines = ["**🤖 LLM Статус:**"] if not providers: lines.append("❌ Провайдеры не настроены.") return ("\n".join(lines), None, []) lines.append(f"📊 Всего провайдеров: {len(providers)}") lines.append(f"🟢 Активных: {len([p for p in providers if p.is_active])}") lines.append(f"⚪ Неактивных: {len([p for p in providers if not p.is_active])}") if active_provider: api_key = service.get_decrypted_api_key(active_provider.id) from src.api.routes.llm import _is_valid_runtime_api_key key_valid = _is_valid_runtime_api_key(api_key) lines.append(f"\n**Активный провайдер:** {active_provider.name}") lines.append(f" └ Тип: {active_provider.provider_type}") lines.append(f" └ Модель: {active_provider.default_model or 'не указана'}") lines.append(f" └ API ключ: {'✅ валидный' if key_valid else '❌ невалидный/отсутствует'}") lines.append(f" └ Статус: {'✅ готов' if key_valid else '❌ настроен не полностью'}") return ( "\n".join(lines), None, [ AssistantAction( type="open_route", label="Настройки LLM", target="/settings/llm", ) ], ) # #endregion handle_get_llm_status # #endregion AssistantToolLlm