wave-code 0.0.5 → 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/README.md +3 -3
  2. package/dist/cli.d.ts +1 -0
  3. package/dist/cli.d.ts.map +1 -1
  4. package/dist/cli.js +2 -2
  5. package/dist/components/App.d.ts +1 -0
  6. package/dist/components/App.d.ts.map +1 -1
  7. package/dist/components/App.js +4 -4
  8. package/dist/components/BashHistorySelector.d.ts.map +1 -1
  9. package/dist/components/BashHistorySelector.js +17 -3
  10. package/dist/components/ChatInterface.d.ts.map +1 -1
  11. package/dist/components/ChatInterface.js +6 -24
  12. package/dist/components/CommandSelector.js +4 -4
  13. package/dist/components/Confirmation.d.ts +11 -0
  14. package/dist/components/Confirmation.d.ts.map +1 -0
  15. package/dist/components/Confirmation.js +148 -0
  16. package/dist/components/DiffDisplay.d.ts +8 -0
  17. package/dist/components/DiffDisplay.d.ts.map +1 -0
  18. package/dist/components/DiffDisplay.js +168 -0
  19. package/dist/components/FileSelector.d.ts +2 -4
  20. package/dist/components/FileSelector.d.ts.map +1 -1
  21. package/dist/components/FileSelector.js +2 -2
  22. package/dist/components/InputBox.d.ts.map +1 -1
  23. package/dist/components/InputBox.js +30 -50
  24. package/dist/components/Markdown.d.ts +6 -0
  25. package/dist/components/Markdown.d.ts.map +1 -0
  26. package/dist/components/Markdown.js +22 -0
  27. package/dist/components/MemoryDisplay.js +1 -1
  28. package/dist/components/MessageItem.d.ts +8 -0
  29. package/dist/components/MessageItem.d.ts.map +1 -0
  30. package/dist/components/MessageItem.js +15 -0
  31. package/dist/components/MessageList.d.ts +1 -1
  32. package/dist/components/MessageList.d.ts.map +1 -1
  33. package/dist/components/MessageList.js +33 -33
  34. package/dist/components/ReasoningDisplay.d.ts +8 -0
  35. package/dist/components/ReasoningDisplay.d.ts.map +1 -0
  36. package/dist/components/ReasoningDisplay.js +10 -0
  37. package/dist/components/SubagentBlock.d.ts +0 -1
  38. package/dist/components/SubagentBlock.d.ts.map +1 -1
  39. package/dist/components/SubagentBlock.js +29 -30
  40. package/dist/components/ToolResultDisplay.d.ts.map +1 -1
  41. package/dist/components/ToolResultDisplay.js +6 -5
  42. package/dist/contexts/useChat.d.ts +14 -2
  43. package/dist/contexts/useChat.d.ts.map +1 -1
  44. package/dist/contexts/useChat.js +128 -17
  45. package/dist/hooks/useInputManager.d.ts +6 -1
  46. package/dist/hooks/useInputManager.d.ts.map +1 -1
  47. package/dist/hooks/useInputManager.js +32 -2
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +30 -5
  50. package/dist/managers/InputManager.d.ts +11 -1
  51. package/dist/managers/InputManager.d.ts.map +1 -1
  52. package/dist/managers/InputManager.js +77 -26
  53. package/dist/print-cli.d.ts +2 -0
  54. package/dist/print-cli.d.ts.map +1 -1
  55. package/dist/print-cli.js +121 -23
  56. package/dist/utils/toolParameterTransforms.d.ts +23 -0
  57. package/dist/utils/toolParameterTransforms.d.ts.map +1 -0
  58. package/dist/utils/toolParameterTransforms.js +77 -0
  59. package/dist/utils/usageSummary.d.ts +6 -0
  60. package/dist/utils/usageSummary.d.ts.map +1 -1
  61. package/dist/utils/usageSummary.js +72 -0
  62. package/package.json +13 -8
  63. package/src/cli.tsx +3 -1
  64. package/src/components/App.tsx +7 -3
  65. package/src/components/BashHistorySelector.tsx +26 -3
  66. package/src/components/ChatInterface.tsx +38 -54
  67. package/src/components/CommandSelector.tsx +5 -5
  68. package/src/components/Confirmation.tsx +253 -0
  69. package/src/components/DiffDisplay.tsx +300 -0
  70. package/src/components/FileSelector.tsx +4 -6
  71. package/src/components/InputBox.tsx +58 -87
  72. package/src/components/Markdown.tsx +29 -0
  73. package/src/components/MemoryDisplay.tsx +1 -1
  74. package/src/components/MessageItem.tsx +96 -0
  75. package/src/components/MessageList.tsx +140 -202
  76. package/src/components/ReasoningDisplay.tsx +33 -0
  77. package/src/components/SubagentBlock.tsx +56 -84
  78. package/src/components/ToolResultDisplay.tsx +9 -5
  79. package/src/contexts/useChat.tsx +194 -21
  80. package/src/hooks/useInputManager.ts +40 -3
  81. package/src/index.ts +45 -5
  82. package/src/managers/InputManager.ts +101 -27
  83. package/src/print-cli.ts +143 -21
  84. package/src/utils/toolParameterTransforms.ts +104 -0
  85. package/src/utils/usageSummary.ts +109 -0
  86. package/dist/components/DiffViewer.d.ts +0 -9
  87. package/dist/components/DiffViewer.d.ts.map +0 -1
  88. package/dist/components/DiffViewer.js +0 -221
  89. package/dist/utils/fileSearch.d.ts +0 -20
  90. package/dist/utils/fileSearch.d.ts.map +0 -1
  91. package/dist/utils/fileSearch.js +0 -102
  92. package/src/components/DiffViewer.tsx +0 -321
  93. package/src/utils/fileSearch.ts +0 -133
