feat: 顶栏新增 TFS 连接测试与 MCP 状态/日志查看

- 后端新增只读端点 POST /api/session/test:用已存配置真正回连一次 TFS,
  验证服务可达与认证有效,不改动会话/配置状态,返回耗时与 Collection 数
- 顶栏加「测试 TFS 连接」按钮:手动触发,图标按结果变色(绿=正常/红=断开),
  结果走右上角 toast
- Electron 将 MCP 子进程 stdio 由 ignore 改为管道捕获,环形缓冲保留最近 500 行;
  跟踪运行状态(pid/运行时长/重启次数/退出码)并探活 /healthz,新增 get-mcp-status
  / get-mcp-logs 两个 IPC,经 preload 与 lib/electron 暴露
- 顶栏加「MCP 服务状态」入口,新增 McpStatusDialog 展示状态摘要与运行日志
  (打开期间每 2 秒刷新、自动滚到底部)

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
fenghp
2026-06-23 11:05:19 +08:00
co-authored by Cursor
parent e9f942e695
commit 9018a6c90e
11 changed files with 501 additions and 6 deletions
+34 -1
View File
@@ -1,4 +1,4 @@
import type { MactfsBridge, ServiceStatus } from "./types"
import type { MactfsBridge, McpLogEntry, McpStatus, ServiceStatus } from "./types"
const DEFAULT_BASE_URL = "http://127.0.0.1:38765"
@@ -96,6 +96,39 @@ export async function revealPath(targetPath: string, isFolder: boolean): Promise
return bridge.revealPath(targetPath, isFolder)
}
/**
* 查询 MCP 子进程运行状态,非 Electron 环境返回未运行占位。
*/
export async function getMcpStatus(): Promise<McpStatus> {
const bridge = getBridge()
if (!bridge) {
return {
running: false,
healthy: false,
pid: null,
sseUrl: "http://127.0.0.1:38766/sse",
startedAt: null,
uptimeMs: 0,
restartCount: 0,
lastExitCode: null,
lastError: "当前不在 Electron 桌面环境,无法访问 MCP 服务",
entryResolved: false,
}
}
return bridge.getMcpStatus()
}
/**
* 读取 MCP 子进程运行日志(最近 500 行),非 Electron 环境返回空数组。
*/
export async function getMcpLogs(): Promise<McpLogEntry[]> {
const bridge = getBridge()
if (!bridge) {
return []
}
return bridge.getMcpLogs()
}
/**
* 构造非 Electron 环境下的占位服务状态。
*/
+3 -1
View File
@@ -1,7 +1,9 @@
export type { MactfsBridge, ServiceHealth, ServiceStatus } from "./types"
export type { MactfsBridge, McpLogEntry, McpStatus, ServiceHealth, ServiceStatus } from "./types"
export {
getApiBaseUrl,
getBridge,
getMcpLogs,
getMcpStatus,
getServiceStatus,
getToken,
isElectron,
+23
View File
@@ -17,6 +17,27 @@ export interface ServiceStatus {
error: string | null
}
// MCP 子进程运行状态,由 Electron 主进程汇总(含 /healthz 探活)。
export interface McpStatus {
running: boolean
healthy: boolean
pid: number | null
sseUrl: string
startedAt: number | null
uptimeMs: number
restartCount: number
lastExitCode: number | null
lastError: string | null
entryResolved: boolean
}
// MCP 单行运行日志(来自子进程 stdout/stderr)。
export interface McpLogEntry {
ts: number
stream: "stdout" | "stderr"
line: string
}
// preload 暴露到 window.mactfs 的窄接口契约。
export interface MactfsBridge {
isElectron: true
@@ -27,6 +48,8 @@ export interface MactfsBridge {
selectDirectory(): Promise<string | null>
pathsExist(paths: string[]): Promise<Record<string, boolean>>
revealPath(targetPath: string, isFolder: boolean): Promise<boolean>
getMcpStatus(): Promise<McpStatus>
getMcpLogs(): Promise<McpLogEntry[]>
}
declare global {