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

@ -21,13 +21,16 @@ import type {
Session,
SessionDetail,
Skill,
SkillDetailResponse,
SkillDraft,
SkillDraftEvalReport,
SkillDraftSafetyReport,
SkillFileContent,
SkillHubInstallResponse,
SkillHubSearchItem,
SkillHubSearchResponse,
SkillHubVersionResponse,
SkillHubVersionsResponse,
SkillLearningCandidate,
SkillReviewRecord,
SlashCommand,
@ -56,6 +59,7 @@ const ACCESS_TOKEN_KEY = 'nanobot_access_token';
const REFRESH_TOKEN_KEY = 'nanobot_refresh_token';
const REQUEST_TIMEOUT_MS = 8000;
const OUTLOOK_REQUEST_TIMEOUT_MS = 45000;
const SKILL_LEARNING_REQUEST_TIMEOUT_MS = 120000;
function isBrowser(): boolean {
return typeof window !== 'undefined';
@ -728,6 +732,21 @@ export async function listSkills(): Promise<Skill[]> {
return fetchJSON('/api/skills');
}
export async function getSkillDetail(skillName: string): Promise<SkillDetailResponse> {
return fetchJSON(`/api/skills/${encodeURIComponent(skillName)}/detail`);
}
export async function getSkillVersion(skillName: string, version: string): Promise<SkillDetailResponse> {
return fetchJSON(`/api/skills/${encodeURIComponent(skillName)}/versions/${encodeURIComponent(version)}`);
}
export async function getSkillFile(skillName: string, version: string, filePath: string): Promise<SkillFileContent> {
const search = new URLSearchParams({ path: filePath });
return fetchJSON(
`/api/skills/${encodeURIComponent(skillName)}/versions/${encodeURIComponent(version)}/file?${search.toString()}`
);
}
export async function listSkillCandidates(status?: string): Promise<SkillLearningCandidate[]> {
const query = status ? `?status=${encodeURIComponent(status)}` : '';
return fetchJSON(`/api/skills/candidates${query}`);
@ -737,6 +756,7 @@ export async function synthesizeSkillDraft(candidateId: string): Promise<SkillDr
return fetchJSON(`/api/skills/candidates/${encodeURIComponent(candidateId)}/draft`, {
method: 'POST',
body: JSON.stringify({}),
timeoutMs: SKILL_LEARNING_REQUEST_TIMEOUT_MS,
});
}
@ -744,6 +764,7 @@ export async function regenerateSkillDraft(candidateId: string): Promise<SkillDr
return fetchJSON(`/api/skills/candidates/${encodeURIComponent(candidateId)}/regenerate`, {
method: 'POST',
body: JSON.stringify({}),
timeoutMs: SKILL_LEARNING_REQUEST_TIMEOUT_MS,
});
}
@ -757,6 +778,7 @@ export async function runSkillLearningOnce(): Promise<{
return fetchJSON('/api/skills/learning/run-once', {
method: 'POST',
body: JSON.stringify({}),
timeoutMs: SKILL_LEARNING_REQUEST_TIMEOUT_MS,
});
}
@ -1301,6 +1323,24 @@ export async function getSkillHubVersion(
);
}
export async function getSkillHubVersions(namespace: string, slug: string): Promise<SkillHubVersionsResponse> {
return fetchJSON(
`/api/marketplaces/skills/${encodeURIComponent(namespace.replace(/^@/, ''))}/${encodeURIComponent(slug)}/versions`
);
}
export async function getSkillHubFile(
namespace: string,
slug: string,
version: string,
filePath: string
): Promise<SkillFileContent> {
const search = new URLSearchParams({ path: filePath });
return fetchJSON(
`/api/marketplaces/skills/${encodeURIComponent(namespace.replace(/^@/, ''))}/${encodeURIComponent(slug)}/versions/${encodeURIComponent(version)}/file?${search.toString()}`
);
}
export async function installSkillHubSkill(
namespace: string,
slug: string,
@ -1441,11 +1481,26 @@ export interface BrowseResult {
items: WorkspaceItem[];
}
export interface WorkspaceFileContent {
name: string;
path: string;
size: number;
content_type: string;
modified: string;
is_binary: boolean;
is_truncated: boolean;
content: string | null;
}
export async function browseWorkspace(path: string = ''): Promise<BrowseResult> {
const params = path ? `?path=${encodeURIComponent(path)}` : '';
return fetchJSON(`/api/workspace/browse${params}`);
}
export async function getWorkspaceFile(path: string): Promise<WorkspaceFileContent> {
return fetchJSON(`/api/workspace/file?path=${encodeURIComponent(path)}`);
}
export function getWorkspaceDownloadUrl(path: string): string {
return buildApiUrl(`/api/workspace/download?path=${encodeURIComponent(path)}`);
}