@@ -0,0 +1,96 @@
1
+ import React from "react";
2
+ import { Box, Text } from "ink";
3
+ import type { Message } from "wave-agent-sdk";
4
+ import { MessageSource } from "wave-agent-sdk";
5
+ import { CommandOutputDisplay } from "./CommandOutputDisplay.js";
6
+ import { ToolResultDisplay } from "./ToolResultDisplay.js";
7
+ import { MemoryDisplay } from "./MemoryDisplay.js";
8
+ import { CompressDisplay } from "./CompressDisplay.js";
9
+ import { SubagentBlock } from "./SubagentBlock.js";
10
+ import { ReasoningDisplay } from "./ReasoningDisplay.js";
11
+ import { Markdown } from "./Markdown.js";
12
+
13
+ export interface MessageItemProps {
14
+ message: Message;
15
+ isExpanded: boolean;
16
+ shouldShowHeader: boolean;
17
+ }
18
+
19
+ export const MessageItem = ({
20
+ message,
21
+ isExpanded,
22
+ shouldShowHeader,
23
+ }: MessageItemProps) => {
24
+ if (message.blocks.length === 0) return null;
25
+ return (
26
+ <Box flexDirection="column" gap={1} marginTop={1}>
27
+ {shouldShowHeader && (
28
+ <Box>
29
+ <Text color={message.role === "user" ? "cyan" : "green"} bold>
30
+ {message.role === "user" ? "👤 You" : "🤖 Assistant"}
31
+ </Text>
32
+ </Box>
33
+ )}
34
+
35
+ <Box flexDirection="column" gap={1}>
36
+ {message.blocks.map((block, blockIndex) => (
37
+ <Box key={blockIndex}>
38
+ {block.type === "text" && block.content.trim() && (
39
+ <Box>
40
+ {block.customCommandContent && (
41
+ <Text color="cyan" bold>
42
+ ⚡{" "}
43
+ </Text>
44
+ )}
45
+ {block.source === MessageSource.HOOK && (
46
+ <Text color="magenta" bold>
47
+ 🔗{" "}
48
+ </Text>
49
+ )}
50
+ <Markdown>{block.content}</Markdown>
51
+ </Box>
52
+ )}
53
+
54
+ {block.type === "error" && (
55
+ <Box>
56
+ <Text color="red">❌ Error: {block.content}</Text>
57
+ </Box>
58
+ )}
59
+
60
+ {block.type === "command_output" && (
61
+ <CommandOutputDisplay block={block} isExpanded={isExpanded} />
62
+ )}
63
+
64
+ {block.type === "tool" && (
65
+ <ToolResultDisplay block={block} isExpanded={isExpanded} />
66
+ )}
67
+
68
+ {block.type === "image" && (
69
+ <Box>
70
+ <Text color="magenta" bold>
71
+ 📷 Image
72
+ </Text>
73
+ {block.imageUrls && block.imageUrls.length > 0 && (
74
+ <Text color="gray" dimColor>
75
+ {" "}
76
+ ({block.imageUrls.length})
77
+ </Text>
78
+ )}
79
+ </Box>
80
+ )}
81
+
82
+ {block.type === "memory" && <MemoryDisplay block={block} />}
83
+
84
+ {block.type === "compress" && (
85
+ <CompressDisplay block={block} isExpanded={isExpanded} />
86
+ )}
87
+
88
+ {block.type === "subagent" && <SubagentBlock block={block} />}
89
+
90
+ {block.type === "reasoning" && <ReasoningDisplay block={block} />}
91
+ </Box>
92
+ ))}
93
+ </Box>
94
+ </Box>
95
+ );
96
+ };
@@ -1,111 +1,7 @@
1
- import React, { useMemo } from "react";
2
- import { Box, Text } from "ink";
1
+ import React from "react";
2
+ import { Box, Text, Static } from "ink";
3
3
  import type { Message } from "wave-agent-sdk";
