wave-code 0.5.0 → 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 (112) hide show
  1. package/dist/components/App.d.ts.map +1 -1
  2. package/dist/components/App.js +40 -2
  3. package/dist/components/BackgroundTaskManager.d.ts +6 -0
  4. package/dist/components/BackgroundTaskManager.d.ts.map +1 -0
  5. package/dist/components/{TaskManager.js → BackgroundTaskManager.js} +1 -1
  6. package/dist/components/ChatInterface.d.ts.map +1 -1
  7. package/dist/components/ChatInterface.js +40 -5
  8. package/dist/components/CommandOutputDisplay.d.ts.map +1 -1
  9. package/dist/components/CommandOutputDisplay.js +6 -17
  10. package/dist/components/CommandSelector.d.ts.map +1 -1
  11. package/dist/components/CommandSelector.js +16 -2
  12. package/dist/components/CompressDisplay.d.ts.map +1 -1
  13. package/dist/components/CompressDisplay.js +6 -10
  14. package/dist/components/ConfirmationDetails.d.ts +9 -0
  15. package/dist/components/ConfirmationDetails.d.ts.map +1 -0
  16. package/dist/components/ConfirmationDetails.js +53 -0
  17. package/dist/components/{Confirmation.d.ts → ConfirmationSelector.d.ts} +3 -3
  18. package/dist/components/ConfirmationSelector.d.ts.map +1 -0
  19. package/dist/components/{Confirmation.js → ConfirmationSelector.js} +34 -96
  20. package/dist/components/DiffDisplay.d.ts.map +1 -1
  21. package/dist/components/DiffDisplay.js +48 -1
  22. package/dist/components/FileSelector.d.ts.map +1 -1
  23. package/dist/components/FileSelector.js +2 -2
  24. package/dist/components/HelpView.d.ts +6 -0
  25. package/dist/components/HelpView.d.ts.map +1 -0
  26. package/dist/components/HelpView.js +24 -0
  27. package/dist/components/HistorySearch.d.ts.map +1 -1
  28. package/dist/components/HistorySearch.js +12 -4
  29. package/dist/components/InputBox.d.ts +1 -3
  30. package/dist/components/InputBox.d.ts.map +1 -1
  31. package/dist/components/InputBox.js +14 -17
  32. package/dist/components/LoadingIndicator.d.ts +11 -0
  33. package/dist/components/LoadingIndicator.d.ts.map +1 -0
  34. package/dist/components/LoadingIndicator.js +6 -0
  35. package/dist/components/Markdown.d.ts.map +1 -1
  36. package/dist/components/Markdown.js +114 -121
  37. package/dist/components/MessageItem.d.ts +1 -1
  38. package/dist/components/MessageItem.d.ts.map +1 -1
  39. package/dist/components/MessageItem.js +3 -5
  40. package/dist/components/MessageList.d.ts +2 -3
  41. package/dist/components/MessageList.d.ts.map +1 -1
  42. package/dist/components/MessageList.js +29 -12
  43. package/dist/components/PlanDisplay.d.ts.map +1 -1
  44. package/dist/components/PlanDisplay.js +4 -12
  45. package/dist/components/RewindCommand.d.ts +4 -0
  46. package/dist/components/RewindCommand.d.ts.map +1 -1
  47. package/dist/components/RewindCommand.js +20 -3
  48. package/dist/components/TaskList.d.ts +3 -0
  49. package/dist/components/TaskList.d.ts.map +1 -0
  50. package/dist/components/TaskList.js +40 -0
  51. package/dist/components/ToolDisplay.d.ts +9 -0
  52. package/dist/components/ToolDisplay.d.ts.map +1 -0
  53. package/dist/components/ToolDisplay.js +44 -0
  54. package/dist/contexts/useChat.d.ts +11 -3
  55. package/dist/contexts/useChat.d.ts.map +1 -1
  56. package/dist/contexts/useChat.js +51 -32
  57. package/dist/hooks/useInputManager.d.ts +4 -15
  58. package/dist/hooks/useInputManager.d.ts.map +1 -1
  59. package/dist/hooks/useInputManager.js +20 -65
  60. package/dist/hooks/useTasks.d.ts +2 -0
  61. package/dist/hooks/useTasks.d.ts.map +1 -0
  62. package/dist/hooks/useTasks.js +5 -0
  63. package/dist/managers/InputManager.d.ts +8 -30
  64. package/dist/managers/InputManager.d.ts.map +1 -1
  65. package/dist/managers/InputManager.js +38 -144
  66. package/dist/print-cli.d.ts.map +1 -1
  67. package/dist/print-cli.js +11 -30
  68. package/package.json +5 -6
  69. package/src/components/App.tsx +51 -3
  70. package/src/components/{TaskManager.tsx → BackgroundTaskManager.tsx} +4 -2
  71. package/src/components/ChatInterface.tsx +80 -23
  72. package/src/components/CommandOutputDisplay.tsx +16 -38
  73. package/src/components/CommandSelector.tsx +41 -17
  74. package/src/components/CompressDisplay.tsx +5 -22
  75. package/src/components/ConfirmationDetails.tsx +108 -0
  76. package/src/components/{Confirmation.tsx → ConfirmationSelector.tsx} +74 -193
  77. package/src/components/DiffDisplay.tsx +71 -1
  78. package/src/components/FileSelector.tsx +0 -2
  79. package/src/components/HelpView.tsx +59 -0
  80. package/src/components/HistorySearch.tsx +45 -21
  81. package/src/components/InputBox.tsx +51 -63
  82. package/src/components/LoadingIndicator.tsx +56 -0
  83. package/src/components/Markdown.tsx +126 -323
  84. package/src/components/MessageItem.tsx +13 -24
  85. package/src/components/MessageList.tsx +48 -82
  86. package/src/components/PlanDisplay.tsx +4 -27
  87. package/src/components/RewindCommand.tsx +39 -2
  88. package/src/components/TaskList.tsx +58 -0
  89. package/src/components/{ToolResultDisplay.tsx → ToolDisplay.tsx} +8 -18
  90. package/src/contexts/useChat.tsx +73 -41
  91. package/src/hooks/useInputManager.ts +21 -83
  92. package/src/hooks/useTasks.ts +6 -0
  93. package/src/managers/InputManager.ts +43 -179
  94. package/src/print-cli.ts +17 -35
  95. package/dist/components/Confirmation.d.ts.map +0 -1
  96. package/dist/components/MemoryDisplay.d.ts +0 -8
  97. package/dist/components/MemoryDisplay.d.ts.map +0 -1
  98. package/dist/components/MemoryDisplay.js +0 -25
  99. package/dist/components/MemoryTypeSelector.d.ts +0 -8
  100. package/dist/components/MemoryTypeSelector.d.ts.map +0 -1
  101. package/dist/components/MemoryTypeSelector.js +0 -38
  102. package/dist/components/SubagentBlock.d.ts +0 -8
  103. package/dist/components/SubagentBlock.d.ts.map +0 -1
  104. package/dist/components/SubagentBlock.js +0 -70
  105. package/dist/components/TaskManager.d.ts +0 -6
  106. package/dist/components/TaskManager.d.ts.map +0 -1
  107. package/dist/components/ToolResultDisplay.d.ts +0 -9
  108. package/dist/components/ToolResultDisplay.d.ts.map +0 -1
  109. package/dist/components/ToolResultDisplay.js +0 -54
  110. package/src/components/MemoryDisplay.tsx +0 -62
  111. package/src/components/MemoryTypeSelector.tsx +0 -98
  112. package/src/components/SubagentBlock.tsx +0 -143
