63 lines
2.3 KiB
Python
63 lines
2.3 KiB
Python
"""Единственная ветка голосовых точек: как её открыть и как сменить за ночь."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
from typing import TYPE_CHECKING
|
|
|
|
from beaver_agent.voice.texts import KEY, ROTATED, TITLE
|
|
|
|
if TYPE_CHECKING:
|
|
from beaver_gateway.conversations.service import Conversations
|
|
from beaver_gateway.storage.models import Conversation
|
|
|
|
AGENT = "beaver-voice"
|
|
"""Кто сидит в голосовой ветке; ему не видно ни справки, ни vault."""
|
|
|
|
FRONTEND = "voice"
|
|
TELEGRAM = "telegram"
|
|
|
|
_log = logging.getLogger("beaver_agent.voice")
|
|
|
|
|
|
async def current(conversations: Conversations) -> Conversation | None:
|
|
conv = await conversations.find_bound(frontend=FRONTEND, external_id=KEY)
|
|
return conv if conv is not None and conv.status == "open" else None
|
|
|
|
|
|
async def open_thread(
|
|
conversations: Conversations, *, agent: str, window: str | None = None
|
|
) -> Conversation:
|
|
"""Завести ветку; без ``window`` окно ей открывает телеграм - новым топиком."""
|
|
conv = await conversations.spawn(
|
|
kind="branch",
|
|
agent=agent,
|
|
title=TITLE,
|
|
origin=FRONTEND,
|
|
binding=(TELEGRAM, window) if window else None,
|
|
)
|
|
await conversations.bind(conv, frontend=FRONTEND, external_id=KEY)
|
|
_log.info("голосовая ветка %s (%s)", conv.external_id, agent)
|
|
return conv
|
|
|
|
|
|
async def window_of(conversations: Conversations, conv: Conversation) -> str | None:
|
|
for binding in await conversations.bindings(conv):
|
|
if binding.frontend == TELEGRAM and binding.visible:
|
|
return binding.external_id
|
|
return None
|
|
|
|
|
|
async def rotate(conversations: Conversations) -> Conversation | None:
|
|
"""Ночью - новая ветка в том же топике; молчавшую за сутки не трогаем."""
|
|
old = await current(conversations)
|
|
if old is None or old.last_user_activity_at is None:
|
|
return None
|
|
new = await open_thread(
|
|
conversations, agent=old.agent_name, window=await window_of(conversations, old)
|
|
)
|
|
await conversations.close(old)
|
|
await conversations.say(new, ROTATED)
|
|
_log.info("голосовая ветка: %s -> %s", old.external_id, new.external_id)
|
|
return new
|