Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 22 additions & 24 deletions src/core/runtime/hooks/useAgentRuntime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,15 @@ export function useOAgent({
const [contextUsage, setContextUsage] = useState<ContextUsage | null>(null);
const [isCompacting, setIsCompacting] = useState(false);
const [mcpServerStatuses, setMcpServerStatuses] = useState<McpServerStatus[]>([]);
const mapMcpStatuses = useCallback(
(servers: Array<{ name: string; status: string; error?: string }> = []): McpServerStatus[] =>
servers.map((s) => ({
name: s.name,
status: toMcpStatusState(s.status),
...(s.error ? { error: s.error } : {}),
})),
[],
);

const buffer = useRef(new StreamingBuffer());
const parentToolMap = useRef<ParentToolMap>(new Map());
Expand Down Expand Up @@ -256,22 +265,15 @@ export function useOAgent({
version: init.claude_code_version,
permissionMode: init.permissionMode,
});
if (init.mcp_servers?.length) {
setMcpServerStatuses(init.mcp_servers.map((s) => ({
name: s.name,
status: toMcpStatusState(s.status),
})));
// Auto-refresh detailed MCP status after a short delay (auth flows may still be in progress)
const sid = sessionIdRef.current;
if (sid) {
setTimeout(() => {
window.clientCore.mcpStatus(sid).then((result) => {
if (result.servers?.length) {
setMcpServerStatuses(result.servers as McpServerStatus[]);
}
}).catch(() => { /* session may have been stopped */ });
}, 3000);
}
setMcpServerStatuses(mapMcpStatuses(init.mcp_servers ?? []));
// Auto-refresh detailed MCP status after a short delay (auth flows may still be in progress)
const sid = sessionIdRef.current;
if (sid) {
setTimeout(() => {
window.clientCore.mcpStatus(sid).then((result) => {
setMcpServerStatuses(mapMcpStatuses(result.servers ?? []));
}).catch(() => { /* session may have been stopped */ });
}, 3000);
}
setIsConnected(true);
setIsProcessing(true);
Expand Down Expand Up @@ -587,16 +589,14 @@ export function useOAgent({
// After auth completes, refresh MCP server statuses
if (!authEvt.isAuthenticating && sessionIdRef.current) {
window.clientCore.mcpStatus(sessionIdRef.current).then((result) => {
if (result.servers?.length) {
setMcpServerStatuses(result.servers as McpServerStatus[]);
}
setMcpServerStatuses(mapMcpStatuses(result.servers ?? []));
}).catch(() => { /* session may have been stopped */ });
}
break;
}
}
},
[resetStreaming, scheduleFlush, flushNow, handleSubagentEvent],
[resetStreaming, scheduleFlush, flushNow, handleSubagentEvent, mapMcpStatuses],
);

const send = useCallback(
Expand Down Expand Up @@ -751,10 +751,8 @@ export function useOAgent({
const refreshMcpStatus = useCallback(async () => {
if (!sessionIdRef.current) return;
const result = await window.clientCore.mcpStatus(sessionIdRef.current);
if (result.servers?.length) {
setMcpServerStatuses(result.servers as McpServerStatus[]);
}
}, []);
setMcpServerStatuses(mapMcpStatuses(result.servers ?? []));
}, [mapMcpStatuses]);

const reconnectMcpServer = useCallback(async (serverName: string) => {
if (!sessionIdRef.current) return;
Expand Down
52 changes: 22 additions & 30 deletions src/core/workspace/hooks/useWorkspaceSessions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,15 @@ export function useSessionManager(projects: Project[], settings: Settings) {
const [draftMcpStatuses, setDraftMcpStatuses] = useState<McpServerStatus[]>([]);
const draftMcpStatusesRef = useRef<McpServerStatus[]>([]);
draftMcpStatusesRef.current = draftMcpStatuses;
const mapMcpStatuses = useCallback(
(servers: Array<{ name: string; status: string; error?: string }> = []): McpServerStatus[] =>
servers.map((s) => ({
name: s.name,
status: toMcpStatusState(s.status),
...(s.error ? { error: s.error } : {}),
})),
[],
);
// OAP agent tracking — needed to restart the session with updated MCP servers
const oapAgentIdRef = useRef<string | null>(null);
// OAP-side session ID — persisted so we can call session/load on revival after restart
Expand Down Expand Up @@ -193,11 +202,8 @@ export function useSessionManager(projects: Project[], settings: Settings) {
// couldn't match it (preStartedSessionIdRef was still null). Query MCP
// status directly now that the session is initialized.
const statusResult = await window.clientCore.mcpStatus(result.sessionId);
if (statusResult.servers?.length && preStartedSessionIdRef.current === result.sessionId) {
setDraftMcpStatuses(statusResult.servers.map(s => ({
name: s.name,
status: toMcpStatusState(s.status),
})));
if (preStartedSessionIdRef.current === result.sessionId) {
setDraftMcpStatuses(mapMcpStatuses(statusResult.servers ?? []));
}
} else {
// Draft was abandoned before eager start completed
Expand Down Expand Up @@ -351,12 +357,7 @@ export function useSessionManager(projects: Project[], settings: Settings) {
backgroundStoreRef.current.handleEvent(event);
if (event.type === "system" && "subtype" in event && event.subtype === "init") {
const init = event as SystemInitEvent;
if (init.mcp_servers?.length) {
setDraftMcpStatuses(init.mcp_servers.map(s => ({
name: s.name,
status: toMcpStatusState(s.status),
})));
}
setDraftMcpStatuses(mapMcpStatuses(init.mcp_servers ?? []));
}
return;
}
Expand Down Expand Up @@ -984,10 +985,7 @@ export function useSessionManager(projects: Project[], settings: Settings) {
? { ...s, id: newId, agentSessionId: result.agentSessionId ?? s.agentSessionId }
: s,
));
setAcpMcpStatuses((result.mcpStatuses ?? []).map(s => ({
name: s.name,
status: toMcpStatusState(s.status),
})));
setAcpMcpStatuses(mapMcpStatuses(result.mcpStatuses ?? []));
setInitialMessages(messagesRef.current);
setInitialMeta({ isProcessing: false, isConnected: true, sessionInfo: null, totalCost: totalCostRef.current });
if (result.configOptions?.length) setInitialConfigOptions(result.configOptions);
Expand Down Expand Up @@ -1258,9 +1256,13 @@ export function useSessionManager(projects: Project[], settings: Settings) {
compact: engine.compact,
oapConfigOptions: oap.configOptions,
setOAPConfig: oap.setConfig,
mcpServerStatuses: isOAP
? (oapMcpStatuses.length > 0 ? oapMcpStatuses : draftMcpStatuses)
: (agent.mcpServerStatuses.length > 0 ? agent.mcpServerStatuses : draftMcpStatuses),
mcpServerStatuses: isDraft
? (
isOAP
? (oapMcpStatuses.length > 0 ? oapMcpStatuses : draftMcpStatuses)
: (agent.mcpServerStatuses.length > 0 ? agent.mcpServerStatuses : draftMcpStatuses)
)
: (isOAP ? oapMcpStatuses : agent.mcpServerStatuses),
mcpStatusPreliminary: isDraft && draftMcpStatuses.length > 0 && (
isOAP ? oapMcpStatuses.length === 0 : agent.mcpServerStatuses.length === 0
),
Expand All @@ -1269,12 +1271,7 @@ export function useSessionManager(projects: Project[], settings: Settings) {
: (preStartedSessionId && isDraft)
? (async () => {
const result = await window.clientCore.mcpStatus(preStartedSessionId);
if (result.servers?.length) {
setDraftMcpStatuses(result.servers.map(s => ({
name: s.name,
status: toMcpStatusState(s.status),
})));
}
setDraftMcpStatuses(mapMcpStatuses(result.servers ?? []));
})
: agent.refreshMcpStatus,
reconnectMcpServer: isOAP
Expand All @@ -1298,12 +1295,7 @@ export function useSessionManager(projects: Project[], settings: Settings) {
await new Promise(r => setTimeout(r, 3000));
}
const statusResult = await window.clientCore.mcpStatus(preStartedSessionId);
if (statusResult.servers?.length) {
setDraftMcpStatuses(statusResult.servers.map(s => ({
name: s.name,
status: toMcpStatusState(s.status),
})));
}
setDraftMcpStatuses(mapMcpStatuses(statusResult.servers ?? []));
})
: agent.reconnectMcpServer,
restartWithMcpServers: isOAP
Expand Down
Loading