wave-code 0.0.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.
- package/README.md +120 -0
- package/bin/wave-code.js +16 -0
- package/dist/cli.d.ts +6 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +62 -0
- package/dist/components/App.d.ts +8 -0
- package/dist/components/App.d.ts.map +1 -0
- package/dist/components/App.js +10 -0
- package/dist/components/BashHistorySelector.d.ts +10 -0
- package/dist/components/BashHistorySelector.d.ts.map +1 -0
- package/dist/components/BashHistorySelector.js +83 -0
- package/dist/components/BashShellManager.d.ts +6 -0
- package/dist/components/BashShellManager.d.ts.map +1 -0
- package/dist/components/BashShellManager.js +116 -0
- package/dist/components/ChatInterface.d.ts +3 -0
- package/dist/components/ChatInterface.d.ts.map +1 -0
- package/dist/components/ChatInterface.js +31 -0
- package/dist/components/CommandOutputDisplay.d.ts +9 -0
- package/dist/components/CommandOutputDisplay.d.ts.map +1 -0
- package/dist/components/CommandOutputDisplay.js +40 -0
- package/dist/components/CommandSelector.d.ts +11 -0
- package/dist/components/CommandSelector.d.ts.map +1 -0
- package/dist/components/CommandSelector.js +60 -0
- package/dist/components/CompressDisplay.d.ts +9 -0
- package/dist/components/CompressDisplay.d.ts.map +1 -0
- package/dist/components/CompressDisplay.js +17 -0
- package/dist/components/DiffViewer.d.ts +9 -0
- package/dist/components/DiffViewer.d.ts.map +1 -0
- package/dist/components/DiffViewer.js +221 -0
- package/dist/components/FileSelector.d.ts +13 -0
- package/dist/components/FileSelector.d.ts.map +1 -0
- package/dist/components/FileSelector.js +48 -0
- package/dist/components/InputBox.d.ts +23 -0
- package/dist/components/InputBox.d.ts.map +1 -0
- package/dist/components/InputBox.js +124 -0
- package/dist/components/McpManager.d.ts +10 -0
- package/dist/components/McpManager.d.ts.map +1 -0
- package/dist/components/McpManager.js +123 -0
- package/dist/components/MemoryDisplay.d.ts +8 -0
- package/dist/components/MemoryDisplay.d.ts.map +1 -0
- package/dist/components/MemoryDisplay.js +25 -0
- package/dist/components/MemoryTypeSelector.d.ts +8 -0
- package/dist/components/MemoryTypeSelector.d.ts.map +1 -0
- package/dist/components/MemoryTypeSelector.js +38 -0
- package/dist/components/MessageList.d.ts +12 -0
- package/dist/components/MessageList.d.ts.map +1 -0
- package/dist/components/MessageList.js +36 -0
- package/dist/components/ToolResultDisplay.d.ts +9 -0
- package/dist/components/ToolResultDisplay.d.ts.map +1 -0
- package/dist/components/ToolResultDisplay.js +52 -0
- package/dist/contexts/useAppConfig.d.ts +11 -0
- package/dist/contexts/useAppConfig.d.ts.map +1 -0
- package/dist/contexts/useAppConfig.js +13 -0
- package/dist/contexts/useChat.d.ts +36 -0
- package/dist/contexts/useChat.d.ts.map +1 -0
- package/dist/contexts/useChat.js +208 -0
- package/dist/hooks/useBashHistorySelector.d.ts +15 -0
- package/dist/hooks/useBashHistorySelector.d.ts.map +1 -0
- package/dist/hooks/useBashHistorySelector.js +61 -0
- package/dist/hooks/useCommandSelector.d.ts +24 -0
- package/dist/hooks/useCommandSelector.d.ts.map +1 -0
- package/dist/hooks/useCommandSelector.js +98 -0
- package/dist/hooks/useFileSelector.d.ts +16 -0
- package/dist/hooks/useFileSelector.d.ts.map +1 -0
- package/dist/hooks/useFileSelector.js +174 -0
- package/dist/hooks/useImageManager.d.ts +13 -0
- package/dist/hooks/useImageManager.d.ts.map +1 -0
- package/dist/hooks/useImageManager.js +46 -0
- package/dist/hooks/useInputHistory.d.ts +11 -0
- package/dist/hooks/useInputHistory.d.ts.map +1 -0
- package/dist/hooks/useInputHistory.js +64 -0
- package/dist/hooks/useInputKeyboardHandler.d.ts +83 -0
- package/dist/hooks/useInputKeyboardHandler.d.ts.map +1 -0
- package/dist/hooks/useInputKeyboardHandler.js +507 -0
- package/dist/hooks/useInputState.d.ts +14 -0
- package/dist/hooks/useInputState.d.ts.map +1 -0
- package/dist/hooks/useInputState.js +57 -0
- package/dist/hooks/useMemoryTypeSelector.d.ts +9 -0
- package/dist/hooks/useMemoryTypeSelector.d.ts.map +1 -0
- package/dist/hooks/useMemoryTypeSelector.js +27 -0
- package/dist/hooks/usePagination.d.ts +20 -0
- package/dist/hooks/usePagination.d.ts.map +1 -0
- package/dist/hooks/usePagination.js +168 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +91 -0
- package/dist/plain-cli.d.ts +7 -0
- package/dist/plain-cli.d.ts.map +1 -0
- package/dist/plain-cli.js +49 -0
- package/dist/utils/clipboard.d.ts +22 -0
- package/dist/utils/clipboard.d.ts.map +1 -0
- package/dist/utils/clipboard.js +347 -0
- package/dist/utils/constants.d.ts +17 -0
- package/dist/utils/constants.d.ts.map +1 -0
- package/dist/utils/constants.js +18 -0
- package/dist/utils/logger.d.ts +72 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +245 -0
- package/package.json +60 -0
- package/src/cli.tsx +82 -0
- package/src/components/App.tsx +31 -0
- package/src/components/BashHistorySelector.tsx +163 -0
- package/src/components/BashShellManager.tsx +306 -0
- package/src/components/ChatInterface.tsx +88 -0
- package/src/components/CommandOutputDisplay.tsx +81 -0
- package/src/components/CommandSelector.tsx +144 -0
- package/src/components/CompressDisplay.tsx +58 -0
- package/src/components/DiffViewer.tsx +321 -0
- package/src/components/FileSelector.tsx +137 -0
- package/src/components/InputBox.tsx +310 -0
- package/src/components/McpManager.tsx +328 -0
- package/src/components/MemoryDisplay.tsx +62 -0
- package/src/components/MemoryTypeSelector.tsx +96 -0
- package/src/components/MessageList.tsx +215 -0
- package/src/components/ToolResultDisplay.tsx +138 -0
- package/src/contexts/useAppConfig.tsx +32 -0
- package/src/contexts/useChat.tsx +300 -0
- package/src/hooks/useBashHistorySelector.ts +77 -0
- package/src/hooks/useCommandSelector.ts +131 -0
- package/src/hooks/useFileSelector.ts +227 -0
- package/src/hooks/useImageManager.ts +64 -0
- package/src/hooks/useInputHistory.ts +74 -0
- package/src/hooks/useInputKeyboardHandler.ts +778 -0
- package/src/hooks/useInputState.ts +66 -0
- package/src/hooks/useMemoryTypeSelector.ts +40 -0
- package/src/hooks/usePagination.ts +203 -0
- package/src/index.ts +108 -0
- package/src/plain-cli.ts +66 -0
- package/src/utils/clipboard.ts +384 -0
- package/src/utils/constants.ts +22 -0
- package/src/utils/logger.ts +301 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { useState, useCallback } from "react";
|
|
2
|
+
|
|
3
|
+
export const useInputState = () => {
|
|
4
|
+
const [inputText, setInputText] = useState("");
|
|
5
|
+
const [cursorPosition, setCursorPosition] = useState(0);
|
|
6
|
+
|
|
7
|
+
const insertTextAtCursor = useCallback((text: string) => {
|
|
8
|
+
setCursorPosition((currentCursor) => {
|
|
9
|
+
setInputText((currentText) => {
|
|
10
|
+
const beforeCursor = currentText.substring(0, currentCursor);
|
|
11
|
+
const afterCursor = currentText.substring(currentCursor);
|
|
12
|
+
return beforeCursor + text + afterCursor;
|
|
13
|
+
});
|
|
14
|
+
return currentCursor + text.length;
|
|
15
|
+
});
|
|
16
|
+
}, []);
|
|
17
|
+
|
|
18
|
+
const deleteCharAtCursor = useCallback(() => {
|
|
19
|
+
setCursorPosition((currentCursor) => {
|
|
20
|
+
if (currentCursor > 0) {
|
|
21
|
+
setInputText((currentText) => {
|
|
22
|
+
const beforeCursor = currentText.substring(0, currentCursor - 1);
|
|
23
|
+
const afterCursor = currentText.substring(currentCursor);
|
|
24
|
+
return beforeCursor + afterCursor;
|
|
25
|
+
});
|
|
26
|
+
return currentCursor - 1;
|
|
27
|
+
}
|
|
28
|
+
return currentCursor;
|
|
29
|
+
});
|
|
30
|
+
}, []);
|
|
31
|
+
|
|
32
|
+
const clearInput = useCallback(() => {
|
|
33
|
+
setInputText("");
|
|
34
|
+
setCursorPosition(0);
|
|
35
|
+
}, []);
|
|
36
|
+
|
|
37
|
+
const moveCursorLeft = useCallback(() => {
|
|
38
|
+
setCursorPosition((current) => Math.max(0, current - 1));
|
|
39
|
+
}, []);
|
|
40
|
+
|
|
41
|
+
const moveCursorRight = useCallback(() => {
|
|
42
|
+
setCursorPosition((current) => Math.min(inputText.length, current + 1));
|
|
43
|
+
}, [inputText.length]);
|
|
44
|
+
|
|
45
|
+
const moveCursorToStart = useCallback(() => {
|
|
46
|
+
setCursorPosition(0);
|
|
47
|
+
}, []);
|
|
48
|
+
|
|
49
|
+
const moveCursorToEnd = useCallback(() => {
|
|
50
|
+
setCursorPosition(inputText.length);
|
|
51
|
+
}, [inputText.length]);
|
|
52
|
+
|
|
53
|
+
return {
|
|
54
|
+
inputText,
|
|
55
|
+
setInputText,
|
|
56
|
+
cursorPosition,
|
|
57
|
+
setCursorPosition,
|
|
58
|
+
insertTextAtCursor,
|
|
59
|
+
deleteCharAtCursor,
|
|
60
|
+
clearInput,
|
|
61
|
+
moveCursorLeft,
|
|
62
|
+
moveCursorRight,
|
|
63
|
+
moveCursorToStart,
|
|
64
|
+
moveCursorToEnd,
|
|
65
|
+
};
|
|
66
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
|
|
3
|
+
export interface UseMemoryTypeSelectorReturn {
|
|
4
|
+
showMemoryTypeSelector: boolean;
|
|
5
|
+
memoryMessage: string;
|
|
6
|
+
activateMemoryTypeSelector: (message: string) => void;
|
|
7
|
+
handleMemoryTypeSelect: (type: "project" | "user") => void;
|
|
8
|
+
handleCancelMemoryTypeSelect: () => void;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const useMemoryTypeSelector = (): UseMemoryTypeSelectorReturn => {
|
|
12
|
+
const [showMemoryTypeSelector, setShowMemoryTypeSelector] = useState(false);
|
|
13
|
+
const [memoryMessage, setMemoryMessage] = useState("");
|
|
14
|
+
|
|
15
|
+
const activateMemoryTypeSelector = (message: string) => {
|
|
16
|
+
setMemoryMessage(message);
|
|
17
|
+
setShowMemoryTypeSelector(true);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const handleMemoryTypeSelect = (type: "project" | "user"): void => {
|
|
21
|
+
setShowMemoryTypeSelector(false);
|
|
22
|
+
setMemoryMessage("");
|
|
23
|
+
// Type parameter is passed by external component, here only responsible for closing selector
|
|
24
|
+
// Actual type handling is completed in useInputKeyboardHandler
|
|
25
|
+
void type; // Explicitly mark parameter as known but unused
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const handleCancelMemoryTypeSelect = () => {
|
|
29
|
+
setShowMemoryTypeSelector(false);
|
|
30
|
+
setMemoryMessage("");
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
return {
|
|
34
|
+
showMemoryTypeSelector,
|
|
35
|
+
memoryMessage,
|
|
36
|
+
activateMemoryTypeSelector,
|
|
37
|
+
handleMemoryTypeSelect,
|
|
38
|
+
handleCancelMemoryTypeSelect,
|
|
39
|
+
};
|
|
40
|
+
};
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { useState, useEffect, useMemo } from "react";
|
|
2
|
+
import { useInput } from "ink";
|
|
3
|
+
import type { Message } from "wave-agent-sdk";
|
|
4
|
+
import { MESSAGES_PER_PAGE } from "../utils/constants.js";
|
|
5
|
+
|
|
6
|
+
interface PaginationInfo {
|
|
7
|
+
currentPage: number;
|
|
8
|
+
totalPages: number;
|
|
9
|
+
startIndex: number;
|
|
10
|
+
endIndex: number;
|
|
11
|
+
messagesPerPage: number;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const usePagination = (messages: Message[]) => {
|
|
15
|
+
const messagesPerPage = MESSAGES_PER_PAGE;
|
|
16
|
+
|
|
17
|
+
// Calculate pagination info, ensuring first page can be incomplete while subsequent pages are complete
|
|
18
|
+
const paginationInfo = useMemo((): PaginationInfo => {
|
|
19
|
+
if (messages.length <= messagesPerPage) {
|
|
20
|
+
// If total messages don't exceed one page, display all messages directly
|
|
21
|
+
return {
|
|
22
|
+
currentPage: 1,
|
|
23
|
+
totalPages: 1,
|
|
24
|
+
startIndex: 0,
|
|
25
|
+
endIndex: messages.length,
|
|
26
|
+
messagesPerPage,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Calculate remaining messages (messages other than the first page)
|
|
31
|
+
const remainingMessages = messages.length % messagesPerPage;
|
|
32
|
+
|
|
33
|
+
if (remainingMessages === 0) {
|
|
34
|
+
// Message count fits perfectly into complete pages, use standard pagination
|
|
35
|
+
const totalPages = Math.ceil(messages.length / messagesPerPage);
|
|
36
|
+
const currentPage = totalPages;
|
|
37
|
+
const startIndex = (currentPage - 1) * messagesPerPage;
|
|
38
|
+
const endIndex = messages.length;
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
currentPage,
|
|
42
|
+
totalPages,
|
|
43
|
+
startIndex,
|
|
44
|
+
endIndex,
|
|
45
|
+
messagesPerPage,
|
|
46
|
+
};
|
|
47
|
+
} else {
|
|
48
|
+
// Has remaining messages, let first page display remaining messages, subsequent pages are complete
|
|
49
|
+
const firstPageMessageCount = remainingMessages;
|
|
50
|
+
const totalPages = Math.floor(messages.length / messagesPerPage) + 1;
|
|
51
|
+
|
|
52
|
+
// Default to showing the last page (complete page)
|
|
53
|
+
const currentPage = totalPages;
|
|
54
|
+
const startIndex =
|
|
55
|
+
firstPageMessageCount + (currentPage - 2) * messagesPerPage;
|
|
56
|
+
const endIndex = messages.length;
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
currentPage,
|
|
60
|
+
totalPages,
|
|
61
|
+
startIndex,
|
|
62
|
+
endIndex,
|
|
63
|
+
messagesPerPage,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
}, [messages.length, messagesPerPage]);
|
|
67
|
+
|
|
68
|
+
// Manually controlled current page (for keyboard navigation)
|
|
69
|
+
const [manualPage, setManualPage] = useState<number | null>(null);
|
|
70
|
+
|
|
71
|
+
// Calculate actual display page info
|
|
72
|
+
const displayInfo = useMemo((): PaginationInfo => {
|
|
73
|
+
if (manualPage === null) {
|
|
74
|
+
return paginationInfo; // Auto mode: display last page
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Manual mode: display user-selected page
|
|
78
|
+
const totalPages = paginationInfo.totalPages;
|
|
79
|
+
const currentPage = Math.min(Math.max(1, manualPage), totalPages);
|
|
80
|
+
|
|
81
|
+
if (messages.length <= messagesPerPage) {
|
|
82
|
+
// Only one page case
|
|
83
|
+
return {
|
|
84
|
+
currentPage,
|
|
85
|
+
totalPages,
|
|
86
|
+
startIndex: 0,
|
|
87
|
+
endIndex: messages.length,
|
|
88
|
+
messagesPerPage,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const remainingMessages = messages.length % messagesPerPage;
|
|
93
|
+
|
|
94
|
+
if (remainingMessages === 0) {
|
|
95
|
+
// Message count fits perfectly into complete pages
|
|
96
|
+
const startIndex = (currentPage - 1) * messagesPerPage;
|
|
97
|
+
const endIndex = Math.min(startIndex + messagesPerPage, messages.length);
|
|
98
|
+
|
|
99
|
+
return {
|
|
100
|
+
currentPage,
|
|
101
|
+
totalPages,
|
|
102
|
+
startIndex,
|
|
103
|
+
endIndex,
|
|
104
|
+
messagesPerPage,
|
|
105
|
+
};
|
|
106
|
+
} else {
|
|
107
|
+
// First page incomplete, subsequent pages complete
|
|
108
|
+
if (currentPage === 1) {
|
|
109
|
+
// First page: display remaining message count
|
|
110
|
+
return {
|
|
111
|
+
currentPage,
|
|
112
|
+
totalPages,
|
|
113
|
+
startIndex: 0,
|
|
114
|
+
endIndex: remainingMessages,
|
|
115
|
+
messagesPerPage,
|
|
116
|
+
};
|
|
117
|
+
} else {
|
|
118
|
+
// Other pages: display complete message count per page
|
|
119
|
+
const firstPageMessageCount = remainingMessages;
|
|
120
|
+
const startIndex =
|
|
121
|
+
firstPageMessageCount + (currentPage - 2) * messagesPerPage;
|
|
122
|
+
const endIndex = Math.min(
|
|
123
|
+
startIndex + messagesPerPage,
|
|
124
|
+
messages.length,
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
return {
|
|
128
|
+
currentPage,
|
|
129
|
+
totalPages,
|
|
130
|
+
startIndex,
|
|
131
|
+
endIndex,
|
|
132
|
+
messagesPerPage,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}, [messages.length, messagesPerPage, manualPage, paginationInfo]);
|
|
137
|
+
|
|
138
|
+
// When message count changes, if user hasn't manually navigated, reset to auto mode
|
|
139
|
+
useEffect(() => {
|
|
140
|
+
if (manualPage !== null) {
|
|
141
|
+
// If user is currently on the last page, keep auto mode
|
|
142
|
+
const totalPages = Math.ceil(messages.length / messagesPerPage);
|
|
143
|
+
if (manualPage >= totalPages) {
|
|
144
|
+
setManualPage(null);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}, [messages.length, messagesPerPage, manualPage]);
|
|
148
|
+
|
|
149
|
+
// Pagination functionality
|
|
150
|
+
const goToPage = (page: number | null) => {
|
|
151
|
+
setManualPage(page);
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
const goToPrevPage = () => {
|
|
155
|
+
const currentPage = manualPage ?? displayInfo.currentPage;
|
|
156
|
+
setManualPage(Math.max(1, currentPage - 1));
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
const goToNextPage = () => {
|
|
160
|
+
const currentPage = manualPage ?? displayInfo.currentPage;
|
|
161
|
+
setManualPage(Math.min(displayInfo.totalPages, currentPage + 1));
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
const goToFirstPage = () => {
|
|
165
|
+
setManualPage(1);
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
const goToLastPage = () => {
|
|
169
|
+
setManualPage(null); // Return to auto mode (last page)
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
// Integrate keyboard shortcut handling
|
|
173
|
+
useInput((input, key) => {
|
|
174
|
+
// Ctrl+U/D shortcuts (Vim/Less style)
|
|
175
|
+
if (key.ctrl) {
|
|
176
|
+
if (input === "u") {
|
|
177
|
+
goToPrevPage();
|
|
178
|
+
} else if (input === "d") {
|
|
179
|
+
goToNextPage();
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Page Up/Down support
|
|
184
|
+
if (key.pageUp) {
|
|
185
|
+
goToPrevPage();
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (key.pageDown) {
|
|
189
|
+
goToNextPage();
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
return {
|
|
194
|
+
displayInfo,
|
|
195
|
+
manualPage,
|
|
196
|
+
setManualPage,
|
|
197
|
+
goToPage,
|
|
198
|
+
goToPrevPage,
|
|
199
|
+
goToNextPage,
|
|
200
|
+
goToFirstPage,
|
|
201
|
+
goToLastPage,
|
|
202
|
+
};
|
|
203
|
+
};
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import yargs from "yargs";
|
|
2
|
+
import { hideBin } from "yargs/helpers";
|
|
3
|
+
import { startCli } from "./cli.js";
|
|
4
|
+
import { listSessions } from "wave-agent-sdk";
|
|
5
|
+
|
|
6
|
+
// Export main function for external use
|
|
7
|
+
export async function main() {
|
|
8
|
+
const argv = await yargs(hideBin(process.argv))
|
|
9
|
+
.option("restore", {
|
|
10
|
+
alias: "r",
|
|
11
|
+
description: "Restore session by ID",
|
|
12
|
+
type: "string",
|
|
13
|
+
})
|
|
14
|
+
.option("continue", {
|
|
15
|
+
alias: "c",
|
|
16
|
+
description: "Continue from last session",
|
|
17
|
+
type: "boolean",
|
|
18
|
+
})
|
|
19
|
+
.option("plain", {
|
|
20
|
+
alias: "p",
|
|
21
|
+
description: "Plain mode with message to send",
|
|
22
|
+
type: "string",
|
|
23
|
+
})
|
|
24
|
+
.option("list-sessions", {
|
|
25
|
+
description: "List all available sessions",
|
|
26
|
+
type: "boolean",
|
|
27
|
+
})
|
|
28
|
+
.version()
|
|
29
|
+
.alias("v", "version")
|
|
30
|
+
.example("$0", "Start CLI with default settings")
|
|
31
|
+
.example("$0 --restore session_123", "Restore specific session")
|
|
32
|
+
.example("$0 --continue", "Continue from last session")
|
|
33
|
+
.example("$0 --plain 'Hello'", "Send message in plain mode")
|
|
34
|
+
.example("$0 -p 'Hello'", "Send message in plain mode (short)")
|
|
35
|
+
.example("$0 --list-sessions", "List all available sessions")
|
|
36
|
+
.help("h")
|
|
37
|
+
.parseAsync();
|
|
38
|
+
|
|
39
|
+
// Handle list sessions command
|
|
40
|
+
if (argv.listSessions) {
|
|
41
|
+
try {
|
|
42
|
+
const currentWorkdir = process.cwd();
|
|
43
|
+
const sessions = await listSessions(currentWorkdir);
|
|
44
|
+
|
|
45
|
+
if (sessions.length === 0) {
|
|
46
|
+
console.log(`No sessions found for workdir: ${currentWorkdir}`);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
console.log(`Available sessions for: ${currentWorkdir}`);
|
|
51
|
+
console.log("==========================================");
|
|
52
|
+
|
|
53
|
+
for (const session of sessions) {
|
|
54
|
+
const startedAt = new Date(session.startedAt).toLocaleString();
|
|
55
|
+
const lastActiveAt = new Date(session.lastActiveAt).toLocaleString();
|
|
56
|
+
|
|
57
|
+
console.log(`ID: ${session.id}`);
|
|
58
|
+
console.log(` Workdir: ${session.workdir}`);
|
|
59
|
+
console.log(` Started: ${startedAt}`);
|
|
60
|
+
console.log(` Last Active: ${lastActiveAt}`);
|
|
61
|
+
console.log(` Last Message Tokens: ${session.latestTotalTokens}`);
|
|
62
|
+
console.log("");
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return;
|
|
66
|
+
} catch (error) {
|
|
67
|
+
console.error("Failed to list sessions:", error);
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Handle plain mode directly
|
|
73
|
+
if (argv.plain !== undefined) {
|
|
74
|
+
const { startPlainCli } = await import("./plain-cli.js");
|
|
75
|
+
return startPlainCli({
|
|
76
|
+
restoreSessionId: argv.restore,
|
|
77
|
+
continueLastSession: argv.continue,
|
|
78
|
+
message: argv.plain,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
await startCli({
|
|
83
|
+
restoreSessionId: argv.restore,
|
|
84
|
+
continueLastSession: argv.continue,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Export CLI function
|
|
89
|
+
export { startCli } from "./cli.js";
|
|
90
|
+
|
|
91
|
+
// Export logger
|
|
92
|
+
export { logger } from "./utils/logger.js";
|
|
93
|
+
|
|
94
|
+
// Export clipboard utilities
|
|
95
|
+
export {
|
|
96
|
+
readClipboardImage,
|
|
97
|
+
cleanupTempImage,
|
|
98
|
+
hasClipboardImage,
|
|
99
|
+
type ClipboardImageResult,
|
|
100
|
+
} from "./utils/clipboard.js";
|
|
101
|
+
|
|
102
|
+
// Execute main function if this file is run directly
|
|
103
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
104
|
+
main().catch((error) => {
|
|
105
|
+
console.error("Failed to start WAVE Code:", error);
|
|
106
|
+
process.exit(1);
|
|
107
|
+
});
|
|
108
|
+
}
|
package/src/plain-cli.ts
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { Agent, AgentCallbacks } from "wave-agent-sdk";
|
|
2
|
+
import { logger } from "./utils/logger.js";
|
|
3
|
+
|
|
4
|
+
export interface PlainCliOptions {
|
|
5
|
+
restoreSessionId?: string;
|
|
6
|
+
continueLastSession?: boolean;
|
|
7
|
+
message?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export async function startPlainCli(options: PlainCliOptions): Promise<void> {
|
|
11
|
+
const { restoreSessionId, continueLastSession, message } = options;
|
|
12
|
+
|
|
13
|
+
if (
|
|
14
|
+
(!message || message.trim() === "") &&
|
|
15
|
+
!continueLastSession &&
|
|
16
|
+
!restoreSessionId
|
|
17
|
+
) {
|
|
18
|
+
console.error(
|
|
19
|
+
"Plain mode requires a message: use --plain 'your message' or -p 'your message'",
|
|
20
|
+
);
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
let agent: Agent;
|
|
25
|
+
let lastAssistantMessage: string | undefined;
|
|
26
|
+
|
|
27
|
+
// Setup callbacks for agent
|
|
28
|
+
const callbacks: AgentCallbacks = {
|
|
29
|
+
onAssistantMessageAdded: (content?: string) => {
|
|
30
|
+
// Store the content instead of immediately printing it
|
|
31
|
+
if (content) {
|
|
32
|
+
lastAssistantMessage = content;
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
try {
|
|
38
|
+
// Initialize agent
|
|
39
|
+
agent = await Agent.create({
|
|
40
|
+
callbacks,
|
|
41
|
+
restoreSessionId,
|
|
42
|
+
continueLastSession,
|
|
43
|
+
logger,
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// Send message if provided and not empty
|
|
47
|
+
if (message && message.trim() !== "") {
|
|
48
|
+
await agent.sendMessage(message);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Output only the last assistant message
|
|
52
|
+
if (lastAssistantMessage) {
|
|
53
|
+
console.log(lastAssistantMessage);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Destroy agent and exit after sendMessage completes
|
|
57
|
+
agent.destroy();
|
|
58
|
+
process.exit(0);
|
|
59
|
+
} catch (error) {
|
|
60
|
+
console.error("Failed to send message:", error);
|
|
61
|
+
if (agent!) {
|
|
62
|
+
agent.destroy();
|
|
63
|
+
}
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
66
|
+
}
|