@@ -13,6 +13,7 @@ export const HistorySearch: React.FC<HistorySearchProps> = ({
13
13
  onSelect,
14
14
  onCancel,
15
15
  }) => {
16
+ const MAX_VISIBLE_ITEMS = 5;
16
17
  const [selectedIndex, setSelectedIndex] = useState(0);
17
18
  const [entries, setEntries] = useState<PromptEntry[]>([]);
18
19
 
@@ -30,8 +31,8 @@ export const HistorySearch: React.FC<HistorySearchProps> = ({
30
31
  useEffect(() => {
31
32
  const fetchHistory = async () => {
32
33
  const results = await PromptHistoryManager.searchHistory(searchQuery);
33
- const limitedResults = results.slice(0, 10);
34
- setEntries(limitedResults); // Limit to 10 results
34
+ const limitedResults = results.slice(0, 20);
35
+ setEntries(limitedResults); // Limit to 20 results
35
36
  setSelectedIndex(0);
36
37
  };
37
38
  fetchHistory();
@@ -75,7 +76,6 @@ export const HistorySearch: React.FC<HistorySearchProps> = ({
75
76
  borderBottom={false}
76
77
  borderLeft={false}
77
78
  borderRight={false}
78
- paddingTop={1}
79
79
  >
80
80
  <Text color="yellow">
81
81
  No history found {searchQuery && `for "${searchQuery}"`}
@@ -102,6 +102,19 @@ export const HistorySearch: React.FC<HistorySearchProps> = ({
102
102
  }
103
103
  };
104
104
 
105
+ // Calculate visible window
106
+ const startIndex = Math.max(
107
+ 0,
108
+ Math.min(
109
+ selectedIndex - Math.floor(MAX_VISIBLE_ITEMS / 2),
110
+ Math.max(0, entries.length - MAX_VISIBLE_ITEMS),
111
+ ),
112
+ );
113
+ const visibleEntries = entries.slice(
114
+ startIndex,
115
+ startIndex + MAX_VISIBLE_ITEMS,
116
+ );
117
+
105
118
  return (
106
119
  <Box
107
120
  flexDirection="column"
@@ -110,7 +123,6 @@ export const HistorySearch: React.FC<HistorySearchProps> = ({
110
123
  borderBottom={false}
111
124
  borderLeft={false}
112
125
  borderRight={false}
113
- paddingTop={1}
114
126
  gap={1}
115
127
  >
116
128
  <Box>
@@ -119,24 +131,36 @@ export const HistorySearch: React.FC<HistorySearchProps> = ({
119
131
  </Text>
120
132
  </Box>
121
133
 
122
- {entries.map((entry, index) => (
123
- <Box key={index} flexDirection="column">
124
- <Text
125
- color={index === selectedIndex ? "black" : "white"}
126
- backgroundColor={index === selectedIndex ? "blue" : undefined}
127
- wrap="truncate-end"
128
- >
129
- {entry.prompt.replace(/\n/g, " ")}
130
- </Text>
131
- {index === selectedIndex && (
132
- <Box marginLeft={4}>
133
- <Text color="gray" dimColor>
134
- {formatTimestamp(entry.timestamp)}
135
- </Text>
134
+ <Box flexDirection="column">
135
+ {visibleEntries.map((entry, index) => {
136
+ const actualIndex = startIndex + index;
137
+ const isSelected = actualIndex === selectedIndex;
138
+ return (
139
+ <Box
140
+ key={actualIndex}
141
+ flexDirection="row"
142
+ justifyContent="space-between"
143
+ >
144
+ <Box flexShrink={1}>
145
+ <Text
146
+ color={isSelected ? "black" : "white"}
147
+ backgroundColor={isSelected ? "blue" : undefined}
148
+ wrap="truncate-end"
149
+ >
150
+ {entry.prompt.replace(/\n/g, " ")}
151
+ </Text>
152
+ </Box>
153
+ {isSelected && (
154
+ <Box marginLeft={2} flexShrink={0}>
155
+ <Text color="gray" dimColor>
156
+ {formatTimestamp(entry.timestamp)}
157
+ </Text>
158
+ </Box>
159
+ )}
136
160
  </Box>
137
- )}
138
- </Box>
139
- ))}
161
+ );
162
+ })}
163
+ </Box>
140
164
 
141
165
  <Box>
142
166
  <Text dimColor>
@@ -4,17 +4,17 @@ import { useInput } from "ink";
4
4
  import { FileSelector } from "./FileSelector.js";
5
5
  import { CommandSelector } from "./CommandSelector.js";
6
6
  import { HistorySearch } from "./HistorySearch.js";
7
- import { MemoryTypeSelector } from "./MemoryTypeSelector.js";
8
- import { TaskManager } from "./TaskManager.js";
7
+ import { BackgroundTaskManager } from "./BackgroundTaskManager.js";
9
8
  import { McpManager } from "./McpManager.js";
10
9
  import { RewindCommand } from "./RewindCommand.js";
10
+ import { HelpView } from "./HelpView.js";
11
11
  import { useInputManager } from "../hooks/useInputManager.js";
12
12
  import { useChat } from "../contexts/useChat.js";
13
13
 
14
14
  import type { McpServerStatus, SlashCommand } from "wave-agent-sdk";
15
15
 
16
16
  export const INPUT_PLACEHOLDER_TEXT =
17
- "Type your message (use @ to reference files, / for commands, # to add memory, Ctrl+R to search history)...";
17
+ "Type your message (use /help for more info)...";
18
18
 
19
19
  export const INPUT_PLACEHOLDER_TEXT_PREFIX = INPUT_PLACEHOLDER_TEXT.substring(
20
20
  0,
@@ -25,13 +25,11 @@ export interface InputBoxProps {
25
25
  isLoading?: boolean;
26
26
  isCommandRunning?: boolean;
27
27
  workdir?: string;
28
- userInputHistory?: string[];
29
28
  sendMessage?: (
30
29
  message: string,
31
30
  images?: Array<{ path: string; mimeType: string }>,
32
31
  ) => void;
33
32
  abortMessage?: () => void;
34
- saveMemory?: (message: string, type: "project" | "user") => Promise<void>;
35
33
  // MCP related properties
36
34
  mcpServers?: McpServerStatus[];
37
35
  connectMcpServer?: (serverName: string) => Promise<boolean>;
@@ -44,10 +42,8 @@ export interface InputBoxProps {
44
42
  export const InputBox: React.FC<InputBoxProps> = ({
45
43
  isLoading = false,
46
44
  isCommandRunning = false,
47
- userInputHistory = [],
48
45
  sendMessage = () => {},
49
46
  abortMessage = () => {},
50
- saveMemory = async () => {},
51
47
  mcpServers = [],
52
48
  connectMcpServer = async () => false,
53
49
  disconnectMcpServer = async () => false,
@@ -60,6 +56,7 @@ export const InputBox: React.FC<InputBoxProps> = ({
60
56
  handleRewindSelect,
61
57
  backgroundCurrentTask,
62
58
  messages,
59
+ getFullMessageThread,
63
60
  } = useChat();
64
61
 
65
62
  // Input manager with all input state and functionality (including images)
@@ -83,26 +80,21 @@ export const InputBox: React.FC<InputBoxProps> = ({
83
80
  handleCancelCommandSelect,
84
81
  handleHistorySearchSelect,
85
82
  handleCancelHistorySearch,
86
- // Memory type selector
87
- showMemoryTypeSelector,
88
- memoryMessage,
89
- handleMemoryTypeSelect,
90
- handleCancelMemoryTypeSelect,
91
83
  // History search
92
84
  showHistorySearch,
93
85
  historySearchQuery,
94
86
  // Task/MCP Manager
95
- showTaskManager,
87
+ showBackgroundTaskManager,
96
88
  showMcpManager,
97
89
  showRewindManager,
98
- setShowTaskManager,
90
+ showHelp,
91
+ setShowBackgroundTaskManager,
99
92
  setShowMcpManager,
100
93
  setShowRewindManager,
94
+ setShowHelp,
101
95
  // Permission mode
102
96
  permissionMode,
103
97
  setPermissionMode,
104
- // Input history
105
- setUserInputHistory,
106
98
  // Main handler
107
99
  handleInput,
108
100
  // Manager ready state
@@ -110,7 +102,6 @@ export const InputBox: React.FC<InputBoxProps> = ({
110
102
  } = useInputManager({
111
103
  onSendMessage: sendMessage,
112
104
  onHasSlashCommand: hasSlashCommand,
113
- onSaveMemory: saveMemory,
114
105
  onAbortMessage: abortMessage,
115
106
  onBackgroundCurrentTask: backgroundCurrentTask,
116
107
  onPermissionModeChange: setChatPermissionMode,
@@ -121,11 +112,6 @@ export const InputBox: React.FC<InputBoxProps> = ({
121
112
  setPermissionMode(chatPermissionMode);
122
113
  }, [chatPermissionMode, setPermissionMode]);
123
114
 
124
- // Set user input history when it changes
125
- useEffect(() => {
126
- setUserInputHistory(userInputHistory);
127
- }, [userInputHistory, setUserInputHistory]);
128
-
129
115
  // Use the InputManager's unified input handler
130
116
  useInput(async (input, key) => {
131
117
  await handleInput(
@@ -177,10 +163,15 @@ export const InputBox: React.FC<InputBoxProps> = ({
177
163
  messages={messages}
178
164
  onSelect={handleRewindSelectWithClose}
179
165
  onCancel={handleRewindCancel}
166
+ getFullMessageThread={getFullMessageThread}
180
167
  />
181
168
  );
182
169
  }
183
170
 
171
+ if (showHelp) {
172
+ return <HelpView onCancel={() => setShowHelp(false)} />;
173
+ }
174
+
184
175
  return (
185
176
  <Box flexDirection="column">
186
177
  {showFileSelector && (
@@ -210,18 +201,12 @@ export const InputBox: React.FC<InputBoxProps> = ({
210
201
  />
211
202
  )}
212
203
 
213
- {showMemoryTypeSelector && (
214
- <MemoryTypeSelector
215
- message={memoryMessage}
216
- onSelect={handleMemoryTypeSelect}
217
- onCancel={handleCancelMemoryTypeSelect}
204
+ {showBackgroundTaskManager && (
205
+ <BackgroundTaskManager
206
+ onCancel={() => setShowBackgroundTaskManager(false)}
218
207
  />
219
208
  )}
220
209
 
221
- {showTaskManager && (
222
- <TaskManager onCancel={() => setShowTaskManager(false)} />
223
- )}
224
-
225
210
  {showMcpManager && (
226
211
  <McpManager
227
212
  onCancel={() => setShowMcpManager(false)}
@@ -231,39 +216,42 @@ export const InputBox: React.FC<InputBoxProps> = ({
231
216
  />
232
217
  )}
233
218
 
234
- {showTaskManager || showMcpManager || showRewindManager || (
235
- <Box flexDirection="column">
236
- <Box
237
- borderStyle="single"
238
- borderColor="gray"
239
- borderLeft={false}
240
- borderRight={false}
241
- >
242
- <Text color={isPlaceholder ? "gray" : "white"}>
243
- {shouldShowCursor ? (
244
- <>
245
- {beforeCursor}
246
- <Text backgroundColor="white" color="black">
247
- {atCursor}
248
- </Text>
249
- {afterCursor}
250
- </>
251
- ) : (
252
- displayText
253
- )}
254
- </Text>
219
+ {showBackgroundTaskManager ||
220
+ showMcpManager ||
221
+ showRewindManager ||
222
+ showHelp || (
223
+ <Box flexDirection="column">
224
+ <Box
225
+ borderStyle="single"
226
+ borderColor="gray"
227
+ borderLeft={false}
228
+ borderRight={false}
229
+ >
230
+ <Text color={isPlaceholder ? "gray" : "white"}>
231
+ {shouldShowCursor ? (
232
+ <>
233
+ {beforeCursor}
234
+ <Text backgroundColor="white" color="black">
235
+ {atCursor}
236
+ </Text>
237
+ {afterCursor}
238
+ </>
239
+ ) : (
240
+ displayText
241
+ )}
242
+ </Text>
243
+ </Box>
244
+ <Box paddingRight={1} justifyContent="space-between" width="100%">
245
+ <Text color="gray">
246
+ Mode:{" "}
247
+ <Text color={permissionMode === "plan" ? "yellow" : "cyan"}>
248
+ {permissionMode}
249
+ </Text>{" "}
250
+ (Shift+Tab to cycle)
251
+ </Text>
252
+ </Box>
255
253
  </Box>
256
- <Box paddingRight={1}>
257
- <Text color="gray">
258
- Mode:{" "}
259
- <Text color={permissionMode === "plan" ? "yellow" : "cyan"}>
260
- {permissionMode}
261
- </Text>{" "}
262
- (Shift+Tab to cycle)
263
- </Text>
264
- </Box>
265
- </Box>
266
- )}
254
+ )}
267
255
  </Box>
268
256
  );
269
257
  };
@@ -0,0 +1,56 @@
1
+ import React from "react";
2
+ import { Box, Text } from "ink";
3
+
4
+ export interface LoadingIndicatorProps {
5
+ isLoading?: boolean;
6
+ isCommandRunning?: boolean;
7
+ isCompressing?: boolean;
8
+ latestTotalTokens?: number;
9
+ }
10
+
11
+ export const LoadingIndicator = ({
12
+ isLoading = false,
13
+ isCommandRunning = false,
14
+ isCompressing = false,
15
+ latestTotalTokens = 0,
16
+ }: LoadingIndicatorProps) => {
17
+ return (
18
+ <Box flexDirection="column">
19
+ {isLoading && (
20
+ <Box>
21
+ <Text color="yellow">✻ AI is thinking... </Text>
22
+ {latestTotalTokens > 0 && (
23
+ <>
24
+ <Text color="gray" dimColor>
25
+ |{" "}
26
+ </Text>
27
+ <Text color="blue" bold>
28
+ {latestTotalTokens.toLocaleString()}
29
+ </Text>
30
+ <Text color="gray" dimColor>
31
+ {" "}
32
+ tokens{" "}
33
+ </Text>
34
+ </>
35
+ )}
36
+ <Text color="gray" dimColor>
37
+ |{" "}
38
+ </Text>
39
+ <Text color="red" bold>
40
+ Esc
41
+ </Text>
42
+ <Text color="gray" dimColor>
43
+ {" "}
44
+ to abort
45
+ </Text>
46
+ </Box>
47
+ )}
48
+ {isCommandRunning && <Text color="blue">🚀 Command is running...</Text>}
49
+ {isCompressing && (
50
+ <Text color="magenta">🗜️ Compressing message history...</Text>
51
+ )}
52
+ </Box>
53
+ );
54
+ };
55
+
56
+ LoadingIndicator.displayName = "LoadingIndicator";