wave-code 0.6.1 → 0.6.2

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 (66) hide show
  1. package/dist/components/App.d.ts.map +1 -1
  2. package/dist/components/App.js +14 -12
  3. package/dist/components/ChatInterface.d.ts.map +1 -1
  4. package/dist/components/ChatInterface.js +2 -1
  5. package/dist/components/CommandOutputDisplay.d.ts.map +1 -1
  6. package/dist/components/CommandOutputDisplay.js +6 -17
  7. package/dist/components/CommandSelector.d.ts.map +1 -1
  8. package/dist/components/CommandSelector.js +6 -0
  9. package/dist/components/ConfirmationSelector.d.ts.map +1 -1
  10. package/dist/components/ConfirmationSelector.js +1 -1
  11. package/dist/components/DiffDisplay.d.ts.map +1 -1
  12. package/dist/components/DiffDisplay.js +4 -0
  13. package/dist/components/HelpView.d.ts +6 -0
  14. package/dist/components/HelpView.d.ts.map +1 -0
  15. package/dist/components/HelpView.js +24 -0
  16. package/dist/components/InputBox.d.ts +1 -1
  17. package/dist/components/InputBox.d.ts.map +1 -1
  18. package/dist/components/InputBox.js +10 -3
  19. package/dist/components/LoadingIndicator.js +1 -1
  20. package/dist/components/MessageItem.d.ts +1 -1
  21. package/dist/components/MessageItem.d.ts.map +1 -1
  22. package/dist/components/MessageItem.js +3 -4
  23. package/dist/components/MessageList.d.ts.map +1 -1
  24. package/dist/components/MessageList.js +24 -7
  25. package/dist/components/RewindCommand.js +1 -1
  26. package/dist/components/TaskList.d.ts.map +1 -1
  27. package/dist/components/TaskList.js +4 -13
  28. package/dist/components/ToolDisplay.d.ts +9 -0
  29. package/dist/components/ToolDisplay.d.ts.map +1 -0
  30. package/dist/components/ToolDisplay.js +44 -0
  31. package/dist/contexts/useChat.d.ts.map +1 -1
  32. package/dist/contexts/useChat.js +15 -1
  33. package/dist/hooks/useInputManager.d.ts +2 -2
  34. package/dist/hooks/useInputManager.d.ts.map +1 -1
  35. package/dist/hooks/useInputManager.js +12 -8
  36. package/dist/managers/InputManager.d.ts +4 -2
  37. package/dist/managers/InputManager.d.ts.map +1 -1
  38. package/dist/managers/InputManager.js +17 -17
  39. package/dist/print-cli.d.ts.map +1 -1
  40. package/dist/print-cli.js +11 -30
  41. package/package.json +2 -2
  42. package/src/components/App.tsx +16 -15
  43. package/src/components/ChatInterface.tsx +3 -2
  44. package/src/components/CommandOutputDisplay.tsx +16 -38
  45. package/src/components/CommandSelector.tsx +6 -0
  46. package/src/components/ConfirmationSelector.tsx +5 -9
  47. package/src/components/DiffDisplay.tsx +9 -0
  48. package/src/components/HelpView.tsx +59 -0
  49. package/src/components/InputBox.tsx +43 -33
  50. package/src/components/LoadingIndicator.tsx +1 -1
  51. package/src/components/MessageItem.tsx +12 -21
  52. package/src/components/MessageList.tsx +40 -17
  53. package/src/components/RewindCommand.tsx +1 -1
  54. package/src/components/TaskList.tsx +4 -16
  55. package/src/components/{ToolResultDisplay.tsx → ToolDisplay.tsx} +6 -16
  56. package/src/contexts/useChat.tsx +16 -1
  57. package/src/hooks/useInputManager.ts +12 -10
  58. package/src/managers/InputManager.ts +19 -21
  59. package/src/print-cli.ts +17 -35
  60. package/dist/components/SubagentBlock.d.ts +0 -8
  61. package/dist/components/SubagentBlock.d.ts.map +0 -1
  62. package/dist/components/SubagentBlock.js +0 -73
  63. package/dist/components/ToolResultDisplay.d.ts +0 -9
  64. package/dist/components/ToolResultDisplay.d.ts.map +0 -1
  65. package/dist/components/ToolResultDisplay.js +0 -54
  66. package/src/components/SubagentBlock.tsx +0 -152
