wave-agent-sdk 0.2.1 → 0.5.0

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 (194) hide show
  1. package/dist/agent.d.ts +66 -20
  2. package/dist/agent.d.ts.map +1 -1
  3. package/dist/agent.js +156 -83
  4. package/dist/constants/prompts.d.ts +7 -2
  5. package/dist/constants/prompts.d.ts.map +1 -1
  6. package/dist/constants/prompts.js +41 -5
  7. package/dist/constants/tools.d.ts +2 -2
  8. package/dist/constants/tools.js +2 -2
  9. package/dist/index.d.ts +1 -1
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +1 -1
  12. package/dist/managers/MemoryRuleManager.d.ts.map +1 -1
  13. package/dist/managers/MemoryRuleManager.js +16 -2
  14. package/dist/managers/aiManager.d.ts +14 -4
  15. package/dist/managers/aiManager.d.ts.map +1 -1
  16. package/dist/managers/aiManager.js +61 -9
  17. package/dist/managers/backgroundBashManager.d.ts.map +1 -1
  18. package/dist/managers/backgroundBashManager.js +1 -0
  19. package/dist/managers/backgroundTaskManager.d.ts +35 -0
  20. package/dist/managers/backgroundTaskManager.d.ts.map +1 -0
  21. package/dist/managers/backgroundTaskManager.js +249 -0
  22. package/dist/managers/bashManager.d.ts.map +1 -1
  23. package/dist/managers/bashManager.js +0 -3
  24. package/dist/managers/foregroundTaskManager.d.ts +9 -0
  25. package/dist/managers/foregroundTaskManager.d.ts.map +1 -0
  26. package/dist/managers/foregroundTaskManager.js +20 -0
  27. package/dist/managers/liveConfigManager.d.ts +1 -1
  28. package/dist/managers/liveConfigManager.d.ts.map +1 -1
  29. package/dist/managers/lspManager.d.ts.map +1 -1
  30. package/dist/managers/lspManager.js +3 -1
  31. package/dist/managers/messageManager.d.ts +34 -4
  32. package/dist/managers/messageManager.d.ts.map +1 -1
  33. package/dist/managers/messageManager.js +104 -13
  34. package/dist/managers/permissionManager.d.ts.map +1 -1
  35. package/dist/managers/permissionManager.js +11 -13
  36. package/dist/managers/pluginManager.d.ts.map +1 -1
  37. package/dist/managers/pluginManager.js +3 -2
  38. package/dist/managers/pluginScopeManager.d.ts +13 -2
  39. package/dist/managers/pluginScopeManager.d.ts.map +1 -1
  40. package/dist/managers/pluginScopeManager.js +38 -0
  41. package/dist/managers/reversionManager.d.ts +39 -0
  42. package/dist/managers/reversionManager.d.ts.map +1 -0
  43. package/dist/managers/reversionManager.js +118 -0
  44. package/dist/managers/slashCommandManager.d.ts +4 -1
  45. package/dist/managers/slashCommandManager.d.ts.map +1 -1
  46. package/dist/managers/slashCommandManager.js +16 -6
  47. package/dist/managers/subagentManager.d.ts +13 -2
  48. package/dist/managers/subagentManager.d.ts.map +1 -1
  49. package/dist/managers/subagentManager.js +144 -35
  50. package/dist/managers/toolManager.d.ts +11 -1
  51. package/dist/managers/toolManager.d.ts.map +1 -1
  52. package/dist/managers/toolManager.js +11 -3
  53. package/dist/services/GitService.d.ts.map +1 -1
  54. package/dist/services/GitService.js +6 -2
  55. package/dist/services/MarketplaceService.d.ts +14 -1
  56. package/dist/services/MarketplaceService.d.ts.map +1 -1
  57. package/dist/services/MarketplaceService.js +72 -4
  58. package/dist/services/MemoryRuleService.d.ts +1 -1
  59. package/dist/services/MemoryRuleService.d.ts.map +1 -1
  60. package/dist/services/MemoryRuleService.js +13 -2
  61. package/dist/services/aiService.js +1 -1
  62. package/dist/services/configurationService.d.ts +18 -2
  63. package/dist/services/configurationService.d.ts.map +1 -1
  64. package/dist/services/configurationService.js +62 -0
  65. package/dist/services/fileWatcher.d.ts +0 -5
  66. package/dist/services/fileWatcher.d.ts.map +1 -1
  67. package/dist/services/fileWatcher.js +0 -11
  68. package/dist/services/memory.js +1 -1
  69. package/dist/services/pluginLoader.d.ts.map +1 -1
  70. package/dist/services/pluginLoader.js +6 -1
  71. package/dist/services/reversionService.d.ts +24 -0
  72. package/dist/services/reversionService.d.ts.map +1 -0
  73. package/dist/services/reversionService.js +76 -0
  74. package/dist/services/session.d.ts +7 -0
  75. package/dist/services/session.d.ts.map +1 -1
  76. package/dist/services/session.js +126 -3
  77. package/dist/tools/bashTool.d.ts +0 -8
  78. package/dist/tools/bashTool.d.ts.map +1 -1
  79. package/dist/tools/bashTool.js +52 -174
  80. package/dist/tools/deleteFileTool.d.ts.map +1 -1
  81. package/dist/tools/deleteFileTool.js +9 -0
  82. package/dist/tools/editTool.d.ts.map +1 -1
  83. package/dist/tools/editTool.js +15 -4
  84. package/dist/tools/multiEditTool.d.ts.map +1 -1
  85. package/dist/tools/multiEditTool.js +16 -5
  86. package/dist/tools/taskOutputTool.d.ts +3 -0
  87. package/dist/tools/taskOutputTool.d.ts.map +1 -0
  88. package/dist/tools/taskOutputTool.js +149 -0
  89. package/dist/tools/taskStopTool.d.ts +3 -0
  90. package/dist/tools/taskStopTool.d.ts.map +1 -0
  91. package/dist/tools/taskStopTool.js +65 -0
  92. package/dist/tools/taskTool.d.ts.map +1 -1
  93. package/dist/tools/taskTool.js +105 -63
  94. package/dist/tools/types.d.ts +7 -0
  95. package/dist/tools/types.d.ts.map +1 -1
  96. package/dist/tools/writeTool.d.ts.map +1 -1
  97. package/dist/tools/writeTool.js +9 -0
  98. package/dist/types/commands.d.ts +1 -0
  99. package/dist/types/commands.d.ts.map +1 -1
  100. package/dist/types/configuration.d.ts +3 -0
  101. package/dist/types/configuration.d.ts.map +1 -1
  102. package/dist/types/environment.d.ts +2 -1
  103. package/dist/types/environment.d.ts.map +1 -1
  104. package/dist/types/environment.js +0 -6
  105. package/dist/types/history.d.ts +5 -0
  106. package/dist/types/history.d.ts.map +1 -0
  107. package/dist/types/history.js +1 -0
  108. package/dist/types/index.d.ts +1 -0
  109. package/dist/types/index.d.ts.map +1 -1
  110. package/dist/types/index.js +1 -0
  111. package/dist/types/marketplace.d.ts +4 -0
  112. package/dist/types/marketplace.d.ts.map +1 -1
  113. package/dist/types/messaging.d.ts +7 -1
  114. package/dist/types/messaging.d.ts.map +1 -1
  115. package/dist/types/processes.d.ts +24 -4
  116. package/dist/types/processes.d.ts.map +1 -1
  117. package/dist/types/reversion.d.ts +29 -0
  118. package/dist/types/reversion.d.ts.map +1 -0
  119. package/dist/types/reversion.js +1 -0
  120. package/dist/utils/builtinSubagents.d.ts.map +1 -1
  121. package/dist/utils/builtinSubagents.js +16 -0
  122. package/dist/utils/constants.d.ts +2 -2
  123. package/dist/utils/constants.d.ts.map +1 -1
  124. package/dist/utils/constants.js +2 -2
  125. package/dist/utils/editUtils.d.ts +4 -9
  126. package/dist/utils/editUtils.d.ts.map +1 -1
  127. package/dist/utils/editUtils.js +54 -55
  128. package/dist/utils/messageOperations.d.ts +3 -1
  129. package/dist/utils/messageOperations.d.ts.map +1 -1
  130. package/dist/utils/messageOperations.js +8 -1
  131. package/dist/utils/openaiClient.d.ts.map +1 -1
  132. package/dist/utils/openaiClient.js +56 -26
  133. package/dist/utils/promptHistory.d.ts +20 -0
  134. package/dist/utils/promptHistory.d.ts.map +1 -0
  135. package/dist/utils/promptHistory.js +117 -0
  136. package/package.json +5 -3
  137. package/src/agent.ts +193 -109
  138. package/src/constants/prompts.ts +45 -5
  139. package/src/constants/tools.ts +2 -2
  140. package/src/index.ts +1 -1
  141. package/src/managers/MemoryRuleManager.ts +18 -2
  142. package/src/managers/aiManager.ts +87 -18
  143. package/src/managers/backgroundBashManager.ts +1 -0
  144. package/src/managers/backgroundTaskManager.ts +306 -0
  145. package/src/managers/bashManager.ts +0 -4
  146. package/src/managers/foregroundTaskManager.ts +26 -0
  147. package/src/managers/liveConfigManager.ts +2 -1
  148. package/src/managers/lspManager.ts +3 -1
  149. package/src/managers/messageManager.ts +136 -18
  150. package/src/managers/permissionManager.ts +11 -13
  151. package/src/managers/pluginManager.ts +4 -3
  152. package/src/managers/pluginScopeManager.ts +57 -8
  153. package/src/managers/reversionManager.ts +152 -0
  154. package/src/managers/slashCommandManager.ts +30 -7
  155. package/src/managers/subagentManager.ts +176 -31
  156. package/src/managers/toolManager.ts +23 -4
  157. package/src/services/GitService.ts +6 -2
  158. package/src/services/MarketplaceService.ts +100 -4
  159. package/src/services/MemoryRuleService.ts +18 -6
  160. package/src/services/aiService.ts +1 -1
  161. package/src/services/configurationService.ts +79 -1
  162. package/src/services/fileWatcher.ts +0 -13
  163. package/src/services/memory.ts +1 -1
  164. package/src/services/pluginLoader.ts +7 -1
  165. package/src/services/reversionService.ts +94 -0
  166. package/src/services/session.ts +161 -3
  167. package/src/tools/bashTool.ts +73 -200
  168. package/src/tools/deleteFileTool.ts +15 -0
  169. package/src/tools/editTool.ts +20 -10
  170. package/src/tools/multiEditTool.ts +21 -11
  171. package/src/tools/taskOutputTool.ts +174 -0
  172. package/src/tools/taskStopTool.ts +72 -0
  173. package/src/tools/taskTool.ts +130 -74
  174. package/src/tools/types.ts +7 -0
  175. package/src/tools/writeTool.ts +14 -0
  176. package/src/types/commands.ts +3 -0
  177. package/src/types/configuration.ts +4 -0
  178. package/src/types/environment.ts +3 -1
  179. package/src/types/history.ts +4 -0
  180. package/src/types/index.ts +1 -0
  181. package/src/types/marketplace.ts +5 -0
  182. package/src/types/messaging.ts +9 -1
  183. package/src/types/processes.ts +33 -4
  184. package/src/types/reversion.ts +29 -0
  185. package/src/utils/builtinSubagents.ts +18 -0
  186. package/src/utils/constants.ts +2 -2
  187. package/src/utils/editUtils.ts +66 -58
  188. package/src/utils/messageOperations.ts +10 -0
  189. package/src/utils/openaiClient.ts +69 -35
  190. package/src/utils/promptHistory.ts +133 -0
  191. package/dist/utils/bashHistory.d.ts +0 -50
  192. package/dist/utils/bashHistory.d.ts.map +0 -1
  193. package/dist/utils/bashHistory.js +0 -256
  194. package/src/utils/bashHistory.ts +0 -320
