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.
Files changed (131) hide show
  1. package/README.md +120 -0
  2. package/bin/wave-code.js +16 -0
  3. package/dist/cli.d.ts +6 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +62 -0
  6. package/dist/components/App.d.ts +8 -0
  7. package/dist/components/App.d.ts.map +1 -0
  8. package/dist/components/App.js +10 -0
  9. package/dist/components/BashHistorySelector.d.ts +10 -0
  10. package/dist/components/BashHistorySelector.d.ts.map +1 -0
  11. package/dist/components/BashHistorySelector.js +83 -0
  12. package/dist/components/BashShellManager.d.ts +6 -0
  13. package/dist/components/BashShellManager.d.ts.map +1 -0
  14. package/dist/components/BashShellManager.js +116 -0
  15. package/dist/components/ChatInterface.d.ts +3 -0
  16. package/dist/components/ChatInterface.d.ts.map +1 -0
  17. package/dist/components/ChatInterface.js +31 -0
  18. package/dist/components/CommandOutputDisplay.d.ts +9 -0
  19. package/dist/components/CommandOutputDisplay.d.ts.map +1 -0
  20. package/dist/components/CommandOutputDisplay.js +40 -0
  21. package/dist/components/CommandSelector.d.ts +11 -0
  22. package/dist/components/CommandSelector.d.ts.map +1 -0
  23. package/dist/components/CommandSelector.js +60 -0
  24. package/dist/components/CompressDisplay.d.ts +9 -0
  25. package/dist/components/CompressDisplay.d.ts.map +1 -0
  26. package/dist/components/CompressDisplay.js +17 -0
  27. package/dist/components/DiffViewer.d.ts +9 -0
  28. package/dist/components/DiffViewer.d.ts.map +1 -0
  29. package/dist/components/DiffViewer.js +221 -0
  30. package/dist/components/FileSelector.d.ts +13 -0
  31. package/dist/components/FileSelector.d.ts.map +1 -0
  32. package/dist/components/FileSelector.js +48 -0
  33. package/dist/components/InputBox.d.ts +23 -0
  34. package/dist/components/InputBox.d.ts.map +1 -0
  35. package/dist/components/InputBox.js +124 -0
  36. package/dist/components/McpManager.d.ts +10 -0
  37. package/dist/components/McpManager.d.ts.map +1 -0
  38. package/dist/components/McpManager.js +123 -0
  39. package/dist/components/MemoryDisplay.d.ts +8 -0
  40. package/dist/components/MemoryDisplay.d.ts.map +1 -0
  41. package/dist/components/MemoryDisplay.js +25 -0
  42. package/dist/components/MemoryTypeSelector.d.ts +8 -0
  43. package/dist/components/MemoryTypeSelector.d.ts.map +1 -0
  44. package/dist/components/MemoryTypeSelector.js +38 -0
  45. package/dist/components/MessageList.d.ts +12 -0
  46. package/dist/components/MessageList.d.ts.map +1 -0
  47. package/dist/components/MessageList.js +36 -0
  48. package/dist/components/ToolResultDisplay.d.ts +9 -0
  49. package/dist/components/ToolResultDisplay.d.ts.map +1 -0
  50. package/dist/components/ToolResultDisplay.js +52 -0
  51. package/dist/contexts/useAppConfig.d.ts +11 -0
  52. package/dist/contexts/useAppConfig.d.ts.map +1 -0
  53. package/dist/contexts/useAppConfig.js +13 -0
  54. package/dist/contexts/useChat.d.ts +36 -0
  55. package/dist/contexts/useChat.d.ts.map +1 -0
  56. package/dist/contexts/useChat.js +208 -0
  57. package/dist/hooks/useBashHistorySelector.d.ts +15 -0
  58. package/dist/hooks/useBashHistorySelector.d.ts.map +1 -0
  59. package/dist/hooks/useBashHistorySelector.js +61 -0
  60. package/dist/hooks/useCommandSelector.d.ts +24 -0
  61. package/dist/hooks/useCommandSelector.d.ts.map +1 -0
  62. package/dist/hooks/useCommandSelector.js +98 -0
  63. package/dist/hooks/useFileSelector.d.ts +16 -0
  64. package/dist/hooks/useFileSelector.d.ts.map +1 -0
  65. package/dist/hooks/useFileSelector.js +174 -0
  66. package/dist/hooks/useImageManager.d.ts +13 -0
  67. package/dist/hooks/useImageManager.d.ts.map +1 -0
  68. package/dist/hooks/useImageManager.js +46 -0
  69. package/dist/hooks/useInputHistory.d.ts +11 -0
  70. package/dist/hooks/useInputHistory.d.ts.map +1 -0
  71. package/dist/hooks/useInputHistory.js +64 -0
  72. package/dist/hooks/useInputKeyboardHandler.d.ts +83 -0
  73. package/dist/hooks/useInputKeyboardHandler.d.ts.map +1 -0
  74. package/dist/hooks/useInputKeyboardHandler.js +507 -0
  75. package/dist/hooks/useInputState.d.ts +14 -0
  76. package/dist/hooks/useInputState.d.ts.map +1 -0
  77. package/dist/hooks/useInputState.js +57 -0
  78. package/dist/hooks/useMemoryTypeSelector.d.ts +9 -0
  79. package/dist/hooks/useMemoryTypeSelector.d.ts.map +1 -0
  80. package/dist/hooks/useMemoryTypeSelector.js +27 -0
  81. package/dist/hooks/usePagination.d.ts +20 -0
  82. package/dist/hooks/usePagination.d.ts.map +1 -0
  83. package/dist/hooks/usePagination.js +168 -0
  84. package/dist/index.d.ts +5 -0
  85. package/dist/index.d.ts.map +1 -0
  86. package/dist/index.js +91 -0
  87. package/dist/plain-cli.d.ts +7 -0
  88. package/dist/plain-cli.d.ts.map +1 -0
  89. package/dist/plain-cli.js +49 -0
  90. package/dist/utils/clipboard.d.ts +22 -0
  91. package/dist/utils/clipboard.d.ts.map +1 -0
  92. package/dist/utils/clipboard.js +347 -0
  93. package/dist/utils/constants.d.ts +17 -0
  94. package/dist/utils/constants.d.ts.map +1 -0
  95. package/dist/utils/constants.js +18 -0
  96. package/dist/utils/logger.d.ts +72 -0
  97. package/dist/utils/logger.d.ts.map +1 -0
  98. package/dist/utils/logger.js +245 -0
  99. package/package.json +60 -0
  100. package/src/cli.tsx +82 -0
  101. package/src/components/App.tsx +31 -0
  102. package/src/components/BashHistorySelector.tsx +163 -0
  103. package/src/components/BashShellManager.tsx +306 -0
  104. package/src/components/ChatInterface.tsx +88 -0
  105. package/src/components/CommandOutputDisplay.tsx +81 -0
  106. package/src/components/CommandSelector.tsx +144 -0
  107. package/src/components/CompressDisplay.tsx +58 -0
  108. package/src/components/DiffViewer.tsx +321 -0
  109. package/src/components/FileSelector.tsx +137 -0
  110. package/src/components/InputBox.tsx +310 -0
  111. package/src/components/McpManager.tsx +328 -0
  112. package/src/components/MemoryDisplay.tsx +62 -0
  113. package/src/components/MemoryTypeSelector.tsx +96 -0
  114. package/src/components/MessageList.tsx +215 -0
  115. package/src/components/ToolResultDisplay.tsx +138 -0
  116. package/src/contexts/useAppConfig.tsx +32 -0
  117. package/src/contexts/useChat.tsx +300 -0
  118. package/src/hooks/useBashHistorySelector.ts +77 -0
  119. package/src/hooks/useCommandSelector.ts +131 -0
  120. package/src/hooks/useFileSelector.ts +227 -0
  121. package/src/hooks/useImageManager.ts +64 -0
  122. package/src/hooks/useInputHistory.ts +74 -0
  123. package/src/hooks/useInputKeyboardHandler.ts +778 -0
  124. package/src/hooks/useInputState.ts +66 -0
  125. package/src/hooks/useMemoryTypeSelector.ts +40 -0
  126. package/src/hooks/usePagination.ts +203 -0
  127. package/src/index.ts +108 -0
  128. package/src/plain-cli.ts +66 -0
  129. package/src/utils/clipboard.ts +384 -0
  130. package/src/utils/constants.ts +22 -0
  131. 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
+ }
@@ -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
+ }