wave-agent-sdk 1.0.5 → 1.0.7

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 (202) hide show
  1. package/dist/agent.d.ts +34 -1
  2. package/dist/agent.js +49 -4
  3. package/dist/index.d.ts +3 -1
  4. package/dist/index.js +1 -1
  5. package/dist/managers/aiManager.d.ts +36 -0
  6. package/dist/managers/aiManager.js +240 -11
  7. package/dist/managers/messageManager.d.ts +2 -4
  8. package/dist/managers/messageManager.js +14 -7
  9. package/dist/managers/slashCommandManager.js +28 -0
  10. package/dist/managers/subagentManager.d.ts +0 -2
  11. package/dist/services/aiService.d.ts +2 -3
  12. package/dist/services/aiService.js +4 -18
  13. package/dist/services/configurationService.d.ts +7 -0
  14. package/dist/services/configurationService.js +10 -0
  15. package/dist/telemetry/instrumentation.d.ts +1 -1
  16. package/dist/telemetry/instrumentation.js +57 -28
  17. package/dist/tools/bashTool.js +16 -6
  18. package/dist/tools/grepTool.js +11 -3
  19. package/dist/types/core.d.ts +1 -34
  20. package/dist/types/index.d.ts +4 -0
  21. package/dist/types/messaging.d.ts +2 -0
  22. package/dist/utils/cacheControlUtils.d.ts +5 -27
  23. package/dist/utils/cacheControlUtils.js +12 -73
  24. package/dist/utils/containerSetup.js +0 -3
  25. package/dist/utils/messageOperations.d.ts +2 -1
  26. package/dist/utils/messageOperations.js +2 -1
  27. package/dist/utils/notificationXml.js +5 -0
  28. package/dist/utils/ripgrep.d.ts +4 -4
  29. package/dist/utils/ripgrep.js +4 -27
  30. package/package.json +20 -8
  31. package/bin/rg +0 -79
  32. package/dist/managers/forkedAgentManager.d.ts +0 -50
  33. package/dist/managers/forkedAgentManager.js +0 -130
  34. package/scripts/install_ripgrep.js +0 -111
  35. package/scripts/postinstall.js +0 -38
  36. package/src/agent.ts +0 -1271
  37. package/src/constants/subagents.ts +0 -4
  38. package/src/constants/toolLimits.ts +0 -15
  39. package/src/constants/tools.ts +0 -24
  40. package/src/core/plugin.ts +0 -237
  41. package/src/core/session.ts +0 -9
  42. package/src/index.ts +0 -38
  43. package/src/managers/MemoryRuleManager.ts +0 -198
  44. package/src/managers/aiManager.ts +0 -2429
  45. package/src/managers/backgroundTaskManager.ts +0 -480
  46. package/src/managers/bangManager.ts +0 -119
  47. package/src/managers/cronManager.ts +0 -401
  48. package/src/managers/foregroundTaskManager.ts +0 -30
  49. package/src/managers/forkedAgentManager.ts +0 -216
  50. package/src/managers/hookManager.ts +0 -1089
  51. package/src/managers/liveConfigManager.ts +0 -445
  52. package/src/managers/lspManager.ts +0 -470
  53. package/src/managers/mcpManager.ts +0 -1010
  54. package/src/managers/messageManager.ts +0 -1184
  55. package/src/managers/messageQueue.ts +0 -157
  56. package/src/managers/permissionManager.ts +0 -1140
  57. package/src/managers/planManager.ts +0 -112
  58. package/src/managers/pluginManager.ts +0 -330
  59. package/src/managers/pluginScopeManager.ts +0 -124
  60. package/src/managers/reversionManager.ts +0 -178
  61. package/src/managers/skillManager.ts +0 -578
  62. package/src/managers/slashCommandManager.ts +0 -564
  63. package/src/managers/subagentManager.ts +0 -915
  64. package/src/managers/toolManager.ts +0 -489
  65. package/src/managers/workflowManager.ts +0 -493
  66. package/src/prompts/autoMemory.ts +0 -33
  67. package/src/prompts/autoMemoryExtraction.ts +0 -146
  68. package/src/prompts/index.ts +0 -506
  69. package/src/prompts/planModeReminders.ts +0 -126
  70. package/src/services/GitService.ts +0 -131
  71. package/src/services/MarketplaceService.ts +0 -1052
  72. package/src/services/MemoryRuleService.ts +0 -71
  73. package/src/services/aiService.ts +0 -919
  74. package/src/services/authService.ts +0 -565
  75. package/src/services/autoMemoryService.ts +0 -280
  76. package/src/services/configurationService.ts +0 -1520
  77. package/src/services/fileWatcher.ts +0 -319
  78. package/src/services/hook.ts +0 -348
  79. package/src/services/initializationService.ts +0 -357
  80. package/src/services/interactionService.ts +0 -229
  81. package/src/services/jsonlHandler.ts +0 -295
  82. package/src/services/memory.ts +0 -234
  83. package/src/services/pluginLoader.ts +0 -252
  84. package/src/services/remoteSettingsService.ts +0 -366
  85. package/src/services/reversionService.ts +0 -122
  86. package/src/services/session.ts +0 -917
  87. package/src/services/taskManager.ts +0 -321
  88. package/src/telemetry/events.ts +0 -65
  89. package/src/telemetry/instrumentation.ts +0 -499
  90. package/src/telemetry/sessionTracing.ts +0 -348
  91. package/src/tools/agentTool.ts +0 -322
  92. package/src/tools/askUserQuestion.ts +0 -160
  93. package/src/tools/bashTool.ts +0 -621
  94. package/src/tools/buildTool.ts +0 -61
  95. package/src/tools/cronCreateTool.ts +0 -161
  96. package/src/tools/cronDeleteTool.ts +0 -51
  97. package/src/tools/cronListTool.ts +0 -47
  98. package/src/tools/editTool.ts +0 -313
  99. package/src/tools/enterPlanMode.ts +0 -124
  100. package/src/tools/enterWorktreeTool.ts +0 -190
  101. package/src/tools/exitPlanMode.ts +0 -139
  102. package/src/tools/exitWorktreeTool.ts +0 -236
  103. package/src/tools/globTool.ts +0 -167
  104. package/src/tools/grepTool.ts +0 -399
  105. package/src/tools/lspTool.ts +0 -883
  106. package/src/tools/readTool.ts +0 -426
  107. package/src/tools/skillTool.ts +0 -248
  108. package/src/tools/taskManagementTools.ts +0 -574
  109. package/src/tools/taskStopTool.ts +0 -78
  110. package/src/tools/types.ts +0 -137
  111. package/src/tools/webFetchTool.ts +0 -373
  112. package/src/tools/workflowTool.ts +0 -205
  113. package/src/tools/writeTool.ts +0 -267
  114. package/src/types/agent.ts +0 -128
  115. package/src/types/auth.ts +0 -19
  116. package/src/types/commands.ts +0 -30
  117. package/src/types/config.ts +0 -43
  118. package/src/types/configuration.ts +0 -168
  119. package/src/types/core.ts +0 -105
  120. package/src/types/cron.ts +0 -13
  121. package/src/types/environment.ts +0 -106
  122. package/src/types/fileSearch.ts +0 -4
  123. package/src/types/history.ts +0 -7
  124. package/src/types/hooks.ts +0 -256
  125. package/src/types/index.ts +0 -41
  126. package/src/types/lsp.ts +0 -98
  127. package/src/types/marketplace.ts +0 -71
  128. package/src/types/mcp.ts +0 -43
  129. package/src/types/memoryRule.ts +0 -31
  130. package/src/types/messaging.ts +0 -114
  131. package/src/types/permissions.ts +0 -80
  132. package/src/types/plugins.ts +0 -39
  133. package/src/types/processes.ts +0 -99
  134. package/src/types/reversion.ts +0 -29
  135. package/src/types/session.ts +0 -12
  136. package/src/types/skills.ts +0 -108
  137. package/src/types/tasks.ts +0 -13
  138. package/src/types/telemetry.ts +0 -98
  139. package/src/types/tools.ts +0 -44
  140. package/src/types/workflow.ts +0 -6
  141. package/src/utils/abortUtils.ts +0 -118
  142. package/src/utils/atomicWrite.ts +0 -61
  143. package/src/utils/bashParser.ts +0 -899
  144. package/src/utils/cacheControlUtils.ts +0 -426
  145. package/src/utils/commandArgumentParser.ts +0 -161
  146. package/src/utils/commandPathResolver.ts +0 -88
  147. package/src/utils/configPaths.ts +0 -220
  148. package/src/utils/configValidator.ts +0 -100
  149. package/src/utils/constants.ts +0 -39
  150. package/src/utils/container.ts +0 -92
  151. package/src/utils/containerSetup.ts +0 -371
  152. package/src/utils/convertMessagesForAPI.ts +0 -326
  153. package/src/utils/cronTasks.ts +0 -128
  154. package/src/utils/cronTasksLock.ts +0 -182
  155. package/src/utils/cronToHuman.ts +0 -99
  156. package/src/utils/customCommands.ts +0 -95
  157. package/src/utils/editUtils.ts +0 -20
  158. package/src/utils/fileFormat.ts +0 -40
  159. package/src/utils/fileSearch.ts +0 -151
  160. package/src/utils/fileUtils.ts +0 -223
  161. package/src/utils/gitUtils.ts +0 -315
  162. package/src/utils/globalLogger.ts +0 -128
  163. package/src/utils/groupMessagesByApiRound.ts +0 -121
  164. package/src/utils/hookMatcher.ts +0 -176
  165. package/src/utils/markdownParser.ts +0 -317
  166. package/src/utils/mcpUtils.ts +0 -138
  167. package/src/utils/messageOperations.ts +0 -659
  168. package/src/utils/modelCapabilities.ts +0 -30
  169. package/src/utils/nameGenerator.ts +0 -99
  170. package/src/utils/notificationXml.ts +0 -57
  171. package/src/utils/openaiClient.ts +0 -251
  172. package/src/utils/parseCronExpression.ts +0 -78
  173. package/src/utils/path.ts +0 -72
  174. package/src/utils/pathEncoder.ts +0 -400
  175. package/src/utils/pathSafety.ts +0 -40
  176. package/src/utils/promptHistory.ts +0 -168
  177. package/src/utils/ripgrep.ts +0 -35
  178. package/src/utils/shellResolver.ts +0 -190
  179. package/src/utils/skillParser.ts +0 -246
  180. package/src/utils/stringUtils.ts +0 -156
  181. package/src/utils/subagentParser.ts +0 -279
  182. package/src/utils/taskReminder.ts +0 -96
  183. package/src/utils/tokenCalculation.ts +0 -43
  184. package/src/utils/tokenEstimate.ts +0 -34
  185. package/src/utils/toolResultStorage.ts +0 -117
  186. package/src/utils/worktreeSession.ts +0 -26
  187. package/src/utils/worktreeUtils.ts +0 -786
  188. package/src/workflow/budgetTracker.ts +0 -34
  189. package/src/workflow/concurrencyLimiter.ts +0 -47
  190. package/src/workflow/journal.ts +0 -95
  191. package/src/workflow/progressReporter.ts +0 -141
  192. package/src/workflow/runState.ts +0 -65
  193. package/src/workflow/scriptRuntime.ts +0 -274
  194. package/src/workflow/structuredOutput.ts +0 -123
  195. package/src/workflow/types.ts +0 -101
  196. package/src/workflow/workflowApis.ts +0 -410
  197. package/vendor/ripgrep/linux-aarch64/rg +0 -0
  198. package/vendor/ripgrep/linux-x86_64/rg +0 -0
  199. package/vendor/ripgrep/macos-aarch64/rg +0 -0
  200. package/vendor/ripgrep/macos-x86_64/rg +0 -0
  201. package/vendor/ripgrep/windows-aarch64/rg.exe +0 -0
  202. package/vendor/ripgrep/windows-x86_64/rg.exe +0 -0
