/
Watashicuvu
/
agentic-tools
Обзор
Документация
Войти
/
Watashicuvu
/
agentic-tools
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
src/cli_agent/context_loader.py
128 строк
4 KB
Якуб
mts update
12 апр 2026, 21:19
12 апр 2026, 21:19
bff6dcd
Код
Авторство
О чём код?
"""Загрузка контекста из .md файлов с YAML frontmatter.""" import re import yaml from pathlib import Path from typing import Dict, List, Any, Optional from dataclasses import dataclass, field @dataclass class AgentContext: """Контекст агента из .md файла.""" name: str description: str tools: List[str] prompt: str metadata: Dict[str, Any] = field(default_factory=dict) class ContextLoader: """Загрузчик контекста из Markdown файлов.""" FRONTMATTER_PATTERN = re.compile(r'^---\s*\n(.*?)\n---\s*\n(.*)$', re.DOTALL) def __init__(self): self._cache: Dict[str, AgentContext] = {} def load(self, file_path: str) -> AgentContext: """Загрузить контекст из .md файла. Args: file_path: Путь к .md файлу с YAML frontmatter Returns: AgentContext с именем, описанием, инструментами и промптом Raises: FileNotFoundError: Если файл не найден ValueError: Если frontmatter некорректен """ path = Path(file_path).resolve() # Проверка кэша if str(path) in self._cache: return self._cache[str(path)] # Чтение файла if not path.exists(): raise FileNotFoundError(f"Context file not found: {file_path}") content = path.read_text(encoding='utf-8') # Парсинг frontmatter match = self.FRONTMATTER_PATTERN.match(content) if not match: raise ValueError(f"No YAML frontmatter found in: {file_path}") frontmatter_yaml = match.group(1) body = match.group(2).strip() # Парсинг YAML try: frontmatter = yaml.safe_load(frontmatter_yaml) except yaml.YAMLError as e: raise ValueError(f"Invalid YAML frontmatter: {e}") # Валидация обязательных полей if not frontmatter.get('name'): raise ValueError("Missing 'name' in frontmatter") if not frontmatter.get('description'): raise ValueError("Missing 'description' in frontmatter") # Извлечение инструментов tools = frontmatter.get('tools', []) if not isinstance(tools, list): raise ValueError("'tools' must be a list") # Создание контекста context = AgentContext( name=frontmatter['name'], description=frontmatter['description'], tools=tools, prompt=body, metadata={k: v for k, v in frontmatter.items() if k not in ['name', 'description', 'tools']} ) # Кэширование self._cache[str(path)] = context return context def load_multiple(self, file_paths: List[str]) -> Dict[str, AgentContext]: """Загрузить несколько контекстов. Args: file_paths: Список путей к .md файлам Returns: Словарь {name: AgentContext} """ contexts = {} for path in file_paths: try: ctx = self.load(path) contexts[ctx.name] = ctx except Exception as e: print(f"Warning: Failed to load {path}: {e}") return contexts def scan_directory(self, dir_path: str) -> List[Path]: """Сканировать директорию на наличие .md файлов. Args: dir_path: Путь к директории Returns: Список найденных .md файлов """ path = Path(dir_path).resolve() if not path.is_dir(): return [] return list(path.glob("*.md")) def clear_cache(self): """Очистить кэш контекстов.""" self._cache.clear()