refactor(cli): migrate core tools to native ToolDisplay property and fix UI rendering (#25186)

This commit is contained in:
Michael Bleigh
2026-05-06 14:23:26 -07:00
committed by GitHub
parent 4a10751b49
commit 90304b279c
33 changed files with 1033 additions and 57 deletions
+59 -28
View File
@@ -26,7 +26,7 @@ import type {
HistoryItemWithoutId,
LoopDetectionConfirmationRequest,
IndividualToolCallDisplay,
HistoryItemToolGroup,
HistoryItemToolDisplayGroup,
} from '../types.js';
import { StreamingState, MessageType } from '../types.js';
import { findLastSafeSplitPoint } from '../utils/markdownUtilities.js';
@@ -81,6 +81,8 @@ export const useAgentStream = ({
useStateAndRef<Set<string>>(new Set());
const [_isFirstToolInGroup, isFirstToolInGroupRef, setIsFirstToolInGroup] =
useStateAndRef<boolean>(true);
const [_hasEmittedBoxInTurn, hasEmittedBoxInTurnRef, setHasEmittedBoxInTurn] =
useStateAndRef<boolean>(false);
const { startNewPrompt } = useSessionStats();
@@ -408,32 +410,27 @@ export const useAgentStream = ({
// Push completed tools to history
useEffect(() => {
const toolsToPush: IndividualToolCallDisplay[] = [];
for (let i = 0; i < trackedTools.length; i++) {
const tc = trackedTools[i];
if (pushedToolCallIdsRef.current.has(tc.callId)) continue;
if (trackedTools.length === 0) return;
if (
// We only push to history once all currently known tools in the turn are terminal.
// This allows ToolGroupDisplay to correctly hoist ALL notices (topics) for the turn.
const allTerminal = trackedTools.every(
(tc) =>
tc.status === 'success' ||
tc.status === 'error' ||
tc.status === 'cancelled'
) {
toolsToPush.push(tc);
} else {
break;
}
}
tc.status === 'cancelled',
);
if (toolsToPush.length > 0) {
const toolsToPush = trackedTools.filter(
(tc) => !pushedToolCallIdsRef.current.has(tc.callId),
);
if (allTerminal && toolsToPush.length > 0) {
const newPushed = new Set(pushedToolCallIdsRef.current);
for (const tc of toolsToPush) {
newPushed.add(tc.callId);
}
const isLastInBatch =
toolsToPush[toolsToPush.length - 1] ===
trackedTools[trackedTools.length - 1];
const appearance = getToolGroupBorderAppearance(
{ type: 'tool_group', tools: trackedTools },
activePtyId,
@@ -442,24 +439,43 @@ export const useAgentStream = ({
backgroundTasks,
);
const historyItem: HistoryItemToolGroup = {
type: 'tool_group',
tools: toolsToPush,
borderTop: isFirstToolInGroupRef.current,
borderBottom: isLastInBatch,
const hasBoxInBatch = toolsToPush.some(
(tc) => tc.display?.format !== 'notice',
);
const shouldStartNewBlock =
isFirstToolInGroupRef.current ||
(!hasEmittedBoxInTurnRef.current && hasBoxInBatch);
const historyItem: HistoryItemToolDisplayGroup = {
type: 'tool_display_group',
tools: toolsToPush.map((tc) => ({
name: tc.name,
description: tc.description,
...tc.display,
status: tc.status,
originalRequestName: tc.originalRequestName,
})),
borderTop: shouldStartNewBlock,
borderBottom: true,
...appearance,
};
addItem(historyItem);
setPushedToolCallIds(newPushed);
if (hasBoxInBatch) {
setHasEmittedBoxInTurn(true);
}
setIsFirstToolInGroup(false);
}
}, [
trackedTools,
pushedToolCallIdsRef,
isFirstToolInGroupRef,
hasEmittedBoxInTurnRef,
setPushedToolCallIds,
setIsFirstToolInGroup,
setHasEmittedBoxInTurn,
addItem,
activePtyId,
isShellFocused,
@@ -468,7 +484,7 @@ export const useAgentStream = ({
const pendingToolGroupItems = useMemo((): HistoryItemWithoutId[] => {
const remainingTools = trackedTools.filter(
(tc) => !pushedToolCallIds.has(tc.callId),
(tc) => !pushedToolCallIdsRef.current.has(tc.callId),
);
const items: HistoryItemWithoutId[] = [];
@@ -482,10 +498,23 @@ export const useAgentStream = ({
);
if (remainingTools.length > 0) {
const hasBoxInPending = remainingTools.some(
(tc) => tc.display?.format !== 'notice',
);
const shouldStartNewBlock =
pushedToolCallIds.size === 0 ||
(!hasEmittedBoxInTurnRef.current && hasBoxInPending);
items.push({
type: 'tool_group',
tools: remainingTools,
borderTop: pushedToolCallIds.size === 0,
type: 'tool_display_group',
tools: remainingTools.map((tc) => ({
name: tc.name,
description: tc.description,
...tc.display,
status: tc.status,
originalRequestName: tc.originalRequestName,
})),
borderTop: shouldStartNewBlock,
borderBottom: false,
...appearance,
});
@@ -513,7 +542,7 @@ export const useAgentStream = ({
(anyVisibleInHistory || anyVisibleInPending)
) {
items.push({
type: 'tool_group' as const,
type: 'tool_display_group',
tools: [],
borderTop: false,
borderBottom: true,
@@ -525,6 +554,8 @@ export const useAgentStream = ({
}, [
trackedTools,
pushedToolCallIds,
pushedToolCallIdsRef,
hasEmittedBoxInTurnRef,
activePtyId,
isShellFocused,
backgroundTasks,