@@ -1,400 +0,0 @@
1
- /**
2
- * Path encoding utility for converting working directory paths to filesystem-safe names
3
- * Handles cross-platform directory name encoding for project-based session organization
4
- */
5
-
6
- import { resolve, join } from "path";
7
- import { createHash } from "crypto";
8
- import { realpath, mkdir } from "fs/promises";
9
- import { homedir, platform } from "os";
10
-
11
- /**
12
- * Project directory information
13
- */
14
- export interface ProjectDirectory {
15
- readonly originalPath: string;
16
- readonly encodedName: string;
17
- readonly encodedPath: string;
18
- readonly pathHash?: string; // For collision resolution
19
- readonly isSymbolicLink: boolean;
20
- }
21
-
22
- /**
23
- * Path encoding configuration options
24
- */
25
- export interface PathEncodingOptions {
26
- maxLength?: number; // Default: 200 characters
27
- pathSeparatorReplacement?: string; // Default: '-'
28
- spaceReplacement?: string; // Default: '_'
29
- invalidCharReplacement?: string; // Default: '_'
30
- hashLength?: number; // Default: 8 characters
31
- }
32
-
33
- /**
34
- * Platform-specific filesystem constraints
35
- */
36
- export interface FilesystemConstraints {
37
- readonly maxDirectoryNameLength: number;
38
- readonly maxPathLength: number;
39
- readonly invalidCharacters: string[];
40
- readonly reservedNames: string[];
41
- readonly caseSensitive: boolean;
42
- }
43
-
44
- /**
45
- * Path validation result
46
- */
47
- export interface PathValidationResult {
48
- readonly isValid: boolean;
49
- readonly errors: string[];
50
- readonly warnings: string[];
51
- readonly suggestedFix?: string;
52
- }
53
-
54
- /**
55
- * PathEncoder class for converting working directory paths to filesystem-safe names
56
- */
57
- export class PathEncoder {
58
- private readonly options: Required<PathEncodingOptions>;
59
- private readonly constraints: FilesystemConstraints;
60
-
61
- constructor(options: PathEncodingOptions = {}) {
62
- this.options = {
63
- maxLength: options.maxLength ?? 200,
64
- pathSeparatorReplacement: options.pathSeparatorReplacement ?? "-",
65
- spaceReplacement: options.spaceReplacement ?? "_",
66
- invalidCharReplacement: options.invalidCharReplacement ?? "_",
67
- hashLength: options.hashLength ?? 8,
68
- };
69
- this.constraints = this.getFilesystemConstraints();
70
- }
71
-
72
- /**
73
- * Encode a working directory path to a filesystem-safe directory name
74
- */
75
- async encode(originalPath: string): Promise<string> {
76
- // Resolve symbolic links and normalize path
77
- const resolvedPath = await this.resolvePath(originalPath);
78
- return this.encodeSync(resolvedPath);
79
- }
80
-
81
- /**
82
- * Synchronously encode a path to a filesystem-safe directory name
83
- * Note: Does not resolve symbolic links - use encode() for full path resolution
84
- */
85
- encodeSync(pathToEncode: string): string {
86
- // Convert to safe directory name
87
- let encoded = pathToEncode;
88
-
89
- // Remove Windows drive letter prefix (e.g. "D:") so encoded names are
90
- // stable across platforms — path.resolve("/home/user/project") yields
91
- // "D:\home\user\project" on Windows and we want the same encoded name
92
- // as on Linux ("home-user-project").
93
- encoded = encoded.replace(/^[a-zA-Z]:/, "");
94
-
95
- // Remove leading slash/backslash to avoid empty directory names
96
- if (encoded.startsWith("/") || encoded.startsWith("\\")) {
97
- encoded = encoded.substring(1);
98
- }
99
-
100
- // Replace path separators with hyphens
101
- encoded = encoded.replace(/[/\\]/g, this.options.pathSeparatorReplacement);
102
-
103
- // Replace spaces with underscores
104
- encoded = encoded.replace(/\s+/g, this.options.spaceReplacement);
105
-
106
- // Replace invalid characters with underscores
107
- const escapedChars = this.constraints.invalidCharacters
108
- .map((c) => `\\${c}`)
109
- .join("");
110
- const invalidChars = new RegExp(`[${escapedChars}]`, "g");
111
- encoded = encoded.replace(
112
- invalidChars,
113
- this.options.invalidCharReplacement,
114
- );
115
-
116
- // Case is preserved
117
-
118
- // Handle length limit with hash
119
- if (encoded.length > this.options.maxLength) {
120
- const hash = this.generateHash(pathToEncode, this.options.hashLength);
121
- const maxBaseLength =
122
- this.options.maxLength - this.options.hashLength - 1; // -1 for separator
123
- encoded = `${encoded.substring(0, maxBaseLength)}-${hash}`;
124
- }
125
-
126
- return encoded;
127
- }
128
-
129
- /**
130
- * Decode an encoded directory name back to original path (limited functionality)
131
- * Note: This is best-effort as encoding is lossy
132
- */
133
- async decode(encodedName: string): Promise<string | null> {
134
- return this.decodeSync(encodedName);
135
- }
136
-
137
- /**
138
- * Synchronously decode an encoded directory name back to original path (limited functionality)
139
- * Note: This is best-effort as encoding is lossy
140
- */
141
- decodeSync(encodedName: string): string | null {
142
- // This is a simplified version - full reversal is not always possible
143
- // due to lossy encoding (case changes, character replacements, hashing)
144
-
145
- // Check if this has a hash suffix
146
- const hashPattern = new RegExp(`-[a-f0-9]{${this.options.hashLength}}$`);
147
- if (hashPattern.test(encodedName)) {
148
- // Cannot reliably decode hashed paths
149
- return null;
150
- }
151
-
152
- // Attempt basic reversal
153
- let decoded = encodedName;
154
-
155
- // Reverse path separator replacement
156
- decoded = decoded.replace(
157
- new RegExp(this.options.pathSeparatorReplacement, "g"),
158
- "/",
159
- );
160
-
161
- // Reverse space replacement
162
- decoded = decoded.replace(
163
- new RegExp(this.options.spaceReplacement, "g"),
164
- " ",
165
- );
166
-
167
- // Add leading slash
168
- decoded = `/${decoded}`;
169
-
170
- return decoded;
171
- }
172
-
173
- /**
174
- * Resolve symbolic links and normalize path before encoding
175
- */
176
- async resolvePath(path: string): Promise<string> {
177
- try {
178
- // Expand tilde to home directory
179
- const expandedPath = this.expandTilde(path);
180
-
181
- // Resolve to absolute path
182
- const absolutePath = resolve(expandedPath);
183
-
184
- // Resolve symbolic links
185
- const resolvedPath = await realpath(absolutePath);
186
-
187
- return resolvedPath;
188
- } catch (error) {
189
- throw new Error(`Failed to resolve path "${path}": ${error}`);
190
- }
191
- }
192
-
193
- /**
194
- * Get project directory info without creating the directory
195
- */
196
- async getProjectDirectory(
197
- originalPath: string,
198
- baseSessionDir: string,
199
- ): Promise<ProjectDirectory> {
200
- // Resolve the original path and check for symbolic links
201
- const expandedPath = this.expandTilde(originalPath);
202
- const absolutePath = resolve(expandedPath);
203
-
204
- let resolvedPath: string;
205
- let isSymbolicLink = false;
206
-
207
- try {
208
- resolvedPath = await realpath(absolutePath);
209
- isSymbolicLink = resolvedPath !== absolutePath;
210
- } catch {
211
- // If realpath fails, use the absolute path
212
- resolvedPath = absolutePath;
213
- }
214
-
215
- // Encode the resolved path. Use encodeSync (pure string transform) rather
216
- // than encode(): realpath was already attempted above with its own fallback,
217
- // so re-resolving via encode()->resolvePath() would throw ENOENT again when
218
- // the workdir no longer exists (e.g. a deleted worktree during agent
219
- // shutdown). Session files live under <baseSessionDir>/<encoded>/ regardless
220
- // of the workdir's existence, so encoding must not require it to exist.
221
- const encodedName = this.encodeSync(resolvedPath);
222
- const encodedPath = join(baseSessionDir, encodedName);
223
-
224
- // Generate hash if encoding resulted in truncation
225
- let pathHash: string | undefined;
226
- if (resolvedPath.length > this.options.maxLength) {
227
- pathHash = this.generateHash(resolvedPath, this.options.hashLength);
228
- }
229
-
230
- return {
231
- originalPath: resolvedPath,
232
- encodedName,
233
- encodedPath,
234
- pathHash,
235
- isSymbolicLink,
236
- };
237
- }
238
-
239
- /**
240
- * Create project directory entity from original path
241
- */
242
- async createProjectDirectory(
243
- originalPath: string,
244
- baseSessionDir: string,
245
- ): Promise<ProjectDirectory> {
246
- const projectDirectory = await this.getProjectDirectory(
247
- originalPath,
248
- baseSessionDir,
249
- );
250
-
251
- // Ensure the encoded directory exists
252
- try {
253
- await mkdir(projectDirectory.encodedPath, { recursive: true });
254
- } catch {
255
- // Ignore errors if directory already exists
256
- }
257
-
258
- return projectDirectory;
259
- }
260
-
261
- /**
262
- * Validate that an encoded name is filesystem-safe
263
- */
264
- validateEncodedName(encodedName: string): boolean {
265
- // Check length
266
- if (encodedName.length > this.constraints.maxDirectoryNameLength) {
267
- return false;
268
- }
269
-
270
- // Check for invalid characters
271
- for (const char of this.constraints.invalidCharacters) {
272
- if (encodedName.includes(char)) {
273
- return false;
274
- }
275
- }
276
-
277
- // Check for reserved names
278
- const lowerName = encodedName.toLowerCase();
279
- if (
280
- this.constraints.reservedNames.some(
281
- (reserved) => reserved.toLowerCase() === lowerName,
282
- )
283
- ) {
284
- return false;
285
- }
286
-
287
- // Check for empty or dots-only names
288
- if (!encodedName.trim() || /^\.+$/.test(encodedName)) {
289
- return false;
290
- }
291
-
292
- return true;
293
- }
294
-
295
- /**
296
- * Handle encoding collisions by generating unique names
297
- */
298
- resolveCollision(baseName: string, existingNames: Set<string>): string {
299
- if (!existingNames.has(baseName)) {
300
- return baseName;
301
- }
302
-
303
- // Try numbered suffixes first
304
- for (let i = 1; i <= 999; i++) {
305
- const candidate = `${baseName}-${i}`;
306
- if (!existingNames.has(candidate)) {
307
- return candidate;
308
- }
309
- }
310
-
311
- // If all numbered suffixes are taken, use hash
312
- const hash = this.generateHash(
313
- baseName + Date.now(),
314
- this.options.hashLength,
315
- );
316
- return `${baseName}-${hash}`;
317
- }
318
-
319
- /**
320
- * Get platform-specific filesystem constraints
321
- */
322
- private getFilesystemConstraints(): FilesystemConstraints {
323
- const currentPlatform = platform();
324
-
325
- switch (currentPlatform) {
326
- case "win32":
327
- return {
328
- maxDirectoryNameLength: 255,
329
- maxPathLength: 260,
330
- invalidCharacters: ["<", ">", ":", '"', "|", "?", "*"],
331
- reservedNames: [
332
- "CON",
333
- "PRN",
334
- "AUX",
335
- "NUL",
336
- "COM1",
337
- "COM2",
338
- "COM3",
339
- "COM4",
340
- "COM5",
341
- "COM6",
342
- "COM7",
343
- "COM8",
344
- "COM9",
345
- "LPT1",
346
- "LPT2",
347
- "LPT3",
348
- "LPT4",
349
- "LPT5",
350
- "LPT6",
351
- "LPT7",
352
- "LPT8",
353
- "LPT9",
354
- ],
355
- caseSensitive: false,
356
- };
357
- case "darwin":
358
- return {
359
- maxDirectoryNameLength: 255,
360
- maxPathLength: 1024,
361
- invalidCharacters: [":"],
362
- reservedNames: [],
363
- caseSensitive: false, // HFS+ is case-insensitive by default
364
- };
365
- default: // Linux and other Unix-like systems
366
- return {
367
- maxDirectoryNameLength: 255,
368
- maxPathLength: 4096,
369
- invalidCharacters: ["\0"],
370
- reservedNames: [],
371
- caseSensitive: true,
372
- };
373
- }
374
- }
375
-
376
- /**
377
- * Generate hash for collision resolution
378
- */
379
- private generateHash(input: string, length: number): string {
380
- return createHash("sha256")
381
- .update(input)
382
- .digest("hex")
383
- .substring(0, length);
384
- }
385
-
386
- /**
387
- * Expand tilde (~) to home directory
388
- */
389
- private expandTilde(path: string): string {
390
- if (path.startsWith("~/") || path === "~") {
391
- return path.replace(/^~/, homedir());
392
- }
393
- return path;
394
- }
395
- }
396
-
397
- /**
398
- * Default PathEncoder instance
399
- */
400
- export const pathEncoder = new PathEncoder();
@@ -1,40 +0,0 @@
1
- import path from "node:path";
2
- import fs from "node:fs";
3
-
4
- /**
5
- * Get the real path of a file or directory, even if it doesn't exist.
6
- * For non-existent paths, it resolves the real path of the nearest existing parent.
7
- */
8
- function getSafeRealPath(p: string): string {
9
- try {
10
- return fs.realpathSync(p);
11
- } catch {
12
- const parent = path.dirname(p);
13
- if (parent === p) return p; // Root reached
14
- return path.join(getSafeRealPath(parent), path.basename(p));
15
- }
16
- }
17
-
18
- /**
19
- * Check if a target path is inside a parent directory.
20
- * Resolves symlinks and handles absolute paths.
21
- * Returns true if target is the same as parent or is a subdirectory of parent.
22
- * @param target The path to check
23
- * @param parent The parent directory path
24
- * @returns boolean
25
- */
26
- export function isPathInside(target: string, parent: string): boolean {
27
- try {
28
- const absoluteTarget = path.resolve(target);
29
- const absoluteParent = path.resolve(parent);
30
-
31
- const realTarget = getSafeRealPath(absoluteTarget);
32
- const realParent = getSafeRealPath(absoluteParent);
33
-
34
- const relative = path.relative(realParent, realTarget);
35
-
36
- return !relative.startsWith("..") && !path.isAbsolute(relative);
37
- } catch {
38
- return false;
39
- }
40
- }
@@ -1,168 +0,0 @@
1
- import fs from "fs";
2
- import { PROMPT_HISTORY_FILE, DATA_DIRECTORY } from "./constants.js";
3
- import { logger } from "./globalLogger.js";
4
- import { PromptEntry } from "../types/history.js";
5
-
6
- /**
7
- * Ensure data directory exists
8
- */
9
- const ensureDataDirectory = (): void => {
10
- try {
11
- if (!fs.existsSync(DATA_DIRECTORY)) {
12
- fs.mkdirSync(DATA_DIRECTORY, { recursive: true });
13
- }
14
- } catch (error) {
15
- logger.debug("Failed to create data directory:", error);
16
- }
17
- };
18
-
19
- const MAX_HISTORY_ENTRIES = 1000;
20
-
21
- export class PromptHistoryManager {
22
- /**
23
- * Add a new prompt to history
24
- */
25
- static async addEntry(
26
- prompt: string,
27
- sessionId?: string,
28
- longTextMap?: Record<string, string>,
29
- workdir?: string,
30
- ): Promise<void> {
31
- try {
32
- if (!prompt.trim()) return;
33
-
34
- ensureDataDirectory();
35
- const entry: PromptEntry = {
36
- prompt,
37
- timestamp: Date.now(),
38
- sessionId,
39
- longTextMap,
40
- workdir,
41
- };
42
-
43
- const line = JSON.stringify(entry) + "\n";
44
- await fs.promises.appendFile(PROMPT_HISTORY_FILE, line, "utf-8");
45
-
46
- // Periodically trim history file to prevent it from growing too large
47
- // We do this randomly (1 in 50 chance) to avoid performance hit on every entry
48
- if (Math.random() < 0.02) {
49
- await this.trimHistory();
50
- }
51
- } catch (error) {
52
- logger.debug("Failed to add prompt to history:", error);
53
- }
54
- }
55
-
56
- /**
57
- * Trim history file to MAX_HISTORY_ENTRIES
58
- */
59
- private static async trimHistory(): Promise<void> {
60
- try {
61
- if (!fs.existsSync(PROMPT_HISTORY_FILE)) return;
62
-
63
- const data = await fs.promises.readFile(PROMPT_HISTORY_FILE, "utf-8");
64
- const lines = data.split("\n").filter((line) => line.trim());
65
-
66
- if (lines.length > MAX_HISTORY_ENTRIES * 1.2) {
67
- const trimmedLines = lines.slice(-MAX_HISTORY_ENTRIES);
68
- await fs.promises.writeFile(
69
- PROMPT_HISTORY_FILE,
70
- trimmedLines.join("\n") + "\n",
71
- "utf-8",
72
- );
73
- }
74
- } catch (error) {
75
- logger.debug("Failed to trim prompt history:", error);
76
- }
77
- }
78
-
79
- /**
80
- * Get all history entries
81
- */
82
- static async getHistory(options?: {
83
- sessionId?: string | string[];
84
- workdir?: string;
85
- }): Promise<PromptEntry[]> {
86
- try {
87
- if (!fs.existsSync(PROMPT_HISTORY_FILE)) {
88
- return [];
89
- }
90
-
91
- const data = await fs.promises.readFile(PROMPT_HISTORY_FILE, "utf-8");
92
- const lines = data.split("\n").filter((line) => line.trim());
93
-
94
- const entries: PromptEntry[] = lines
95
- .map((line) => {
96
- try {
97
- return JSON.parse(line) as PromptEntry;
98
- } catch {
99
- logger.debug("Failed to parse history line:", line);
100
- return null;
101
- }
102
- })
103
- .filter((entry): entry is PromptEntry => entry !== null);
104
-
105
- // Filter by sessionId if provided
106
- let filteredEntries = entries;
107
- if (options?.sessionId) {
108
- const sessionIds = Array.isArray(options.sessionId)
109
- ? options.sessionId
110
- : [options.sessionId];
111
- filteredEntries = filteredEntries.filter(
112
- (entry) => entry.sessionId && sessionIds.includes(entry.sessionId),
113
- );
114
- }
115
-
116
- // Filter by workdir if provided
117
- if (options?.workdir) {
118
- filteredEntries = filteredEntries.filter(
119
- (entry) => entry.workdir === options.workdir,
120
- );
121
- }
122
-
123
- // Deduplicate by prompt, keeping the most recent one
124
- const uniqueEntries: PromptEntry[] = [];
125
- const seenPrompts = new Set<string>();
126
-
127
- // Process from newest to oldest
128
- for (let i = filteredEntries.length - 1; i >= 0; i--) {
129
- const entry = filteredEntries[i];
130
- if (!seenPrompts.has(entry.prompt)) {
131
- uniqueEntries.push(entry);
132
- seenPrompts.add(entry.prompt);
133
- }
134
- }
135
-
136
- return uniqueEntries;
137
- } catch (error) {
138
- logger.debug("Failed to load prompt history:", error);
139
- return [];
140
- }
141
- }
142
-
143
- /**
144
- * Search history by query
145
- */
146
- static async searchHistory(
147
- query: string,
148
- options?: {
149
- sessionId?: string | string[];
150
- workdir?: string;
151
- },
152
- ): Promise<PromptEntry[]> {
153
- try {
154
- const history = await this.getHistory(options);
155
- if (!query.trim()) {
156
- return history;
157
- }
158
-
159
- const normalizedQuery = query.toLowerCase();
160
- return history.filter((entry) =>
161
- entry.prompt.toLowerCase().includes(normalizedQuery),
162
- );
163
- } catch (error) {
164
- logger.debug("Failed to search prompt history:", error);
165
- return [];
166
- }
167
- }
168
- }
@@ -1,35 +0,0 @@
1
- import path from "path";
2
- import process from "process";
3
- import { getPackageRoot } from "./configPaths.js";
4
-
5
- /**
6
- * Detect the current platform and architecture to find the correct bundled ripgrep binary.
7
- */
8
- function getPlatformKey(): string {
9
- const platform = process.platform;
10
- const arch = process.arch;
11
-
12
- if (platform === "darwin") {
13
- return arch === "arm64" ? "macos-aarch64" : "macos-x86_64";
14
- } else if (platform === "linux") {
15
- return arch === "arm64" ? "linux-aarch64" : "linux-x86_64";
16
- } else if (platform === "win32") {
17
- return arch === "arm64" ? "windows-aarch64" : "windows-x86_64";
18
- }
19
-
20
- throw new Error(`Unsupported platform: ${platform}-${arch}`);
21
- }
22
-
23
- const platformKey = getPlatformKey();
24
- const isWindows = platformKey.startsWith("windows");
25
- const binaryName = isWindows ? "rg.exe" : "rg";
26
-
27
- /**
28
- * Path to the ripgrep binary bundled in the vendor directory.
29
- * Uses findUpSync to locate the package root, working correctly even
30
- * when bundled (e.g. esbuild into a VS Code extension).
31
- */
32
- export const rgPath = path.join(
33
- getPackageRoot(),
34
- `vendor/ripgrep/${platformKey}/${binaryName}`,
35
- );