feat(delegation): 添加直连模式下的委托公告回调机制
- 引入 DirectAnnouncementCallback 类型用于处理直连模式下的公告 - 在 DelegationManager 中添加 _direct_announcement_callback 属性和设置方法 - 实现 _notify_direct_announcement 方法用于在非总线模式下将公告回写到本地会话 - 在委托取消、完成和分组完成时添加对直连公告的通知逻辑 feat(web): 增加 WebSocket 广播器支持实时会话更新通知 - 创建 WebSocketBroadcaster 类用于跟踪认证的 WebSocket 连接并广播 JSON 事件 - 在应用启动时初始化 websocket_broadcaster 实例 - 实现连接注册、注销和消息广播功能 - 添加过期连接清理机制 feat(agent): 新增系统公告处理方法支持本地处理 - 在 AgentLoop 中添加 process_system_announcement 方法用于在无常驻 run() 场景下处理系统公告 - 创建 InboundMessage 并通过 _process_message 进行处理 feat(cron): 改进定时任务的会话路由解析和实时更新 - 添加 _resolve_cron_session_key 和 _infer_cron_route_from_session_key 辅助函数 - 在 cron 任务执行完成后通过 WebSocket 广播会话更新事件 - 在添加定时任务时自动推断目标会话的渠道和聊天 ID refactor: 项目名称从 Boardware Genius 统一改为 Boardware Agent Sandbox - 更新前端页面标题和描述文本中的产品名称 - 添加新的品牌 Logo 图片资源 - 在前端布局中使用新的 Logo 显示 - 更新授权门户中的品牌信息和 Logo 显示 feat(frontend): 添加会话更新事件监听实现消息自动刷新 - 定义 SessionUpdatedEvent 类型接口 - 在 ChatPage 中添加会话更新事件的处理逻辑 - 当收到会话更新事件时自动重新加载会话列表和当前会话消息 feat(api): 扩展定时任务 API 支持会话键参数 - 在 addCronJob API 参数中添加 session_key 字段 - 更新前端 Cron 页面的表单处理以传递当前会话键
This commit is contained in:
@ -11,6 +11,7 @@ from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import uuid
|
||||
from collections.abc import Awaitable, Callable
|
||||
from dataclasses import dataclass, field
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
@ -30,6 +31,8 @@ from nanobot.bus.events import InboundMessage, OutboundMessage
|
||||
from nanobot.bus.queue import MessageBus
|
||||
from nanobot.providers.base import LLMProvider
|
||||
|
||||
DirectAnnouncementCallback = Callable[[str, dict[str, str], str, bool], Awaitable[None]]
|
||||
|
||||
|
||||
@dataclass
|
||||
class DelegationRun:
|
||||
@ -83,6 +86,14 @@ class DelegationManager:
|
||||
backend_identity=backend_identity,
|
||||
)
|
||||
self._running_tasks: dict[str, DelegationRun] = {}
|
||||
self._direct_announcement_callback: DirectAnnouncementCallback | None = None
|
||||
|
||||
def set_direct_announcement_callback(
|
||||
self,
|
||||
callback: DirectAnnouncementCallback | None,
|
||||
) -> None:
|
||||
"""注册直连模式下的本地公告处理器。"""
|
||||
self._direct_announcement_callback = callback
|
||||
|
||||
async def dispatch(
|
||||
self,
|
||||
@ -309,6 +320,26 @@ class DelegationManager:
|
||||
for run_id in list(self._running_tasks):
|
||||
await self.cancel(run_id)
|
||||
|
||||
async def _notify_direct_announcement(
|
||||
self,
|
||||
content: str,
|
||||
origin: dict[str, str],
|
||||
sender_id: str,
|
||||
) -> None:
|
||||
"""在非 bus 模式下,把公告直接回写到本地会话。"""
|
||||
callback = self._direct_announcement_callback
|
||||
if callback is None:
|
||||
return
|
||||
try:
|
||||
await callback(
|
||||
content,
|
||||
origin,
|
||||
sender_id,
|
||||
not has_process_event_sink(),
|
||||
)
|
||||
except Exception as exc:
|
||||
logger.warning("Failed to handle direct delegation announcement: {}", exc)
|
||||
|
||||
async def _run_dispatch(
|
||||
self,
|
||||
run_id: str,
|
||||
@ -753,6 +784,16 @@ class DelegationManager:
|
||||
origin,
|
||||
sender_id="delegation-cancel",
|
||||
)
|
||||
else:
|
||||
await self._notify_direct_announcement(
|
||||
(
|
||||
f"[Delegation '{label}' cancelled]\n\n"
|
||||
f"Task: {task}\n\n"
|
||||
"Tell the user briefly that the delegated work was cancelled."
|
||||
),
|
||||
origin,
|
||||
"delegation-cancel",
|
||||
)
|
||||
await self._emit_direct_user_message(
|
||||
f"The delegated work '{label}' for task '{task}' was cancelled. Tell the user briefly.",
|
||||
f"已取消委派任务:{label}",
|
||||
@ -780,6 +821,8 @@ class DelegationManager:
|
||||
)
|
||||
if announce_via_bus:
|
||||
await self._publish_announcement(content, origin, sender_id="delegation")
|
||||
else:
|
||||
await self._notify_direct_announcement(content, origin, "delegation")
|
||||
await self._emit_direct_user_message(
|
||||
content,
|
||||
f"{result.agent_name} 已完成:{result.summary}",
|
||||
@ -815,6 +858,12 @@ class DelegationManager:
|
||||
origin,
|
||||
sender_id="delegation-group",
|
||||
)
|
||||
else:
|
||||
await self._notify_direct_announcement(
|
||||
summary,
|
||||
origin,
|
||||
"delegation-group",
|
||||
)
|
||||
await self._emit_direct_user_message(
|
||||
summary,
|
||||
"多 agent 协作已完成,请查看各 agent 的结果与最终结论。",
|
||||
|
||||
@ -738,6 +738,25 @@ class AgentLoop:
|
||||
archive_all=archive_all, memory_window=self.memory_window,
|
||||
)
|
||||
|
||||
async def process_system_announcement(
|
||||
self,
|
||||
content: str,
|
||||
*,
|
||||
origin_channel: str,
|
||||
origin_chat_id: str,
|
||||
sender_id: str = "delegation",
|
||||
) -> str:
|
||||
"""在无常驻 run() 的场景下,本地处理一条 system 公告。"""
|
||||
await self._connect_mcp()
|
||||
msg = InboundMessage(
|
||||
channel="system",
|
||||
sender_id=sender_id,
|
||||
chat_id=f"{origin_channel}:{origin_chat_id}",
|
||||
content=content,
|
||||
)
|
||||
response = await self._process_message(msg)
|
||||
return response.content if response else ""
|
||||
|
||||
async def process_direct(
|
||||
self,
|
||||
content: str,
|
||||
|
||||
Reference in New Issue
Block a user