Files

152 lines
5.3 KiB
Python

"""Роли и их экземпляры: кто с каким промптом, скиллами, руками и границами."""
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
from beaver_agent.voice import AGENT as VOICE
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", "send_file"),
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 voice(name: str, model: str) -> ClaudeAgent:
"""Колонки по квартире: чужие люди, поэтому ни vault, ни инструментов."""
return ClaudeAgent(
name=name,
model=model,
cwd=Path("/tmp"), # noqa: S108
prompts=prompts.VOICE_AGENT,
options=ClaudeOptions(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"),
voice(VOICE, "claude-haiku-4-5-20251001"),
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"),
]