4
- import { MessageSource } from "wave-agent-sdk";
5
- import { DiffViewer } from "./DiffViewer.js";
6
- import { CommandOutputDisplay } from "./CommandOutputDisplay.js";
7
- import { ToolResultDisplay } from "./ToolResultDisplay.js";
8
- import { MemoryDisplay } from "./MemoryDisplay.js";
9
- import { CompressDisplay } from "./CompressDisplay.js";
10
- import { SubagentBlock } from "./SubagentBlock.js";
11
- import { usePagination } from "../hooks/usePagination.js";
12
-
13
- // Function to render a single message
14
- const renderMessageItem = (
15
- message: Message,
16
- originalIndex: number,
17
- isExpanded: boolean,
18
- previousMessage?: Message,
19
- ) => {
20
- const shouldShowHeader = previousMessage?.role !== message.role;
21
-
22
- return (
23
- <Box key={`message-${originalIndex}`} flexDirection="column">
24
- {shouldShowHeader && (
25
- <Box>
26
- <Text color={message.role === "user" ? "cyan" : "green"} bold>
27
- {message.role === "user" ? "👤 You" : "🤖 Assistant"}
28
- <Text color="gray" dimColor>
29
- {" "}
30
- #{originalIndex + 1}
31
- </Text>
32
- </Text>
33
- </Box>
34
- )}
35
-
36
- <Box
37
- marginLeft={2}
38
- flexDirection="column"
39
- gap={1}
40
- marginTop={shouldShowHeader ? 1 : 0}
41
- >
42
- {message.blocks.map((block, blockIndex) => (
43
- <Box key={blockIndex}>
44
- {block.type === "text" && block.content.trim() && (
45
- <Box>
46
- <Text>
47
- {block.customCommandContent && (
48
- <Text color="cyan" bold>
49
- ⚡{" "}
50
- </Text>
51
- )}
52
- {block.source === MessageSource.HOOK && (
53
- <Text color="magenta" bold>
54
- 🔗{" "}
55
- </Text>
56
- )}
57
- {block.content}
58
- </Text>
59
- </Box>
60
- )}
61
-
62
- {block.type === "error" && (
63
- <Box>
64
- <Text color="red">❌ Error: {block.content}</Text>
65
- </Box>
66
- )}
67
-
68
- {block.type === "diff" && (
69
- <DiffViewer block={block} isExpanded={isExpanded} />
70
- )}
71
-
72
- {block.type === "command_output" && (
73
- <CommandOutputDisplay block={block} isExpanded={isExpanded} />
74
- )}
75
-
76
- {block.type === "tool" && (
77
- <ToolResultDisplay block={block} isExpanded={isExpanded} />
78
- )}
79
-
80
- {block.type === "image" && (
81
- <Box>
82
- <Text color="magenta" bold>
83
- 📷 Image
84
- </Text>
85
- {block.imageUrls && block.imageUrls.length > 0 && (
86
- <Text color="gray" dimColor>
87
- {" "}
88
- ({block.imageUrls.length})
89
- </Text>
90
- )}
91
- </Box>
92
- )}
93
-
94
- {block.type === "memory" && <MemoryDisplay block={block} />}
95
-
96
- {block.type === "compress" && (
97
- <CompressDisplay block={block} isExpanded={isExpanded} />
98
- )}
99
-
100
- {block.type === "subagent" && (
101
- <SubagentBlock block={block} isExpanded={isExpanded} />
102
- )}
103
- </Box>
104
- ))}
105
- </Box>
106
- </Box>
107
- );
108
- };
4
+ import { MessageItem } from "./MessageItem.js";
109
5
 
