@wonderwhy-er/desktop-commander 0.1.33 → 0.1.35

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 (50) hide show
  1. package/README.md +105 -36
  2. package/dist/command-manager.d.ts +1 -7
  3. package/dist/command-manager.js +31 -50
  4. package/dist/config-manager.d.ts +27 -16
  5. package/dist/config-manager.js +109 -191
  6. package/dist/config.js +8 -4
  7. package/dist/error-handlers.d.ts +7 -0
  8. package/dist/error-handlers.js +15 -0
  9. package/dist/handlers/command-handlers.d.ts +4 -18
  10. package/dist/handlers/command-handlers.js +15 -3
  11. package/dist/handlers/edit-search-handlers.d.ts +3 -12
  12. package/dist/handlers/edit-search-handlers.js +10 -7
  13. package/dist/handlers/filesystem-handlers.d.ts +9 -66
  14. package/dist/handlers/filesystem-handlers.js +106 -65
  15. package/dist/handlers/index.d.ts +0 -1
  16. package/dist/handlers/index.js +0 -1
  17. package/dist/handlers/process-handlers.d.ts +3 -12
  18. package/dist/handlers/terminal-handlers.d.ts +5 -24
  19. package/dist/index.js +18 -3
  20. package/dist/sandbox/index.d.ts +9 -0
  21. package/dist/sandbox/index.js +50 -0
  22. package/dist/sandbox/mac-sandbox.d.ts +19 -0
  23. package/dist/sandbox/mac-sandbox.js +174 -0
  24. package/dist/server.js +156 -176
  25. package/dist/setup-claude-server.js +98 -49
  26. package/dist/terminal-manager.d.ts +1 -1
  27. package/dist/terminal-manager.js +26 -4
  28. package/dist/tools/config.d.ts +0 -58
  29. package/dist/tools/config.js +44 -107
  30. package/dist/tools/debug-path.d.ts +1 -0
  31. package/dist/tools/debug-path.js +44 -0
  32. package/dist/tools/edit.d.ts +3 -1
  33. package/dist/tools/edit.js +19 -7
  34. package/dist/tools/execute.d.ts +4 -18
  35. package/dist/tools/execute.js +27 -8
  36. package/dist/tools/filesystem-fixed.d.ts +22 -0
  37. package/dist/tools/filesystem-fixed.js +176 -0
  38. package/dist/tools/filesystem.d.ts +4 -6
  39. package/dist/tools/filesystem.js +106 -75
  40. package/dist/tools/process.d.ts +3 -12
  41. package/dist/tools/process.js +12 -3
  42. package/dist/tools/schemas.d.ts +15 -14
  43. package/dist/tools/schemas.js +10 -6
  44. package/dist/tools/search.js +3 -3
  45. package/dist/types.d.ts +12 -0
  46. package/dist/utils.d.ts +5 -0
  47. package/dist/utils.js +92 -32
  48. package/dist/version.d.ts +1 -1
  49. package/dist/version.js +1 -1
  50. package/package.json +1 -2
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * @param requestedPath The path to validate
7
7
  * @returns Promise<string> The validated path
8
- * @throws Error if the path or its parent directories don't exist
8
+ * @throws Error if the path or its parent directories don't exist or if the path is not allowed
9
9
  */
10
10
  export declare function validatePath(requestedPath: string): Promise<string>;
