diff --git a/CHANGELOG.md b/CHANGELOG.md
index 69337d08a..44b80bd04 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,10 @@
## What's new in 4.0.31
+### Improvements
+
+- **RovoDev**: Collapsed completed tool call results in the thinking drawer for a more compact chat view. Users can still expand the drawer to see details.
+
### Bug Fixes
- **RovoDev**: Hid stack traces, stderr, and log details from external users while preserving them for Atlassian users.
diff --git a/src/rovo-dev/ui/RovoDev.css b/src/rovo-dev/ui/RovoDev.css
index 29a3a078b..81d829553 100644
--- a/src/rovo-dev/ui/RovoDev.css
+++ b/src/rovo-dev/ui/RovoDev.css
@@ -302,6 +302,21 @@ body {
word-break: break-all;
}
+.tool-return-collapsed {
+ border: none;
+ padding: 2px 6px;
+ margin-bottom: 2px;
+ gap: 6px;
+}
+
+.tool-return-collapsed-text {
+ font-size: 12px;
+ color: var(--vscode-input-placeholderForeground);
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
.tool-return-bash-command {
pre {
margin: 0;
diff --git a/src/rovo-dev/ui/common/common.tsx b/src/rovo-dev/ui/common/common.tsx
index 8afd17014..46c710137 100644
--- a/src/rovo-dev/ui/common/common.tsx
+++ b/src/rovo-dev/ui/common/common.tsx
@@ -215,6 +215,7 @@ export const renderChatHistory = (
retryAfterError: () => void,
onError: (error: Error, errorMessage: string) => void,
isAtlassianUser?: boolean,
+ collapsedToolReturns?: boolean,
) => {
switch (msg.event_kind) {
case 'tool-return':
@@ -223,7 +224,15 @@ export const renderChatHistory = (
if (message.todoData) {
return ;
}
- return ;
+ return (
+
+ );
});
case '_RovoDevDialog':
let customButton: { text: string; onClick: () => void } | undefined = undefined;
diff --git a/src/rovo-dev/ui/messaging/MessageDrawer.tsx b/src/rovo-dev/ui/messaging/MessageDrawer.tsx
index 41a44461c..7e65ff286 100644
--- a/src/rovo-dev/ui/messaging/MessageDrawer.tsx
+++ b/src/rovo-dev/ui/messaging/MessageDrawer.tsx
@@ -80,6 +80,7 @@ export const MessageDrawer: React.FC = ({
retryPromptAfterError,
onError,
isAtlassianUser,
+ true, // collapse tool returns for compact display
),
)}
diff --git a/src/rovo-dev/ui/tools/ToolReturnItem.test.tsx b/src/rovo-dev/ui/tools/ToolReturnItem.test.tsx
index c0fef7d1a..b7fbdf546 100644
--- a/src/rovo-dev/ui/tools/ToolReturnItem.test.tsx
+++ b/src/rovo-dev/ui/tools/ToolReturnItem.test.tsx
@@ -124,4 +124,65 @@ describe('ToolReturnParsedItem', () => {
render();
}).not.toThrow();
});
+
+ test('renders collapsed view with content and title', () => {
+ const msg: ToolReturnParseResult = {
+ content: 'Replaced code',
+ title: 'myFile.ts',
+ type: 'modify',
+ filePath: '/path/to/myFile.ts',
+ };
+
+ const { getByText, container } = render(
+ ,
+ );
+
+ expect(container.querySelector('.tool-return-collapsed')).toBeTruthy();
+ expect(getByText('Replaced code — myFile.ts')).toBeTruthy();
+ });
+
+ test('renders collapsed view with content only (no title)', () => {
+ const msg: ToolReturnParseResult = {
+ content: 'Searched files',
+ type: 'open',
+ };
+
+ const { getByText, container } = render(
+ ,
+ );
+
+ expect(container.querySelector('.tool-return-collapsed')).toBeTruthy();
+ expect(getByText('Searched files')).toBeTruthy();
+ });
+
+ test('collapsed view calls openFile when clicked with filePath', () => {
+ const filePath = '/path/to/file.ts';
+ const msg: ToolReturnParseResult = {
+ content: 'Opened file',
+ type: 'open',
+ filePath,
+ };
+
+ const { getByText } = render(
+ ,
+ );
+
+ fireEvent.click(getByText('Opened file'));
+ expect(mockOpenFile).toHaveBeenCalledWith(filePath);
+ });
+
+ test('renders expanded view by default (collapsed=false)', () => {
+ const msg: ToolReturnParseResult = {
+ content: 'Replaced code',
+ title: 'myFile.ts',
+ type: 'modify',
+ filePath: '/path/to/myFile.ts',
+ };
+
+ const { container } = render(
+ ,
+ );
+
+ expect(container.querySelector('.tool-return-collapsed')).toBeNull();
+ });
});
diff --git a/src/rovo-dev/ui/tools/ToolReturnItem.tsx b/src/rovo-dev/ui/tools/ToolReturnItem.tsx
index 8d509f389..2cf6e1305 100644
--- a/src/rovo-dev/ui/tools/ToolReturnItem.tsx
+++ b/src/rovo-dev/ui/tools/ToolReturnItem.tsx
@@ -13,7 +13,8 @@ export const ToolReturnParsedItem: React.FC<{
msg: ToolReturnParseResult;
openFile: OpenFileFunc;
onLinkClick: (href: string) => void;
-}> = ({ msg, openFile, onLinkClick }) => {
+ collapsed?: boolean;
+}> = ({ msg, openFile, onLinkClick, collapsed = false }) => {
const toolIcon = React.useMemo(() => (msg.type ? iconMap[msg.type] : undefined), [msg.type]);
const filePathClass = msg.filePath && msg.type !== 'delete' ? 'tool-return-file-path' : '';
@@ -28,6 +29,21 @@ export const ToolReturnParsedItem: React.FC<{
[msg.filePath, msg.type, openFile],
);
+ if (collapsed) {
+ return (
+
+ {toolIcon}
+
+ {msg.content ?? ''}
+ {msg.title ? ` — ${msg.title}` : ''}
+
+
+ );
+ }
+
return (
{toolIcon}