feat(cli): overhaul thinking UI (#18725)

This commit is contained in:
Keith Guerin
2026-03-06 20:20:27 -08:00
committed by GitHub
parent 9455ecd78c
commit e5d58c2b5a
29 changed files with 763 additions and 184 deletions
+68 -27
View File
@@ -62,11 +62,31 @@ export const MainContent = () => {
return -1;
}, [uiState.history]);
const augmentedHistory = useMemo(
() =>
uiState.history.map((item, index) => {
const isExpandable = index > lastUserPromptIndex;
const prevType =
index > 0 ? uiState.history[index - 1]?.type : undefined;
const isFirstThinking =
item.type === 'thinking' && prevType !== 'thinking';
const isFirstAfterThinking =
item.type !== 'thinking' && prevType === 'thinking';
return {
item,
isExpandable,
isFirstThinking,
isFirstAfterThinking,
};
}),
[uiState.history, lastUserPromptIndex],
);
const historyItems = useMemo(
() =>
uiState.history.map((h, index) => {
const isExpandable = index > lastUserPromptIndex;
return (
augmentedHistory.map(
({ item, isExpandable, isFirstThinking, isFirstAfterThinking }) => (
<MemoizedHistoryItemDisplay
terminalWidth={mainAreaWidth}
availableTerminalHeight={
@@ -75,21 +95,22 @@ export const MainContent = () => {
: undefined
}
availableTerminalHeightGemini={MAX_GEMINI_MESSAGE_LINES}
key={h.id}
item={h}
key={item.id}
item={item}
isPending={false}
commands={uiState.slashCommands}
isExpandable={isExpandable}
isFirstThinking={isFirstThinking}
isFirstAfterThinking={isFirstAfterThinking}
/>
);
}),
),
),
[
uiState.history,
augmentedHistory,
mainAreaWidth,
staticAreaMaxItemHeight,
uiState.slashCommands,
uiState.constrainHeight,
lastUserPromptIndex,
],
);
@@ -106,18 +127,31 @@ export const MainContent = () => {
const pendingItems = useMemo(
() => (
<Box flexDirection="column">
{pendingHistoryItems.map((item, i) => (
<HistoryItemDisplay
key={i}
availableTerminalHeight={
uiState.constrainHeight ? staticAreaMaxItemHeight : undefined
}
terminalWidth={mainAreaWidth}
item={{ ...item, id: 0 }}
isPending={true}
isExpandable={true}
/>
))}
{pendingHistoryItems.map((item, i) => {
const prevType =
i === 0
? uiState.history.at(-1)?.type
: pendingHistoryItems[i - 1]?.type;
const isFirstThinking =
item.type === 'thinking' && prevType !== 'thinking';
const isFirstAfterThinking =
item.type !== 'thinking' && prevType === 'thinking';
return (
<HistoryItemDisplay
key={i}
availableTerminalHeight={
uiState.constrainHeight ? staticAreaMaxItemHeight : undefined
}
terminalWidth={mainAreaWidth}
item={{ ...item, id: 0 }}
isPending={true}
isExpandable={true}
isFirstThinking={isFirstThinking}
isFirstAfterThinking={isFirstAfterThinking}
/>
);
})}
{showConfirmationQueue && confirmingTool && (
<ToolConfirmationQueue confirmingTool={confirmingTool} />
)}
@@ -130,20 +164,25 @@ export const MainContent = () => {
mainAreaWidth,
showConfirmationQueue,
confirmingTool,
uiState.history,
],
);
const virtualizedData = useMemo(
() => [
{ type: 'header' as const },
...uiState.history.map((item, index) => ({
type: 'history' as const,
item,
isExpandable: index > lastUserPromptIndex,
})),
...augmentedHistory.map(
({ item, isExpandable, isFirstThinking, isFirstAfterThinking }) => ({
type: 'history' as const,
item,
isExpandable,
isFirstThinking,
isFirstAfterThinking,
}),
),
{ type: 'pending' as const },
],
[uiState.history, lastUserPromptIndex],
[augmentedHistory],
);
const renderItem = useCallback(
@@ -171,6 +210,8 @@ export const MainContent = () => {
isPending={false}
commands={uiState.slashCommands}
isExpandable={item.isExpandable}
isFirstThinking={item.isFirstThinking}
isFirstAfterThinking={item.isFirstAfterThinking}
/>
);
} else {