feat(config,compose): dispatcher agent, api frontend, merge prompt and morning seed
This commit is contained in:
@@ -1,15 +1,17 @@
|
||||
import os
|
||||
from datetime import date
|
||||
from datetime import date, timedelta
|
||||
from pathlib import Path
|
||||
|
||||
from beaver_gateway.agents.base import BaseAgent, ExposedMcp
|
||||
from beaver_gateway.agents.claude import ClaudeAgent, ClaudeOptions
|
||||
from beaver_gateway.agents.raycast import RaycastAgent, RemoteTool, UserPreferences
|
||||
from beaver_gateway.core.conversations import ConversationTexts, SeedContext
|
||||
from beaver_gateway.core.prompt import assemble
|
||||
from beaver_gateway.core.registry import Gateway
|
||||
from beaver_gateway.core.turn_record import TurnRecord, slugify
|
||||
from beaver_gateway.frontends.admin import AdminFrontend
|
||||
from beaver_gateway.frontends.anthropic import AnthropicMessagesFrontend
|
||||
from beaver_gateway.frontends.api import ApiFrontend
|
||||
from beaver_gateway.frontends.base import Frontend
|
||||
from beaver_gateway.frontends.markdown import MarkdownFrontend
|
||||
from beaver_gateway.frontends.mcp_server import McpServerFrontend
|
||||
@@ -60,8 +62,31 @@ DEEP_PROMPT = (
|
||||
)
|
||||
QUICK_PROMPT = assemble((*VOICE, PROFILE, overlay("quick", "быстрый")))
|
||||
|
||||
# Диспетчер: тот же голос, окружение по kind (§3.12), оверлей по роли.
|
||||
# Форк ветки (слив) думает как дистиллятор в окружении джоба.
|
||||
_DISPATCHER_BASE = (*VOICE, PROFILE, CORRECTIONS, VAULT_MAP)
|
||||
DISPATCHER_PROMPTS = {
|
||||
"master": (
|
||||
*_DISPATCHER_BASE,
|
||||
environment("мастер"),
|
||||
overlay("dispatcher", "диспетчер"),
|
||||
),
|
||||
"branch": (*_DISPATCHER_BASE, environment("ветка"), overlay("branch", "ветка")),
|
||||
"fork": (
|
||||
*_DISPATCHER_BASE,
|
||||
environment("джоб"),
|
||||
overlay("distiller", "дистиллятор"),
|
||||
),
|
||||
"job": (
|
||||
*_DISPATCHER_BASE,
|
||||
environment("джоб"),
|
||||
overlay("distiller", "дистиллятор"),
|
||||
),
|
||||
}
|
||||
|
||||
# §4.3: наборы скиллов = папки = плагины. Глубокие грузят общие + vault.
|
||||
DEEP_SKILLS = (SKILLS / "общие", SKILLS / "vault")
|
||||
DISPATCHER_SKILLS = (SKILLS / "общие", SKILLS / "диспетчер", SKILLS / "vault")
|
||||
|
||||
|
||||
def chat_log_path(record: TurnRecord, vault: Path) -> Path:
|
||||
@@ -128,6 +153,24 @@ UserPrefsRu = lambda: UserPreferences( # noqa: E731
|
||||
)
|
||||
|
||||
|
||||
def dispatcher(name: str, model: str, effort: str | None = None) -> ClaudeAgent:
|
||||
return ClaudeAgent(
|
||||
name=name,
|
||||
model=model,
|
||||
cwd=VAULT,
|
||||
prompt_sources=DISPATCHER_PROMPTS["master"],
|
||||
prompt_sources_by_kind=DISPATCHER_PROMPTS,
|
||||
skill_sets=DISPATCHER_SKILLS,
|
||||
gateway_tools=("read_conversation", "spawn", "say", "schedule"),
|
||||
options=ClaudeOptions(
|
||||
effort=effort,
|
||||
# §3.7: у диспетчера AskUserQuestion остаётся, планов и ноутбуков нет.
|
||||
disallowed_tools=("ExitPlanMode", "EnterPlanMode", "NotebookEdit"),
|
||||
),
|
||||
expose_mcps=CLAUDE_MCPS,
|
||||
)
|
||||
|
||||
|
||||
def deep(name: str, model: str, effort: str | None = None) -> ClaudeAgent:
|
||||
return ClaudeAgent(
|
||||
name=name,
|
||||
@@ -168,6 +211,8 @@ def raycast(name: str, model: str, reasoning_effort: str | None = None) -> Rayca
|
||||
|
||||
|
||||
agents: list[BaseAgent] = [
|
||||
# §12.D4: диспетчер на medium; high - по руке или в ветке.
|
||||
dispatcher("beaver-dispatcher", "claude-opus-5", effort="medium"),
|
||||
deep("beaver-opus-high", "claude-opus-5", effort="high"),
|
||||
raycast("beaver-gemini-pro-high", "google-gemini-3.1-pro", reasoning_effort="high"),
|
||||
deep("beaver-fable-high", "claude-fable-5", effort="high"),
|
||||
@@ -196,6 +241,7 @@ frontends: list[Frontend] = [
|
||||
),
|
||||
McpServerFrontend(host="0.0.0.0", port=62991, public_base_url=_public("/mcp")),
|
||||
AdminFrontend(host="0.0.0.0", port=62992, public_base_url=_public("/admin")),
|
||||
ApiFrontend(host="0.0.0.0", port=62994, public_base_url=_public("/api")),
|
||||
MarkdownFrontend(
|
||||
host="0.0.0.0",
|
||||
port=62993,
|
||||
@@ -208,4 +254,22 @@ frontends: list[Frontend] = [
|
||||
]
|
||||
|
||||
|
||||
gateway = Gateway(agents=agents, mcps=mcps, frontends=frontends)
|
||||
def _read(path: Path) -> str | None:
|
||||
return path.read_text(encoding="utf-8").strip() if path.exists() else None
|
||||
|
||||
|
||||
def seed_body(ctx: SeedContext) -> str | None:
|
||||
"""§8.2: утренний сид - вчерашний хендаут из `дни/`; остальные сиды - gateway."""
|
||||
if ctx.seed != "morning":
|
||||
return None
|
||||
yesterday = date.today() - timedelta(days=1)
|
||||
handout = _read(BEAVER / "дни" / f"{yesterday:%Y-%m-%d}.md")
|
||||
return handout or "Хендаут за вчера не приехал."
|
||||
|
||||
|
||||
texts = ConversationTexts(
|
||||
merge_prompt=_read(GRANULES / "слив.md") or ConversationTexts().merge_prompt,
|
||||
seed=seed_body,
|
||||
)
|
||||
|
||||
gateway = Gateway(agents=agents, mcps=mcps, frontends=frontends, texts=texts)
|
||||
|
||||
Reference in New Issue
Block a user