wave-code 0.0.5 → 0.0.6

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 (57) hide show
  1. package/README.md +2 -2
  2. package/dist/components/ChatInterface.d.ts.map +1 -1
  3. package/dist/components/ChatInterface.js +4 -24
  4. package/dist/components/CommandSelector.js +4 -4
  5. package/dist/components/DiffViewer.d.ts +1 -1
  6. package/dist/components/DiffViewer.d.ts.map +1 -1
  7. package/dist/components/DiffViewer.js +15 -15
  8. package/dist/components/FileSelector.js +2 -2
  9. package/dist/components/InputBox.d.ts.map +1 -1
  10. package/dist/components/InputBox.js +21 -50
  11. package/dist/components/Markdown.d.ts +6 -0
  12. package/dist/components/Markdown.d.ts.map +1 -0
  13. package/dist/components/Markdown.js +22 -0
  14. package/dist/components/MessageItem.d.ts +9 -0
  15. package/dist/components/MessageItem.d.ts.map +1 -0
  16. package/dist/components/MessageItem.js +15 -0
  17. package/dist/components/MessageList.d.ts +1 -1
  18. package/dist/components/MessageList.d.ts.map +1 -1
  19. package/dist/components/MessageList.js +33 -33
  20. package/dist/components/SubagentBlock.d.ts +0 -1
  21. package/dist/components/SubagentBlock.d.ts.map +1 -1
  22. package/dist/components/SubagentBlock.js +29 -30
  23. package/dist/components/ToolResultDisplay.js +5 -5
  24. package/dist/contexts/useChat.d.ts +2 -2
  25. package/dist/contexts/useChat.d.ts.map +1 -1
  26. package/dist/contexts/useChat.js +18 -9
  27. package/dist/hooks/useInputManager.d.ts +3 -1
  28. package/dist/hooks/useInputManager.d.ts.map +1 -1
  29. package/dist/hooks/useInputManager.js +15 -2
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +9 -2
  32. package/dist/managers/InputManager.d.ts +3 -1
  33. package/dist/managers/InputManager.d.ts.map +1 -1
  34. package/dist/managers/InputManager.js +44 -24
  35. package/dist/print-cli.d.ts +1 -0
  36. package/dist/print-cli.d.ts.map +1 -1
  37. package/dist/print-cli.js +88 -23
  38. package/dist/utils/usageSummary.d.ts +6 -0
  39. package/dist/utils/usageSummary.d.ts.map +1 -1
  40. package/dist/utils/usageSummary.js +72 -0
  41. package/package.json +10 -6
  42. package/src/components/ChatInterface.tsx +13 -43
  43. package/src/components/CommandSelector.tsx +5 -5
  44. package/src/components/DiffViewer.tsx +18 -16
  45. package/src/components/FileSelector.tsx +2 -2
  46. package/src/components/InputBox.tsx +22 -74
  47. package/src/components/Markdown.tsx +29 -0
  48. package/src/components/MessageItem.tsx +104 -0
  49. package/src/components/MessageList.tsx +142 -202
  50. package/src/components/SubagentBlock.tsx +56 -84
  51. package/src/components/ToolResultDisplay.tsx +5 -5
  52. package/src/contexts/useChat.tsx +22 -13
  53. package/src/hooks/useInputManager.ts +21 -3
  54. package/src/index.ts +12 -2
  55. package/src/managers/InputManager.ts +55 -25
  56. package/src/print-cli.ts +103 -21
  57. package/src/utils/usageSummary.ts +109 -0
