wave-code 0.0.3 → 0.0.5
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.
- package/dist/components/InputBox.d.ts.map +1 -1
- package/dist/components/InputBox.js +69 -95
- package/dist/components/MemoryDisplay.js +1 -1
- package/dist/components/MemoryTypeSelector.js +1 -1
- package/dist/components/MessageList.d.ts.map +1 -1
- package/dist/components/MessageList.js +2 -1
- package/dist/components/SubagentBlock.d.ts +1 -1
- package/dist/components/SubagentBlock.d.ts.map +1 -1
- package/dist/components/SubagentBlock.js +12 -2
- package/dist/components/ToolResultDisplay.js +1 -1
- package/dist/contexts/useChat.d.ts +2 -1
- package/dist/contexts/useChat.d.ts.map +1 -1
- package/dist/contexts/useChat.js +18 -0
- package/dist/hooks/useInputManager.d.ts +91 -0
- package/dist/hooks/useInputManager.d.ts.map +1 -0
- package/dist/hooks/useInputManager.js +319 -0
- package/dist/index.js +9 -9
- package/dist/managers/InputManager.d.ts +169 -0
- package/dist/managers/InputManager.d.ts.map +1 -0
- package/dist/managers/InputManager.js +806 -0
- package/dist/print-cli.d.ts +7 -0
- package/dist/print-cli.d.ts.map +1 -0
- package/dist/{plain-cli.js → print-cli.js} +21 -2
- package/dist/utils/constants.d.ts +1 -1
- package/dist/utils/constants.js +1 -1
- package/dist/utils/fileSearch.d.ts +20 -0
- package/dist/utils/fileSearch.d.ts.map +1 -0
- package/dist/utils/fileSearch.js +102 -0
- package/dist/utils/logger.js +3 -3
- package/dist/utils/usageSummary.d.ts +27 -0
- package/dist/utils/usageSummary.d.ts.map +1 -0
- package/dist/utils/usageSummary.js +82 -0
- package/package.json +2 -2
- package/src/components/InputBox.tsx +114 -153
- package/src/components/MemoryDisplay.tsx +1 -1
- package/src/components/MemoryTypeSelector.tsx +1 -1
- package/src/components/MessageList.tsx +14 -10
- package/src/components/SubagentBlock.tsx +14 -3
- package/src/components/ToolResultDisplay.tsx +1 -1
- package/src/contexts/useChat.tsx +23 -0
- package/src/hooks/useInputManager.ts +443 -0
- package/src/index.ts +9 -9
- package/src/managers/InputManager.ts +1102 -0
- package/src/{plain-cli.ts → print-cli.ts} +21 -3
- package/src/utils/constants.ts +1 -1
- package/src/utils/fileSearch.ts +133 -0
- package/src/utils/logger.ts +3 -3
- package/src/utils/usageSummary.ts +125 -0
- package/dist/hooks/useBashHistorySelector.d.ts +0 -15
- package/dist/hooks/useBashHistorySelector.d.ts.map +0 -1
- package/dist/hooks/useBashHistorySelector.js +0 -61
- package/dist/hooks/useCommandSelector.d.ts +0 -24
- package/dist/hooks/useCommandSelector.d.ts.map +0 -1
- package/dist/hooks/useCommandSelector.js +0 -98
- package/dist/hooks/useFileSelector.d.ts +0 -16
- package/dist/hooks/useFileSelector.d.ts.map +0 -1
- package/dist/hooks/useFileSelector.js +0 -174
- package/dist/hooks/useImageManager.d.ts +0 -13
- package/dist/hooks/useImageManager.d.ts.map +0 -1
- package/dist/hooks/useImageManager.js +0 -46
- package/dist/hooks/useInputHistory.d.ts +0 -11
- package/dist/hooks/useInputHistory.d.ts.map +0 -1
- package/dist/hooks/useInputHistory.js +0 -64
- package/dist/hooks/useInputKeyboardHandler.d.ts +0 -83
- package/dist/hooks/useInputKeyboardHandler.d.ts.map +0 -1
- package/dist/hooks/useInputKeyboardHandler.js +0 -507
- package/dist/hooks/useInputState.d.ts +0 -14
- package/dist/hooks/useInputState.d.ts.map +0 -1
- package/dist/hooks/useInputState.js +0 -57
- package/dist/hooks/useMemoryTypeSelector.d.ts +0 -9
- package/dist/hooks/useMemoryTypeSelector.d.ts.map +0 -1
- package/dist/hooks/useMemoryTypeSelector.js +0 -27
- package/dist/plain-cli.d.ts +0 -7
- package/dist/plain-cli.d.ts.map +0 -1
- package/src/hooks/useBashHistorySelector.ts +0 -77
- package/src/hooks/useCommandSelector.ts +0 -131
- package/src/hooks/useFileSelector.ts +0 -227
- package/src/hooks/useImageManager.ts +0 -64
- package/src/hooks/useInputHistory.ts +0 -74
- package/src/hooks/useInputKeyboardHandler.ts +0 -778
- package/src/hooks/useInputState.ts +0 -66
- package/src/hooks/useMemoryTypeSelector.ts +0 -40
|
@@ -1,19 +1,14 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, { useCallback, useEffect } from "react";
|
|
2
2
|
import { Box, Text } from "ink";
|
|
3
|
+
import { useInput } from "ink";
|
|
3
4
|
import { FileSelector } from "./FileSelector.js";
|
|
4
5
|
import { CommandSelector } from "./CommandSelector.js";
|
|
5
6
|
import { BashHistorySelector } from "./BashHistorySelector.js";
|
|
6
7
|
import { MemoryTypeSelector } from "./MemoryTypeSelector.js";
|
|
7
8
|
import { BashShellManager } from "./BashShellManager.js";
|
|
8
9
|
import { McpManager } from "./McpManager.js";
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
import { useCommandSelector } from "../hooks/useCommandSelector.js";
|
|
12
|
-
import { useBashHistorySelector } from "../hooks/useBashHistorySelector.js";
|
|
13
|
-
import { useMemoryTypeSelector } from "../hooks/useMemoryTypeSelector.js";
|
|
14
|
-
import { useInputHistory } from "../hooks/useInputHistory.js";
|
|
15
|
-
import { useInputKeyboardHandler } from "../hooks/useInputKeyboardHandler.js";
|
|
16
|
-
import { useImageManager } from "../hooks/useImageManager.js";
|
|
10
|
+
import { useInputManager } from "../hooks/useInputManager.js";
|
|
11
|
+
|
|
17
12
|
import type { McpServerStatus, SlashCommand } from "wave-agent-sdk";
|
|
18
13
|
|
|
19
14
|
export const INPUT_PLACEHOLDER_TEXT =
|
|
@@ -60,169 +55,137 @@ export const InputBox: React.FC<InputBoxProps> = ({
|
|
|
60
55
|
}) => {
|
|
61
56
|
// Get current working directory
|
|
62
57
|
const currentWorkdir = workdir || process.cwd();
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
58
|
+
|
|
59
|
+
// Simple history navigation reset function
|
|
60
|
+
const resetHistoryNavigation = useCallback(() => {
|
|
61
|
+
// This will be handled by InputManager through callbacks
|
|
62
|
+
}, []);
|
|
63
|
+
|
|
64
|
+
// Input manager with all input state and functionality (including images)
|
|
68
65
|
const {
|
|
69
66
|
inputText,
|
|
70
|
-
setInputText,
|
|
71
67
|
cursorPosition,
|
|
72
|
-
setCursorPosition,
|
|
73
|
-
insertTextAtCursor,
|
|
74
|
-
deleteCharAtCursor,
|
|
75
68
|
clearInput,
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
} = useInputState();
|
|
81
|
-
|
|
82
|
-
// File selector functionality
|
|
83
|
-
const {
|
|
69
|
+
// Image management
|
|
70
|
+
attachedImages,
|
|
71
|
+
clearImages,
|
|
72
|
+
// File selector
|
|
84
73
|
showFileSelector,
|
|
85
74
|
filteredFiles,
|
|
86
|
-
searchQuery,
|
|
87
|
-
activateFileSelector,
|
|
75
|
+
fileSearchQuery: searchQuery,
|
|
88
76
|
handleFileSelect: handleFileSelectorSelect,
|
|
89
77
|
handleCancelFileSelect,
|
|
90
|
-
|
|
91
|
-
checkForAtDeletion,
|
|
92
|
-
atPosition,
|
|
93
|
-
} = useFileSelector();
|
|
94
|
-
|
|
95
|
-
// Command selector functionality
|
|
96
|
-
const {
|
|
78
|
+
// Command selector
|
|
97
79
|
showCommandSelector,
|
|
98
80
|
commandSearchQuery,
|
|
99
|
-
activateCommandSelector,
|
|
100
81
|
handleCommandSelect: handleCommandSelectorSelect,
|
|
101
82
|
handleCommandInsert: handleCommandSelectorInsert,
|
|
102
83
|
handleCancelCommandSelect,
|
|
103
|
-
|
|
104
|
-
checkForSlashDeletion,
|
|
105
|
-
slashPosition,
|
|
106
|
-
} = useCommandSelector({
|
|
107
|
-
onShowBashManager: () => setShowBashManager(true),
|
|
108
|
-
onShowMcpManager: () => setShowMcpManager(true),
|
|
109
|
-
sendMessage: async (content: string) => {
|
|
110
|
-
await sendMessage(content);
|
|
111
|
-
},
|
|
112
|
-
hasSlashCommand,
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
// Bash history selector functionality
|
|
116
|
-
const {
|
|
84
|
+
// Bash history selector
|
|
117
85
|
showBashHistorySelector,
|
|
118
86
|
bashHistorySearchQuery,
|
|
119
|
-
activateBashHistorySelector,
|
|
120
87
|
handleBashHistorySelect: handleBashHistorySelectorSelect,
|
|
121
88
|
handleBashHistoryExecute,
|
|
122
89
|
handleCancelBashHistorySelect,
|
|
123
|
-
|
|
124
|
-
checkForExclamationDeletion,
|
|
125
|
-
exclamationPosition,
|
|
126
|
-
} = useBashHistorySelector();
|
|
127
|
-
|
|
128
|
-
// Memory type selector functionality
|
|
129
|
-
const {
|
|
90
|
+
// Memory type selector
|
|
130
91
|
showMemoryTypeSelector,
|
|
131
92
|
memoryMessage,
|
|
132
|
-
activateMemoryTypeSelector,
|
|
133
93
|
handleMemoryTypeSelect: handleMemoryTypeSelectorSelect,
|
|
134
94
|
handleCancelMemoryTypeSelect,
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
95
|
+
// Bash/MCP Manager
|
|
96
|
+
showBashManager,
|
|
97
|
+
showMcpManager,
|
|
98
|
+
setShowBashManager,
|
|
99
|
+
setShowMcpManager,
|
|
100
|
+
// Input history
|
|
101
|
+
setUserInputHistory,
|
|
102
|
+
// Main handler
|
|
103
|
+
handleInput,
|
|
104
|
+
} = useInputManager({
|
|
105
|
+
onShowBashManager: () => setShowBashManager(true),
|
|
106
|
+
onShowMcpManager: () => setShowMcpManager(true),
|
|
107
|
+
onSendMessage: sendMessage,
|
|
108
|
+
onHasSlashCommand: hasSlashCommand,
|
|
109
|
+
onSaveMemory: saveMemory,
|
|
110
|
+
onAbortMessage: abortMessage,
|
|
111
|
+
onResetHistoryNavigation: resetHistoryNavigation,
|
|
140
112
|
});
|
|
141
113
|
|
|
142
|
-
//
|
|
143
|
-
|
|
144
|
-
|
|
114
|
+
// Set user input history when it changes
|
|
115
|
+
useEffect(() => {
|
|
116
|
+
setUserInputHistory(userInputHistory);
|
|
117
|
+
}, [userInputHistory, setUserInputHistory]);
|
|
145
118
|
|
|
146
|
-
//
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
cursorPosition,
|
|
157
|
-
setCursorPosition,
|
|
158
|
-
moveCursorLeft,
|
|
159
|
-
moveCursorRight,
|
|
160
|
-
moveCursorToStart,
|
|
161
|
-
moveCursorToEnd,
|
|
162
|
-
deleteCharAtCursor,
|
|
163
|
-
insertTextAtCursor,
|
|
164
|
-
clearInput,
|
|
165
|
-
resetHistoryNavigation,
|
|
166
|
-
navigateHistory,
|
|
167
|
-
handlePasteImage,
|
|
168
|
-
attachedImages,
|
|
169
|
-
clearImages,
|
|
170
|
-
showFileSelector,
|
|
171
|
-
activateFileSelector,
|
|
172
|
-
handleFileSelect: handleFileSelectorSelect,
|
|
173
|
-
handleCancelFileSelect,
|
|
174
|
-
updateSearchQuery,
|
|
175
|
-
checkForAtDeletion,
|
|
176
|
-
atPosition,
|
|
177
|
-
showCommandSelector,
|
|
178
|
-
activateCommandSelector,
|
|
179
|
-
handleCommandSelect: handleCommandSelectorSelect,
|
|
180
|
-
handleCommandInsert: handleCommandSelectorInsert,
|
|
181
|
-
handleCancelCommandSelect,
|
|
182
|
-
updateCommandSearchQuery,
|
|
183
|
-
checkForSlashDeletion,
|
|
184
|
-
slashPosition,
|
|
185
|
-
showBashHistorySelector,
|
|
186
|
-
activateBashHistorySelector,
|
|
187
|
-
handleBashHistorySelect: handleBashHistorySelectorSelect,
|
|
188
|
-
handleBashHistoryExecute,
|
|
189
|
-
handleCancelBashHistorySelect,
|
|
190
|
-
updateBashHistorySearchQuery,
|
|
191
|
-
checkForExclamationDeletion,
|
|
192
|
-
exclamationPosition,
|
|
193
|
-
showMemoryTypeSelector,
|
|
194
|
-
activateMemoryTypeSelector,
|
|
195
|
-
handleMemoryTypeSelect: handleMemoryTypeSelectorSelect,
|
|
196
|
-
showBashManager,
|
|
197
|
-
showMcpManager,
|
|
198
|
-
isCommandRunning,
|
|
199
|
-
isLoading,
|
|
200
|
-
sendMessage,
|
|
201
|
-
abortMessage,
|
|
202
|
-
saveMemory,
|
|
119
|
+
// Use the InputManager's unified input handler
|
|
120
|
+
useInput(async (input, key) => {
|
|
121
|
+
await handleInput(
|
|
122
|
+
input,
|
|
123
|
+
key,
|
|
124
|
+
attachedImages,
|
|
125
|
+
isLoading,
|
|
126
|
+
isCommandRunning,
|
|
127
|
+
clearImages,
|
|
128
|
+
);
|
|
203
129
|
});
|
|
204
130
|
|
|
131
|
+
// Handler functions for keyboard events
|
|
132
|
+
const handleFileSelect = useCallback(
|
|
133
|
+
(filePath: string) => {
|
|
134
|
+
handleFileSelectorSelect(filePath);
|
|
135
|
+
},
|
|
136
|
+
[handleFileSelectorSelect],
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
const handleCommandSelect = useCallback(
|
|
140
|
+
(command: string) => {
|
|
141
|
+
handleCommandSelectorSelect(command);
|
|
142
|
+
},
|
|
143
|
+
[handleCommandSelectorSelect],
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
const handleBashHistorySelect = useCallback(
|
|
147
|
+
(command: string) => {
|
|
148
|
+
handleBashHistorySelectorSelect(command);
|
|
149
|
+
},
|
|
150
|
+
[handleBashHistorySelectorSelect],
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
const keyboardHandleBashHistoryExecute = useCallback(
|
|
154
|
+
(command: string) => {
|
|
155
|
+
const commandToExecute = handleBashHistoryExecute(command);
|
|
156
|
+
// Clear input box and execute command, ensure command starts with !
|
|
157
|
+
const bashCommand = commandToExecute.startsWith("!")
|
|
158
|
+
? commandToExecute
|
|
159
|
+
: `!${commandToExecute}`;
|
|
160
|
+
clearInput();
|
|
161
|
+
sendMessage(bashCommand);
|
|
162
|
+
},
|
|
163
|
+
[handleBashHistoryExecute, clearInput, sendMessage],
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
const handleMemoryTypeSelect = useCallback(
|
|
167
|
+
async (type: "project" | "user") => {
|
|
168
|
+
const currentMessage = inputText.trim();
|
|
169
|
+
if (currentMessage.startsWith("#")) {
|
|
170
|
+
await saveMemory(currentMessage, type);
|
|
171
|
+
}
|
|
172
|
+
// Call the handler function to close the selector
|
|
173
|
+
handleMemoryTypeSelectorSelect(type);
|
|
174
|
+
// Clear input box
|
|
175
|
+
clearInput();
|
|
176
|
+
},
|
|
177
|
+
[inputText, saveMemory, handleMemoryTypeSelectorSelect, clearInput],
|
|
178
|
+
);
|
|
179
|
+
|
|
205
180
|
const isPlaceholder = !inputText;
|
|
206
181
|
const placeholderText = INPUT_PLACEHOLDER_TEXT;
|
|
207
182
|
|
|
208
183
|
// Create adapter function for CommandSelector
|
|
209
184
|
const handleCommandInsert = useCallback(
|
|
210
185
|
(command: string) => {
|
|
211
|
-
|
|
212
|
-
command,
|
|
213
|
-
inputText,
|
|
214
|
-
cursorPosition,
|
|
215
|
-
);
|
|
216
|
-
setInputText(result.newInput);
|
|
217
|
-
setCursorPosition(result.newCursorPosition);
|
|
186
|
+
handleCommandSelectorInsert(command);
|
|
218
187
|
},
|
|
219
|
-
[
|
|
220
|
-
handleCommandSelectorInsert,
|
|
221
|
-
inputText,
|
|
222
|
-
cursorPosition,
|
|
223
|
-
setInputText,
|
|
224
|
-
setCursorPosition,
|
|
225
|
-
],
|
|
188
|
+
[handleCommandSelectorInsert],
|
|
226
189
|
);
|
|
227
190
|
|
|
228
191
|
// Split text into three parts: before cursor, cursor position, after cursor
|
|
@@ -288,21 +251,19 @@ export const InputBox: React.FC<InputBoxProps> = ({
|
|
|
288
251
|
)}
|
|
289
252
|
{showBashManager || showMcpManager || (
|
|
290
253
|
<Box borderStyle="single" borderColor="gray" paddingX={1}>
|
|
291
|
-
<
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
</Text>
|
|
305
|
-
</Box>
|
|
254
|
+
<Text color={isPlaceholder ? "gray" : "white"}>
|
|
255
|
+
{shouldShowCursor ? (
|
|
256
|
+
<>
|
|
257
|
+
{beforeCursor}
|
|
258
|
+
<Text backgroundColor="white" color="black">
|
|
259
|
+
{atCursor}
|
|
260
|
+
</Text>
|
|
261
|
+
{afterCursor}
|
|
262
|
+
</>
|
|
263
|
+
) : (
|
|
264
|
+
displayText
|
|
265
|
+
)}
|
|
266
|
+
</Text>
|
|
306
267
|
</Box>
|
|
307
268
|
)}
|
|
308
269
|
</Box>
|
|
@@ -27,7 +27,7 @@ export const MemoryDisplay: React.FC<MemoryDisplayProps> = ({ block }) => {
|
|
|
27
27
|
if (memoryType === "user") {
|
|
28
28
|
return `Memory saved to ${storagePath || "user-memory.md"}`;
|
|
29
29
|
} else {
|
|
30
|
-
return `Memory saved to ${storagePath || "
|
|
30
|
+
return `Memory saved to ${storagePath || "AGENTS.md"}`;
|
|
31
31
|
}
|
|
32
32
|
};
|
|
33
33
|
|
|
@@ -18,7 +18,7 @@ export const MemoryTypeSelector: React.FC<MemoryTypeSelectorProps> = ({
|
|
|
18
18
|
{
|
|
19
19
|
type: "project" as const,
|
|
20
20
|
label: "Project Memory",
|
|
21
|
-
description: "Save to current project (
|
|
21
|
+
description: "Save to current project (AGENTS.md)",
|
|
22
22
|
},
|
|
23
23
|
{
|
|
24
24
|
type: "user" as const,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React, { useMemo } from "react";
|
|
2
2
|
import { Box, Text } from "ink";
|
|
3
3
|
import type { Message } from "wave-agent-sdk";
|
|
4
|
+
import { MessageSource } from "wave-agent-sdk";
|
|
4
5
|
import { DiffViewer } from "./DiffViewer.js";
|
|
5
6
|
import { CommandOutputDisplay } from "./CommandOutputDisplay.js";
|
|
6
7
|
import { ToolResultDisplay } from "./ToolResultDisplay.js";
|
|
@@ -42,7 +43,19 @@ const renderMessageItem = (
|
|
|
42
43
|
<Box key={blockIndex}>
|
|
43
44
|
{block.type === "text" && block.content.trim() && (
|
|
44
45
|
<Box>
|
|
45
|
-
<Text>
|
|
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>
|
|
46
59
|
</Box>
|
|
47
60
|
)}
|
|
48
61
|
|
|
@@ -84,15 +97,6 @@ const renderMessageItem = (
|
|
|
84
97
|
<CompressDisplay block={block} isExpanded={isExpanded} />
|
|
85
98
|
)}
|
|
86
99
|
|
|
87
|
-
{block.type === "custom_command" && (
|
|
88
|
-
<Box>
|
|
89
|
-
<Text color="cyan" bold>
|
|
90
|
-
⚡
|
|
91
|
-
</Text>
|
|
92
|
-
<Text>{block.originalInput || `/${block.commandName}`}</Text>
|
|
93
|
-
</Box>
|
|
94
|
-
)}
|
|
95
|
-
|
|
96
100
|
{block.type === "subagent" && (
|
|
97
101
|
<SubagentBlock block={block} isExpanded={isExpanded} />
|
|
98
102
|
)}
|
|
@@ -4,7 +4,7 @@ import type {
|
|
|
4
4
|
SubagentBlock as SubagentBlockType,
|
|
5
5
|
Message,
|
|
6
6
|
MessageBlock,
|
|
7
|
-
} from "wave-agent-sdk
|
|
7
|
+
} from "wave-agent-sdk";
|
|
8
8
|
import { ToolResultDisplay } from "./ToolResultDisplay.js";
|
|
9
9
|
|
|
10
10
|
// Component to render individual message blocks
|
|
@@ -17,9 +17,20 @@ const MessageBlockRenderer: React.FC<MessageBlockRendererProps> = ({
|
|
|
17
17
|
block,
|
|
18
18
|
isExpanded,
|
|
19
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
|
+
|
|
20
28
|
switch (block.type) {
|
|
21
|
-
case "text":
|
|
22
|
-
|
|
29
|
+
case "text": {
|
|
30
|
+
const maxLines = isExpanded ? 50 : 10;
|
|
31
|
+
const truncatedContent = truncateText(block.content, maxLines);
|
|
32
|
+
return <Text>{truncatedContent}</Text>;
|
|
33
|
+
}
|
|
23
34
|
|
|
24
35
|
case "error":
|
|
25
36
|
return <Text color="red">❌ Error: {block.content}</Text>;
|
package/src/contexts/useChat.tsx
CHANGED
|
@@ -13,9 +13,11 @@ import type {
|
|
|
13
13
|
McpServerStatus,
|
|
14
14
|
BackgroundShell,
|
|
15
15
|
SlashCommand,
|
|
16
|
+
Usage,
|
|
16
17
|
} from "wave-agent-sdk";
|
|
17
18
|
import { Agent, AgentCallbacks } from "wave-agent-sdk";
|
|
18
19
|
import { logger } from "../utils/logger.js";
|
|
20
|
+
import { displayUsageSummary } from "../utils/usageSummary.js";
|
|
19
21
|
|
|
20
22
|
// Main Chat Context
|
|
21
23
|
export interface ChatContextType {
|
|
@@ -49,6 +51,8 @@ export interface ChatContextType {
|
|
|
49
51
|
// Slash Command functionality
|
|
50
52
|
slashCommands: SlashCommand[];
|
|
51
53
|
hasSlashCommand: (commandId: string) => boolean;
|
|
54
|
+
// Usage tracking
|
|
55
|
+
usages: Usage[];
|
|
52
56
|
}
|
|
53
57
|
|
|
54
58
|
const ChatContext = createContext<ChatContextType | null>(null);
|
|
@@ -91,6 +95,9 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({ children }) => {
|
|
|
91
95
|
// Command state
|
|
92
96
|
const [slashCommands, setSlashCommands] = useState<SlashCommand[]>([]);
|
|
93
97
|
|
|
98
|
+
// Usage tracking state
|
|
99
|
+
const [usages, setUsages] = useState<Usage[]>([]);
|
|
100
|
+
|
|
94
101
|
const agentRef = useRef<Agent | null>(null);
|
|
95
102
|
|
|
96
103
|
// Listen for Ctrl+O hotkey to toggle collapse/expand state
|
|
@@ -125,6 +132,9 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({ children }) => {
|
|
|
125
132
|
onShellsChange: (shells) => {
|
|
126
133
|
setBackgroundShells([...shells]);
|
|
127
134
|
},
|
|
135
|
+
onUsagesChange: (newUsages) => {
|
|
136
|
+
setUsages([...newUsages]);
|
|
137
|
+
},
|
|
128
138
|
};
|
|
129
139
|
|
|
130
140
|
try {
|
|
@@ -153,6 +163,9 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({ children }) => {
|
|
|
153
163
|
// Get initial commands
|
|
154
164
|
const agentSlashCommands = agent.getSlashCommands?.() || [];
|
|
155
165
|
setSlashCommands(agentSlashCommands);
|
|
166
|
+
|
|
167
|
+
// Get initial usages
|
|
168
|
+
setUsages(agent.usages);
|
|
156
169
|
} catch (error) {
|
|
157
170
|
console.error("Failed to initialize AI manager:", error);
|
|
158
171
|
}
|
|
@@ -165,6 +178,15 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({ children }) => {
|
|
|
165
178
|
useEffect(() => {
|
|
166
179
|
return () => {
|
|
167
180
|
if (agentRef.current) {
|
|
181
|
+
try {
|
|
182
|
+
// Display usage summary before cleanup
|
|
183
|
+
const usages = agentRef.current.usages;
|
|
184
|
+
const sessionFilePath = agentRef.current.sessionFilePath;
|
|
185
|
+
displayUsageSummary(usages, sessionFilePath);
|
|
186
|
+
} catch {
|
|
187
|
+
// Silently ignore usage summary errors during cleanup
|
|
188
|
+
}
|
|
189
|
+
|
|
168
190
|
agentRef.current.destroy();
|
|
169
191
|
}
|
|
170
192
|
};
|
|
@@ -292,6 +314,7 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({ children }) => {
|
|
|
292
314
|
killBackgroundShell,
|
|
293
315
|
slashCommands,
|
|
294
316
|
hasSlashCommand,
|
|
317
|
+
usages,
|
|
295
318
|
};
|
|
296
319
|
|
|
297
320
|
return (
|