mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-06-15 02:49:49 +08:00
🐛 fix(ai-mcp): 澄清外部客户端接入文案并统一状态语义
- 将外部客户端安装区统一表述为接入流程\n- 按客户端状态调整主按钮文案与重复操作禁用态\n- 同步 MCP 设置导航描述与相关测试断言
This commit is contained in:
@@ -62,21 +62,21 @@ describe('AIMCPClientInstallPanel', () => {
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(markup).toContain('这里是在把当前 GoNavi 的 MCP 启动配置写给外部客户端');
|
||||
expect(markup).toContain('写入外部客户端配置');
|
||||
expect(markup).toContain('这里是在把 GoNavi MCP 接入 Claude Code / Codex');
|
||||
expect(markup).toContain('接入外部客户端');
|
||||
expect(markup).toContain('目标客户端');
|
||||
expect(markup).toContain('选择目标客户端');
|
||||
expect(markup).toContain('写入当前 GoNavi 配置');
|
||||
expect(markup).toContain('重启对应客户端');
|
||||
expect(markup).toContain('未写入');
|
||||
expect(markup).toContain('写入接入配置');
|
||||
expect(markup).toContain('重启目标客户端');
|
||||
expect(markup).toContain('未接入');
|
||||
expect(markup).toContain('需更新');
|
||||
expect(markup).toContain('复制配置路径');
|
||||
expect(markup).toContain('复制启动命令');
|
||||
expect(markup).toContain('更新已选客户端配置');
|
||||
expect(markup).toContain('Codex 状态');
|
||||
expect(markup).toContain('更新 Codex 接入配置');
|
||||
expect(markup).toContain('已选客户端状态');
|
||||
expect(markup).toContain('CLI 检测:已检测到 codex');
|
||||
expect(markup).toContain('当前已选中,将只对这个客户端执行写入或更新');
|
||||
expect(markup).toContain('已选目标:Codex');
|
||||
expect(markup).toContain('当前目标客户端:Codex');
|
||||
});
|
||||
|
||||
it('shows an already-connected label and supports prewriting config when the client command is not detected locally', () => {
|
||||
@@ -127,10 +127,10 @@ describe('AIMCPClientInstallPanel', () => {
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(markup).toContain('写入到已选客户端');
|
||||
expect(markup).toContain('接入到 Claude Code');
|
||||
expect(markup).toContain('CLI 检测:未检测到 claude');
|
||||
expect(markup).toContain('未检测到本机 claude 命令');
|
||||
expect(markup).toContain('已写入');
|
||||
expect(markup).toContain('已接入');
|
||||
});
|
||||
|
||||
it('makes repeated install avoidance explicit when the selected client already matches current GoNavi', () => {
|
||||
@@ -181,9 +181,9 @@ describe('AIMCPClientInstallPanel', () => {
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(markup).toContain('当前状态:已写入当前 GoNavi,无需重复写入');
|
||||
expect(markup).toContain('当前已写入,无需重复写入');
|
||||
expect(markup).toContain('下面的主按钮会自动禁用,避免重复写入');
|
||||
expect(markup).toContain('当前状态:已接入当前 GoNavi,无需重复操作');
|
||||
expect(markup).toContain('Claude Code 已接入当前 GoNavi');
|
||||
expect(markup).toContain('下面的主按钮会自动禁用,避免重复操作');
|
||||
});
|
||||
|
||||
it('prefers the client that already matches current GoNavi over another stale installed record', () => {
|
||||
@@ -234,7 +234,7 @@ describe('AIMCPClientInstallPanel', () => {
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(markup).toContain('Claude Code 状态');
|
||||
expect(markup).toContain('当前状态:已写入当前 GoNavi,无需重复写入');
|
||||
expect(markup).toContain('已选客户端状态');
|
||||
expect(markup).toContain('当前状态:已接入当前 GoNavi,无需重复操作');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -30,7 +30,7 @@ const hasStatusIssue = (status: AIMCPClientInstallStatus | undefined) =>
|
||||
const getStatusTone = (status: AIMCPClientInstallStatus | undefined, darkMode: boolean) => {
|
||||
if (status?.matchesCurrent) {
|
||||
return {
|
||||
label: '已写入',
|
||||
label: '已接入',
|
||||
color: '#16a34a',
|
||||
bg: darkMode ? 'rgba(34,197,94,0.18)' : 'rgba(34,197,94,0.12)',
|
||||
};
|
||||
@@ -50,7 +50,7 @@ const getStatusTone = (status: AIMCPClientInstallStatus | undefined, darkMode: b
|
||||
};
|
||||
}
|
||||
return {
|
||||
label: '未写入',
|
||||
label: '未接入',
|
||||
color: darkMode ? 'rgba(255,255,255,0.72)' : '#64748b',
|
||||
bg: darkMode ? 'rgba(255,255,255,0.08)' : 'rgba(100,116,139,0.08)',
|
||||
};
|
||||
@@ -67,28 +67,28 @@ const resolveClientCommandName = (status: AIMCPClientInstallStatus | undefined)
|
||||
const getStatusSummary = (status: AIMCPClientInstallStatus | undefined) => {
|
||||
const label = status?.displayName || '这个客户端';
|
||||
if (status?.matchesCurrent) {
|
||||
return `${label} 已写入当前这份 GoNavi MCP,可直接在这个客户端里调用。`;
|
||||
return `${label} 已接入当前这份 GoNavi MCP,可直接在这个客户端里调用。`;
|
||||
}
|
||||
if (status?.installed) {
|
||||
return `${label} 里已经有旧的 GoNavi 记录,更新后会切到当前这份 GoNavi。`;
|
||||
return `${label} 里已经有旧的 GoNavi 接入记录,更新后会切到当前这份 GoNavi。`;
|
||||
}
|
||||
if (hasStatusIssue(status)) {
|
||||
return `${label} 的接入状态读取失败,建议先刷新检测。`;
|
||||
}
|
||||
return `当前还没有把这份 GoNavi MCP 写入 ${label}。`;
|
||||
return `当前还没有把这份 GoNavi MCP 接入 ${label}。`;
|
||||
};
|
||||
|
||||
const getClientOptionSummary = (status: AIMCPClientInstallStatus | undefined) => {
|
||||
if (status?.matchesCurrent) {
|
||||
return '当前这份 GoNavi MCP 已写入到这个客户端。';
|
||||
return '当前这份 GoNavi MCP 已接入到这个客户端。';
|
||||
}
|
||||
if (status?.installed) {
|
||||
return '检测到旧的 GoNavi MCP 记录,建议更新为当前安装路径。';
|
||||
return '检测到旧的 GoNavi 接入记录,建议更新为当前安装路径。';
|
||||
}
|
||||
if (hasStatusIssue(status)) {
|
||||
return '接入状态读取异常,建议先刷新再处理。';
|
||||
}
|
||||
return '尚未写入 GoNavi MCP 配置。';
|
||||
return '尚未把当前 GoNavi MCP 接入到这里。';
|
||||
};
|
||||
|
||||
const getClientDetectionSummary = (status: AIMCPClientInstallStatus | undefined) => {
|
||||
@@ -97,30 +97,31 @@ const getClientDetectionSummary = (status: AIMCPClientInstallStatus | undefined)
|
||||
if (status?.clientDetected) {
|
||||
return `已检测到本机 ${commandName} 命令,接入或更新后重启 ${label} 即可验证。`;
|
||||
}
|
||||
return `未检测到本机 ${commandName} 命令;如果 CLI 还没加入 PATH,也可以先写入 ${label} 配置,稍后再重启验证。`;
|
||||
return `未检测到本机 ${commandName} 命令;如果 CLI 还没加入 PATH,也可以先写入 ${label} 的接入配置,稍后再重启验证。`;
|
||||
};
|
||||
|
||||
const getSelectedClientStateLine = (status: AIMCPClientInstallStatus | undefined) => {
|
||||
if (status?.matchesCurrent) {
|
||||
return '已写入当前 GoNavi,无需重复写入';
|
||||
return '已接入当前 GoNavi,无需重复操作';
|
||||
}
|
||||
if (status?.installed) {
|
||||
return '已存在旧记录,建议更新到当前 GoNavi 路径';
|
||||
return '已存在旧接入记录,建议更新到当前 GoNavi 路径';
|
||||
}
|
||||
if (hasStatusIssue(status)) {
|
||||
return '状态读取异常,建议先刷新检测';
|
||||
}
|
||||
return '当前还没有写入 GoNavi MCP 配置';
|
||||
return '当前还没有接入 GoNavi MCP';
|
||||
};
|
||||
|
||||
const resolveActionLabel = (status: AIMCPClientInstallStatus | undefined) => {
|
||||
const label = status?.displayName || '目标客户端';
|
||||
if (status?.matchesCurrent) {
|
||||
return '当前已写入,无需重复写入';
|
||||
return `${label} 已接入当前 GoNavi`;
|
||||
}
|
||||
if (status?.installed) {
|
||||
return '更新已选客户端配置';
|
||||
return `更新 ${label} 接入配置`;
|
||||
}
|
||||
return '写入到已选客户端';
|
||||
return `接入到 ${label}`;
|
||||
};
|
||||
|
||||
const AIMCPClientInstallPanel: React.FC<AIMCPClientInstallPanelProps> = ({
|
||||
@@ -164,17 +165,17 @@ const AIMCPClientInstallPanel: React.FC<AIMCPClientInstallPanelProps> = ({
|
||||
}}
|
||||
>
|
||||
<div style={{ fontWeight: 700, fontSize: 13, color: overlayTheme.titleText }}>
|
||||
这里是在把当前 GoNavi 的 MCP 启动配置写给外部客户端,不是给 GoNavi 自己安装 MCP。
|
||||
这里是在把 GoNavi MCP 接入 Claude Code / Codex,不是给 GoNavi 自己安装插件。
|
||||
</div>
|
||||
<div style={{ fontSize: 12, color: overlayTheme.mutedText, lineHeight: 1.7 }}>
|
||||
你只需要选中 Claude Code 或 Codex 其中一个目标,GoNavi 就会把“如何启动当前这份 GoNavi MCP”的配置写入那个客户端的用户级配置文件,不会重装 GoNavi,也不会替换 GoNavi 自己的程序文件。
|
||||
你只需要选中 Claude Code 或 Codex 其中一个目标,GoNavi 就会把“如何启动当前这份 GoNavi MCP”的信息写入那个客户端的用户级配置文件,不会重装 GoNavi,也不会替换 GoNavi 自己的程序文件。
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
|
||||
<div style={{ fontWeight: 700, fontSize: 14, color: overlayTheme.titleText }}>写入外部客户端配置</div>
|
||||
<div style={{ fontWeight: 700, fontSize: 14, color: overlayTheme.titleText }}>接入外部客户端</div>
|
||||
<div style={{ fontSize: 12, color: overlayTheme.mutedText, lineHeight: 1.7 }}>
|
||||
先选择 1 个目标客户端,再执行写入或更新。GoNavi 会自动把当前安装路径写入它的用户级 MCP 配置文件,不需要你自己找本机 exe,也不需要手动改配置。
|
||||
先选择 1 个目标客户端,再执行接入或更新。GoNavi 会自动把当前安装路径写入它的用户级 MCP 配置文件,不需要你自己找本机 exe,也不需要手动改配置。
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
@@ -186,8 +187,8 @@ const AIMCPClientInstallPanel: React.FC<AIMCPClientInstallPanelProps> = ({
|
||||
>
|
||||
{[
|
||||
{ step: '1', title: '选择目标客户端', detail: 'Claude Code 和 Codex 二选一即可。' },
|
||||
{ step: '2', title: '写入当前 GoNavi 配置', detail: '只改用户级 MCP 配置,不会重装 GoNavi。' },
|
||||
{ step: '3', title: '重启对应客户端', detail: '重启后就能在外部 CLI 里调用当前 GoNavi MCP。' },
|
||||
{ step: '2', title: '写入接入配置', detail: '只改用户级 MCP 配置,不会重装 GoNavi。' },
|
||||
{ step: '3', title: '重启目标客户端', detail: '重启后就能在外部 CLI 里调用当前 GoNavi MCP。' },
|
||||
].map((item) => (
|
||||
<div
|
||||
key={item.step}
|
||||
@@ -317,10 +318,10 @@ const AIMCPClientInstallPanel: React.FC<AIMCPClientInstallPanelProps> = ({
|
||||
>
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
|
||||
<div style={{ fontWeight: 700, fontSize: 13, color: overlayTheme.titleText }}>
|
||||
{selectedStatus?.displayName || '客户端'} 状态
|
||||
已选客户端状态
|
||||
</div>
|
||||
<div style={{ fontSize: 12, color: overlayTheme.mutedText, lineHeight: 1.7 }}>
|
||||
已选目标:{selectedStatus?.displayName || '未选择客户端'}
|
||||
当前目标客户端:{selectedStatus?.displayName || '未选择客户端'}
|
||||
</div>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
|
||||
<div style={{ fontWeight: 700, fontSize: 13, color: overlayTheme.titleText }}>
|
||||
@@ -403,7 +404,7 @@ const AIMCPClientInstallPanel: React.FC<AIMCPClientInstallPanelProps> = ({
|
||||
<div style={{ fontSize: 12, color: overlayTheme.mutedText, lineHeight: 1.6 }}>
|
||||
{getClientDetectionSummary(selectedStatus)}
|
||||
{' '}
|
||||
已经是当前配置时,下面的主按钮会自动禁用,避免重复写入。
|
||||
已经接入当前这份 GoNavi 时,下面的主按钮会自动禁用,避免重复操作。
|
||||
</div>
|
||||
<Button
|
||||
type={selectedStatus?.matchesCurrent ? 'default' : 'primary'}
|
||||
|
||||
@@ -95,8 +95,8 @@ describe('AISettingsMCPSection', () => {
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(markup).toContain('写入外部客户端配置');
|
||||
expect(markup).toContain('尚未写入 GoNavi MCP 配置');
|
||||
expect(markup).toContain('接入外部客户端');
|
||||
expect(markup).toContain('尚未把当前 GoNavi MCP 接入到这里');
|
||||
expect(markup).toContain('常见启动方式模板');
|
||||
expect(markup).toContain('Node 脚本');
|
||||
expect(markup).toContain('新增 MCP 服务');
|
||||
|
||||
@@ -28,7 +28,7 @@ const AI_SETTINGS_NAV_ITEMS: Array<{
|
||||
{ key: 'providers', title: '模型供应商', description: '配置大模型接口与秘钥', icon: <ApiOutlined /> },
|
||||
{ key: 'safety', title: '安全控制', description: '限制 AI 操作风险级别', icon: <SafetyCertificateOutlined /> },
|
||||
{ key: 'context', title: '上下文', description: '配置携带的数据架构信息', icon: <RobotOutlined /> },
|
||||
{ key: 'mcp', title: 'MCP 服务', description: '接入外部工具源', icon: <AppstoreOutlined /> },
|
||||
{ key: 'mcp', title: 'MCP 服务', description: '把 GoNavi 接入外部客户端并管理工具源', icon: <AppstoreOutlined /> },
|
||||
{ key: 'skills', title: 'Skills', description: '配置可复用提示模块', icon: <ExperimentOutlined /> },
|
||||
{ key: 'tools', title: '内置工具', description: '查看 AI 可调用的数据探针', icon: <ToolOutlined /> },
|
||||
{ key: 'prompts', title: '内置提示词', description: '查看系统预设的底层要求', icon: <ExperimentOutlined /> },
|
||||
|
||||
Reference in New Issue
Block a user