@@ -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,153 @@ 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
+ isStatic={true}
79
+ />
80
+ );
81
+ }}
82
+ </Static>
83
+
84
+ {/* Dynamic messages */}
85
+ {dynamicMessages.map((message, index) => {
86
+ const messageIndex = staticMessages.length + index;
155
87
  const previousMessage =
156
- originalIndex > 0 ? messages[originalIndex - 1] : undefined;
157
- return renderMessageItem(
158
- message,
159
- originalIndex,
160
- isExpanded,
161
- previousMessage,
88
+ messageIndex > 0 ? displayMessages[messageIndex - 1] : undefined;
89
+ return (
90
+ <Box key={`dynamic-${index}`} marginTop={-1}>
91
+ <MessageItem
92
+ message={message}
93
+ shouldShowHeader={previousMessage?.role !== message.role}
94
+ isExpanded={isExpanded}
95
+ isStatic={false}
96
+ />
97
+ </Box>
162
98
  );
163
99
  })}
164
- </Box>
165
100
 
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
- )}
101
+ {(isLoading || isCommandRunning || isCompressing) && (
102
+ <Box flexDirection="column" gap={1}>
103
+ {isLoading && (
104
+ <Box>
105
+ <Text color="yellow">💭 AI is thinking... </Text>
106
+ <Text color="gray" dimColor>
107
+ |{" "}
108
+ </Text>
109
+ <Text color="red" bold>
110
+ Esc
111
+ </Text>
112
+ <Text color="gray" dimColor>
113
+ {" "}
114
+ to abort
115
+ </Text>
116
+ </Box>
117
+ )}
118
+ {isCommandRunning && (
119
+ <Text color="blue">🚀 Command is running...</Text>
120
+ )}
121
+ {isCompressing && (
122
+ <Text color="magenta">🗜️ Compressing message history...</Text>
123
+ )}
124
+ </Box>
125
+ )}
200
126
 
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>
127
+ {/* Bottom info and shortcut key hints */}
128
+ {messages.length > 0 && (
129
+ <Box>
130
+ <Box justifyContent="space-between" width="100%">
131
+ <Box>
132
+ <Text color="gray">
133
+ Messages {messages.length}
134
+ {latestTotalTokens > 0 && (
135
+ <>
136
+ <Text color="gray" dimColor>
137
+ {" "}
138
+ |{" "}
139
+ </Text>
140
+ <Text color="blue" bold>
141
+ {latestTotalTokens.toLocaleString()}
142
+ </Text>
143
+ <Text color="gray" dimColor>
144
+ {" "}
145
+ tokens
146
+ </Text>
147
+ </>
148
+ )}
149
+ </Text>
150
+ </Box>
210
151
  <Text color="gray" dimColor>
211
- {" "}
212
- <Text color="cyan">Ctrl+U/D</Text> Navigate
152
+ <Text color="cyan">Ctrl+O</Text> Toggle{" "}
153
+ {isExpanded ? "Collapse" : "Expand"}
213
154
  </Text>
214
155
  </Box>
215
- <Text color="gray" dimColor>
216
- <Text color="cyan">Ctrl+O</Text> Toggle{" "}
217
- {isExpanded ? "Collapse" : "Expand"}
218
- </Text>
219
156
  </Box>
220
- </Box>
221
- )}
222
- </Box>
223
- );
224
- };
157
+ )}
158
+ </Box>
159
+ );
160
+ },
161
+ );
162
+
163
+ // Add display name for debugging
164
+ MessageList.displayName = "MessageList";
@@ -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
  };
