"""Роли и их экземпляры: кто с каким промптом, скиллами, руками и границами.""" from __future__ import annotations from datetime import date from pathlib import Path from typing import TYPE_CHECKING from beaver_gateway.agents.claude import ClaudeAgent, ClaudeOptions from beaver_gateway.agents.raycast import RaycastAgent, RemoteTool, UserPreferences from beaver_agent import hands, prompts, skills from beaver_agent.policy import ( DEEP_DISALLOWED, DISPATCHER_DISALLOWED, DISTILLER_DISALLOWED, STRICT_ZONES, TRIAGE_DISALLOWED, VAULT_POLICY, forbid_skills, vault_zones, ) from beaver_agent.vault import TZ, VAULT if TYPE_CHECKING: from beaver_gateway.agents.base import BaseAgent def dispatcher(name: str, model: str, effort: str) -> ClaudeAgent: """Мастер и ветки: полный голос, все руки, vault - дом.""" return ClaudeAgent( name=name, model=model, cwd=VAULT, prompts=prompts.DISPATCHER, skill_sets=skills.DISPATCHER, gateway_tools=("read_conversation", "spawn", "say", "schedule"), options=ClaudeOptions(effort=effort, disallowed_tools=DISPATCHER_DISALLOWED), policy=( *VAULT_POLICY, forbid_skills(skills.MASTER_FORBIDDEN, kinds=("master",)), ), expose_mcps=hands.DISPATCHER, ) def deep(name: str, model: str, effort: str) -> ClaudeAgent: """Глубокий чат в файле vault; «ок, обсудили» - тулза close_chat.""" return ClaudeAgent( name=name, model=model, cwd=VAULT, prompts=prompts.DEEP, skill_sets=skills.DEEP, gateway_tools=("close_chat",), options=ClaudeOptions(effort=effort, disallowed_tools=DEEP_DISALLOWED), policy=VAULT_POLICY, expose_mcps=hands.CLAUDE, ) def distiller(name: str, model: str, effort: str) -> ClaudeAgent: """Форк закрытого чата и недельная чистка состояния: Read/Write в мета/бобер.""" return ClaudeAgent( name=name, model=model, cwd=VAULT, prompts=prompts.DISTILLER, options=ClaudeOptions( effort=effort, tools=("Read", "Write"), disallowed_tools=DISTILLER_DISALLOWED, ), policy=(vault_zones(STRICT_ZONES),), ) def curator(name: str, model: str, effort: str) -> ClaudeAgent: """Куратор памяти: раскладывает новое по наблюдениям, будит мастера через inject.""" return ClaudeAgent( name=name, model=model, cwd=VAULT, prompts=prompts.CURATOR, gateway_tools=("inject",), options=ClaudeOptions( effort=effort, tools=("Read", "Write", "Edit", "Grep", "Glob"), disallowed_tools=DISTILLER_DISALLOWED, ), policy=(vault_zones(STRICT_ZONES),), ) def triage(name: str, model: str, effort: str) -> ClaudeAgent: """Дешёвый крон-тёрн без vault: решает, будить ли мастера.""" return ClaudeAgent( name=name, model=model, cwd=Path("/tmp"), # noqa: S108 prompts=prompts.TRIAGE, gateway_tools=("say", "inject"), options=ClaudeOptions( effort=effort, tools=(), disallowed_tools=TRIAGE_DISALLOWED ), ) def raycast(name: str, model: str, effort: str) -> RaycastAgent: """Быстрые ответы через Raycast: веб и чтение страниц, vault через obsidian-fs.""" return RaycastAgent( name=name, model=model, system_prompt=prompts.QUICK, reasoning_effort=effort, available_native_tools=(RemoteTool.WEB_SEARCH, RemoteTool.READ_PAGE), user_preferences=lambda: UserPreferences( locale="ru-RU", timezone=TZ, current_date=date.today().isoformat() ), expose_mcps=hands.RAYCAST, ) agents: list[BaseAgent] = [ dispatcher("beaver-dispatcher", "claude-opus-5", "high"), deep("beaver-opus-high", "claude-opus-5", "high"), deep("beaver-opus-medium", "claude-opus-5", "medium"), deep("beaver-opus-xhigh", "claude-opus-5", "xhigh"), deep("beaver-fable-high", "claude-fable-5-1", "high"), deep("beaver-fable-medium", "claude-fable-5-1", "medium"), distiller("beaver-distiller", "claude-opus-5", "medium"), curator("beaver-curator", "claude-opus-5", "high"), triage("beaver-triage", "claude-sonnet-5", "low"), raycast("beaver-gemini-pro-high", "google-gemini-3.1-pro", "high"), raycast("beaver-gemini-pro-low", "google-gemini-3.1-pro", "low"), raycast("beaver-gemini-flash-high", "google-gemini-3.5-flash", "high"), raycast("beaver-gemini-flash-low", "google-gemini-3.5-flash", "low"), ]