feat(outlook): 添加Outlook集成功能支持

添加完整的Outlook MCP集成,包括邮件和日历功能,通过AuthZ模式进行认证和权限管理,
支持邮箱连接、断开、状态检查和数据同步等功能。

fix(config): 统一配置文件路径从.nanobot到.beaver

将配置文件路径从/root/.nanobot统一更改为/root/.beaver,更新Dockerfile中的环境变量定义,
确保所有组件使用一致的配置目录结构。

feat(agent): 添加代理删除功能和助手身份提示

为代理注册表添加delete_agent方法,实现代理的动态删除功能;同时添加海狸助手身份提示,
确保AI助手在交互中保持一致的身份认知。

feat(engine): 增强引擎循环并添加意图决策快照

扩展AgentLoop类,添加intent_agent_decision参数用于意图驱动的代理决策,并在会话中记录
决策快照,便于后续分析和调试。

feat(authz): 扩展认证客户端功能

为AuthzClient添加设置权限、用户注册、后端注册和Outlook设置管理等新方法,增强系统
的认证和授权能力。
This commit is contained in:
2026-05-14 16:01:46 +08:00
parent 30ab74ffb2
commit ebfa242862
35 changed files with 3979 additions and 462 deletions

View File

@ -548,8 +548,13 @@ class AgentService:
provider=router_provider,
model=getattr(router_runtime, "model", None),
recent_messages=session_manager.get_messages_as_conversation(session_id),
intent_skill=self._load_intent_agent_skill(loaded),
thinking_enabled=kwargs.get("thinking_enabled"),
)
kwargs["intent_agent_decision"] = self._intent_decision_payload(
decision,
active_task=active_task,
)
if active_task is not None and decision.short_title and not active_task.metadata.get("short_title"):
active_task.metadata["short_title"] = decision.short_title
task_service.store.upsert_task(active_task)
@ -796,6 +801,28 @@ class AgentService:
raise RuntimeError(f"Engine loader did not provide required dependency {field_name!r}")
return value
@staticmethod
def _load_intent_agent_skill(loaded: Any) -> str | None:
skills_loader = getattr(loaded, "skills_loader", None)
if skills_loader is None:
return None
return skills_loader.load_skill("intent-agent-router")
@staticmethod
def _intent_decision_payload(decision: Any, *, active_task: TaskRecord | None) -> dict[str, Any]:
action = decision.action or ("create_task" if decision.is_task and active_task is None else decision.mode)
return {
"agent": "intent_agent",
"choice": action,
"mode": "task" if decision.is_task else "simple",
"reason": decision.reason,
"active_task_id": active_task.task_id if active_task is not None else None,
"starts_new_task": bool(decision.starts_new_task or (decision.is_task and active_task is None)),
"closes_task": bool(decision.closes_task),
"abandons_task": bool(decision.abandons_task),
"short_title": decision.short_title,
}
@staticmethod
def _skill_names_for_run(loaded: Any, run_id: str) -> list[str]:
store = getattr(loaded, "run_memory_store", None)