@@ -11,23 +11,23 @@ export const ToolResultDisplay: React.FC<ToolResultDisplayProps> = ({
11
11
  block,
12
12
  isExpanded = false,
13
13
  }) => {
14
- const { parameters, result, compactParams, isRunning, success, error, name } =
14
+ const { parameters, result, compactParams, stage, success, error, name } =
15
15
  block;
16
16
 
17
17
  // Directly use compactParams
18
18
  // (no change needed as we destructured it above)
19
19
 
20
20
  const getStatusColor = () => {
21
- if (isRunning) return "yellow";
21
+ if (stage === "running") return "yellow";
22
22
  if (success) return "green";
23
23
  if (error || success === false) return "red";
24
24
  return "gray"; // Unknown state or no state information
25
25
  };
26
26
 
27
27
  const getStatusText = () => {
28
- if (isRunning) return "🔄";
28
+ if (stage === "running") return "🔄";
29
29
  if (success) return "";
30
- if (error || success === false) return "❌ Failed";
30
+ if (error || success === false) return "❌";
31
31
  return ""; // Don't display text for unknown state
32
32
  };
33
33
 
@@ -70,7 +70,7 @@ export const ToolResultDisplay: React.FC<ToolResultDisplayProps> = ({
70
70
  <Text color="white">{toolName}</Text>
71
71
  {/* Display compactParams in collapsed state */}
72
72
  {!isExpanded && compactParams && (
73
- <Text color="gray"> ({compactParams})</Text>
73
+ <Text color="gray"> {compactParams}</Text>
74
74
  )}
75
75
  <Text color={getStatusColor()}> {getStatusText()}</Text>
76
76
  {/* Display image indicator */}
@@ -13,7 +13,6 @@ import type {
13
13
  McpServerStatus,
14
14
  BackgroundShell,
15
15
  SlashCommand,
16
- Usage,
17
16
  } from "wave-agent-sdk";
18
17
  import { Agent, AgentCallbacks } from "wave-agent-sdk";
19
18
  import { logger } from "../utils/logger.js";
@@ -51,8 +50,8 @@ export interface ChatContextType {
51
50
  // Slash Command functionality
52
51
  slashCommands: SlashCommand[];
53
52
  hasSlashCommand: (commandId: string) => boolean;
54
- // Usage tracking
55
- usages: Usage[];
53
+ // Subagent messages
54
+ subagentMessages: Record<string, Message[]>;
56
55
  }
57
56
 
58
57
  const ChatContext = createContext<ChatContextType | null>(null);
@@ -95,15 +94,23 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({ children }) => {
95
94
  // Command state
96
95
  const [slashCommands, setSlashCommands] = useState<SlashCommand[]>([]);
97
96
 
98
- // Usage tracking state
99
- const [usages, setUsages] = useState<Usage[]>([]);
97
+ // Subagent messages state
98
+ const [subagentMessages, setSubagentMessages] = useState<
99
+ Record<string, Message[]>
100
+ >({});
100
101
 
101
102
  const agentRef = useRef<Agent | null>(null);
102
103
 
103
104
  // Listen for Ctrl+O hotkey to toggle collapse/expand state
104
105
  useInput((input, key) => {
105
106
  if (key.ctrl && input === "o") {
106
- setIsExpanded((prev) => !prev);
107
+ // Clear terminal screen when expanded state changes
108
+ process.stdout.write("\x1Bc", () => {
109
+ setIsExpanded((prev) => {
110
+ const newExpanded = !prev;
111
+ return newExpanded;
112
+ });
113
+ });
107
114
  }
108
115
  });
109
116
 
@@ -118,7 +125,9 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({ children }) => {
118
125
  setMcpServers([...servers]);
119
126
  },
120
127
  onSessionIdChange: (sessionId) => {
121
- setSessionId(sessionId);
128
+ process.stdout.write("\x1Bc", () => {
129
+ setSessionId(sessionId);
130
+ });
122
131
  },
123
132
  onLatestTotalTokensChange: (tokens) => {
124
133
  setlatestTotalTokens(tokens);
@@ -132,8 +141,11 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({ children }) => {
132
141
  onShellsChange: (shells) => {
133
142
  setBackgroundShells([...shells]);
134
143
  },
135
- onUsagesChange: (newUsages) => {
136
- setUsages([...newUsages]);
144
+ onSubagentMessagesChange: (subagentId, messages) => {
145
+ setSubagentMessages((prev) => ({
146
+ ...prev,
147
+ [subagentId]: [...messages],
148
+ }));
137
149
  },
138
150
  };
139
151
 
@@ -163,9 +175,6 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({ children }) => {
163
175
  // Get initial commands
164
176
  const agentSlashCommands = agent.getSlashCommands?.() || [];
165
177
  setSlashCommands(agentSlashCommands);
166
-
167
- // Get initial usages
168
- setUsages(agent.usages);
169
178
  } catch (error) {
170
179
  console.error("Failed to initialize AI manager:", error);
171
180
  }
@@ -314,7 +323,7 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({ children }) => {
314
323
  killBackgroundShell,
315
324
  slashCommands,
316
325
  hasSlashCommand,
317
- usages,
326
+ subagentMessages,
318
327
  };
319
328
 
320
329
  return (