mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-05-09 14:52:45 +08:00
108 lines
3.1 KiB
Python
108 lines
3.1 KiB
Python
"""Agent 客户端交互请求管理。"""
|
|
|
|
from dataclasses import dataclass, field
|
|
from datetime import datetime, timedelta
|
|
from threading import Lock
|
|
from typing import Dict, List, Optional
|
|
import uuid
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class AgentInteractionOption:
|
|
"""交互选项。"""
|
|
|
|
label: str
|
|
value: str
|
|
|
|
|
|
@dataclass
|
|
class PendingAgentInteraction:
|
|
"""待处理的 Agent 客户端交互请求。"""
|
|
|
|
request_id: str
|
|
session_id: str
|
|
user_id: str
|
|
channel: Optional[str]
|
|
source: Optional[str]
|
|
username: Optional[str]
|
|
title: Optional[str]
|
|
prompt: str
|
|
options: List[AgentInteractionOption]
|
|
created_at: datetime = field(default_factory=datetime.now)
|
|
|
|
|
|
class AgentInteractionManager:
|
|
"""管理 Agent 发起的客户端交互请求。"""
|
|
|
|
_ttl = timedelta(hours=24)
|
|
|
|
def __init__(self):
|
|
self._pending_interactions: Dict[str, PendingAgentInteraction] = {}
|
|
self._lock = Lock()
|
|
|
|
def _cleanup_locked(self):
|
|
expire_before = datetime.now() - self._ttl
|
|
expired_ids = [
|
|
request_id
|
|
for request_id, request in self._pending_interactions.items()
|
|
if request.created_at < expire_before
|
|
]
|
|
for request_id in expired_ids:
|
|
self._pending_interactions.pop(request_id, None)
|
|
|
|
def create_request(
|
|
self,
|
|
session_id: str,
|
|
user_id: str,
|
|
channel: Optional[str],
|
|
source: Optional[str],
|
|
username: Optional[str],
|
|
title: Optional[str],
|
|
prompt: str,
|
|
options: List[AgentInteractionOption],
|
|
) -> PendingAgentInteraction:
|
|
with self._lock:
|
|
self._cleanup_locked()
|
|
request_id = uuid.uuid4().hex[:12]
|
|
while request_id in self._pending_interactions:
|
|
request_id = uuid.uuid4().hex[:12]
|
|
request = PendingAgentInteraction(
|
|
request_id=request_id,
|
|
session_id=session_id,
|
|
user_id=str(user_id),
|
|
channel=channel,
|
|
source=source,
|
|
username=username,
|
|
title=title,
|
|
prompt=prompt,
|
|
options=options,
|
|
)
|
|
self._pending_interactions[request_id] = request
|
|
return request
|
|
|
|
def resolve(
|
|
self,
|
|
request_id: str,
|
|
option_index: int,
|
|
user_id: Optional[str] = None,
|
|
) -> Optional[tuple[PendingAgentInteraction, AgentInteractionOption]]:
|
|
with self._lock:
|
|
self._cleanup_locked()
|
|
request = self._pending_interactions.get(request_id)
|
|
if not request:
|
|
return None
|
|
if user_id is not None and str(request.user_id) != str(user_id):
|
|
return None
|
|
if option_index < 1 or option_index > len(request.options):
|
|
return None
|
|
option = request.options[option_index - 1]
|
|
self._pending_interactions.pop(request_id, None)
|
|
return request, option
|
|
|
|
def clear(self):
|
|
with self._lock:
|
|
self._pending_interactions.clear()
|
|
|
|
|
|
agent_interaction_manager = AgentInteractionManager()
|