110
6
  export interface MessageListProps {
111
7
  messages: Message[];
@@ -116,109 +12,151 @@ export interface MessageListProps {
116
12
  isExpanded?: boolean;
117
13
  }
118
14
 
119
- export const MessageList: React.FC<MessageListProps> = ({
120
- messages,
121
- isLoading = false,
122
- isCommandRunning = false,
123
- isCompressing = false,
124
- latestTotalTokens = 0,
125
- isExpanded = false,
126
- }) => {
127
- // Use original messages for pagination calculation
128
- const { displayInfo } = usePagination(messages);
129
-
130
- // Get current page messages while preserving original index information
131
- const currentMessagesWithIndex = useMemo(() => {
132
- return messages
133
- .slice(displayInfo.startIndex, displayInfo.endIndex)
134
- .map((message, index) => ({
135
- message,
136
- originalIndex: displayInfo.startIndex + index,
137
- }));
138
- }, [messages, displayInfo.startIndex, displayInfo.endIndex]);
15
+ export const MessageList = React.memo(
16
+ ({
17
+ messages,
18
+ isLoading = false,
19
+ isCommandRunning = false,
20
+ isCompressing = false,
21
+ latestTotalTokens = 0,
22
+ isExpanded = false,
23
+ }: MessageListProps) => {
24
+ // Empty message state
25
+ if (messages.length === 0) {
26
+ return (
27
+ <Box flexDirection="column" paddingY={1}>
28
+ <Text color="gray">Welcome to WAVE Code Assistant!</Text>
29
+ </Box>
30
+ );
31
+ }
32
+
33
+ // Limit messages when expanded to prevent long rendering times
34
+ const maxExpandedMessages = 20;
35
+ const shouldLimitMessages =
36
+ isExpanded && messages.length > maxExpandedMessages;
37
+ const displayMessages = shouldLimitMessages
38
+ ? messages.slice(-maxExpandedMessages)
39
+ : messages;
40
+ const omittedCount = shouldLimitMessages
41
+ ? messages.length - maxExpandedMessages
42
+ : 0;
43
+
44
+ // Compute which messages to render statically vs dynamically
45
+ const shouldRenderLastDynamic = isLoading || isCommandRunning;
46
+ const staticMessages = shouldRenderLastDynamic
47
+ ? displayMessages.slice(0, -1)
48
+ : displayMessages;
49
+ const dynamicMessages =
50
+ shouldRenderLastDynamic && displayMessages.length > 0
51
+ ? [displayMessages[displayMessages.length - 1]]
52
+ : [];
139
53
 
140
- // Empty message state
141
- if (messages.length === 0) {
142
54
  return (
143
- <Box flexDirection="column" paddingY={1}>
144
- <Text color="gray">Welcome to WAVE Code Assistant!</Text>
145
- </Box>
146
- );
147
- }
148
-
149
- return (
150
- <Box flexDirection="column" gap={1} marginTop={1}>
151
- {/* Message list */}
152
- <Box flexDirection="column" gap={1}>
153
- {currentMessagesWithIndex.map(({ message, originalIndex }) => {
154
- // Get previous message
55
+ <Box flexDirection="column" paddingX={1} gap={1}>
56
+ {/* Show omitted message count when limiting */}
57
+ {omittedCount > 0 && (
58
+ <Box>
59
+ <Text color="gray" dimColor>
60
+ ... {omittedCount} earlier message{omittedCount !== 1 ? "s" : ""}{" "}
61
+ omitted (showing latest {maxExpandedMessages})
62
+ </Text>
63
+ </Box>
64
+ )}
65
+
66
+ {/* Static messages */}
67
+ <Static items={staticMessages}>
68
+ {(message, key) => {
69
+ // Get previous message
70
+ const previousMessage =
71
+ key > 0 ? staticMessages[key - 1] : undefined;
72
+ return (
73
+ <MessageItem
74
+ key={key}
75
+ message={message}
76
+ shouldShowHeader={previousMessage?.role !== message.role}
77
+ isExpanded={isExpanded}
78
+ />
79
+ );
80
+ }}
81
+ </Static>
82
+
83
+ {/* Dynamic messages */}
84
+ {dynamicMessages.map((message, index) => {
85
+ const messageIndex = staticMessages.length + index;
155
86
  const previousMessage =
156
- originalIndex > 0 ? messages[originalIndex - 1] : undefined;
157
- return renderMessageItem(
158
- message,
159
- originalIndex,
160
- isExpanded,
161
- previousMessage,
87
+ messageIndex > 0 ? displayMessages[messageIndex - 1] : undefined;
88
+ return (
89
+ <Box key={`dynamic-${index}`} marginTop={-1}>
90
+ <MessageItem
91
+ message={message}
92
+ shouldShowHeader={previousMessage?.role !== message.role}
93
+ isExpanded={isExpanded}
94
+ />
95
+ </Box>
162
96
  );
163
97
  })}
164
- </Box>
165
98
 
166
- {/* Loading state display - only show in non-expanded state */}
167
- {!isExpanded && (isLoading || isCommandRunning || isCompressing) && (
168
- <Box flexDirection="column" gap={1}>
169
- {isLoading && (
170
- <Box>
171
- <Text color="yellow">💭 AI is thinking... </Text>
172
- <Text color="gray" dimColor>
173
- {" "}
174
- |{" "}
175
- </Text>
176
- <Text color="blue" bold>
177
- {latestTotalTokens.toLocaleString()}
178
- </Text>
179
- <Text color="gray" dimColor>
180
- {" "}
181
- tokens |{" "}
182
- </Text>
183
- <Text color="red" bold>
184
- Esc
185
- </Text>
186
- <Text color="gray" dimColor>
187
- {" "}
188
- to abort
189
- </Text>
190
- </Box>
191
- )}
192
- {isCommandRunning && (
193
- <Text color="blue">🚀 Command is running...</Text>
194
- )}
195
- {isCompressing && (
196
- <Text color="magenta">🗜️ Compressing message history...</Text>
197
- )}
198
- </Box>
199
- )}
99
+ {(isLoading || isCommandRunning || isCompressing) && (
100
+ <Box flexDirection="column" gap={1}>
101
+ {isLoading && (
102
+ <Box>
103
+ <Text color="yellow">💭 AI is thinking... </Text>
104
+ <Text color="gray" dimColor>
105
+ |{" "}
106
+ </Text>
107
+ <Text color="red" bold>
108
+ Esc
109
+ </Text>
110
+ <Text color="gray" dimColor>
111
+ {" "}
112
+ to abort
113
+ </Text>
114
+ </Box>
115
+ )}
116
+ {isCommandRunning && (
117
+ <Text color="blue">🚀 Command is running...</Text>
118
+ )}
119
+ {isCompressing && (
120
+ <Text color="magenta">🗜️ Compressing message history...</Text>
121
+ )}
122
+ </Box>
123
+ )}
200
124
 
201
- {/* Bottom info and shortcut key hints */}
202
- {messages.length > 0 && (
203
- <Box>
204
- <Box justifyContent="space-between" width="100%">
205
- <Box>
206
- <Text color="gray">
207
- Messages {messages.length} Page {displayInfo.currentPage}/
208
- {displayInfo.totalPages}
209
- </Text>
125
+ {/* Bottom info and shortcut key hints */}
126
+ {messages.length > 0 && (
127
+ <Box>
128
+ <Box justifyContent="space-between" width="100%">
129
+ <Box>
130
+ <Text color="gray">
131
+ Messages {messages.length}
132
+ {latestTotalTokens > 0 && (
133
+ <>
134
+ <Text color="gray" dimColor>
135
+ {" "}
136
+ |{" "}
137
+ </Text>
138
+ <Text color="blue" bold>
139
+ {latestTotalTokens.toLocaleString()}
140
+ </Text>
141
+ <Text color="gray" dimColor>
142
+ {" "}
143
+ tokens
144
+ </Text>
145
+ </>
146
+ )}
147
+ </Text>
148
+ </Box>
210
149
  <Text color="gray" dimColor>
211
- {" "}
212
- <Text color="cyan">Ctrl+U/D</Text> Navigate
150
+ <Text color="cyan">Ctrl+O</Text> Toggle{" "}
151
+ {isExpanded ? "Collapse" : "Expand"}
213
152
  </Text>
214
153
  </Box>
215
- <Text color="gray" dimColor>
216
- <Text color="cyan">Ctrl+O</Text> Toggle{" "}
217
- {isExpanded ? "Collapse" : "Expand"}
218
- </Text>
219
154
  </Box>
220
- </Box>
221
- )}
222
- </Box>
223
- );
224
- };
155
+ )}
156
+ </Box>
157
+ );
158
+ },
159
+ );
160
+
161
+ // Add display name for debugging
162
+ MessageList.displayName = "MessageList";
@@ -0,0 +1,33 @@
1
+ import React from "react";
2
+ import { Box } from "ink";
3
+ import type { ReasoningBlock } from "wave-agent-sdk";
4
+ import { Markdown } from "./Markdown.js";
5
+
6
+ interface ReasoningDisplayProps {
7
+ block: ReasoningBlock;
8
+ }
9
+
10
+ export const ReasoningDisplay: React.FC<ReasoningDisplayProps> = ({
11
+ block,
12
+ }) => {
13
+ const { content } = block;
14
+
15
+ if (!content || !content.trim()) {
16
+ return null;
17
+ }
18
+
19
+ return (
20
+ <Box
21
+ borderRight={false}
22
+ borderTop={false}
23
+ borderBottom={false}
24
+ borderStyle="classic"
25
+ borderColor="blue"
26
+ paddingLeft={1}
27
+ >
28
+ <Box flexDirection="column">
29
+ <Markdown>{content}</Markdown>
30
+ </Box>
31
+ </Box>
32
+ );
33
+ };
@@ -1,57 +1,18 @@
1
1
  import React from "react";
2
2
  import { Box, Text } from "ink";
3
- import type {
4
- SubagentBlock as SubagentBlockType,
5
- Message,
6
- MessageBlock,
7
- } from "wave-agent-sdk";
8
- import { ToolResultDisplay } from "./ToolResultDisplay.js";
9
-
10
- // Component to render individual message blocks
11
- interface MessageBlockRendererProps {
12
- block: MessageBlock;
13
- isExpanded: boolean;
14
- }
15
-
16
- const MessageBlockRenderer: React.FC<MessageBlockRendererProps> = ({
17
- block,
18
- isExpanded,
19
- }) => {
20
- const truncateText = (text: string, maxLines: number): string => {
21
- const lines = text.split("\n");
22
- if (lines.length <= maxLines) {
23
- return text;
24
- }
25
- return lines.slice(0, maxLines).join("\n") + "\n...";
26
- };
27
-
28
- switch (block.type) {
29
- case "text": {
30
- const maxLines = isExpanded ? 50 : 10;
31
- const truncatedContent = truncateText(block.content, maxLines);
32
- return <Text>{truncatedContent}</Text>;
33
- }
34
-
35
- case "error":
36
- return <Text color="red">❌ Error: {block.content}</Text>;
37
-
38
- case "tool":
39
- return <ToolResultDisplay block={block} isExpanded={isExpanded} />;
40
-
41
- default:
42
- return null;
43
- }
44
- };
3
+ import type { SubagentBlock as SubagentBlockType } from "wave-agent-sdk";
4
+ import { useChat } from "../contexts/useChat.js";
45
5
 
46
6
  interface SubagentBlockProps {
47
7
  block: SubagentBlockType;
48
- isExpanded?: boolean;
49
8
  }
50
9
 
51
- export const SubagentBlock: React.FC<SubagentBlockProps> = ({
52
- block,
53
- isExpanded = false,
54
- }) => {
10
+ export const SubagentBlock: React.FC<SubagentBlockProps> = ({ block }) => {
11
+ const { subagentMessages } = useChat();
12
+
13
+ // Get messages for this subagent from context
14
+ const messages = subagentMessages[block.subagentId] || [];
15
+
55
16
  // Status indicator mapping
56
17
  const getStatusIndicator = (status: SubagentBlockType["status"]) => {
57
18
  switch (status) {
@@ -70,14 +31,40 @@ export const SubagentBlock: React.FC<SubagentBlockProps> = ({
70
31
 
71
32
  const statusInfo = getStatusIndicator(block.status);
72
33
 
73
- // Determine how many messages to show
74
- const messagesToShow = isExpanded
75
- ? block.messages.slice(-10) // Up to 10 most recent when expanded
76
- : block.messages.slice(-2); // Up to 2 most recent when collapsed
34
+ // Find the last 2 tool names and their compact params, and count total tools
35
+ const getLastTwoTools = (): {
36
+ tools: Array<{ name: string; compactParams?: string }>;
37
+ totalToolCount: number;
38
+ } => {
39
+ const tools: Array<{ name: string; compactParams?: string }> = [];
40
+ let totalToolCount = 0;
41
+
42
+ for (let i = messages.length - 1; i >= 0; i--) {
43
+ const message = messages[i];
44
+ for (let j = message.blocks.length - 1; j >= 0; j--) {
45
+ const messageBlock = message.blocks[j];
46
+ if (messageBlock.type === "tool" && messageBlock.name) {
47
+ totalToolCount++;
48
+ if (tools.length < 2) {
49
+ tools.push({
50
+ name: messageBlock.name,
51
+ compactParams: messageBlock.compactParams,
52
+ });
53
+ }
54
+ }
55
+ }
56
+ }
57
+ return { tools: tools.reverse(), totalToolCount }; // Reverse to show oldest first, newest last
58
+ };
59
+
60
+ const { tools: lastTwoTools, totalToolCount } = getLastTwoTools();
77
61
 
78
62
  return (
79
63
  <Box
80
- borderStyle="round"
64
+ borderRight={false}
65
+ borderTop={false}
66
+ borderBottom={false}
67
+ borderStyle="classic"
81
68
  borderColor="magenta"
82
69
  paddingX={1}
83
70
  paddingY={0}
@@ -85,54 +72,39 @@ export const SubagentBlock: React.FC<SubagentBlockProps> = ({
85
72
  marginBottom={1}
86
73
  >
87
74
  {/* Header Section */}
88
- <Box
89
- flexDirection="row"
90
- justifyContent="space-between"
91
- alignItems="center"
92
- >
75
+ <Box flexDirection="row" gap={1}>
93
76
  <Box flexDirection="row" alignItems="center">
94
77
  <Text color="cyan">🤖 {block.subagentName}</Text>
95
78
  <Text color={statusInfo.color} dimColor={false}>
96
79
  {" "}
97
80
  {statusInfo.icon}
98
81
  </Text>
99
- </Box>
100
-
101
- {!isExpanded && (
102
82
  <Text color="gray" dimColor>
103
- {block.messages.length} messages
83
+ {" "}
84
+ ({messages.length} messages)
104
85
  </Text>
105
- )}
86
+ </Box>
106
87
  </Box>
107
88
 
108
- {/* Messages Section */}
109
- {messagesToShow.length > 0 && (
89
+ {/* Tool Names Section - Vertical List */}
90
+ {lastTwoTools.length > 0 && (
110
91
  <Box flexDirection="column" marginTop={1} gap={1}>
111
- {messagesToShow.map((message: Message, index: number) => (
112
- <Box key={index} flexDirection="column" marginBottom={0} gap={1}>
113
- {message.blocks.map(
114
- (messageBlock: MessageBlock, blockIndex: number) => (
115
- <Box key={blockIndex} flexDirection="column">
116
- <MessageBlockRenderer
117
- block={messageBlock}
118
- isExpanded={isExpanded}
119
- />
120
- </Box>
121
- ),
92
+ {totalToolCount > 2 && (
93
+ <Text color="gray" dimColor>
94
+ ...
95
+ </Text>
96
+ )}
97
+ {lastTwoTools.map((tool, index) => (
98
+ <Box key={index} flexDirection="row">
99
+ <Text color="magenta">🔧 </Text>
100
+ <Text color="white">{tool.name}</Text>
101
+ {tool.compactParams && (
102
+ <Text color="gray"> {tool.compactParams}</Text>
122
103
  )}
123
104
  </Box>
124
105
  ))}
125
106
  </Box>
126
107
  )}
127
-
128
- {/* Show truncation indicator if there are more messages */}
129
- {!isExpanded && block.messages.length > 2 && (
130
- <Box marginTop={1}>
131
- <Text color="gray" dimColor>
132
- ... and {block.messages.length - 2} more messages (Ctrl+O to expand)
133
- </Text>
134
- </Box>
135
- )}
136
108
  </Box>
137
109
  );
138
110
  };