fix(ui): resolve unwanted vertical spacing around various tool output treatments (#24449)
@@ -4,16 +4,14 @@
|
||||
</style>
|
||||
<rect width="920" height="666" fill="#000000" />
|
||||
<g transform="translate(10, 10)">
|
||||
<rect x="0" y="0" width="900" height="17" fill="#141414" />
|
||||
<text x="0" y="2" fill="#000000" textLength="900" lengthAdjust="spacingAndGlyphs">▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀</text>
|
||||
<rect x="0" y="17" width="9" height="17" fill="#141414" />
|
||||
<rect x="9" y="17" width="18" height="17" fill="#141414" />
|
||||
<text x="9" y="19" fill="#d7afff" textLength="18" lengthAdjust="spacingAndGlyphs">> </text>
|
||||
<rect x="27" y="17" width="324" height="17" fill="#141414" />
|
||||
<text x="27" y="19" fill="#ffffff" textLength="324" lengthAdjust="spacingAndGlyphs">Can you edit InputPrompt.tsx for me?</text>
|
||||
<rect x="351" y="17" width="549" height="17" fill="#141414" />
|
||||
<rect x="0" y="34" width="900" height="17" fill="#141414" />
|
||||
<text x="0" y="36" fill="#000000" textLength="900" lengthAdjust="spacingAndGlyphs">▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄</text>
|
||||
<rect x="0" y="0" width="9" height="17" fill="#141414" />
|
||||
<rect x="9" y="0" width="18" height="17" fill="#141414" />
|
||||
<text x="9" y="2" fill="#d7afff" textLength="18" lengthAdjust="spacingAndGlyphs">> </text>
|
||||
<rect x="27" y="0" width="324" height="17" fill="#141414" />
|
||||
<text x="27" y="2" fill="#ffffff" textLength="324" lengthAdjust="spacingAndGlyphs">Can you edit InputPrompt.tsx for me?</text>
|
||||
<rect x="351" y="0" width="549" height="17" fill="#141414" />
|
||||
<rect x="0" y="17" width="900" height="17" fill="#141414" />
|
||||
<text x="0" y="19" fill="#000000" textLength="900" lengthAdjust="spacingAndGlyphs">▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄</text>
|
||||
<text x="0" y="53" fill="#ffffaf" textLength="891" lengthAdjust="spacingAndGlyphs">╭─────────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="0" y="70" fill="#ffffaf" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="70" fill="#ffffaf" textLength="135" lengthAdjust="spacingAndGlyphs" font-weight="bold">Action Required</text>
|
||||
@@ -55,7 +53,7 @@
|
||||
<text x="198" y="189" fill="#0000ee" textLength="36" lengthAdjust="spacingAndGlyphs">true</text>
|
||||
<text x="234" y="189" fill="#00cd00" textLength="9" lengthAdjust="spacingAndGlyphs">;</text>
|
||||
<text x="882" y="189" fill="#ffffaf" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="189" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">█</text>
|
||||
<text x="891" y="189" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">▄</text>
|
||||
<text x="0" y="206" fill="#ffffaf" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="206" fill="#afafaf" textLength="18" lengthAdjust="spacingAndGlyphs">48</text>
|
||||
<text x="63" y="206" fill="#e5e5e5" textLength="54" lengthAdjust="spacingAndGlyphs">const </text>
|
||||
|
||||
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
@@ -1,9 +1,9 @@
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`Full Terminal Tool Confirmation Snapshot > renders tool confirmation box in the frame of the entire terminal 1`] = `
|
||||
"▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
|
||||
> Can you edit InputPrompt.tsx for me?
|
||||
" > Can you edit InputPrompt.tsx for me?
|
||||
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
|
||||
|
||||
╭─────────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ Action Required │
|
||||
│ │
|
||||
@@ -12,7 +12,7 @@ exports[`Full Terminal Tool Confirmation Snapshot > renders tool confirmation bo
|
||||
│ ... first 44 lines hidden (Ctrl+O to show) ... │
|
||||
│ 45 const line45 = true; │
|
||||
│ 46 const line46 = true; │
|
||||
│ 47 const line47 = true; │█
|
||||
│ 47 const line47 = true; │▄
|
||||
│ 48 const line48 = true; │█
|
||||
│ 49 const line49 = true; │█
|
||||
│ 50 const line50 = true; │█
|
||||
|
||||
@@ -49,6 +49,7 @@ interface HistoryItemDisplayProps {
|
||||
isExpandable?: boolean;
|
||||
isFirstThinking?: boolean;
|
||||
isFirstAfterThinking?: boolean;
|
||||
isToolGroupBoundary?: boolean;
|
||||
suppressNarration?: boolean;
|
||||
}
|
||||
|
||||
@@ -62,14 +63,17 @@ export const HistoryItemDisplay: React.FC<HistoryItemDisplayProps> = ({
|
||||
isExpandable,
|
||||
isFirstThinking = false,
|
||||
isFirstAfterThinking = false,
|
||||
isToolGroupBoundary = false,
|
||||
suppressNarration = false,
|
||||
}) => {
|
||||
const settings = useSettings();
|
||||
const inlineThinkingMode = getInlineThinkingMode(settings);
|
||||
const itemForDisplay = useMemo(() => escapeAnsiCtrlCodes(item), [item]);
|
||||
|
||||
const needsTopMarginAfterThinking =
|
||||
isFirstAfterThinking && inlineThinkingMode !== 'off';
|
||||
const needTopMargin = !!(
|
||||
(isFirstAfterThinking && inlineThinkingMode !== 'off') ||
|
||||
isToolGroupBoundary
|
||||
);
|
||||
|
||||
// If there's a topic update in this turn, we suppress the regular narration
|
||||
// and thoughts as they are being "replaced" by the update_topic tool.
|
||||
@@ -87,7 +91,7 @@ export const HistoryItemDisplay: React.FC<HistoryItemDisplayProps> = ({
|
||||
flexDirection="column"
|
||||
key={itemForDisplay.id}
|
||||
width={terminalWidth}
|
||||
marginTop={needsTopMarginAfterThinking ? 1 : 0}
|
||||
marginTop={needTopMargin ? 1 : 0}
|
||||
>
|
||||
{/* Render standard message types */}
|
||||
{itemForDisplay.type === 'thinking' && inlineThinkingMode !== 'off' && (
|
||||
@@ -214,6 +218,7 @@ export const HistoryItemDisplay: React.FC<HistoryItemDisplayProps> = ({
|
||||
borderTop={itemForDisplay.borderTop}
|
||||
borderBottom={itemForDisplay.borderBottom}
|
||||
isExpandable={isExpandable}
|
||||
isToolGroupBoundary={isToolGroupBoundary}
|
||||
/>
|
||||
)}
|
||||
{itemForDisplay.type === 'subagent' && (
|
||||
|
||||
@@ -103,12 +103,16 @@ export const MainContent = () => {
|
||||
item.type === 'thinking' && prevType !== 'thinking';
|
||||
const isFirstAfterThinking =
|
||||
item.type !== 'thinking' && prevType === 'thinking';
|
||||
const isToolGroupBoundary =
|
||||
(item.type !== 'tool_group' && prevType === 'tool_group') ||
|
||||
(item.type === 'tool_group' && prevType !== 'tool_group');
|
||||
|
||||
return {
|
||||
item,
|
||||
isExpandable: i > lastUserPromptIndex,
|
||||
isFirstThinking,
|
||||
isFirstAfterThinking,
|
||||
isToolGroupBoundary,
|
||||
suppressNarration: suppressNarrationFlags[i] ?? false,
|
||||
};
|
||||
}),
|
||||
@@ -123,6 +127,7 @@ export const MainContent = () => {
|
||||
isExpandable,
|
||||
isFirstThinking,
|
||||
isFirstAfterThinking,
|
||||
isToolGroupBoundary,
|
||||
suppressNarration,
|
||||
}) => (
|
||||
<MemoizedHistoryItemDisplay
|
||||
@@ -140,6 +145,7 @@ export const MainContent = () => {
|
||||
isExpandable={isExpandable}
|
||||
isFirstThinking={isFirstThinking}
|
||||
isFirstAfterThinking={isFirstAfterThinking}
|
||||
isToolGroupBoundary={isToolGroupBoundary}
|
||||
suppressNarration={suppressNarration}
|
||||
/>
|
||||
),
|
||||
@@ -175,6 +181,9 @@ export const MainContent = () => {
|
||||
item.type === 'thinking' && prevType !== 'thinking';
|
||||
const isFirstAfterThinking =
|
||||
item.type !== 'thinking' && prevType === 'thinking';
|
||||
const isToolGroupBoundary =
|
||||
(item.type !== 'tool_group' && prevType === 'tool_group') ||
|
||||
(item.type === 'tool_group' && prevType !== 'tool_group');
|
||||
|
||||
const suppressNarration =
|
||||
suppressNarrationFlags[uiState.history.length + i] ?? false;
|
||||
@@ -191,6 +200,7 @@ export const MainContent = () => {
|
||||
isExpandable={true}
|
||||
isFirstThinking={isFirstThinking}
|
||||
isFirstAfterThinking={isFirstAfterThinking}
|
||||
isToolGroupBoundary={isToolGroupBoundary}
|
||||
suppressNarration={suppressNarration}
|
||||
/>
|
||||
);
|
||||
@@ -224,6 +234,7 @@ export const MainContent = () => {
|
||||
isExpandable,
|
||||
isFirstThinking,
|
||||
isFirstAfterThinking,
|
||||
isToolGroupBoundary,
|
||||
suppressNarration,
|
||||
}) => ({
|
||||
type: 'history' as const,
|
||||
@@ -231,6 +242,7 @@ export const MainContent = () => {
|
||||
isExpandable,
|
||||
isFirstThinking,
|
||||
isFirstAfterThinking,
|
||||
isToolGroupBoundary,
|
||||
suppressNarration,
|
||||
}),
|
||||
),
|
||||
@@ -266,6 +278,7 @@ export const MainContent = () => {
|
||||
isExpandable={item.isExpandable}
|
||||
isFirstThinking={item.isFirstThinking}
|
||||
isFirstAfterThinking={item.isFirstAfterThinking}
|
||||
isToolGroupBoundary={item.isToolGroupBoundary}
|
||||
suppressNarration={item.suppressNarration}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -43,12 +43,10 @@ Tips for getting started:
|
||||
│ ✓ tool1 Description for tool 1 │
|
||||
│ │
|
||||
╰──────────────────────────────────────────────────────────────────────────╯
|
||||
|
||||
╭──────────────────────────────────────────────────────────────────────────╮
|
||||
│ ✓ tool2 Description for tool 2 │
|
||||
│ │
|
||||
╰──────────────────────────────────────────────────────────────────────────╯
|
||||
|
||||
╭──────────────────────────────────────────────────────────────────────────╮
|
||||
│ o tool3 Description for tool 3 │
|
||||
│ │
|
||||
@@ -95,7 +93,6 @@ Tips for getting started:
|
||||
│ ✓ tool1 Description for tool 1 │
|
||||
│ │
|
||||
╰──────────────────────────────────────────────────────────────────────────╯
|
||||
|
||||
╭──────────────────────────────────────────────────────────────────────────╮
|
||||
│ ✓ tool2 Description for tool 2 │
|
||||
│ │
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
exports[`MainContent > MainContent Tool Output Height Logic > 'ASB mode - Focused shell should expand' 1`] = `
|
||||
"ScrollableList
|
||||
AppHeader(full)
|
||||
|
||||
╭──────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ ⠋ Shell Command Running a long command... │
|
||||
│ │
|
||||
@@ -23,6 +24,7 @@ AppHeader(full)
|
||||
exports[`MainContent > MainContent Tool Output Height Logic > 'ASB mode - Unfocused shell' 1`] = `
|
||||
"ScrollableList
|
||||
AppHeader(full)
|
||||
|
||||
╭──────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ ⠋ Shell Command Running a long command... │
|
||||
│ │
|
||||
@@ -42,6 +44,7 @@ AppHeader(full)
|
||||
|
||||
exports[`MainContent > MainContent Tool Output Height Logic > 'Normal mode - Constrained height' 1`] = `
|
||||
"AppHeader(full)
|
||||
|
||||
╭──────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ ⠋ Shell Command Running a long command... │
|
||||
│ │
|
||||
@@ -61,6 +64,7 @@ exports[`MainContent > MainContent Tool Output Height Logic > 'Normal mode - Con
|
||||
|
||||
exports[`MainContent > MainContent Tool Output Height Logic > 'Normal mode - Unconstrained height' 1`] = `
|
||||
"AppHeader(full)
|
||||
|
||||
╭──────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ ⠋ Shell Command Running a long command... │
|
||||
│ │
|
||||
@@ -93,6 +97,7 @@ exports[`MainContent > renders a ToolConfirmationQueue without an extra line whe
|
||||
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
|
||||
> Apply plan
|
||||
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
|
||||
|
||||
╭──────────────────────────────────────────────────────────────────────────────╮
|
||||
│ Ready to start implementation? │
|
||||
│ │
|
||||
@@ -103,6 +108,7 @@ exports[`MainContent > renders a ToolConfirmationQueue without an extra line whe
|
||||
|
||||
exports[`MainContent > renders a split tool group without a gap between static and pending areas 1`] = `
|
||||
"AppHeader(full)
|
||||
|
||||
╭──────────────────────────────────────────────────────────────────────────╮
|
||||
│ ✓ test-tool A tool for testing │
|
||||
│ │
|
||||
@@ -128,6 +134,7 @@ exports[`MainContent > renders a subagent with a complete box including bottom b
|
||||
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
|
||||
> Investigate
|
||||
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
|
||||
|
||||
╭──────────────────────────────────────────────────────────────────────────╮
|
||||
│ ≡ Running Agent... (ctrl+o to collapse) │
|
||||
│ │
|
||||
|
||||
@@ -113,6 +113,7 @@ interface ToolGroupMessageProps {
|
||||
borderTop?: boolean;
|
||||
borderBottom?: boolean;
|
||||
isExpandable?: boolean;
|
||||
isToolGroupBoundary?: boolean;
|
||||
}
|
||||
|
||||
// Main component renders the border and maps the tools using ToolMessage
|
||||
@@ -126,6 +127,7 @@ export const ToolGroupMessage: React.FC<ToolGroupMessageProps> = ({
|
||||
borderTop: borderTopOverride,
|
||||
borderBottom: borderBottomOverride,
|
||||
isExpandable,
|
||||
isToolGroupBoundary,
|
||||
}) => {
|
||||
const settings = useSettings();
|
||||
const isLowErrorVerbosity = settings.merged.ui?.errorVerbosity !== 'full';
|
||||
@@ -219,10 +221,11 @@ export const ToolGroupMessage: React.FC<ToolGroupMessageProps> = ({
|
||||
|
||||
const staticHeight = useMemo(() => {
|
||||
let height = 0;
|
||||
|
||||
for (let i = 0; i < groupedTools.length; i++) {
|
||||
const group = groupedTools[i];
|
||||
const isFirst = i === 0;
|
||||
const isLast = i === groupedTools.length - 1;
|
||||
|
||||
const prevGroup = i > 0 ? groupedTools[i - 1] : null;
|
||||
const prevIsCompact =
|
||||
prevGroup &&
|
||||
@@ -235,42 +238,85 @@ export const ToolGroupMessage: React.FC<ToolGroupMessageProps> = ({
|
||||
!Array.isArray(nextGroup) &&
|
||||
isCompactTool(nextGroup, isCompactModeEnabled);
|
||||
|
||||
const nextIsTopicToolCall =
|
||||
nextGroup && !Array.isArray(nextGroup) && isTopicTool(nextGroup.name);
|
||||
|
||||
const isAgentGroup = Array.isArray(group);
|
||||
const isCompact =
|
||||
!isAgentGroup && isCompactTool(group, isCompactModeEnabled);
|
||||
const isTopicToolCall = !isAgentGroup && isTopicTool(group.name);
|
||||
|
||||
const showClosingBorder = !isCompact && (nextIsCompact || isLast);
|
||||
|
||||
if (isFirst) {
|
||||
height += borderTopOverride ? 1 : 0;
|
||||
} else if (isCompact !== prevIsCompact) {
|
||||
// Add a 1-line gap when transitioning between compact and standard tools (or vice versa)
|
||||
height += 1;
|
||||
// Align isFirst logic with rendering
|
||||
let isFirst = i === 0;
|
||||
if (!isFirst) {
|
||||
// Check if all previous tools were topics (matches rendering logic exactly)
|
||||
let allPreviousTopics = true;
|
||||
for (let j = 0; j < i; j++) {
|
||||
const prevGroupItem = groupedTools[j];
|
||||
if (
|
||||
Array.isArray(prevGroupItem) ||
|
||||
!isTopicTool(prevGroupItem.name)
|
||||
) {
|
||||
allPreviousTopics = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
isFirst = allPreviousTopics;
|
||||
}
|
||||
|
||||
const isFirstProp = !!(isFirst
|
||||
? (borderTopOverride ?? true)
|
||||
: prevIsCompact);
|
||||
|
||||
const showClosingBorder =
|
||||
!isCompact &&
|
||||
!isTopicToolCall &&
|
||||
(nextIsCompact || nextIsTopicToolCall || isLast);
|
||||
|
||||
if (isAgentGroup) {
|
||||
// Agent group
|
||||
height += 1; // Header
|
||||
height += group.length; // 1 line per agent
|
||||
if (isFirstProp) height += 1; // Top border
|
||||
if (showClosingBorder) height += 1; // Bottom border
|
||||
// Agent Group Spacing Breakdown:
|
||||
// 1. Top Boundary (0 or 1): Only present via borderTop if isFirstProp is true.
|
||||
// 2. Header Content (1): The "≡ Running Agent..." status text.
|
||||
// 3. Agent List (group.length lines): One line per agent in the group.
|
||||
// 4. Closing Border (1): Added if transition logic (showClosingBorder) requires it.
|
||||
height +=
|
||||
(isFirstProp ? 1 : 0) +
|
||||
1 +
|
||||
group.length +
|
||||
(showClosingBorder ? 1 : 0);
|
||||
} else if (isTopicToolCall) {
|
||||
// Topic Message Spacing Breakdown:
|
||||
// 1. Top Margin (1): Present unless it's the very first item following a boundary.
|
||||
// 2. Topic Content (1).
|
||||
// 3. Bottom Margin (1): Always present around TopicMessage for breathing room.
|
||||
const hasTopMargin = !(isFirst && isToolGroupBoundary);
|
||||
height += (hasTopMargin ? 1 : 0) + 1 + 1;
|
||||
} else if (isCompact) {
|
||||
// Compact Tool: Always renders as a single dense line.
|
||||
height += 1;
|
||||
} else {
|
||||
if (isCompact) {
|
||||
height += 1; // Base height for compact tool
|
||||
} else {
|
||||
// Static overhead for standard tool header:
|
||||
height +=
|
||||
TOOL_RESULT_STATIC_HEIGHT +
|
||||
TOOL_RESULT_STANDARD_RESERVED_LINE_COUNT;
|
||||
}
|
||||
// Standard Tool (ToolMessage / ShellToolMessage) Spacing Breakdown:
|
||||
// 1. TOOL_RESULT_STANDARD_RESERVED_LINE_COUNT (4) accounts for the top boundary,
|
||||
// internal separator, header padding, and the group closing border.
|
||||
// (Subtract 1 to isolate the group-level closing border.)
|
||||
// 2. Header Content (1): TOOL_RESULT_STATIC_HEIGHT (the tool name/status).
|
||||
// 3. Output File Message (1): (conditional) if outputFile is present.
|
||||
// 4. Group Closing Border (1): (conditional) if transition logic (showClosingBorder) requires it.
|
||||
height +=
|
||||
TOOL_RESULT_STANDARD_RESERVED_LINE_COUNT -
|
||||
1 +
|
||||
TOOL_RESULT_STATIC_HEIGHT +
|
||||
(group.outputFile ? 1 : 0) +
|
||||
(showClosingBorder ? 1 : 0);
|
||||
}
|
||||
}
|
||||
return height;
|
||||
}, [groupedTools, isCompactModeEnabled, borderTopOverride]);
|
||||
}, [
|
||||
groupedTools,
|
||||
isCompactModeEnabled,
|
||||
borderTopOverride,
|
||||
isToolGroupBoundary,
|
||||
]);
|
||||
|
||||
let countToolCallsWithResults = 0;
|
||||
for (const tool of visibleToolCalls) {
|
||||
@@ -325,9 +371,7 @@ export const ToolGroupMessage: React.FC<ToolGroupMessageProps> = ({
|
||||
*/
|
||||
width={terminalWidth}
|
||||
paddingRight={TOOL_MESSAGE_HORIZONTAL_MARGIN}
|
||||
// When border will be present, add margin of 1 to create spacing from the
|
||||
// previous message.
|
||||
marginBottom={(borderBottomOverride ?? true) ? 1 : 0}
|
||||
marginBottom={0}
|
||||
>
|
||||
{visibleToolCalls.length === 0 &&
|
||||
isExplicitClosingSlice &&
|
||||
@@ -371,41 +415,27 @@ export const ToolGroupMessage: React.FC<ToolGroupMessageProps> = ({
|
||||
nextGroup &&
|
||||
!Array.isArray(nextGroup) &&
|
||||
isCompactTool(nextGroup, isCompactModeEnabled);
|
||||
const nextIsTopicToolCall =
|
||||
nextGroup && !Array.isArray(nextGroup) && isTopicTool(nextGroup.name);
|
||||
|
||||
const isAgentGroup = Array.isArray(group);
|
||||
const isCompact =
|
||||
!isAgentGroup && isCompactTool(group, isCompactModeEnabled);
|
||||
const isTopicToolCall = !isAgentGroup && isTopicTool(group.name);
|
||||
|
||||
// When border is present, add margin of 1 to create spacing from the
|
||||
// previous message.
|
||||
let marginTop = 0;
|
||||
if (isFirst) {
|
||||
marginTop = (borderTopOverride ?? false) ? 1 : 0;
|
||||
} else if (isCompact && prevIsCompact) {
|
||||
marginTop = 0;
|
||||
} else if (isCompact || prevIsCompact) {
|
||||
marginTop = 1;
|
||||
} else {
|
||||
// For subsequent standard tools scenarios, the ToolMessage and
|
||||
// ShellToolMessage components manage their own top spacing by passing
|
||||
// `isFirst=false` to their internal StickyHeader which then applies
|
||||
// a paddingTop=1 to create desired gap between standard tool outputs.
|
||||
marginTop = 0;
|
||||
}
|
||||
|
||||
const isFirstProp = !!(isFirst
|
||||
? (borderTopOverride ?? true)
|
||||
: prevIsCompact);
|
||||
|
||||
const showClosingBorder =
|
||||
!isCompact && !isTopicToolCall && (nextIsCompact || isLast);
|
||||
!isCompact &&
|
||||
!isTopicToolCall &&
|
||||
(nextIsCompact || nextIsTopicToolCall || isLast);
|
||||
|
||||
if (isAgentGroup) {
|
||||
return (
|
||||
<Box
|
||||
key={group[0].callId}
|
||||
marginTop={marginTop}
|
||||
flexDirection="column"
|
||||
width={contentWidth}
|
||||
>
|
||||
@@ -450,16 +480,16 @@ export const ToolGroupMessage: React.FC<ToolGroupMessageProps> = ({
|
||||
|
||||
return (
|
||||
<Fragment key={tool.callId}>
|
||||
<Box
|
||||
flexDirection="column"
|
||||
minHeight={1}
|
||||
width={contentWidth}
|
||||
marginTop={marginTop}
|
||||
>
|
||||
<Box flexDirection="column" minHeight={1} width={contentWidth}>
|
||||
{isCompact ? (
|
||||
<DenseToolMessage {...commonProps} />
|
||||
) : isTopicToolCall ? (
|
||||
<TopicMessage {...commonProps} />
|
||||
<Box
|
||||
marginTop={isFirst && isToolGroupBoundary ? 0 : 1}
|
||||
marginBottom={1}
|
||||
>
|
||||
<TopicMessage {...commonProps} />
|
||||
</Box>
|
||||
) : isShellToolCall ? (
|
||||
<ShellToolMessage {...commonProps} config={config} />
|
||||
) : (
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
exports[`ToolGroupMessage Compact Rendering > does not add an extra empty line between a compact tool and a standard tool 1`] = `
|
||||
" ✓ ReadFolder Listing files → file1.txt
|
||||
|
||||
╭──────────────────────────────────────────────────────────────────────────╮
|
||||
│ ✓ non-compact-tool Doing something │
|
||||
│ │
|
||||
@@ -17,7 +16,6 @@ exports[`ToolGroupMessage Compact Rendering > does not add an extra empty line b
|
||||
│ │
|
||||
│ some large output │
|
||||
╰──────────────────────────────────────────────────────────────────────────╯
|
||||
|
||||
✓ ReadFolder Listing files → file1.txt
|
||||
"
|
||||
`;
|
||||
|
||||
@@ -62,8 +62,9 @@ exports[`<ToolGroupMessage /> > Golden Snapshots > renders empty tool calls arra
|
||||
|
||||
exports[`<ToolGroupMessage /> > Golden Snapshots > renders header when scrolled 1`] = `
|
||||
"╭──────────────────────────────────────────────────────────────────────────╮
|
||||
│ ✓ tool-1 Description 1. This is a long description that will need to b… │
|
||||
│──────────────────────────────────────────────────────────────────────────│ ▄
|
||||
│ ✓ tool-1 Description 1. This is a long description that will need to b… │ ▄
|
||||
│──────────────────────────────────────────────────────────────────────────│ █
|
||||
│ line3 │ █
|
||||
│ line4 │ █
|
||||
│ line5 │ █
|
||||
│ │ █
|
||||
@@ -72,12 +73,13 @@ exports[`<ToolGroupMessage /> > Golden Snapshots > renders header when scrolled
|
||||
│ line1 │ █
|
||||
│ line2 │ █
|
||||
╰──────────────────────────────────────────────────────────────────────────╯ █
|
||||
█
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`<ToolGroupMessage /> > Golden Snapshots > renders mixed tool calls including update_topic 1`] = `
|
||||
" Testing Topic: This is the description
|
||||
"
|
||||
Testing Topic: This is the description
|
||||
|
||||
╭──────────────────────────────────────────────────────────────────────────╮
|
||||
│ ✓ read_file Read a file │
|
||||
│ │
|
||||
@@ -131,17 +133,18 @@ exports[`<ToolGroupMessage /> > Golden Snapshots > renders tool call with output
|
||||
`;
|
||||
|
||||
exports[`<ToolGroupMessage /> > Golden Snapshots > renders two tool groups where only the last line of the previous group is visible 1`] = `
|
||||
"╭──────────────────────────────────────────────────────────────────────────╮
|
||||
"╰──────────────────────────────────────────────────────────────────────────╯
|
||||
╭──────────────────────────────────────────────────────────────────────────╮
|
||||
│ ✓ tool-2 Description 2 │
|
||||
│ │
|
||||
│ line1 │ ▄
|
||||
│ │ ▄
|
||||
│ line1 │ █
|
||||
╰──────────────────────────────────────────────────────────────────────────╯ █
|
||||
█
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`<ToolGroupMessage /> > Golden Snapshots > renders update_topic tool call using TopicMessage > update_topic_tool 1`] = `
|
||||
" Testing Topic: This is the description
|
||||
"
|
||||
Testing Topic: This is the description
|
||||
"
|
||||
`;
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
exports[`ToolMessage Sticky Header Regression > verifies that ShellToolMessage in a ToolGroupMessage in a ScrollableList has sticky headers 1`] = `
|
||||
"╭────────────────────────────────────────────────────────────────────────╮ █
|
||||
│ ✓ Shell Command Description for Shell Command │ ▀
|
||||
│ ✓ Shell Command Description for Shell Command │ █
|
||||
│ │
|
||||
│ shell-01 │
|
||||
│ shell-02 │
|
||||
@@ -11,7 +11,7 @@ exports[`ToolMessage Sticky Header Regression > verifies that ShellToolMessage i
|
||||
|
||||
exports[`ToolMessage Sticky Header Regression > verifies that ShellToolMessage in a ToolGroupMessage in a ScrollableList has sticky headers 2`] = `
|
||||
"╭────────────────────────────────────────────────────────────────────────╮
|
||||
│ ✓ Shell Command Description for Shell Command │
|
||||
│ ✓ Shell Command Description for Shell Command │ ▄
|
||||
│────────────────────────────────────────────────────────────────────────│ █
|
||||
│ shell-06 │ ▀
|
||||
│ shell-07 │
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="920" height="343" viewBox="0 0 920 343">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="920" height="360" viewBox="0 0 920 360">
|
||||
<style>
|
||||
text { font-family: Consolas, "Courier New", monospace; font-size: 14px; dominant-baseline: text-before-edge; white-space: pre; }
|
||||
</style>
|
||||
<rect width="920" height="343" fill="#000000" />
|
||||
<rect width="920" height="360" fill="#000000" />
|
||||
<g transform="translate(10, 10)">
|
||||
<text x="9" y="19" fill="#4796e4" textLength="9" lengthAdjust="spacingAndGlyphs">▝</text>
|
||||
<text x="18" y="19" fill="#6688d9" textLength="9" lengthAdjust="spacingAndGlyphs">▜</text>
|
||||
@@ -30,16 +30,16 @@
|
||||
<text x="72" y="189" fill="#ffffff" textLength="189" lengthAdjust="spacingAndGlyphs"> for more information</text>
|
||||
<text x="0" y="206" fill="#ffffff" textLength="450" lengthAdjust="spacingAndGlyphs">3. Ask coding questions, edit code or run commands</text>
|
||||
<text x="0" y="223" fill="#ffffff" textLength="315" lengthAdjust="spacingAndGlyphs">4. Be specific for the best results</text>
|
||||
<text x="0" y="240" fill="#ffffaf" textLength="864" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="0" y="257" fill="#ffffaf" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="257" fill="#ffffaf" textLength="9" lengthAdjust="spacingAndGlyphs">⊶</text>
|
||||
<text x="45" y="257" fill="#ffffff" textLength="153" lengthAdjust="spacingAndGlyphs" font-weight="bold">google_web_search</text>
|
||||
<text x="855" y="257" fill="#ffffaf" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="257" fill="#ffffaf" textLength="864" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="0" y="274" fill="#ffffaf" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="274" fill="#ffffaf" textLength="9" lengthAdjust="spacingAndGlyphs">⊶</text>
|
||||
<text x="45" y="274" fill="#ffffff" textLength="153" lengthAdjust="spacingAndGlyphs" font-weight="bold">google_web_search</text>
|
||||
<text x="855" y="274" fill="#ffffaf" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="291" fill="#ffffaf" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="291" fill="#ffffff" textLength="108" lengthAdjust="spacingAndGlyphs">Searching...</text>
|
||||
<text x="855" y="291" fill="#ffffaf" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="308" fill="#ffffaf" textLength="864" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
<text x="0" y="308" fill="#ffffaf" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="308" fill="#ffffff" textLength="108" lengthAdjust="spacingAndGlyphs">Searching...</text>
|
||||
<text x="855" y="308" fill="#ffffaf" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="325" fill="#ffffaf" textLength="864" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.0 KiB |
@@ -1,8 +1,8 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="920" height="343" viewBox="0 0 920 343">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="920" height="360" viewBox="0 0 920 360">
|
||||
<style>
|
||||
text { font-family: Consolas, "Courier New", monospace; font-size: 14px; dominant-baseline: text-before-edge; white-space: pre; }
|
||||
</style>
|
||||
<rect width="920" height="343" fill="#000000" />
|
||||
<rect width="920" height="360" fill="#000000" />
|
||||
<g transform="translate(10, 10)">
|
||||
<text x="9" y="19" fill="#4796e4" textLength="9" lengthAdjust="spacingAndGlyphs">▝</text>
|
||||
<text x="18" y="19" fill="#6688d9" textLength="9" lengthAdjust="spacingAndGlyphs">▜</text>
|
||||
@@ -30,16 +30,16 @@
|
||||
<text x="72" y="189" fill="#ffffff" textLength="189" lengthAdjust="spacingAndGlyphs"> for more information</text>
|
||||
<text x="0" y="206" fill="#ffffff" textLength="450" lengthAdjust="spacingAndGlyphs">3. Ask coding questions, edit code or run commands</text>
|
||||
<text x="0" y="223" fill="#ffffff" textLength="315" lengthAdjust="spacingAndGlyphs">4. Be specific for the best results</text>
|
||||
<text x="0" y="240" fill="#87afff" textLength="864" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="0" y="257" fill="#87afff" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="257" fill="#87afff" textLength="9" lengthAdjust="spacingAndGlyphs">⊶</text>
|
||||
<text x="45" y="257" fill="#ffffff" textLength="153" lengthAdjust="spacingAndGlyphs" font-weight="bold">run_shell_command</text>
|
||||
<text x="855" y="257" fill="#87afff" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="257" fill="#87afff" textLength="864" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="0" y="274" fill="#87afff" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="274" fill="#87afff" textLength="9" lengthAdjust="spacingAndGlyphs">⊶</text>
|
||||
<text x="45" y="274" fill="#ffffff" textLength="153" lengthAdjust="spacingAndGlyphs" font-weight="bold">run_shell_command</text>
|
||||
<text x="855" y="274" fill="#87afff" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="291" fill="#87afff" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="291" fill="#ffffff" textLength="162" lengthAdjust="spacingAndGlyphs">Running command...</text>
|
||||
<text x="855" y="291" fill="#87afff" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="308" fill="#87afff" textLength="864" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
<text x="0" y="308" fill="#87afff" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="308" fill="#ffffff" textLength="162" lengthAdjust="spacingAndGlyphs">Running command...</text>
|
||||
<text x="855" y="308" fill="#87afff" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="325" fill="#87afff" textLength="864" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.0 KiB |
@@ -1,8 +1,8 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="920" height="343" viewBox="0 0 920 343">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="920" height="360" viewBox="0 0 920 360">
|
||||
<style>
|
||||
text { font-family: Consolas, "Courier New", monospace; font-size: 14px; dominant-baseline: text-before-edge; white-space: pre; }
|
||||
</style>
|
||||
<rect width="920" height="343" fill="#000000" />
|
||||
<rect width="920" height="360" fill="#000000" />
|
||||
<g transform="translate(10, 10)">
|
||||
<text x="9" y="19" fill="#4796e4" textLength="9" lengthAdjust="spacingAndGlyphs">▝</text>
|
||||
<text x="18" y="19" fill="#6688d9" textLength="9" lengthAdjust="spacingAndGlyphs">▜</text>
|
||||
@@ -30,16 +30,16 @@
|
||||
<text x="72" y="189" fill="#ffffff" textLength="189" lengthAdjust="spacingAndGlyphs"> for more information</text>
|
||||
<text x="0" y="206" fill="#ffffff" textLength="450" lengthAdjust="spacingAndGlyphs">3. Ask coding questions, edit code or run commands</text>
|
||||
<text x="0" y="223" fill="#ffffff" textLength="315" lengthAdjust="spacingAndGlyphs">4. Be specific for the best results</text>
|
||||
<text x="0" y="240" fill="#ffffaf" textLength="864" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="0" y="257" fill="#ffffaf" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="257" fill="#ffffaf" textLength="9" lengthAdjust="spacingAndGlyphs">⊶</text>
|
||||
<text x="45" y="257" fill="#ffffff" textLength="153" lengthAdjust="spacingAndGlyphs" font-weight="bold">google_web_search</text>
|
||||
<text x="855" y="257" fill="#ffffaf" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="257" fill="#ffffaf" textLength="864" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="0" y="274" fill="#ffffaf" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="274" fill="#ffffaf" textLength="9" lengthAdjust="spacingAndGlyphs">⊶</text>
|
||||
<text x="45" y="274" fill="#ffffff" textLength="153" lengthAdjust="spacingAndGlyphs" font-weight="bold">google_web_search</text>
|
||||
<text x="855" y="274" fill="#ffffaf" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="291" fill="#ffffaf" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="291" fill="#ffffff" textLength="108" lengthAdjust="spacingAndGlyphs">Searching...</text>
|
||||
<text x="855" y="291" fill="#ffffaf" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="308" fill="#ffffaf" textLength="864" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
<text x="0" y="308" fill="#ffffaf" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="308" fill="#ffffff" textLength="108" lengthAdjust="spacingAndGlyphs">Searching...</text>
|
||||
<text x="855" y="308" fill="#ffffaf" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="325" fill="#ffffaf" textLength="864" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.0 KiB |
@@ -15,12 +15,12 @@ Tips for getting started:
|
||||
2. /help for more information
|
||||
3. Ask coding questions, edit code or run commands
|
||||
4. Be specific for the best results
|
||||
|
||||
╭──────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ ⊶ google_web_search │
|
||||
│ │
|
||||
│ Searching... │
|
||||
╰──────────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
"
|
||||
╰──────────────────────────────────────────────────────────────────────────────────────────────╯"
|
||||
`;
|
||||
|
||||
exports[`MainContent tool group border SVG snapshots > should render SVG snapshot for a shell tool 1`] = `
|
||||
@@ -38,12 +38,12 @@ Tips for getting started:
|
||||
2. /help for more information
|
||||
3. Ask coding questions, edit code or run commands
|
||||
4. Be specific for the best results
|
||||
|
||||
╭──────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ ⊶ run_shell_command │
|
||||
│ │
|
||||
│ Running command... │
|
||||
╰──────────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
"
|
||||
╰──────────────────────────────────────────────────────────────────────────────────────────────╯"
|
||||
`;
|
||||
|
||||
exports[`MainContent tool group border SVG snapshots > should render SVG snapshot for an empty slice following a search tool 1`] = `
|
||||
@@ -61,10 +61,10 @@ Tips for getting started:
|
||||
2. /help for more information
|
||||
3. Ask coding questions, edit code or run commands
|
||||
4. Be specific for the best results
|
||||
|
||||
╭──────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ ⊶ google_web_search │
|
||||
│ │
|
||||
│ Searching... │
|
||||
╰──────────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
"
|
||||
╰──────────────────────────────────────────────────────────────────────────────────────────────╯"
|
||||
`;
|
||||
|
||||