@@ -1,256 +0,0 @@
1
- /**
2
- * Bash command history management module
3
- * Used for persistent storage and searching of bash commands executed by users
4
- */
5
- import fs from "fs";
6
- import { BASH_HISTORY_FILE, DATA_DIRECTORY } from "./constants.js";
7
- import { logger } from "./globalLogger.js";
8
- const HISTORY_VERSION = 1;
9
- const MAX_HISTORY_SIZE = 1000;
10
- /**
11
- * Ensure data directory exists
12
- */
13
- const ensureDataDirectory = () => {
14
- try {
15
- if (!fs.existsSync(DATA_DIRECTORY)) {
16
- fs.mkdirSync(DATA_DIRECTORY, { recursive: true });
17
- }
18
- }
19
- catch (error) {
20
- logger.debug("Failed to create data directory:", error);
21
- }
22
- };
23
- /**
24
- * Load bash history
25
- */
26
- export const loadBashHistory = () => {
27
- try {
28
- ensureDataDirectory();
29
- if (!fs.existsSync(BASH_HISTORY_FILE)) {
30
- return {
31
- commands: [],
32
- version: HISTORY_VERSION,
33
- };
34
- }
35
- const data = fs.readFileSync(BASH_HISTORY_FILE, "utf-8");
36
- const history = JSON.parse(data);
37
- // Version compatibility check
38
- if (history.version !== HISTORY_VERSION) {
39
- logger.debug("Bash history version mismatch, resetting history");
40
- return {
41
- commands: [],
42
- version: HISTORY_VERSION,
43
- };
44
- }
45
- return history;
46
- }
47
- catch (error) {
48
- logger.debug("Failed to load bash history:", error);
49
- return {
50
- commands: [],
51
- version: HISTORY_VERSION,
52
- };
53
- }
54
- };
55
- /**
56
- * Save bash history
57
- */
58
- export const saveBashHistory = (history) => {
59
- try {
60
- // Skip saving to file when in test environment
61
- if (process.env.NODE_ENV === "test") {
62
- logger.debug("Skipping bash history save in test environment");
63
- return;
64
- }
65
- ensureDataDirectory();
66
- // Limit history size
67
- if (history.commands.length > MAX_HISTORY_SIZE) {
68
- history.commands = history.commands.slice(-MAX_HISTORY_SIZE);
69
- }
70
- const data = JSON.stringify(history, null, 2);
71
- fs.writeFileSync(BASH_HISTORY_FILE, data, "utf-8");
72
- }
73
- catch (error) {
74
- logger.debug("Failed to save bash history:", error);
75
- }
76
- };
77
- /**
78
- * Add command to bash history
79
- */
80
- export const addBashCommandToHistory = (command, workdir) => {
81
- try {
82
- const history = loadBashHistory();
83
- const timestamp = Date.now();
84
- // Check if it's a duplicate consecutive command to avoid duplicate recording
85
- const lastCommand = history.commands[history.commands.length - 1];
86
- if (lastCommand &&
87
- lastCommand.command === command &&
88
- lastCommand.workdir === workdir) {
89
- // Update timestamp of the last record
90
- lastCommand.timestamp = timestamp;
91
- }
92
- else {
93
- // Add new command record
94
- history.commands.push({
95
- command,
96
- timestamp,
97
- workdir,
98
- });
99
- }
100
- saveBashHistory(history);
101
- logger.debug("Added bash command to history:", { command, workdir });
102
- }
103
- catch (error) {
104
- logger.debug("Failed to add bash command to history:", error);
105
- }
106
- };
107
- /**
108
- * Search bash history by keywords
109
- */
110
- export const searchBashHistory = (query, limit = 10) => {
111
- try {
112
- const history = loadBashHistory();
113
- const normalizedQuery = query.toLowerCase().trim();
114
- const filteredCommands = history.commands;
115
- if (!normalizedQuery) {
116
- // If no search query, return recent commands (deduplicated)
117
- const deduped = deduplicateCommands(filteredCommands);
118
- return deduped.slice(0, limit); // Latest first
119
- }
120
- // Search by relevance
121
- const matches = filteredCommands
122
- .filter((entry) => {
123
- // Command content matching
124
- const command = entry.command.toLowerCase();
125
- return command.includes(normalizedQuery);
126
- })
127
- .map((entry) => {
128
- // Calculate match score
129
- const command = entry.command.toLowerCase();
130
- let score = 0;
131
- // Exact match gets higher score
132
- if (command.includes(normalizedQuery)) {
133
- score += 10;
134
- }
135
- // Command prefix match gets higher score
136
- if (command.startsWith(normalizedQuery)) {
137
- score += 20;
138
- }
139
- // Word boundary match gets higher score
140
- const words = command.split(/\s+/);
141
- if (words.some((word) => word.startsWith(normalizedQuery))) {
142
- score += 15;
143
- }
144
- // Timestamp influence (newer gets higher score)
145
- score += entry.timestamp / 1000000; // Normalize timestamp
146
- return { entry, score };
147
- })
148
- .sort((a, b) => b.score - a.score) // Sort by score descending
149
- .map((item) => item.entry);
150
- // Deduplicate search results, keep latest record
151
- const dedupedMatches = deduplicateCommands(matches);
152
- const result = dedupedMatches.slice(0, limit);
153
- logger.debug("Bash history search results:", {
154
- query,
155
- workdir: process.cwd(),
156
- originalCount: matches.length,
157
- dedupedCount: result.length,
158
- });
159
- return result;
160
- }
161
- catch (error) {
162
- logger.debug("Failed to search bash history:", error);
163
- return [];
164
- }
165
- };
166
- /**
167
- * Deduplicate command list, keep latest record for each command
168
- */
169
- const deduplicateCommands = (commands) => {
170
- const commandMap = new Map();
171
- // Iterate through all commands, keep latest record for each
172
- for (const entry of commands) {
173
- const existing = commandMap.get(entry.command);
174
- if (!existing || entry.timestamp > existing.timestamp) {
175
- commandMap.set(entry.command, entry);
176
- }
177
- }
178
- // Sort by timestamp and return (new to old)
179
- return Array.from(commandMap.values()).sort((a, b) => b.timestamp - a.timestamp);
180
- };
181
- /**
182
- * Get recently used bash commands
183
- */
184
- export const getRecentBashCommands = (limit = 10) => {
185
- try {
186
- const history = loadBashHistory();
187
- // Return recent commands after deduplication
188
- const deduped = deduplicateCommands(history.commands);
189
- return deduped.slice(0, limit); // Latest first
190
- }
191
- catch (error) {
192
- logger.debug("Failed to get recent bash commands:", error);
193
- return [];
194
- }
195
- };
196
- /**
197
- * Delete a specific command from bash history
198
- */
199
- export const deleteBashCommandFromHistory = (command, workdir) => {
200
- try {
201
- const history = loadBashHistory();
202
- const initialLength = history.commands.length;
203
- history.commands = history.commands.filter((entry) => {
204
- if (workdir) {
205
- return !(entry.command === command && entry.workdir === workdir);
206
- }
207
- return entry.command !== command;
208
- });
209
- if (history.commands.length !== initialLength) {
210
- saveBashHistory(history);
211
- logger.debug("Deleted bash command from history:", { command, workdir });
212
- }
213
- }
214
- catch (error) {
215
- logger.debug("Failed to delete bash command from history:", error);
216
- }
217
- };
218
- /**
219
- * Clear bash history
220
- */
221
- export const clearBashHistory = () => {
222
- try {
223
- const history = {
224
- commands: [],
225
- version: HISTORY_VERSION,
226
- };
227
- saveBashHistory(history);
228
- logger.debug("Bash history cleared");
229
- }
230
- catch (error) {
231
- logger.debug("Failed to clear bash history:", error);
232
- }
233
- };
234
- /**
235
- * Get bash command statistics
236
- */
237
- export const getBashCommandStats = () => {
238
- try {
239
- const history = loadBashHistory();
240
- const uniqueCommands = new Set(history.commands.map((entry) => entry.command));
241
- const workdirs = Array.from(new Set(history.commands.map((entry) => entry.workdir)));
242
- return {
243
- totalCommands: history.commands.length,
244
- uniqueCommands: uniqueCommands.size,
245
- workdirs,
246
- };
247
- }
248
- catch (error) {
249
- logger.debug("Failed to get bash command stats:", error);
250
- return {
251
- totalCommands: 0,
252
- uniqueCommands: 0,
253
- workdirs: [],
254
- };
255
- }
256
- };
@@ -1,320 +0,0 @@
1
- /**
2
- * Bash command history management module
3
- * Used for persistent storage and searching of bash commands executed by users
4
- */
5
-
6
- import fs from "fs";
7
- import { BASH_HISTORY_FILE, DATA_DIRECTORY } from "./constants.js";
8
- import { logger } from "./globalLogger.js";
9
-
10
- export interface BashHistoryEntry {
11
- command: string;
12
- timestamp: number;
13
- workdir: string;
14
- }
15
-
16
- export interface BashHistory {
17
- commands: BashHistoryEntry[];
18
- version: number;
19
- }
20
-
21
- const HISTORY_VERSION = 1;
22
- const MAX_HISTORY_SIZE = 1000;
23
-
24
- /**
25
- * Ensure data directory exists
26
- */
27
- const ensureDataDirectory = (): void => {
28
- try {
29
- if (!fs.existsSync(DATA_DIRECTORY)) {
30
- fs.mkdirSync(DATA_DIRECTORY, { recursive: true });
31
- }
32
- } catch (error) {
33
- logger.debug("Failed to create data directory:", error);
34
- }
35
- };
36
-
37
- /**
38
- * Load bash history
39
- */
40
- export const loadBashHistory = (): BashHistory => {
41
- try {
42
- ensureDataDirectory();
43
-
44
- if (!fs.existsSync(BASH_HISTORY_FILE)) {
45
- return {
46
- commands: [],
47
- version: HISTORY_VERSION,
48
- };
49
- }
50
-
51
- const data = fs.readFileSync(BASH_HISTORY_FILE, "utf-8");
52
- const history: BashHistory = JSON.parse(data);
53
-
54
- // Version compatibility check
55
- if (history.version !== HISTORY_VERSION) {
56
- logger.debug("Bash history version mismatch, resetting history");
57
- return {
58
- commands: [],
59
- version: HISTORY_VERSION,
60
- };
61
- }
62
-
63
- return history;
64
- } catch (error) {
65
- logger.debug("Failed to load bash history:", error);
66
- return {
67
- commands: [],
68
- version: HISTORY_VERSION,
69
- };
70
- }
71
- };
72
-
73
- /**
74
- * Save bash history
75
- */
76
- export const saveBashHistory = (history: BashHistory): void => {
77
- try {
78
- // Skip saving to file when in test environment
79
- if (process.env.NODE_ENV === "test") {
80
- logger.debug("Skipping bash history save in test environment");
81
- return;
82
- }
83
-
84
- ensureDataDirectory();
85
-
86
- // Limit history size
87
- if (history.commands.length > MAX_HISTORY_SIZE) {
88
- history.commands = history.commands.slice(-MAX_HISTORY_SIZE);
89
- }
90
-
91
- const data = JSON.stringify(history, null, 2);
92
- fs.writeFileSync(BASH_HISTORY_FILE, data, "utf-8");
93
- } catch (error) {
94
- logger.debug("Failed to save bash history:", error);
95
- }
96
- };
97
-
98
- /**
99
- * Add command to bash history
100
- */
101
- export const addBashCommandToHistory = (
102
- command: string,
103
- workdir: string,
104
- ): void => {
105
- try {
106
- const history = loadBashHistory();
107
- const timestamp = Date.now();
108
-
109
- // Check if it's a duplicate consecutive command to avoid duplicate recording
110
- const lastCommand = history.commands[history.commands.length - 1];
111
- if (
112
- lastCommand &&
113
- lastCommand.command === command &&
114
- lastCommand.workdir === workdir
115
- ) {
116
- // Update timestamp of the last record
117
- lastCommand.timestamp = timestamp;
118
- } else {
119
- // Add new command record
120
- history.commands.push({
121
- command,
122
- timestamp,
123
- workdir,
124
- });
125
- }
126
-
127
- saveBashHistory(history);
128
- logger.debug("Added bash command to history:", { command, workdir });
129
- } catch (error) {
130
- logger.debug("Failed to add bash command to history:", error);
131
- }
132
- };
133
-
134
- /**
135
- * Search bash history by keywords
136
- */
137
- export const searchBashHistory = (
138
- query: string,
139
- limit: number = 10,
140
- ): BashHistoryEntry[] => {
141
- try {
142
- const history = loadBashHistory();
143
- const normalizedQuery = query.toLowerCase().trim();
144
-
145
- const filteredCommands = history.commands;
146
-
147
- if (!normalizedQuery) {
148
- // If no search query, return recent commands (deduplicated)
149
- const deduped = deduplicateCommands(filteredCommands);
150
- return deduped.slice(0, limit); // Latest first
151
- }
152
-
153
- // Search by relevance
154
- const matches = filteredCommands
155
- .filter((entry) => {
156
- // Command content matching
157
- const command = entry.command.toLowerCase();
158
- return command.includes(normalizedQuery);
159
- })
160
- .map((entry) => {
161
- // Calculate match score
162
- const command = entry.command.toLowerCase();
163
- let score = 0;
164
-
165
- // Exact match gets higher score
166
- if (command.includes(normalizedQuery)) {
167
- score += 10;
168
- }
169
-
170
- // Command prefix match gets higher score
171
- if (command.startsWith(normalizedQuery)) {
172
- score += 20;
173
- }
174
-
175
- // Word boundary match gets higher score
176
- const words = command.split(/\s+/);
177
- if (words.some((word) => word.startsWith(normalizedQuery))) {
178
- score += 15;
179
- }
180
-
181
- // Timestamp influence (newer gets higher score)
182
- score += entry.timestamp / 1000000; // Normalize timestamp
183
-
184
- return { entry, score };
185
- })
186
- .sort((a, b) => b.score - a.score) // Sort by score descending
187
- .map((item) => item.entry);
188
-
189
- // Deduplicate search results, keep latest record
190
- const dedupedMatches = deduplicateCommands(matches);
191
- const result = dedupedMatches.slice(0, limit);
192
-
193
- logger.debug("Bash history search results:", {
194
- query,
195
- workdir: process.cwd(),
196
- originalCount: matches.length,
197
- dedupedCount: result.length,
198
- });
199
-
200
- return result;
201
- } catch (error) {
202
- logger.debug("Failed to search bash history:", error);
203
- return [];
204
- }
205
- };
206
-
207
- /**
208
- * Deduplicate command list, keep latest record for each command
209
- */
210
- const deduplicateCommands = (
211
- commands: BashHistoryEntry[],
212
- ): BashHistoryEntry[] => {
213
- const commandMap = new Map<string, BashHistoryEntry>();
214
-
215
- // Iterate through all commands, keep latest record for each
216
- for (const entry of commands) {
217
- const existing = commandMap.get(entry.command);
218
- if (!existing || entry.timestamp > existing.timestamp) {
219
- commandMap.set(entry.command, entry);
220
- }
221
- }
222
-
223
- // Sort by timestamp and return (new to old)
224
- return Array.from(commandMap.values()).sort(
225
- (a, b) => b.timestamp - a.timestamp,
226
- );
227
- };
228
-
229
- /**
230
- * Get recently used bash commands
231
- */
232
- export const getRecentBashCommands = (
233
- limit: number = 10,
234
- ): BashHistoryEntry[] => {
235
- try {
236
- const history = loadBashHistory();
237
-
238
- // Return recent commands after deduplication
239
- const deduped = deduplicateCommands(history.commands);
240
- return deduped.slice(0, limit); // Latest first
241
- } catch (error) {
242
- logger.debug("Failed to get recent bash commands:", error);
243
- return [];
244
- }
245
- };
246
-
247
- /**
248
- * Delete a specific command from bash history
249
- */
250
- export const deleteBashCommandFromHistory = (
251
- command: string,
252
- workdir?: string,
253
- ): void => {
254
- try {
255
- const history = loadBashHistory();
256
- const initialLength = history.commands.length;
257
-
258
- history.commands = history.commands.filter((entry) => {
259
- if (workdir) {
260
- return !(entry.command === command && entry.workdir === workdir);
261
- }
262
- return entry.command !== command;
263
- });
264
-
265
- if (history.commands.length !== initialLength) {
266
- saveBashHistory(history);
267
- logger.debug("Deleted bash command from history:", { command, workdir });
268
- }
269
- } catch (error) {
270
- logger.debug("Failed to delete bash command from history:", error);
271
- }
272
- };
273
-
274
- /**
275
- * Clear bash history
276
- */
277
- export const clearBashHistory = (): void => {
278
- try {
279
- const history: BashHistory = {
280
- commands: [],
281
- version: HISTORY_VERSION,
282
- };
283
- saveBashHistory(history);
284
- logger.debug("Bash history cleared");
285
- } catch (error) {
286
- logger.debug("Failed to clear bash history:", error);
287
- }
288
- };
289
-
290
- /**
291
- * Get bash command statistics
292
- */
293
- export const getBashCommandStats = (): {
294
- totalCommands: number;
295
- uniqueCommands: number;
296
- workdirs: string[];
297
- } => {
298
- try {
299
- const history = loadBashHistory();
300
- const uniqueCommands = new Set(
301
- history.commands.map((entry) => entry.command),
302
- );
303
- const workdirs = Array.from(
304
- new Set(history.commands.map((entry) => entry.workdir)),
305
- );
306
-
307
- return {
308
- totalCommands: history.commands.length,
309
- uniqueCommands: uniqueCommands.size,
310
- workdirs,
311
- };
312
- } catch (error) {
313
- logger.debug("Failed to get bash command stats:", error);
314
- return {
315
- totalCommands: 0,
316
- uniqueCommands: 0,
317
- workdirs: [],
318
- };
319
- }
320
- };