11
11
  export interface FileResult {
@@ -16,17 +16,16 @@ export interface FileResult {
16
16
  /**
17
17
  * Read file content from a URL
18
18
  * @param url URL to fetch content from
19
- * @param returnMetadata Whether to return metadata with the content
20
19
  * @returns File content or file result with metadata
21
20
  */
22
- export declare function readFileFromUrl(url: string, returnMetadata?: boolean): Promise<string | FileResult>;
21
+ export declare function readFileFromUrl(url: string): Promise<FileResult>;
23
22
  /**
24
23
  * Read file content from the local filesystem
25
24
  * @param filePath Path to the file
26
25
  * @param returnMetadata Whether to return metadata with the content
27
26
  * @returns File content or file result with metadata
28
27
  */
29
- export declare function readFileFromDisk(filePath: string, returnMetadata?: boolean): Promise<string | FileResult>;
28
+ export declare function readFileFromDisk(filePath: string): Promise<FileResult>;
30
29
  /**
31
30
  * Read a file from either the local filesystem or a URL
32
31
  * @param filePath Path to the file or URL
@@ -34,7 +33,7 @@ export declare function readFileFromDisk(filePath: string, returnMetadata?: bool
34
33
  * @param isUrl Whether the path is a URL
35
34
  * @returns File content or file result with metadata
36
35
  */
37
- export declare function readFile(filePath: string, returnMetadata?: boolean, isUrl?: boolean): Promise<string | FileResult>;
36
+ export declare function readFile(filePath: string, isUrl?: boolean): Promise<FileResult>;
38
37
  export declare function writeFile(filePath: string, content: string): Promise<void>;
39
38
  export interface MultiFileResult {
40
39
  path: string;
@@ -49,4 +48,3 @@ export declare function listDirectory(dirPath: string): Promise<string[]>;
49
48
  export declare function moveFile(sourcePath: string, destinationPath: string): Promise<void>;
50
49
  export declare function searchFiles(rootPath: string, pattern: string): Promise<string[]>;
51
50
  export declare function getFileInfo(filePath: string): Promise<Record<string, any>>;
52
- export declare function listAllowedDirectories(): string[];
@@ -2,22 +2,35 @@ import fs from "fs/promises";
2
2
  import path from "path";
3
3
  import os from 'os';
4
4
  import fetch from 'cross-fetch';
5
- import { withTimeout } from '../utils.js';
6
- // Store allowed directories - temporarily allowing all paths
7
- // TODO: Make this configurable through a configuration file
8
- const allowedDirectories = [
9
- "/" // Root directory - effectively allows all paths
10
- ];
11
- // Original implementation commented out for future reference
12
- /*
13
- const allowedDirectories: string[] = [
14
- process.cwd(), // Current working directory
15
- os.homedir() // User's home directory
16
- ];
17
- */
5
+ import { capture, withTimeout } from '../utils.js';
6
+ import { configManager } from '../config-manager.js';
7
+ // Initialize allowed directories from configuration
8
+ async function getAllowedDirs() {
9
+ try {
10
+ let allowedDirectories;
11
+ const config = await configManager.getConfig();
12
+ if (config.allowedDirectories && Array.isArray(config.allowedDirectories)) {
13
+ allowedDirectories = config.allowedDirectories;
14
+ }
15
+ else {
16
+ // Fall back to default directories if not configured
17
+ allowedDirectories = [
18
+ os.homedir() // User's home directory
19
+ ];
20
+ // Update config with default
21
+ await configManager.setValue('allowedDirectories', allowedDirectories);
22
+ }
23
+ return allowedDirectories;
24
+ }
25
+ catch (error) {
26
+ console.error('Failed to initialize allowed directories:', error);
27
+ // Keep the default permissive path
28
+ }
29
+ return [];
30
+ }
18
31
  // Normalize all paths consistently
19
32
  function normalizePath(p) {
20
- return path.normalize(p).toLowerCase();
33
+ return path.normalize(expandHome(p)).toLowerCase();
21
34
  }
22
35
  function expandHome(filepath) {
23
36
  if (filepath.startsWith('~/') || filepath === '~') {
@@ -49,6 +62,47 @@ async function validateParentDirectories(directoryPath) {
49
62
  return validateParentDirectories(parentDir);
50
63
  }
51
64
  }
65
+ /**
66
+ * Checks if a path is within any of the allowed directories
67
+ *
68
+ * @param pathToCheck Path to check
69
+ * @returns boolean True if path is allowed
70
+ */
71
+ async function isPathAllowed(pathToCheck) {
72
+ // If root directory is allowed, all paths are allowed
73
+ const allowedDirectories = await getAllowedDirs();
74
+ if (allowedDirectories.includes('/') || allowedDirectories.length === 0) {
75
+ return true;
76
+ }
77
+ let normalizedPathToCheck = normalizePath(pathToCheck);
78
+ if (normalizedPathToCheck.slice(-1) === path.sep) {
79
+ normalizedPathToCheck = normalizedPathToCheck.slice(0, -1);
80
+ }
81
+ // Check if the path is within any allowed directory
82
+ const isAllowed = allowedDirectories.some(allowedDir => {
83
+ let normalizedAllowedDir = normalizePath(allowedDir);
84
+ if (normalizedAllowedDir.slice(-1) === path.sep) {
85
+ normalizedAllowedDir = normalizedAllowedDir.slice(0, -1);
86
+ }
87
+ // Check if path is exactly the allowed directory
88
+ if (normalizedPathToCheck === normalizedAllowedDir) {
89
+ return true;
90
+ }
91
+ // Check if path is a subdirectory of the allowed directory
92
+ // Make sure to add a separator to prevent partial directory name matches
93
+ // e.g. /home/user vs /home/username
94
+ const subdirCheck = normalizedPathToCheck.startsWith(normalizedAllowedDir + path.sep);
95
+ if (subdirCheck) {
96
+ return true;
97
+ }
98
+ // If allowed directory is the root (C:\ on Windows), allow access to the entire drive
99
+ if (normalizedAllowedDir === 'c:' && process.platform === 'win32') {
100
+ return normalizedPathToCheck.startsWith('c:');
101
+ }
102
+ return false;
103
+ });
104
+ return isAllowed;
105
+ }
52
106
  /**
53
107
  * Validates a path to ensure it can be accessed or created.
54
108
  * For existing paths, returns the real path (resolving symlinks).
@@ -56,7 +110,7 @@ async function validateParentDirectories(directoryPath) {
56
110
  *
57
111
  * @param requestedPath The path to validate
58
112
  * @returns Promise<string> The validated path
59
- * @throws Error if the path or its parent directories don't exist
113
+ * @throws Error if the path or its parent directories don't exist or if the path is not allowed
60
114
  */
61
115
  export async function validatePath(requestedPath) {
62
116
  const PATH_VALIDATION_TIMEOUT = 10000; // 10 seconds timeout
@@ -67,6 +121,10 @@ export async function validatePath(requestedPath) {
67
121
  const absolute = path.isAbsolute(expandedPath)
68
122
  ? path.resolve(expandedPath)
69
123
  : path.resolve(process.cwd(), expandedPath);
124
+ // Check if path is allowed
125
+ if (!(await isPathAllowed(absolute))) {
126
+ throw (`Path not allowed: ${requestedPath}. Must be within one of these directories: ${(await getAllowedDirs()).join(', ')}`);
127
+ }
70
128
  // Check if path exists
71
129
  try {
72
130
  const stats = await fs.stat(absolute);
@@ -87,17 +145,17 @@ export async function validatePath(requestedPath) {
87
145
  // Execute with timeout
88
146
  const result = await withTimeout(validationOperation(), PATH_VALIDATION_TIMEOUT, `Path validation for ${requestedPath}`, null);
89
147
  if (result === null) {
90
- throw new Error(`Path validation timed out after ${PATH_VALIDATION_TIMEOUT / 1000} seconds for: ${requestedPath}`);
148
+ // Return a path with an error indicator instead of throwing
149
+ throw new Error(`Path validation failed for path: ${requestedPath}`);
91
150
  }
92
151
  return result;
93
152
  }
94
153
  /**
95
154
  * Read file content from a URL
96
155
  * @param url URL to fetch content from
97
- * @param returnMetadata Whether to return metadata with the content
98
156
  * @returns File content or file result with metadata
99
157
  */
100
- export async function readFileFromUrl(url, returnMetadata) {
158
+ export async function readFileFromUrl(url) {
101
159
  // Import the MIME type utilities
102
160
  const { isImageFile } = await import('./mime-types.js');
103
161
  // Set up fetch with timeout
@@ -120,32 +178,22 @@ export async function readFileFromUrl(url, returnMetadata) {
120
178
  // For images, convert to base64
121
179
  const buffer = await response.arrayBuffer();
122
180
  const content = Buffer.from(buffer).toString('base64');
123
- if (returnMetadata === true) {
124
- return { content, mimeType: contentType, isImage };
125
- }
126
- else {
127
- return content;
128
- }
181
+ return { content, mimeType: contentType, isImage };
129
182
  }
130
183
  else {
131
184
  // For text content
132
185
  const content = await response.text();
133
- if (returnMetadata === true) {
134
- return { content, mimeType: contentType, isImage };
135
- }
136
- else {
137
- return content;
138
- }
186
+ return { content, mimeType: contentType, isImage };
139
187
  }
140
188
  }
141
189
  catch (error) {
142
190
  // Clear the timeout to prevent memory leaks
143
191
  clearTimeout(timeoutId);
144
- // Improve error message for timeout/abort cases
145
- if (error instanceof DOMException && error.name === 'AbortError') {
146
- throw new Error(`URL fetch timed out after ${FETCH_TIMEOUT_MS}ms: ${url}`);
147
- }
148
- throw new Error(`Failed to fetch URL: ${error instanceof Error ? error.message : String(error)}`);
192
+ // Return error information instead of throwing
193
+ const errorMessage = error instanceof DOMException && error.name === 'AbortError'
194
+ ? `URL fetch timed out after ${FETCH_TIMEOUT_MS}ms: ${url}`
195
+ : `Failed to fetch URL: ${error instanceof Error ? error.message : String(error)}`;
196
+ throw new Error(errorMessage);
149
197
  }
150
198
  }
151
199
  /**
@@ -154,7 +202,7 @@ export async function readFileFromUrl(url, returnMetadata) {
154
202
  * @param returnMetadata Whether to return metadata with the content
155
203
  * @returns File content or file result with metadata
156
204
  */
157
- export async function readFileFromDisk(filePath, returnMetadata) {
205
+ export async function readFileFromDisk(filePath) {
158
206
  // Import the MIME type utilities
159
207
  const { getMimeType, isImageFile } = await import('./mime-types.js');
160
208
  const validPath = await validatePath(filePath);
@@ -164,21 +212,18 @@ export async function readFileFromDisk(filePath, returnMetadata) {
164
212
  const MAX_SIZE = 100 * 1024; // 100KB limit
165
213
  if (stats.size > MAX_SIZE) {
166
214
  const message = `File too large (${(stats.size / 1024).toFixed(2)}KB > ${MAX_SIZE / 1024}KB limit)`;
167
- if (returnMetadata) {
168
- return {
169
- content: message,
170
- mimeType: 'text/plain',
171
- isImage: false
172
- };
173
- }
174
- else {
175
- return message;
176
- }
215
+ return {
216
+ content: message,
217
+ mimeType: 'text/plain',
218
+ isImage: false
219
+ };
177
220
  }
178
221
  }
179
222
  catch (error) {
223
+ console.error('error catch ' + error);
224
+ capture('server_read_file_error', { error: error });
180
225
  // If we can't stat the file, continue anyway and let the read operation handle errors
181
- console.error(`Failed to stat file ${validPath}:`, error);
226
+ //console.error(`Failed to stat file ${validPath}:`, error);
182
227
  }
183
228
  // Detect the MIME type based on file extension
184
229
  const mimeType = getMimeType(validPath);
@@ -190,41 +235,28 @@ export async function readFileFromDisk(filePath, returnMetadata) {
190
235
  // For image files, read as Buffer and convert to base64
191
236
  const buffer = await fs.readFile(validPath);
192
237
  const content = buffer.toString('base64');
193
- if (returnMetadata === true) {
194
- return { content, mimeType, isImage };
195
- }
196
- else {
197
- return content;
198
- }
238
+ return { content, mimeType, isImage };
199
239
  }
200
240
  else {
201
241
  // For all other files, try to read as UTF-8 text
202
242
  try {
203
243
  const content = await fs.readFile(validPath, "utf-8");
204
- if (returnMetadata === true) {
205
- return { content, mimeType, isImage };
206
- }
207
- else {
208
- return content;
209
- }
244
+ return { content, mimeType, isImage };
210
245
  }
211
246
  catch (error) {
212
247
  // If UTF-8 reading fails, treat as binary and return base64 but still as text
213
248
  const buffer = await fs.readFile(validPath);
214
249
  const content = `Binary file content (base64 encoded):\n${buffer.toString('base64')}`;
215
- if (returnMetadata === true) {
216
- return { content, mimeType: 'text/plain', isImage: false };
217
- }
218
- else {
219
- return content;
220
- }
250
+ return { content, mimeType: 'text/plain', isImage: false };
221
251
  }
222
252
  }
223
253
  };
224
254
  // Execute with timeout
225
- const result = await withTimeout(readOperation(), FILE_READ_TIMEOUT, `Read file operation for ${filePath}`, returnMetadata ?
226
- { content: `Operation timed out after ${FILE_READ_TIMEOUT / 1000} seconds`, mimeType: 'text/plain', isImage: false } :
227
- `Operation timed out after ${FILE_READ_TIMEOUT / 1000} seconds`);
255
+ const result = await withTimeout(readOperation(), FILE_READ_TIMEOUT, `Read file operation for ${filePath}`, null);
256
+ if (result == null) {
257
+ // Handles the impossible case where withTimeout resolves to null instead of throwing
258
+ throw new Error('Failed to read the file');
259
+ }
228
260
  return result;
229
261
  }
230
262
  /**
@@ -234,10 +266,10 @@ export async function readFileFromDisk(filePath, returnMetadata) {
234
266
  * @param isUrl Whether the path is a URL
235
267
  * @returns File content or file result with metadata
236
268
  */
237
- export async function readFile(filePath, returnMetadata, isUrl) {
269
+ export async function readFile(filePath, isUrl) {
238
270
  return isUrl
239
- ? readFileFromUrl(filePath, returnMetadata)
240
- : readFileFromDisk(filePath, returnMetadata);
271
+ ? readFileFromUrl(filePath)
272
+ : readFileFromDisk(filePath);
241
273
  }
242
274
  export async function writeFile(filePath, content) {
243
275
  const validPath = await validatePath(filePath);
@@ -247,7 +279,7 @@ export async function readMultipleFiles(paths) {
247
279
  return Promise.all(paths.map(async (filePath) => {
248
280
  try {
249
281
  const validPath = await validatePath(filePath);
250
- const fileResult = await readFile(validPath, true);
282
+ const fileResult = await readFile(validPath);
251
283
  return {
252
284
  path: filePath,
253
285
  content: typeof fileResult === 'string' ? fileResult : fileResult.content,
@@ -316,6 +348,5 @@ export async function getFileInfo(filePath) {
316
348
  permissions: stats.mode.toString(8).slice(-3),
317
349
  };
318
350
  }
319
- export function listAllowedDirectories() {
320
- return ["/ (All paths are currently allowed)"];
321
- }
351
+ // This function has been replaced with configManager.getConfig()
352
+ // Use get_config tool to retrieve allowedDirectories
@@ -1,12 +1,3 @@
1
- export declare function listProcesses(): Promise<{
2
- content: Array<{
3
- type: string;
4
- text: string;
5
- }>;
6
- }>;
7
- export declare function killProcess(args: unknown): Promise<{
8
- content: {
9
- type: string;
10
- text: string;
11
- }[];
12
- }>;
1
+ import { ServerResult } from '../types.js';
2
+ export declare function listProcesses(): Promise<ServerResult>;
3
+ export declare function killProcess(args: unknown): Promise<ServerResult>;
@@ -27,13 +27,19 @@ export async function listProcesses() {
27
27
  };
28
28
  }
29
29
  catch (error) {
30
- throw new Error('Failed to list processes');
30
+ return {
31
+ content: [{ type: "text", text: `Error: Failed to list processes: ${error instanceof Error ? error.message : String(error)}` }],
32
+ isError: true,
33
+ };
31
34
  }
32
35
  }
33
36
  export async function killProcess(args) {
34
37
  const parsed = KillProcessArgsSchema.safeParse(args);
35
38
  if (!parsed.success) {
36
- throw new Error(`Invalid arguments for kill_process: ${parsed.error}`);
39
+ return {
40
+ content: [{ type: "text", text: `Error: Invalid arguments for kill_process: ${parsed.error}` }],
41
+ isError: true,
42
+ };
37
43
  }
38
44
  try {
39
45
  process.kill(parsed.data.pid);
@@ -42,6 +48,9 @@ export async function killProcess(args) {
42
48
  };
43
49
  }
44
50
  catch (error) {
45
- throw new Error(`Failed to kill process: ${error instanceof Error ? error.message : String(error)}`);
51
+ return {
52
+ content: [{ type: "text", text: `Error: Failed to kill process: ${error instanceof Error ? error.message : String(error)}` }],
53
+ isError: true,
54
+ };
46
55
  }
47
56
  }
@@ -1,13 +1,28 @@
1
1
  import { z } from "zod";
2
+ export declare const GetConfigArgsSchema: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
3
+ export declare const SetConfigValueArgsSchema: z.ZodObject<{
4
+ key: z.ZodString;
5
+ value: z.ZodAny;
6
+ }, "strip", z.ZodTypeAny, {
7
+ key: string;
8
+ value?: any;
9
+ }, {
10
+ key: string;
11
+ value?: any;
12
+ }>;
13
+ export declare const ListProcessesArgsSchema: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
2
14
  export declare const ExecuteCommandArgsSchema: z.ZodObject<{
3
15
  command: z.ZodString;
4
16
  timeout_ms: z.ZodOptional<z.ZodNumber>;
17
+ shell: z.ZodOptional<z.ZodString>;
5
18
  }, "strip", z.ZodTypeAny, {
6
19
  command: string;
7
20
  timeout_ms?: number | undefined;
21
+ shell?: string | undefined;
8
22
  }, {
9
23
  command: string;
10
24
  timeout_ms?: number | undefined;
25
+ shell?: string | undefined;
11
26
  }>;
12
27
  export declare const ReadOutputArgsSchema: z.ZodObject<{
13
28
  pid: z.ZodNumber;
@@ -31,20 +46,6 @@ export declare const KillProcessArgsSchema: z.ZodObject<{
31
46
  }, {
32
47
  pid: number;
33
48
  }>;
34
- export declare const BlockCommandArgsSchema: z.ZodObject<{
35
- command: z.ZodString;
36
- }, "strip", z.ZodTypeAny, {
37
- command: string;
38
- }, {
39
- command: string;
40
- }>;
41
- export declare const UnblockCommandArgsSchema: z.ZodObject<{
42
- command: z.ZodString;
43
- }, "strip", z.ZodTypeAny, {
44
- command: string;
45
- }, {
46
- command: string;
47
- }>;
48
49
  export declare const ReadFileArgsSchema: z.ZodObject<{
49
50
  path: z.ZodString;
50
51
  isUrl: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
@@ -1,8 +1,18 @@
1
1
  import { z } from "zod";
2
+ console.error("Loading schemas.ts");
3
+ // Config tools schemas
4
+ export const GetConfigArgsSchema = z.object({});
5
+ export const SetConfigValueArgsSchema = z.object({
6
+ key: z.string(),
7
+ value: z.any(),
8
+ });
9
+ // Empty schemas
10
+ export const ListProcessesArgsSchema = z.object({});
2
11
  // Terminal tools schemas
3
12
  export const ExecuteCommandArgsSchema = z.object({
4
13
  command: z.string(),
5
14
  timeout_ms: z.number().optional(),
15
+ shell: z.string().optional(),
6
16
  });
7
17
  export const ReadOutputArgsSchema = z.object({
8
18
  pid: z.number(),
@@ -14,12 +24,6 @@ export const ListSessionsArgsSchema = z.object({});
14
24
  export const KillProcessArgsSchema = z.object({
15
25
  pid: z.number(),
16
26
  });
17
- export const BlockCommandArgsSchema = z.object({
18
- command: z.string(),
19
- });
20
- export const UnblockCommandArgsSchema = z.object({
21
- command: z.string(),
22
- });
23
27
  // Filesystem tools schemas
24
28
  export const ReadFileArgsSchema = z.object({
25
29
  path: z.string(),
@@ -3,6 +3,7 @@ import path from 'path';
3
3
  import fs from 'fs/promises';
4
4
  import { validatePath } from './filesystem.js';
5
5
  import { rgPath } from '@vscode/ripgrep';
6
+ import { capture } from "../utils.js";
6
7
  // Function to search file contents using ripgrep
7
8
  export async function searchCode(options) {
8
9
  const { rootPath, pattern, filePattern, ignoreCase = true, maxResults = 1000, includeHidden = false, contextLines = 0 } = options;
@@ -77,8 +78,8 @@ export async function searchCode(options) {
77
78
  }
78
79
  }
79
80
  catch (e) {
80
- // Skip non-JSON output
81
- console.error('Error parsing ripgrep output:', e);
81
+ capture('server_request_error', { error: 'Error parsing ripgrep output:' + e });
82
+ console.error();
82
83
  }
83
84
  }
84
85
  resolve(results);
@@ -164,7 +165,6 @@ export async function searchTextInFiles(options) {
164
165
  return await searchCode(options);
165
166
  }
166
167
  catch (error) {
167
- console.error('Ripgrep search failed, falling back to native implementation:', error);
168
168
  return searchCodeFallback({
169
169
  ...options,
170
170
  excludeDirs: ['node_modules', '.git', 'dist']
package/dist/types.d.ts CHANGED
@@ -29,3 +29,15 @@ export interface CompletedSession {
29
29
  startTime: Date;
30
30
  endTime: Date;
31
31
  }
32
+ export interface ServerResponseContent {
33
+ type: string;
34
+ text?: string;
35
+ data?: string;
36
+ mimeType?: string;
37
+ }
38
+ export interface ServerResult {
39
+ content: ServerResponseContent[];
40
+ isError?: boolean;
41
+ _meta?: Record<string, unknown>;
42
+ }
43
+ export type ToolHandler<T = unknown> = (args: T) => Promise<ServerResult>;
package/dist/utils.d.ts CHANGED
@@ -1,3 +1,8 @@
1
+ /**
2
+ * Send an event to Google Analytics
3
+ * @param event Event name
4
+ * @param properties Optional event properties
5
+ */
1
6
  export declare const capture: (event: string, properties?: any) => void;
2
7
  /**
3
8
  * Executes a promise with a timeout. If the promise doesn't resolve or reject within