feat(core): add support for MCP progress updates (#19046)

This commit is contained in:
N. Taylor Mullen
2026-02-18 12:46:12 -08:00
committed by GitHub
parent 1cf05b0375
commit 14415316c0
14 changed files with 270 additions and 14 deletions

View File

@@ -320,4 +320,31 @@ describe('<ToolMessage />', () => {
);
expect(lastFrame()).toMatchSnapshot();
});
it('renders progress information appended to description for executing tools', () => {
const { lastFrame } = renderWithContext(
<ToolMessage
{...baseProps}
status={CoreToolCallStatus.Executing}
progressMessage="Working on it..."
progressPercent={42}
/>,
StreamingState.Responding,
);
expect(lastFrame()).toContain(
'A tool for testing (Working on it... - 42%)',
);
});
it('renders only percentage when progressMessage is missing', () => {
const { lastFrame } = renderWithContext(
<ToolMessage
{...baseProps}
status={CoreToolCallStatus.Executing}
progressPercent={75}
/>,
StreamingState.Responding,
);
expect(lastFrame()).toContain('A tool for testing (75%)');
});
});

View File

@@ -55,6 +55,8 @@ export const ToolMessage: React.FC<ToolMessageProps> = ({
embeddedShellFocused,
ptyId,
config,
progressMessage,
progressPercent,
}) => {
const isThisShellFocused = checkIsShellFocused(
name,
@@ -89,6 +91,8 @@ export const ToolMessage: React.FC<ToolMessageProps> = ({
status={status}
description={description}
emphasis={emphasis}
progressMessage={progressMessage}
progressPercent={progressPercent}
/>
<FocusHint
shouldShowFocusHint={shouldShowFocusHint}

View File

@@ -183,6 +183,8 @@ type ToolInfoProps = {
description: string;
status: CoreToolCallStatus;
emphasis: TextEmphasis;
progressMessage?: string;
progressPercent?: number;
};
export const ToolInfo: React.FC<ToolInfoProps> = ({
@@ -190,6 +192,8 @@ export const ToolInfo: React.FC<ToolInfoProps> = ({
description,
status: coreStatus,
emphasis,
progressMessage,
progressPercent,
}) => {
const status = mapCoreStatusToDisplayStatus(coreStatus);
const nameColor = React.useMemo<string>(() => {
@@ -210,6 +214,24 @@ export const ToolInfo: React.FC<ToolInfoProps> = ({
// Hide description for completed Ask User tools (the result display speaks for itself)
const isCompletedAskUser = isCompletedAskUserTool(name, status);
let displayDescription = description;
if (status === ToolCallStatus.Executing) {
const parts: string[] = [];
if (progressMessage) {
parts.push(progressMessage);
}
if (progressPercent !== undefined) {
parts.push(`${Math.round(progressPercent)}%`);
}
if (parts.length > 0) {
const progressInfo = parts.join(' - ');
displayDescription = description
? `${description} (${progressInfo})`
: progressInfo;
}
}
return (
<Box overflow="hidden" height={1} flexGrow={1} flexShrink={1}>
<Text strikethrough={status === ToolCallStatus.Canceled} wrap="truncate">
@@ -219,7 +241,7 @@ export const ToolInfo: React.FC<ToolInfoProps> = ({
{!isCompletedAskUser && (
<>
{' '}
<Text color={theme.text.secondary}>{description}</Text>
<Text color={theme.text.secondary}>{displayDescription}</Text>
</>
)}
</Text>

View File

@@ -59,6 +59,8 @@ export function mapToDisplay(
let outputFile: string | undefined = undefined;
let ptyId: number | undefined = undefined;
let correlationId: string | undefined = undefined;
let progressMessage: string | undefined = undefined;
let progressPercent: number | undefined = undefined;
switch (call.status) {
case CoreToolCallStatus.Success:
@@ -77,6 +79,8 @@ export function mapToDisplay(
case CoreToolCallStatus.Executing:
resultDisplay = call.liveOutput;
ptyId = call.pid;
progressMessage = call.progressMessage;
progressPercent = call.progressPercent;
break;
case CoreToolCallStatus.Scheduled:
case CoreToolCallStatus.Validating:
@@ -100,6 +104,8 @@ export function mapToDisplay(
outputFile,
ptyId,
correlationId,
progressMessage,
progressPercent,
approvalMode: call.approvalMode,
};
});

View File

@@ -104,6 +104,8 @@ export function useToolScheduler(
[config, messageBus],
);
useEffect(() => () => scheduler.dispose(), [scheduler]);
const internalAdaptToolCalls = useCallback(
(coreCalls: ToolCall[], prevTracked: TrackedToolCall[]) =>
adaptToolCalls(coreCalls, prevTracked),

View File

@@ -108,6 +108,8 @@ export interface IndividualToolCallDisplay {
outputFile?: string;
correlationId?: string;
approvalMode?: ApprovalMode;
progressMessage?: string;
progressPercent?: number;
}
export interface CompressionProps {