Files
ss-tools/backend/src/api/routes/assistant/_tool_search_dashboards.py
busya b5e741077d feat: attention-optimized semantic protocol v2.7
Core changes:
- Add @defgroup/@ingroup to 1791 C2+ contracts (555 files) for HCA 128× pre-training DSA grouping
- Add §0.1 Pre-Training Frequency matrix to semantics-core
- Add §VIII Attention Architecture rules (ATTN_1-4) with MLA/CSA/HCA/DSA mechanics
- Add @defgroup/@ingroup to canonical syntax (§II) and all contract examples

Agent prompts (5 files):
- Add ZERO-STATE RATIONALE with MLA/CSA/HCA/DSA compression mechanics
- Add pre-training note: @RATIONALE/@REJECTED are in-context learned tags
- svelte-coder: add missing #region contract, fix Svelte rule violations
- python-coder/fullstack-coder: honor function contracts from speckit plan
- qa-tester: add attention compliance audit (P3 ATTN_1-4 checks)

Skills (6 files):
- Translate all axiom_config descriptions to English
- Fix doc_dirs to index .opencode/ and .specify/
- Deduplicate 5× complexity_rules → single global_tags catalog
- Reduce semantics-svelte 591→485 lines (remove duplicate code blocks)
- Fix semantics-testing: 'Short IDs' → 'Short hierarchical IDs'
- Fix all examples: flat IDs → hierarchical Domain.Name format
- Fix Svelte examples: replace raw Tailwind + <button> with semantic tokens + /ui

Speckit workflow (commands + templates):
- speckit.plan: add Function-Level Contracts for C3+ with @PRE/@POST/@TEST_EDGE
- speckit.plan: add Attention Compliance Gate (ATTN_1-4 before contract generation)
- speckit.tasks: add function contract inlining format (constraints in task description)
- speckit.specify: load semantics-core for spec density rules
- spec-template: add #region contract, @SEMANTICS grouping, hierarchical IDs
- ux-reference-template: add #region wrapper
- plan-template: add attention gate, @defgroup/@ingroup guidance
- tasks-template: add attention audit + rebuild + orphan check tasks
- constitution.md: translate to English, add Principle VIII (attention-optimized contracts)

Reference modules rewritten (hierarchical IDs + full contracts):
- Auth.Jwt: 6 child contracts with @RATIONALE/@REJECTED/@TEST_EDGE
- Api.Auth: 5 endpoints with @TEST_EDGE + molecular CoT markers
- Migration.Model: @defgroup Migration with 18 @ACTION + 6 @INVARIANT

Scripts:
- add_defgroup_ingroup.py: zero-risk additive @ingroup migration (1791 insertions)
- migrate_hierarchical.py: flat→hierarchical ID dry-run analysis (792 contracts)
- merge_prompts.py: merge all prompts/skills/commands into one review file

Config:
- axiom_config.yaml: 749→395 lines (-47%), English, doc_dirs include prompts
- Fix test_datasets.py import collision (rename → test_datasets_routes.py)
- Fix test_preview.py: SupersetClient→get_superset_client, AsyncMock, logger f-string
2026-06-08 16:30:59 +03:00

123 lines
4.2 KiB
Python
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.

# #region AssistantToolSearchDashboards [C:3] [TYPE Module] [SEMANTICS assistant, tool, dashboards, search]
# @defgroup AssistantApi Module group.
# @BRIEF Handler for the "search_dashboards" tool — search and list dashboards from an environment.
# @LAYER API
# @RELATION DEPENDS_ON -> [AssistantToolRegistry]
# @RELATION DEPENDS_ON -> [SupersetClient]
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.superset_client import SupersetClient
from src.core.task_manager import TaskManager
from src.schemas.auth import User
from ._resolvers import _resolve_env_id
from ._schemas import AssistantAction
from ._tool_registry import assistant_tool
# #region handle_search_dashboards [C:3] [TYPE Function]
# @ingroup AssistantApi
@assistant_tool(
operation="search_dashboards",
domain="dashboards",
description="Search and list dashboards by name/id from an environment. Shows id, title, and URL for each dashboard.",
optional_entities=["environment", "search", "page", "page_size"],
risk_level="safe",
requires_confirmation=False,
)
@belief_scope("search_dashboards")
async def handle_search_dashboards(
intent: dict[str, Any],
current_user: User,
task_manager: TaskManager,
config_manager: ConfigManager,
db: Session,
) -> tuple[str, str | None, list[AssistantAction]]:
"""Search and list dashboards from an environment."""
entities = intent.get("entities", {})
env_token = entities.get("environment")
search = entities.get("search")
page = int(entities.get("page", 1))
page_size = min(int(entities.get("page_size", 20)), 100)
env_id = _resolve_env_id(env_token, config_manager)
if not env_id:
# Show available environments if none specified
envs = config_manager.get_environments()
if not envs:
return ("Нет доступных окружений.", None, [])
env_list = "\n".join(f"- {e.id} ({e.name})" for e in envs)
return (
f"Укажите окружение. Доступные:\n{env_list}\n\n"
f"Пример: `покажи дашборды из окружения dev`",
None,
[],
)
env_map = {e.id: e for e in config_manager.get_environments()}
env = env_map.get(env_id)
if not env:
return (f"Окружение {env_id} не найдено.", None, [])
client = SupersetClient(env)
all_dashboards = await client.get_dashboards_summary(require_slug=True)
# Filter by search term
if search:
search_lower = search.lower()
filtered = [
d
for d in all_dashboards
if search_lower in str(d.get("id", ""))
or search_lower in str(d.get("title", "")).lower()
or search_lower in str(d.get("slug", "")).lower()
]
else:
filtered = list(all_dashboards)
total = len(filtered)
start = (page - 1) * page_size
page_items = filtered[start : start + page_size]
if not page_items:
if search:
return (
f"Дашборды по запросу «{search}» в окружении {env.name} не найдены.",
None,
[],
)
return (f"В окружении {env.name} нет дашбордов.", None, [])
lines = [f"📊 Дашборды в окружении **{env.name}** ({total} всего):"]
for d in page_items:
title = d.get("title", "Без названия")
did = d.get("id", "?")
slug = d.get("slug", "")
slug_str = f" ({slug})" if slug else ""
lines.append(f"- #{did} {title}{slug_str}")
if start + page_size < total:
lines.append(f"\n... и ещё {total - start - page_size}")
actions = [
AssistantAction(
type="open_route",
label=f"Открыть дашборды в {env.name}",
target=f"/dashboards?env_id={env_id}",
)
]
return ("\n".join(lines), None, actions)
# #endregion handle_search_dashboards
# #endregion AssistantToolSearchDashboards