feat(ai): 完善远程 MCP 指引与排障体验

This commit is contained in:
Syngnat
2026-06-11 08:31:20 +08:00
parent 26fb650e04
commit 4a944ad23f
16 changed files with 577 additions and 3 deletions

View File

@@ -26,6 +26,43 @@ export const BUILTIN_AI_INSPECTION_TOOL_INFO: AIBuiltinToolInfo[] = [
},
},
},
{
name: "inspect_ai_support_bundle",
icon: "📦",
desc: "导出 AI 排障支持包",
detail:
"一次性汇总 AI 应用健康、供应商与 MCP 状态、应用日志摘要、连接失败摘要、消息流结构、上下文体量、远程 MCP 接入和工具目录索引。适合用户反馈“AI 不稳定”“MCP/连接/日志一起看”“要给开发排障材料”时先生成一份不含密钥和数据库密码的支持包。",
params: "keyword?, sessionId?, lineLimit?(默认 120), includeLogLines?(默认 false), includeMessageContent?(默认 false), publicUrl?, tokenConfigured?",
tool: {
type: "function",
function: {
name: "inspect_ai_support_bundle",
description:
"生成 GoNavi AI 排障支持包,汇总 AI 应用健康、供应商和发送前置、MCP 配置和远程接入、应用日志摘要、数据库连接失败摘要、当前 AI 消息流、上下文体量风险和工具目录索引。默认不包含数据库密码、供应商密钥、MCP 环境变量值、日志原文或完整消息内容。适用于用户反馈 AI 不稳定、MCP/连接/日志问题交织、需要一次性导出排障证据或准备给开发定位时优先调用。",
parameters: {
type: "object",
properties: {
keyword: { type: "string", description: "可选,按关键词过滤日志和工具目录,例如 ai、mcp、mysql、error、openclaw" },
connectionKeyword: { type: "string", description: "可选,分析连接失败日志时使用的关键词;不传时复用 keyword" },
sessionId: { type: "string", description: "可选,指定要诊断的 AI 会话 ID不传时使用当前活动会话" },
lineLimit: { type: "number", description: "可选,最多分析多少行应用日志,默认 120最大 240" },
includeLogLines: { type: "boolean", description: "可选,是否附带日志原文行,默认 false需要引用原文时再开启" },
includeMessageContent: { type: "boolean", description: "可选,是否附带消息内容预览,默认 false排查气泡内容时再开启" },
includeDetails: { type: "boolean", description: "可选,是否附带上下文体量明细,默认 false" },
publicUrl: { type: "string", description: "可选,云端 Agent 访问 GoNavi MCP 的公网/隧道 URL用于远程 MCP 支持包" },
localAddr: { type: "string", description: "可选Windows 本机 HTTP MCP 监听地址,默认 127.0.0.1:8765" },
path: { type: "string", description: "可选Streamable HTTP MCP 路径,默认 /mcp" },
exposeStrategy: {
type: "string",
enum: ["reverse_proxy", "ssh_reverse_tunnel", "cloudflare_tunnel", "tailscale", "custom"],
description: "可选,远程暴露方式,用于生成对应安全提醒",
},
tokenConfigured: { type: "boolean", description: "可选,是否已经准备随机 Bearer Token传 false 会返回鉴权告警" },
},
},
},
},
},
{
name: "inspect_ai_setup_health",
icon: "🩺",

View File

@@ -44,6 +44,11 @@ export const BUILTIN_TOOL_FLOWS: AIBuiltinToolFlow[] = [
steps: 'inspect_app_health -> inspect_ai_setup_health / inspect_app_logs / inspect_recent_connection_failures / inspect_ai_last_render_error / inspect_ai_message_flow',
description: '适合用户反馈 AI 不稳定、连接和 MCP 问题交织、回复气泡显示异常,或需要先看整体健康状态时,一次汇总配置、日志、连接失败、渲染异常、消息流和工作区现场。',
},
{
title: '导出 AI 排障支持包',
steps: 'inspect_ai_support_bundle -> inspect_app_health / inspect_ai_context_budget / inspect_ai_message_flow / inspect_mcp_remote_access',
description: '适合需要一次性带走排障证据,或用户反馈 AI 不成熟、不稳定、MCP/连接/日志/上下文都可能相关时,先生成不含密钥和数据库密码的支持包。',
},
{
title: '选择 AI 工具路线',
steps: 'inspect_ai_tool_catalog -> inspect_ai_runtime / inspect_mcp_setup',

View File

@@ -17,6 +17,14 @@ describe('aiToolRegistry', () => {
expect(info?.tool.function.description).toContain('聊天发送前置');
});
it('registers the ai-support-bundle inspector as a builtin tool', () => {
const info = BUILTIN_AI_TOOL_INFO.find((item) => item.name === 'inspect_ai_support_bundle');
expect(info).toBeTruthy();
expect(info?.desc).toContain('排障支持包');
expect(info?.tool.function.description).toContain('默认不包含数据库密码');
expect(info?.tool.function.parameters?.properties?.includeMessageContent?.description).toContain('默认 false');
});
it('registers the ai-safety inspector as a builtin tool', () => {
const info = BUILTIN_AI_TOOL_INFO.find((item) => item.name === 'inspect_ai_safety');
expect(info).toBeTruthy();
@@ -222,6 +230,7 @@ describe('aiToolRegistry', () => {
expect(tools.some((item) => item.function.name === 'inspect_ai_runtime')).toBe(true);
expect(tools.some((item) => item.function.name === 'inspect_ai_setup_health')).toBe(true);
expect(tools.some((item) => item.function.name === 'inspect_ai_support_bundle')).toBe(true);
expect(tools.some((item) => item.function.name === 'inspect_ai_safety')).toBe(true);
expect(tools.some((item) => item.function.name === 'inspect_ai_providers')).toBe(true);
expect(tools.some((item) => item.function.name === 'inspect_ai_chat_readiness')).toBe(true);

View File

@@ -18,6 +18,58 @@ export interface RemoteMCPClientQuickStart {
securityNotes: string[];
}
export interface RemoteMCPParameterGuide {
key: string;
title: string;
required: boolean;
fill: string;
example: string;
avoid: string;
}
export const REMOTE_MCP_PARAMETER_GUIDES: RemoteMCPParameterGuide[] = [
{
key: 'publicUrl',
title: '公网/隧道 URL',
required: true,
fill: '填云端 Agent 能访问到的 Streamable HTTP MCP 地址,通常以 /mcp 结尾。',
example: 'https://agent-gateway.example.com/mcp',
avoid: '不要填 Windows 本机的 127.0.0.1;云端 Linux 访问不到这个地址。',
},
{
key: 'bearerToken',
title: 'Bearer Token',
required: true,
fill: '填一段随机长 tokenWindows 启动命令和云端 Agent 配置必须一致。',
example: 'Authorization: Bearer gnv_xxx',
avoid: '不要使用空 token、短 token也不要把数据库密码当 token 填进去。',
},
{
key: 'localAddr',
title: '本机监听地址',
required: true,
fill: 'Windows GoNavi HTTP MCP 默认监听 127.0.0.1:8765再交给隧道或反向代理转发。',
example: DEFAULT_REMOTE_MCP_LOCAL_ADDR,
avoid: '没有网关隔离时不要直接绑定 0.0.0.0 暴露到公网。',
},
{
key: 'path',
title: 'MCP 路径',
required: true,
fill: '本机启动命令、隧道 URL 和云端 Agent 配置里的路径要保持一致。',
example: DEFAULT_REMOTE_MCP_PATH,
avoid: '不要一边用 /mcp另一边配置 /api/mcp路径不一致会 404。',
},
{
key: 'serverId',
title: '服务 ID',
required: false,
fill: '给云端 Agent 识别这条 MCP 服务的名称,默认 gonavi 即可。',
example: 'gonavi',
avoid: '不要频繁改名,否则 Agent 里已有的工具引用可能失效。',
},
];
export const EMPTY_MCP_CLIENT_STATUSES: AIMCPClientInstallStatus[] = [
{
client: 'claude-code',