From 80b04dc505bf1c784a54c5d80d971310b05144cc Mon Sep 17 00:00:00 2001
From: Taylor Mullen <ntaylormullen@google.com>
Date: Tue, 22 Apr 2025 07:48:12 -0400
Subject: Update UI of tool messages

- Bring tool messages in line with original envisioned UI of: https://screenshot.googleplex.com/9yZCX636LzpMrgc
  - In particular this represents more descriptive names. FWIW we already had this tech we just weren't passing around information correctly (`displayName` vs. `name`)
 - Add gray to our list of color pallete's and removed Background (unused)
 - Re-enabled representing canceled messages
 - Migrated back towards a cleaner tool message design of status symbols & border colors vs. overly verbose text.
 - Removed border from confirmation diffs.
Fixes https://b.corp.google.com/issues/412598909
---
 .../cli/src/ui/components/messages/ToolMessage.tsx | 103 +++++++++------------
 1 file changed, 46 insertions(+), 57 deletions(-)

(limited to 'packages/cli/src/ui/components/messages/ToolMessage.tsx')

diff --git a/packages/cli/src/ui/components/messages/ToolMessage.tsx b/packages/cli/src/ui/components/messages/ToolMessage.tsx
index 53f31db2..ab590f53 100644
--- a/packages/cli/src/ui/components/messages/ToolMessage.tsx
+++ b/packages/cli/src/ui/components/messages/ToolMessage.tsx
@@ -9,74 +9,63 @@ import { Box, Text } from 'ink';
 import Spinner from 'ink-spinner';
 import { IndividualToolCallDisplay, ToolCallStatus } from '../../types.js';
 import { DiffRenderer } from './DiffRenderer.js';
-import { FileDiff, ToolResultDisplay } from '@gemini-code/server';
 import { Colors } from '../../colors.js';
+import { MarkdownRenderer } from '../../utils/MarkdownRenderer.js';
 
 export const ToolMessage: React.FC<IndividualToolCallDisplay> = ({
-  callId,
   name,
   description,
   resultDisplay,
   status,
 }) => {
-  const typedResultDisplay = resultDisplay as ToolResultDisplay | undefined;
-
-  let color = Colors.SubtleComment;
-  let prefix = '';
-  switch (status) {
-    case ToolCallStatus.Pending:
-      prefix = 'Pending:';
-      break;
-    case ToolCallStatus.Invoked:
-      prefix = 'Executing:';
-      break;
-    case ToolCallStatus.Confirming:
-      color = Colors.AccentYellow;
-      prefix = 'Confirm:';
-      break;
-    case ToolCallStatus.Success:
-      color = Colors.AccentGreen;
-      prefix = 'Success:';
-      break;
-    case ToolCallStatus.Error:
-      color = Colors.AccentRed;
-      prefix = 'Error:';
-      break;
-    default:
-      // Handle unexpected status if necessary, or just break
-      break;
-  }
-
-  const title = `${prefix} ${name}`;
-
+  const statusIndicatorWidth = 3;
+  const hasResult = resultDisplay && resultDisplay.toString().trim().length > 0;
   return (
-    <Box key={callId} flexDirection="column" paddingX={1}>
-      <Box>
-        {status === ToolCallStatus.Invoked && (
-          <Box marginRight={1}>
-            <Text color={Colors.AccentBlue}>
-              <Spinner type="dots" />
+    <Box paddingX={1} paddingY={0} flexDirection="column">
+      <Box minHeight={1}>
+        {/* Status Indicator */}
+        <Box minWidth={statusIndicatorWidth}>
+          {status === ToolCallStatus.Pending && <Spinner type="dots" />}
+          {status === ToolCallStatus.Success && (
+            <Text color={Colors.AccentGreen}>✔</Text>
+          )}
+          {status === ToolCallStatus.Confirming && (
+            <Text color={Colors.AccentPurple}>?</Text>
+          )}
+          {status === ToolCallStatus.Canceled && (
+            <Text color={Colors.AccentYellow} bold>
+              -
             </Text>
-          </Box>
-        )}
-        <Text bold color={color}>
-          {title}
-        </Text>
-        <Text color={color}>
-          {status === ToolCallStatus.Error && typedResultDisplay
-            ? `: ${typedResultDisplay}`
-            : ` - ${description}`}
-        </Text>
-      </Box>
-      {status === ToolCallStatus.Success && typedResultDisplay && (
-        <Box flexDirection="column" marginLeft={2}>
-          {typeof typedResultDisplay === 'string' ? (
-            <Text>{typedResultDisplay}</Text>
-          ) : (
-            <DiffRenderer
-              diffContent={(typedResultDisplay as FileDiff).fileDiff}
-            />
           )}
+          {status === ToolCallStatus.Error && (
+            <Text color={Colors.AccentRed} bold>
+              x
+            </Text>
+          )}
+        </Box>
+        <Box>
+          <Text
+            wrap="truncate-end"
+            strikethrough={status === ToolCallStatus.Canceled}
+          >
+            <Text bold>{name}</Text>{' '}
+            <Text color={Colors.SubtleComment}>{description}</Text>
+          </Text>
+        </Box>
+      </Box>
+      {hasResult && (
+        <Box paddingLeft={statusIndicatorWidth}>
+          <Box flexShrink={1} flexDirection="row">
+            {/* Use default text color (white) or gray instead of dimColor */}
+            {typeof resultDisplay === 'string' && (
+              <Box flexDirection="column">
+                {MarkdownRenderer.render(resultDisplay)}
+              </Box>
+            )}
+            {typeof resultDisplay === 'object' && (
+              <DiffRenderer diffContent={resultDisplay.fileDiff} />
+            )}
+          </Box>
         </Box>
       )}
     </Box>
-- 
cgit v1.2.3