@@ -18,7 +18,7 @@ export const LoadingIndicator = ({
18
18
  <Box flexDirection="column">
19
19
  {isLoading && (
20
20
  <Box>
21
- <Text color="yellow">šŸ’­ AI is thinking... </Text>
21
+ <Text color="yellow">✻ AI is thinking... </Text>
22
22
  {latestTotalTokens > 0 && (
23
23
  <>
24
24
  <Text color="gray" dimColor>
@@ -3,9 +3,8 @@ import { Box, Text } from "ink";
3
3
  import type { Message } from "wave-agent-sdk";
4
4
  import { MessageSource } from "wave-agent-sdk";
5
5
  import { CommandOutputDisplay } from "./CommandOutputDisplay.js";
6
- import { ToolResultDisplay } from "./ToolResultDisplay.js";
6
+ import { ToolDisplay } from "./ToolDisplay.js";
7
7
  import { CompressDisplay } from "./CompressDisplay.js";
8
- import { SubagentBlock } from "./SubagentBlock.js";
9
8
  import { ReasoningDisplay } from "./ReasoningDisplay.js";
10
9
  import { Markdown } from "./Markdown.js";
11
10
 
@@ -15,23 +14,11 @@ export interface MessageItemProps {
15
14
  shouldShowHeader: boolean;
16
15
  }
17
16
 
18
- export const MessageItem = ({
19
- message,
20
- isExpanded,
21
- shouldShowHeader,
22
- }: MessageItemProps) => {
17
+ export const MessageItem = ({ message, isExpanded }: MessageItemProps) => {
23
18
  if (message.blocks.length === 0) return null;
24
19
 
25
20
  return (
26
21
  <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
22
  <Box flexDirection="column" gap={1}>
36
23
  {message.blocks.map((block, blockIndex) => (
37
24
  <Box key={blockIndex}>
@@ -39,15 +26,21 @@ export const MessageItem = ({
39
26
  <Box>
40
27
  {block.customCommandContent && (
41
28
  <Text color="cyan" bold>
42
- ⚔{" "}
29
+ ⚔
43
30
  </Text>
44
31
  )}
45
32
  {block.source === MessageSource.HOOK && (
46
33
  <Text color="magenta" bold>
47
- šŸ”—{" "}
34
+ šŸ”—
35
+ </Text>
36
+ )}
37
+ {message.role === "user" ? (
38
+ <Text backgroundColor="gray" color="white">
39
+ {block.content}
48
40
  </Text>
41
+ ) : (
42
+ <Markdown>{block.content}</Markdown>
49
43
  )}
50
- <Markdown>{block.content}</Markdown>
51
44
  </Box>
52
45
  )}
53
46
 
@@ -62,7 +55,7 @@ export const MessageItem = ({
62
55
  )}
63
56
 
64
57
  {block.type === "tool" && (
65
- <ToolResultDisplay block={block} isExpanded={isExpanded} />
58
+ <ToolDisplay block={block} isExpanded={isExpanded} />
66
59
  )}
67
60
 
68
61
  {block.type === "image" && (
@@ -83,8 +76,6 @@ export const MessageItem = ({
83
76
  <CompressDisplay block={block} isExpanded={isExpanded} />
84
77
  )}
85
78
 
86
- {block.type === "subagent" && <SubagentBlock block={block} />}
87
-
88
79
  {block.type === "reasoning" && <ReasoningDisplay block={block} />}
89
80
  </Box>
90
81
  ))}
@@ -1,6 +1,12 @@
1
1
  import React from "react";
2
2
  import { Box, Text, Static } from "ink";
3
3
  import type { Message } from "wave-agent-sdk";
4
+ import {
5
+ TASK_CREATE_TOOL_NAME,
6
+ TASK_GET_TOOL_NAME,
7
+ TASK_UPDATE_TOOL_NAME,
8
+ TASK_LIST_TOOL_NAME,
9
+ } from "wave-agent-sdk";
4
10
  import { MessageItem } from "./MessageItem.js";
5
11
 
6
12
  export interface MessageListProps {
@@ -34,16 +40,43 @@ export const MessageList = React.memo(
34
40
  const maxExpandedMessages = 20;
35
41
  const shouldLimitMessages =
36
42
  isExpanded && messages.length > maxExpandedMessages;
43
+
44
+ // Filter out task management tools and empty messages
45
+ const taskMgmtTools = [
46
+ TASK_CREATE_TOOL_NAME,
47
+ TASK_GET_TOOL_NAME,
48
+ TASK_UPDATE_TOOL_NAME,
49
+ TASK_LIST_TOOL_NAME,
50
+ ];
51
+ const filteredMessages = messages
52
+ .map((message) => ({
53
+ ...message,
54
+ blocks: message.blocks.filter(
55
+ (block) =>
56
+ !(
57
+ block.type === "tool" &&
58
+ typeof block.name === "string" &&
59
+ taskMgmtTools.includes(block.name)
60
+ ),
61
+ ),
62
+ }))
63
+ .filter((message) => message.blocks.length > 0);
64
+
37
65
  const displayMessages = shouldLimitMessages
38
- ? messages.slice(-maxExpandedMessages)
39
- : messages;
40
- const omittedCount = shouldLimitMessages
41
- ? messages.length - maxExpandedMessages
42
- : 0;
66
+ ? filteredMessages.slice(-maxExpandedMessages)
67
+ : filteredMessages;
43
68
 
44
69
  // Compute which messages to render statically vs dynamically
70
+ const lastMessage = displayMessages[displayMessages.length - 1];
71
+ const hasNonEndTool = lastMessage?.blocks.some(
72
+ (block) => block.type === "tool" && block.stage !== "end",
73
+ );
74
+ const hasRunningCommand = lastMessage?.blocks.some(
75
+ (block) => block.type === "command_output" && block.isRunning,
76
+ );
45
77
  const shouldRenderLastDynamic =
46
- !forceStaticLastMessage && (isLoading || isCommandRunning);
78
+ !forceStaticLastMessage &&
79
+ (isLoading || isCommandRunning || hasNonEndTool || hasRunningCommand);
47
80
  const staticMessages = shouldRenderLastDynamic
48
81
  ? displayMessages.slice(0, -1)
49
82
  : displayMessages;
@@ -53,17 +86,7 @@ export const MessageList = React.memo(
53
86
  : [];
54
87
 
55
88
  return (
56
- <Box flexDirection="column" gap={1} paddingBottom={1}>
57
- {/* Show omitted message count when limiting */}
58
- {omittedCount > 0 && (
59
- <Box>
60
- <Text color="gray" dimColor>
61
- ... {omittedCount} earlier message{omittedCount !== 1 ? "s" : ""}{" "}
62
- omitted (showing latest {maxExpandedMessages})
63
- </Text>
64
- </Box>
65
- )}
66
-
89
+ <Box flexDirection="column" paddingBottom={1}>
67
90
  {/* Static messages */}
68
91
  <Static items={staticMessages}>
69
92
  {(message, key) => {
@@ -143,7 +143,7 @@ export const RewindCommand: React.FC<RewindCommandProps> = ({
143
143
  <Box>
144
144
  <Text color="red" dimColor>
145
145
  āš ļø Warning: This will delete all subsequent messages and revert file
146
- changes.
146
+ and task list changes.
147
147
  </Text>
148
148
  </Box>
149
149
  </Box>
@@ -1,14 +1,11 @@
1
1
  import React from "react";
2
2
  import { useChat } from "../contexts/useChat.js";
3
- import { Box, Text, useStdout } from "ink";
3
+ import { Box, Text } from "ink";
4
4
  import { useTasks } from "../hooks/useTasks.js";
5
5
 
6
6
  export const TaskList: React.FC = () => {
7
7
  const tasks = useTasks();
8
8
  const { isTaskListVisible } = useChat();
9
- const { stdout } = useStdout();
10
- const terminalWidth = stdout?.columns ?? 80;
11
- const maxSubjectWidth = Math.max(20, terminalWidth - 10);
12
9
 
13
10
  if (tasks.length === 0 || !isTaskListVisible) {
14
11
  return null;
@@ -20,9 +17,9 @@ export const TaskList: React.FC = () => {
20
17
  }
21
18
  switch (status) {
22
19
  case "pending":
23
- return <Text color="gray">ā—‹</Text>;
20
+ return <Text color="gray">ā–”</Text>;
24
21
  case "in_progress":
25
- return <Text color="yellow">ā—</Text>;
22
+ return <Text color="yellow">ā– </Text>;
26
23
  case "completed":
27
24
  return <Text color="green">āœ“</Text>;
28
25
  case "deleted":
@@ -32,13 +29,6 @@ export const TaskList: React.FC = () => {
32
29
  }
33
30
  };
34
31
 
35
- const truncate = (text: string, maxWidth: number) => {
36
- if (text.length <= maxWidth) {
37
- return text;
38
- }
39
- return text.slice(0, maxWidth - 3) + "...";
40
- };
41
-
42
32
  return (
43
33
  <Box flexDirection="column">
44
34
  {tasks.map((task) => {
@@ -59,9 +49,7 @@ export const TaskList: React.FC = () => {
59
49
  return (
60
50
  <Box key={task.id} gap={1}>
61
51
  {getStatusIcon(task.status, isBlocked)}
62
- <Text dimColor={isDimmed}>
63
- {truncate(fullText, maxSubjectWidth)}
64
- </Text>
52
+ <Text dimColor={isDimmed}>{fullText}</Text>
65
53
  </Box>
66
54
  );
67
55
  })}
@@ -3,12 +3,12 @@ import { Box, Text } from "ink";
3
3
  import type { ToolBlock } from "wave-agent-sdk";
4
4
  import { DiffDisplay } from "./DiffDisplay.js";
5
5
 
6
- interface ToolResultDisplayProps {
6
+ interface ToolDisplayProps {
7
7
  block: ToolBlock;
8
8
  isExpanded?: boolean;
9
9
  }
10
10
 
11
- export const ToolResultDisplay: React.FC<ToolResultDisplayProps> = ({
11
+ export const ToolDisplay: React.FC<ToolDisplayProps> = ({
12
12
  block,
13
13
  isExpanded = false,
14
14
  }) => {
@@ -25,13 +25,6 @@ export const ToolResultDisplay: React.FC<ToolResultDisplayProps> = ({
25
25
  return "gray"; // Unknown state or no state information
26
26
  };
27
27
 
28
- const getStatusText = () => {
29
- if (stage === "running") return "šŸ”„";
30
- if (success) return "";
31
- if (error || success === false) return "āŒ";
32
- return ""; // Don't display text for unknown state
33
- };
34
-
35
28
  const hasImages = () => {
36
29
  return block.images && block.images.length > 0;
37
30
  };
@@ -44,9 +37,6 @@ export const ToolResultDisplay: React.FC<ToolResultDisplayProps> = ({
44
37
 
45
38
  const toolName = name ? String(name) : "Tool";
46
39
 
47
- const isBackgroundable =
48
- stage === "running" && (toolName === "Bash" || toolName === "Task");
49
-
50
40
  // Get shortResult, if not available show last 5 lines of result
51
41
  const getShortResult = () => {
52
42
  if (block.shortResult) {
@@ -70,16 +60,16 @@ export const ToolResultDisplay: React.FC<ToolResultDisplayProps> = ({
70
60
  return (
71
61
  <Box flexDirection="column">
72
62
  <Box>
73
- <Text color="magenta">šŸ”§ </Text>
74
- <Text color="white">{toolName}</Text>
63
+ <Box flexShrink={0}>
64
+ <Text color={getStatusColor()}>ā— </Text>
65
+ <Text color="white">{toolName}</Text>
66
+ </Box>
75
67
  {/* Display compactParams in collapsed state */}
76
68
  {!isExpanded && compactParams && (
77
69
  <Text color="gray"> {compactParams}</Text>
78
70
  )}
79
- <Text color={getStatusColor()}> {getStatusText()}</Text>
80
71
  {/* Display image indicator */}
81
72
  {hasImages() && <Text color="blue"> {getImageIndicator()}</Text>}
82
- {isBackgroundable && <Text color="gray"> [Ctrl-B] Background</Text>}
83
73
  </Box>
84
74
 
85
75
  {/* Display shortResult in collapsed state */}
@@ -119,6 +119,13 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
119
119
 
120
120
  // Message Display State
121
121
  const [isExpanded, setIsExpanded] = useState(false);
122
+ const isExpandedRef = useRef(isExpanded);
123
+ const frozenMessagesRef = useRef<Message[] | null>(null);
124
+
125
+ useEffect(() => {
126
+ isExpandedRef.current = isExpanded;
127
+ }, [isExpanded]);
128
+
122
129
  const [isTaskListVisible, setIsTaskListVisible] = useState(true);
123
130
 
124
131
  // AI State
@@ -220,7 +227,11 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
220
227
  const initializeAgent = async () => {
221
228
  const callbacks: AgentCallbacks = {
222
229
  onMessagesChange: (newMessages) => {
223
- setMessages([...newMessages]);
230
+ if (isExpandedRef.current) {
231
+ frozenMessagesRef.current = [...newMessages];
232
+ } else {
233
+ setMessages([...newMessages]);
234
+ }
224
235
  },
225
236
  onServersChange: (servers) => {
226
237
  setMcpServers([...servers]);
@@ -517,6 +528,10 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
517
528
  // Clear terminal screen when expanded state changes
518
529
  setIsExpanded((prev) => {
519
530
  const newExpanded = !prev;
531
+ if (!newExpanded && frozenMessagesRef.current) {
532
+ setMessages(frozenMessagesRef.current);
533
+ frozenMessagesRef.current = null;
534
+ }
520
535
  return newExpanded;
521
536
  });
522
537
  }
@@ -37,6 +37,7 @@ export const useInputManager = (
37
37
  useState(false);
38
38
  const [showMcpManager, setShowMcpManager] = useState(false);
39
39
  const [showRewindManager, setShowRewindManager] = useState(false);
40
+ const [showHelp, setShowHelp] = useState(false);
40
41
  const [permissionMode, setPermissionModeState] =
41
42
  useState<PermissionMode>("default");
42
43
  const [attachedImages, setAttachedImages] = useState<AttachedImage[]>([]);
@@ -67,6 +68,9 @@ export const useInputManager = (
67
68
  onRewindManagerStateChange: (show) => {
68
69
  setShowRewindManager(show);
69
70
  },
71
+ onHelpStateChange: (show) => {
72
+ setShowHelp(show);
73
+ },
70
74
  onPermissionModeChange: (mode) => {
71
75
  setPermissionModeState(mode);
72
76
  callbacks.onPermissionModeChange?.(mode);
@@ -101,6 +105,9 @@ export const useInputManager = (
101
105
  onRewindManagerStateChange: (show) => {
102
106
  setShowRewindManager(show);
103
107
  },
108
+ onHelpStateChange: (show) => {
109
+ setShowHelp(show);
110
+ },
104
111
  onPermissionModeChange: (mode) => {
105
112
  setPermissionModeState(mode);
106
113
  callbacks.onPermissionModeChange?.(mode);
@@ -150,14 +157,6 @@ export const useInputManager = (
150
157
  managerRef.current?.moveCursorRight();
151
158
  }, []);
152
159
 
153
- const moveCursorToStart = useCallback(() => {
154
- managerRef.current?.moveCursorToStart();
155
- }, []);
156
-
157
- const moveCursorToEnd = useCallback(() => {
158
- managerRef.current?.moveCursorToEnd();
159
- }, []);
160
-
161
160
  // File selector methods
162
161
  const activateFileSelector = useCallback((position: number) => {
163
162
  managerRef.current?.activateFileSelector(position);
@@ -268,6 +267,7 @@ export const useInputManager = (
268
267
  showBackgroundTaskManager,
269
268
  showMcpManager,
270
269
  showRewindManager,
270
+ showHelp,
271
271
  permissionMode,
272
272
  attachedImages,
273
273
  isManagerReady,
@@ -278,8 +278,6 @@ export const useInputManager = (
278
278
  clearInput,
279
279
  moveCursorLeft,
280
280
  moveCursorRight,
281
- moveCursorToStart,
282
- moveCursorToEnd,
283
281
 
284
282
  // File selector
285
283
  activateFileSelector,
@@ -314,6 +312,10 @@ export const useInputManager = (
314
312
  managerRef.current?.setShowRewindManager(show);
315
313
  setShowRewindManager(show);
316
314
  }, []),
315
+ setShowHelp: useCallback((show: boolean) => {
316
+ managerRef.current?.setShowHelp(show);
317
+ setShowHelp(show);
318
+ }, []),
317
319
  setPermissionMode: useCallback((mode: PermissionMode) => {
318
320
  setPermissionModeState(mode);
319
321
  managerRef.current?.setPermissionMode(mode);
@@ -32,6 +32,7 @@ export interface InputManagerCallbacks {
32
32
  onBackgroundTaskManagerStateChange?: (show: boolean) => void;
33
33
  onMcpManagerStateChange?: (show: boolean) => void;
34
34
  onRewindManagerStateChange?: (show: boolean) => void;
35
+ onHelpStateChange?: (show: boolean) => void;
35
36
  onImagesStateChange?: (images: AttachedImage[]) => void;
36
37
  onSendMessage?: (
37
38
  content: string,
@@ -84,6 +85,7 @@ export class InputManager {
84
85
  private showBackgroundTaskManager: boolean = false;
85
86
  private showMcpManager: boolean = false;
86
87
  private showRewindManager: boolean = false;
88
+ private showHelp: boolean = false;
87
89
 
88
90
  // Permission mode state
89
91
  private permissionMode: PermissionMode = "default";
@@ -181,14 +183,6 @@ export class InputManager {
181
183
  this.setCursorPosition(this.cursorPosition + 1);
182
184
  }
183
185
 
184
- moveCursorToStart(): void {
185
- this.setCursorPosition(0);
186
- }
187
-
188
- moveCursorToEnd(): void {
189
- this.setCursorPosition(this.inputText.length);
190
- }
191
-
192
186
  // File selector methods
193
187
  private async searchFiles(query: string): Promise<void> {
194
188
  try {
@@ -357,6 +351,9 @@ export class InputManager {
357
351
  } else if (command === "rewind") {
358
352
  this.setShowRewindManager(true);
359
353
  commandExecuted = true;
354
+ } else if (command === "help") {
355
+ this.setShowHelp(true);
356
+ commandExecuted = true;
360
357
  }
361
358
  }
362
359
  })();
@@ -661,6 +658,15 @@ export class InputManager {
661
658
  this.callbacks.onRewindManagerStateChange?.(show);
662
659
  }
663
660
 
661
+ getShowHelp(): boolean {
662
+ return this.showHelp;
663
+ }
664
+
665
+ setShowHelp(show: boolean): void {
666
+ this.showHelp = show;
667
+ this.callbacks.onHelpStateChange?.(show);
668
+ }
669
+
664
670
  // Permission mode methods
665
671
  getPermissionMode(): PermissionMode {
666
672
  return this.permissionMode;
@@ -854,16 +860,6 @@ export class InputManager {
854
860
  return true;
855
861
  }
856
862
 
857
- if (("home" in key && key.home) || (key.ctrl && input === "a")) {
858
- this.moveCursorToStart();
859
- return true;
860
- }
861
-
862
- if (("end" in key && key.end) || (key.ctrl && input === "e")) {
863
- this.moveCursorToEnd();
864
- return true;
865
- }
866
-
867
863
  // Handle Ctrl+V for pasting images
868
864
  if (key.ctrl && input === "v") {
869
865
  this.handlePasteImage().catch((error) => {
@@ -947,14 +943,16 @@ export class InputManager {
947
943
  this.showHistorySearch ||
948
944
  this.showBackgroundTaskManager ||
949
945
  this.showMcpManager ||
950
- this.showRewindManager
946
+ this.showRewindManager ||
947
+ this.showHelp
951
948
  ) {
952
949
  if (
953
950
  this.showBackgroundTaskManager ||
954
951
  this.showMcpManager ||
955
- this.showRewindManager
952
+ this.showRewindManager ||
953
+ this.showHelp
956
954
  ) {
957
- // Task manager, MCP manager and Rewind don't need to handle input, handled by component itself
955
+ // Task manager, MCP manager, Rewind and Help don't need to handle input, handled by component itself
958
956
  // Return true to indicate we've "handled" it (by ignoring it) so it doesn't leak to normal input
959
957
  return true;
960
958
  }
package/src/print-cli.ts CHANGED
@@ -76,42 +76,10 @@ export async function startPrintCli(options: PrintCliOptions): Promise<void> {
76
76
  process.stdout.write(chunk);
77
77
  },
78
78
 
79
- // Tool block callback - display tool name when tool starts
80
- onToolBlockUpdated: (params) => {
81
- // Print tool name only during 'running' stage (happens once per tool call)
82
- if (params.stage === "running" && params.name) {
83
- process.stdout.write(`\nšŸ”§ ${params.name}`);
84
- if (params.compactParams) {
85
- process.stdout.write(` ${params.compactParams}`);
86
- }
87
- process.stdout.write(`\n`);
88
- }
89
- },
90
-
91
- // Subagent block callbacks
92
- onSubAgentBlockAdded: (subagentId: string, parameters) => {
93
- // Display subagent creation with indentation
94
- process.stdout.write(
95
- `\nšŸ¤– Subagent [${parameters.subagent_type}]: ${parameters.description}\n`,
96
- );
97
- },
98
- onSubAgentBlockUpdated: (subagentId: string, status) => {
99
- // Display subagent status updates
100
- const statusIconMap = {
101
- active: "šŸ”„",
102
- completed: "āœ…",
103
- error: "āŒ",
104
- aborted: "āš ļø",
105
- } as const;
106
-
107
- const statusIcon = statusIconMap[status] ?? "šŸ”„";
108
- process.stdout.write(` ${statusIcon} Subagent status: ${status}\n`);
109
- },
110
79
  // Subagent message callbacks
111
80
  onSubagentAssistantMessageAdded: (subagentId: string) => {
112
81
  subagentReasoningStates.set(subagentId, false);
113
82
  subagentContentStates.set(subagentId, false);
114
- // Subagent assistant message started - add indentation
115
83
  process.stdout.write("\n ");
116
84
  },
117
85
  onSubagentAssistantReasoningUpdated: (
@@ -132,13 +100,27 @@ export async function startPrintCli(options: PrintCliOptions): Promise<void> {
132
100
  process.stdout.write("\n šŸ“ Response: ");
133
101
  subagentContentStates.set(subagentId, true);
134
102
  }
135
- // Stream subagent content with indentation - output only the new chunk
136
103
  process.stdout.write(chunk);
137
104
  },
138
- onSubagentUserMessageAdded: (_subagentId: string, params) => {
139
- // Display subagent user messages with indentation
105
+ onSubagentUserMessageAdded: (
106
+ _subagentId: string,
107
+ params: { content: string },
108
+ ) => {
140
109
  process.stdout.write(`\n šŸ‘¤ User: ${params.content}\n`);
141
110
  },
111
+
112
+ // Tool block callback - display tool name when tool starts
113
+ onToolBlockUpdated: (params) => {
114
+ // Print tool name only during 'running' stage (happens once per tool call)
115
+ if (params.stage === "running" && params.name) {
116
+ process.stdout.write(`\nšŸ”§ ${params.name}`);
117
+ if (params.compactParams) {
118
+ process.stdout.write(` ${params.compactParams}`);
119
+ }
120
+ process.stdout.write(`\n`);
121
+ }
122
+ },
123
+
142
124
  // Error block callback
143
125
  onErrorBlockAdded: (error: string) => {
144
126
  // Display error blocks with distinct formatting
@@ -1,8 +0,0 @@
1
- import React from "react";
2
- import type { SubagentBlock as SubagentBlockType } from "wave-agent-sdk";
3
- interface SubagentBlockProps {
4
- block: SubagentBlockType;
5
- }
6
- export declare const SubagentBlock: React.FC<SubagentBlockProps>;
7
- export {};
8
- //# sourceMappingURL=SubagentBlock.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"SubagentBlock.d.ts","sourceRoot":"","sources":["../../src/components/SubagentBlock.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkB,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EAAE,aAAa,IAAI,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAIzE,UAAU,kBAAkB;IAC1B,KAAK,EAAE,iBAAiB,CAAC;CAC1B;AAED,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CA6ItD,CAAC"}
@@ -1,73 +0,0 @@
1
- import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { useMemo } from "react";
3
- import { Box, Text } from "ink";
4
- import { useChat } from "../contexts/useChat.js";
5
- import { Markdown } from "./Markdown.js";
6
- export const SubagentBlock = ({ block }) => {
7
- const { subagentMessages, subagentLatestTokens } = useChat();
8
- // Get messages for this subagent from context
9
- const messages = useMemo(() => subagentMessages[block.subagentId] || [], [subagentMessages, block.subagentId]);
10
- // Get latest turn tokens for this subagent
11
- const latestTurnTokens = subagentLatestTokens[block.subagentId] || 0;
12
- // If the subagent is running in the background, don't show the block
13
- if (block.runInBackground) {
14
- return null;
15
- }
16
- // Status indicator mapping
17
- const getStatusIndicator = (status) => {
18
- switch (status) {
19
- case "active":
20
- return { icon: "šŸ”„", color: "yellow" };
21
- case "completed":
22
- return { icon: "āœ…", color: "green" };
23
- case "error":
24
- return { icon: "āŒ", color: "red" };
25
- case "aborted":
26
- return { icon: "ā¹ļø", color: "gray" };
27
- default:
28
- return { icon: "ā³", color: "gray" };
29
- }
30
- };
31
- const statusInfo = getStatusIndicator(block.status);
32
- // Find the last 2 tool names and their compact params, and count total tools
33
- const getLastTwoTools = () => {
34
- const tools = [];
35
- let totalToolCount = 0;
36
- for (let i = messages.length - 1; i >= 0; i--) {
37
- const message = messages[i];
38
- for (let j = message.blocks.length - 1; j >= 0; j--) {
39
- const messageBlock = message.blocks[j];
40
- if (messageBlock.type === "tool" && messageBlock.name) {
41
- totalToolCount++;
42
- if (tools.length < 2) {
43
- tools.push({
44
- name: messageBlock.name,
45
- compactParams: messageBlock.compactParams,
46
- });
47
- }
48
- }
49
- }
50
- }
51
- return { tools: tools.reverse(), totalToolCount }; // Reverse to show oldest first, newest last
52
- };
53
- const { tools: lastTwoTools } = getLastTwoTools();
54
- // Get the last text message content if completed
55
- const getLastTextMessage = () => {
56
- if (block.status !== "completed")
57
- return null;
58
- for (let i = messages.length - 1; i >= 0; i--) {
59
- const message = messages[i];
60
- if (message.role === "assistant") {
61
- for (let j = message.blocks.length - 1; j >= 0; j--) {
62
- const messageBlock = message.blocks[j];
63
- if (messageBlock.type === "text" && messageBlock.content) {
64
- return messageBlock.content;
65
- }
66
- }
67
- }
68
- }
69
- return null;
70
- };
71
- const lastTextMessage = getLastTextMessage();
72
- return (_jsxs(Box, { borderRight: false, borderTop: false, borderBottom: false, borderStyle: "classic", borderColor: "magenta", paddingX: 1, flexDirection: "column", children: [_jsx(Box, { flexDirection: "row", gap: 1, children: _jsxs(Box, { flexDirection: "row", alignItems: "center", children: [_jsxs(Text, { color: "cyan", children: ["\uD83E\uDD16 ", block.subagentName] }), _jsxs(Text, { color: statusInfo.color, dimColor: false, children: [" ", statusInfo.icon] }), _jsxs(Text, { color: "gray", dimColor: true, children: [" ", "(", messages.length, " messages", latestTurnTokens > 0 && (_jsxs(_Fragment, { children: [" | ", _jsx(Text, { color: "blue", bold: true, children: latestTurnTokens.toLocaleString() }), " tokens"] })), ")"] })] }) }), lastTextMessage && (_jsx(Box, { children: _jsx(Markdown, { children: lastTextMessage }) })), block.status !== "completed" && lastTwoTools.length > 0 && (_jsx(Box, { flexDirection: "column", children: lastTwoTools.map((tool, index) => (_jsxs(Box, { flexDirection: "row", children: [_jsx(Text, { color: "magenta", children: "\uD83D\uDD27 " }), _jsx(Text, { color: "white", children: tool.name }), tool.compactParams && (_jsxs(Text, { color: "gray", children: [" ", tool.compactParams] }))] }, index))) }))] }));
73
- };
@@ -1,9 +0,0 @@
1
- import React from "react";
2
- import type { ToolBlock } from "wave-agent-sdk";
3
- interface ToolResultDisplayProps {
4
- block: ToolBlock;
5
- isExpanded?: boolean;
6
- }
7
- export declare const ToolResultDisplay: React.FC<ToolResultDisplayProps>;
8
- export {};
9
- //# sourceMappingURL=ToolResultDisplay.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ToolResultDisplay.d.ts","sourceRoot":"","sources":["../../src/components/ToolResultDisplay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAGhD,UAAU,sBAAsB;IAC9B,KAAK,EAAE,SAAS,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,eAAO,MAAM,iBAAiB,EAAE,KAAK,CAAC,EAAE,CAAC,sBAAsB,CAyI9D,CAAC"}