feat(assistant): implement tool registry and expand assistant capabilities
Introduce a centralized tool registry system for the assistant to manage executable operations, permissions, and tool catalogs. This refactors the assistant dispatch logic from a monolithic approach to a modular, decorator-based registry. Key changes: - Implement `AssistantToolRegistry` to handle tool registration, permission checks, and safe operation identification. - Add a suite of new assistant tools: backup, commit, branch creation, deployment, health summary, environment listing, LLM operations, maintenance, migration, and dashboard searching. - Refactor `_dispatch.py` and `_llm_planner.py` to utilize the new registry for intent resolution and tool catalog building. - Enhance the LLM planner to support more descriptive clarification responses in Russian when intents are ambiguous. - Update the frontend to support the new tool-based workflow, including improved i18n labels for assistant operations and a new step-by-step wizard for the migration page. - Add ADR-0008 to document the architectural decision for the tool registry.
This commit is contained in:
97
backend/src/api/routes/assistant/_tool_llm_validation.py
Normal file
97
backend/src/api/routes/assistant/_tool_llm_validation.py
Normal file
@@ -0,0 +1,97 @@
|
||||
# #region AssistantToolLlmValidation [C:3] [TYPE Module] [SEMANTICS assistant, tool, llm, validation]
|
||||
# @BRIEF Handler for the "run_llm_validation" tool — run LLM dashboard validation.
|
||||
# @LAYER API
|
||||
# @RELATION DEPENDS_ON -> [AssistantToolRegistry]
|
||||
# @RELATION DEPENDS_ON -> [LLMProviderService]
|
||||
# @RELATION DEPENDS_ON -> [TaskManager]
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from fastapi import HTTPException
|
||||
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 ._resolvers import (
|
||||
_resolve_dashboard_id_entity,
|
||||
_resolve_env_id,
|
||||
_resolve_provider_id,
|
||||
)
|
||||
from ._schemas import AssistantAction
|
||||
from ._tool_registry import _check_any_permission, assistant_tool
|
||||
|
||||
|
||||
# #region handle_run_llm_validation [C:3] [TYPE Function]
|
||||
@assistant_tool(
|
||||
operation="run_llm_validation",
|
||||
domain="llm",
|
||||
description="Run LLM dashboard validation by dashboard id/slug/title",
|
||||
optional_entities=["dashboard_ref", "environment", "provider"],
|
||||
risk_level="guarded",
|
||||
requires_confirmation=False,
|
||||
permission_checks=[("plugin:llm_dashboard_validation", "EXECUTE")],
|
||||
)
|
||||
@belief_scope("run_llm_validation")
|
||||
async def handle_run_llm_validation(
|
||||
intent: dict[str, Any],
|
||||
current_user: User,
|
||||
task_manager: TaskManager,
|
||||
config_manager: ConfigManager,
|
||||
db: Session,
|
||||
) -> tuple[str, str | None, list[AssistantAction]]:
|
||||
"""Run LLM dashboard validation."""
|
||||
_check_any_permission(current_user, [("plugin:llm_dashboard_validation", "EXECUTE")])
|
||||
entities = intent.get("entities", {})
|
||||
env_token = entities.get("environment")
|
||||
env_id = _resolve_env_id(env_token, config_manager) or _resolve_env_id(
|
||||
None, config_manager
|
||||
)
|
||||
dashboard_id = _resolve_dashboard_id_entity(
|
||||
entities, config_manager, env_hint=env_token
|
||||
)
|
||||
provider_id = _resolve_provider_id(
|
||||
entities.get("provider"),
|
||||
db,
|
||||
config_manager=config_manager,
|
||||
task_key="dashboard_validation",
|
||||
)
|
||||
if not dashboard_id or not env_id or (not provider_id):
|
||||
raise HTTPException(
|
||||
status_code=422,
|
||||
detail="Missing dashboard_id/environment/provider. Укажите ID/slug дашборда или окружение.",
|
||||
)
|
||||
provider = LLMProviderService(db).get_provider(provider_id)
|
||||
if not provider or not bool(provider.is_multimodal):
|
||||
raise HTTPException(
|
||||
status_code=422,
|
||||
detail="Selected provider model is not multimodal for dashboard validation. Выберите мультимодальную модель (например, gpt-4o).",
|
||||
)
|
||||
task = await task_manager.create_task(
|
||||
plugin_id="llm_dashboard_validation",
|
||||
params={
|
||||
"dashboard_id": str(dashboard_id),
|
||||
"environment_id": env_id,
|
||||
"provider_id": provider_id,
|
||||
},
|
||||
user_id=current_user.id,
|
||||
)
|
||||
return (
|
||||
f"LLM-валидация запущена. task_id={task.id}",
|
||||
task.id,
|
||||
[
|
||||
AssistantAction(type="open_task", label="Open Task", target=task.id),
|
||||
AssistantAction(
|
||||
type="open_reports", label="Open Reports", target="/reports"
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
# #endregion handle_run_llm_validation
|
||||
# #endregion AssistantToolLlmValidation
|
||||
Reference in New Issue
Block a user