@wonderwhy-er/desktop-commander 0.1.34 → 0.1.36

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 (63) hide show
  1. package/LICENSE +2 -2
  2. package/README.md +186 -56
  3. package/dist/command-manager.d.ts +1 -7
  4. package/dist/command-manager.js +31 -50
  5. package/dist/config-manager.d.ts +28 -16
  6. package/dist/config-manager.js +124 -189
  7. package/dist/config.d.ts +2 -2
  8. package/dist/config.js +7 -4
  9. package/dist/error-handlers.js +4 -0
  10. package/dist/handlers/edit-search-handlers.d.ts +3 -1
  11. package/dist/handlers/edit-search-handlers.js +9 -19
  12. package/dist/handlers/filesystem-handlers.d.ts +0 -4
  13. package/dist/handlers/filesystem-handlers.js +11 -19
  14. package/dist/handlers/index.d.ts +0 -1
  15. package/dist/handlers/index.js +0 -1
  16. package/dist/index.js +19 -4
  17. package/dist/polyform-license-src/edit/edit.d.ts +15 -0
  18. package/dist/polyform-license-src/edit/edit.js +163 -0
  19. package/dist/polyform-license-src/edit/fuzzySearch.d.ts +30 -0
  20. package/dist/polyform-license-src/edit/fuzzySearch.js +121 -0
  21. package/dist/polyform-license-src/edit/handlers.d.ts +16 -0
  22. package/dist/polyform-license-src/edit/handlers.js +24 -0
  23. package/dist/polyform-license-src/edit/index.d.ts +12 -0
  24. package/dist/polyform-license-src/edit/index.js +13 -0
  25. package/dist/polyform-license-src/edit/schemas.d.ts +25 -0
  26. package/dist/polyform-license-src/edit/schemas.js +16 -0
  27. package/dist/polyform-license-src/index.d.ts +9 -0
  28. package/dist/polyform-license-src/index.js +10 -0
  29. package/dist/sandbox/index.d.ts +9 -0
  30. package/dist/sandbox/index.js +50 -0
  31. package/dist/sandbox/mac-sandbox.d.ts +19 -0
  32. package/dist/sandbox/mac-sandbox.js +174 -0
  33. package/dist/server.js +181 -176
  34. package/dist/setup-claude-server.js +554 -244
  35. package/dist/terminal-manager.d.ts +1 -1
  36. package/dist/terminal-manager.js +22 -3
  37. package/dist/tools/config.d.ts +0 -58
  38. package/dist/tools/config.js +44 -107
  39. package/dist/tools/debug-path.d.ts +1 -0
  40. package/dist/tools/debug-path.js +44 -0
  41. package/dist/tools/edit.d.ts +8 -6
  42. package/dist/tools/edit.js +165 -35
  43. package/dist/tools/execute.js +6 -6
  44. package/dist/tools/filesystem-fixed.d.ts +22 -0
  45. package/dist/tools/filesystem-fixed.js +176 -0
  46. package/dist/tools/filesystem.d.ts +4 -6
  47. package/dist/tools/filesystem.js +157 -87
  48. package/dist/tools/fuzzySearch.d.ts +22 -0
  49. package/dist/tools/fuzzySearch.js +113 -0
  50. package/dist/tools/pdf-reader.d.ts +13 -0
  51. package/dist/tools/pdf-reader.js +214 -0
  52. package/dist/tools/schemas.d.ts +29 -19
  53. package/dist/tools/schemas.js +15 -8
  54. package/dist/tools/search.js +5 -4
  55. package/dist/utils/capture.d.ts +15 -0
  56. package/dist/utils/capture.js +175 -0
  57. package/dist/utils/withTimeout.d.ts +11 -0
  58. package/dist/utils/withTimeout.js +52 -0
  59. package/dist/utils.d.ts +15 -1
  60. package/dist/utils.js +174 -41
  61. package/dist/version.d.ts +1 -1
  62. package/dist/version.js +1 -1
  63. package/package.json +2 -3
@@ -1,242 +1,177 @@
1
1
  import fs from 'fs/promises';
2
2
  import path from 'path';
3
+ import { existsSync } from 'fs';
4
+ import { mkdir } from 'fs/promises';
5
+ import os from 'os';
3
6
  import { CONFIG_FILE } from './config.js';
4
- import * as process from 'process';
5
7
  /**
6
- * Manages reading and writing server configuration
8
+ * Singleton config manager for the server
7
9
  */
8
- export class ConfigManager {
10
+ class ConfigManager {
9
11
  constructor() {
10
12
  this.config = {};
11
13
  this.initialized = false;
14
+ // Get user's home directory
15
+ // Define config directory and file paths
16
+ this.configPath = CONFIG_FILE;
12
17
  }
13
18
  /**
14
- * Load configuration from disk
19
+ * Initialize configuration - load from disk or create default
15
20
  */
16
- async loadConfig() {
21
+ async init() {
22
+ if (this.initialized)
23
+ return;
17
24
  try {
18
- console.error(`Loading config from ${CONFIG_FILE}...`);
19
- console.error(`Current working directory: ${process.cwd()}`);
20
- console.error(`Absolute config path: ${path.resolve(CONFIG_FILE)}`);
21
25
  // Ensure config directory exists
22
- const configDir = path.dirname(CONFIG_FILE);
23
- try {
24
- console.error(`Ensuring config directory exists: ${configDir}`);
25
- await fs.mkdir(configDir, { recursive: true });
26
- console.error(`Config directory ready: ${configDir}`);
27
- }
28
- catch (mkdirError) {
29
- console.error(`Error creating config directory: ${mkdirError.message}`);
30
- // Continue if directory already exists
31
- if (mkdirError.code !== 'EEXIST') {
32
- throw mkdirError;
33
- }
34
- }
35
- // Check if the directory exists and is writable
36
- try {
37
- const dirStats = await fs.stat(configDir);
38
- console.error(`Config directory exists: ${dirStats.isDirectory()}`);
39
- await fs.access(configDir, fs.constants.W_OK);
40
- console.error(`Directory ${configDir} is writable`);
41
- }
42
- catch (dirError) {
43
- console.error(`Config directory check error: ${dirError.message}`);
44
- }
45
- // Check file permissions
46
- try {
47
- const fileStats = await fs.stat(CONFIG_FILE).catch(() => null);
48
- if (fileStats) {
49
- console.error(`Config file exists, permissions: ${fileStats.mode.toString(8)}`);
50
- }
51
- else {
52
- console.error('Config file does not exist, will create');
53
- }
54
- }
55
- catch (statError) {
56
- console.error(`Error checking file stats: ${statError.message}`);
26
+ const configDir = path.dirname(this.configPath);
27
+ if (!existsSync(configDir)) {
28
+ await mkdir(configDir, { recursive: true });
57
29
  }
58
- let configData;
30
+ // Check if config file exists
59
31
  try {
60
- configData = await fs.readFile(CONFIG_FILE, 'utf-8');
61
- console.error(`Config file read successfully, content length: ${configData.length}`);
62
- }
63
- catch (readError) {
64
- console.error(`Error reading config file: ${readError.message}, code: ${readError.code}, stack: ${readError.stack}`);
65
- if (readError.code === 'ENOENT') {
66
- console.error('Config file does not exist, will create default');
67
- }
68
- else {
69
- throw readError;
70
- }
71
- }
72
- if (configData) {
73
- try {
74
- this.config = JSON.parse(configData);
75
- console.error(`Config parsed successfully: ${JSON.stringify(this.config, null, 2)}`);
76
- }
77
- catch (parseError) {
78
- console.error(`Failed to parse config JSON: ${parseError.message}`);
79
- // If file exists but has invalid JSON, use default empty config
80
- this.config = {};
81
- }
82
- }
83
- else {
84
- // If file doesn't exist, use default empty config
85
- this.config = {};
86
- }
87
- this.initialized = true;
88
- // Create default config file if it doesn't exist
89
- if (!configData) {
90
- console.error('Creating default config file');
32
+ await fs.access(this.configPath);
33
+ // Load existing config
34
+ const configData = await fs.readFile(this.configPath, 'utf8');
35
+ this.config = JSON.parse(configData);
36
+ }
37
+ catch (error) {
38
+ // Config file doesn't exist, create default
39
+ this.config = this.getDefaultConfig();
91
40
  await this.saveConfig();
92
41
  }
42
+ this.initialized = true;
93
43
  }
94
44
  catch (error) {
95
- console.error(`Unexpected error in loadConfig: ${error instanceof Error ? error.message : String(error)}`);
96
- console.error(error instanceof Error && error.stack ? error.stack : 'No stack trace available');
97
- // Initialize with empty config
98
- this.config = {};
99
- this.initialized = true; // Mark as initialized even with empty config
45
+ console.error('Failed to initialize config:', error);
46
+ // Fall back to default config in memory
47
+ this.config = this.getDefaultConfig();
48
+ this.initialized = true;
100
49
  }
101
- return this.config;
102
50
  }
103
51
  /**
104
- * Save current configuration to disk
52
+ * Alias for init() to maintain backward compatibility
53
+ */
54
+ async loadConfig() {
55
+ return this.init();
56
+ }
57
+ /**
58
+ * Create default configuration
59
+ */
60
+ getDefaultConfig() {
61
+ return {
62
+ blockedCommands: [
63
+ // Disk and partition management
64
+ "mkfs", // Create a filesystem on a device
65
+ "format", // Format a storage device (cross-platform)
66
+ "mount", // Mount a filesystem
67
+ "umount", // Unmount a filesystem
68
+ "fdisk", // Manipulate disk partition tables
69
+ "dd", // Convert and copy files, can write directly to disks
70
+ "parted", // Disk partition manipulator
71
+ "diskpart", // Windows disk partitioning utility
72
+ // System administration and user management
73
+ "sudo", // Execute command as superuser
74
+ "su", // Substitute user identity
75
+ "passwd", // Change user password
76
+ "adduser", // Add a user to the system
77
+ "useradd", // Create a new user
78
+ "usermod", // Modify user account
79
+ "groupadd", // Create a new group
80
+ "chsh", // Change login shell
81
+ "visudo", // Edit the sudoers file
82
+ // System control
83
+ "shutdown", // Shutdown the system
84
+ "reboot", // Restart the system
85
+ "halt", // Stop the system
86
+ "poweroff", // Power off the system
87
+ "init", // Change system runlevel
88
+ // Network and security
89
+ "iptables", // Linux firewall administration
90
+ "firewall", // Generic firewall command
91
+ "netsh", // Windows network configuration
92
+ // Windows system commands
93
+ "sfc", // System File Checker
94
+ "bcdedit", // Boot Configuration Data editor
95
+ "reg", // Windows registry editor
96
+ "net", // Network/user/service management
97
+ "sc", // Service Control manager
98
+ "runas", // Execute command as another user
99
+ "cipher", // Encrypt/decrypt files or wipe data
100
+ "takeown" // Take ownership of files
101
+ ],
102
+ defaultShell: os.platform() === 'win32' ? 'powershell.exe' : 'bash',
103
+ allowedDirectories: [],
104
+ telemetryEnabled: true // Default to opt-out approach (telemetry on by default)
105
+ };
106
+ }
107
+ /**
108
+ * Save config to disk
105
109
  */
106
110
  async saveConfig() {
107
111
  try {
108
- console.error(`Saving config to ${CONFIG_FILE}...`);
109
- console.error(`Current working directory: ${process.cwd()}`);
110
- console.error(`Absolute config path: ${path.resolve(CONFIG_FILE)}`);
111
- // Always try to create the config directory first
112
- const configDir = path.dirname(CONFIG_FILE);
113
- try {
114
- console.error(`Ensuring config directory exists: ${configDir}`);
115
- await fs.mkdir(configDir, { recursive: true });
116
- console.error(`Config directory ready: ${configDir}`);
117
- }
118
- catch (mkdirError) {
119
- console.error(`Failed to create directory: ${mkdirError.message}`);
120
- if (mkdirError.code !== 'EEXIST') {
121
- throw mkdirError;
122
- }
123
- }
124
- // Check directory permissions
125
- try {
126
- await fs.access(configDir, fs.constants.W_OK);
127
- console.error(`Directory ${configDir} is writable`);
128
- }
129
- catch (accessError) {
130
- console.error(`Directory access error: ${accessError.message}`);
131
- throw new Error(`Config directory is not writable: ${accessError.message}`);
132
- }
133
- const configJson = JSON.stringify(this.config, null, 2);
134
- console.error(`Config to save: ${configJson}`);
135
- try {
136
- // Try to write the file with explicit encoding and permissions
137
- await fs.writeFile(CONFIG_FILE, configJson, {
138
- encoding: 'utf-8',
139
- mode: 0o644 // Readable/writable by owner, readable by others
140
- });
141
- console.error('Config saved successfully');
142
- }
143
- catch (writeError) {
144
- console.error(`Write file error: ${writeError.message}, code: ${writeError.code}, stack: ${writeError.stack}`);
145
- throw writeError;
146
- }
112
+ await fs.writeFile(this.configPath, JSON.stringify(this.config, null, 2), 'utf8');
147
113
  }
148
114
  catch (error) {
149
- console.error(`Failed to save configuration: ${error instanceof Error ? error.message : String(error)}`);
150
- console.error(error instanceof Error && error.stack ? error.stack : 'No stack trace available');
151
- throw new Error(`Failed to save configuration: ${error instanceof Error ? error.message : String(error)}`);
115
+ console.error('Failed to save config:', error);
116
+ throw error;
152
117
  }
153
118
  }
119
+ /**
120
+ * Get the entire config
121
+ */
122
+ async getConfig() {
123
+ await this.init();
124
+ return { ...this.config };
125
+ }
154
126
  /**
155
127
  * Get a specific configuration value
156
128
  */
157
129
  async getValue(key) {
158
- if (!this.initialized) {
159
- console.error(`getValue for key "${key}" - loading config first`);
160
- await this.loadConfig();
161
- }
162
- console.error(`Getting value for key "${key}": ${JSON.stringify(this.config[key])}`);
130
+ await this.init();
163
131
  return this.config[key];
164
132
  }
165
133
  /**
166
134
  * Set a specific configuration value
167
135
  */
168
136
  async setValue(key, value) {
169
- console.error(`Setting value for key "${key}": ${JSON.stringify(value)}`);
170
- if (!this.initialized) {
171
- console.error('setValue - loading config first');
172
- await this.loadConfig();
137
+ await this.init();
138
+ // Special handling for telemetry opt-out
139
+ if (key === 'telemetryEnabled' && value === false) {
140
+ // Get the current value before changing it
141
+ const currentValue = this.config[key];
142
+ // Only capture the opt-out event if telemetry was previously enabled
143
+ if (currentValue !== false) {
144
+ // Import the capture function dynamically to avoid circular dependencies
145
+ const { capture } = await import('./utils/capture.js');
146
+ // Send a final telemetry event noting that the user has opted out
147
+ // This helps us track opt-out rates while respecting the user's choice
148
+ await capture('server_telemetry_opt_out', {
149
+ reason: 'user_disabled',
150
+ prev_value: currentValue
151
+ });
152
+ }
173
153
  }
154
+ // Update the value
174
155
  this.config[key] = value;
175
156
  await this.saveConfig();
176
157
  }
177
- /**
178
- * Get the entire configuration object
179
- */
180
- async getConfig() {
181
- if (!this.initialized) {
182
- console.error('getConfig - loading config first');
183
- await this.loadConfig();
184
- }
185
- console.error(`Getting full config: ${JSON.stringify(this.config, null, 2)}`);
186
- return { ...this.config }; // Return a copy to prevent untracked mutations
187
- }
188
158
  /**
189
159
  * Update multiple configuration values at once
190
160
  */
191
- async updateConfig(partialConfig) {
192
- console.error(`Updating config with: ${JSON.stringify(partialConfig, null, 2)}`);
193
- if (!this.initialized) {
194
- console.error('updateConfig - loading config first');
195
- await this.loadConfig();
196
- }
197
- this.config = {
198
- ...this.config,
199
- ...partialConfig
200
- };
161
+ async updateConfig(updates) {
162
+ await this.init();
163
+ this.config = { ...this.config, ...updates };
201
164
  await this.saveConfig();
202
165
  return { ...this.config };
203
166
  }
204
- }
205
- // Memory-only version that doesn't try to save to filesystem
206
- class MemoryConfigManager {
207
- constructor() {
208
- this.config = {};
209
- this.initialized = true;
210
- }
211
- async loadConfig() {
212
- console.error('Using memory-only configuration (no filesystem operations)');
213
- return this.config;
214
- }
215
- async saveConfig() {
216
- console.error('Memory-only configuration - changes will not persist after restart');
217
- // No-op - we don't save to filesystem
218
- return;
219
- }
220
- async getValue(key) {
221
- console.error(`Getting memory value for key "${key}": ${JSON.stringify(this.config[key])}`);
222
- return this.config[key];
223
- }
224
- async setValue(key, value) {
225
- console.error(`Setting memory value for key "${key}": ${JSON.stringify(value)}`);
226
- this.config[key] = value;
227
- }
228
- async getConfig() {
229
- console.error(`Getting full memory config: ${JSON.stringify(this.config, null, 2)}`);
230
- return { ...this.config };
231
- }
232
- async updateConfig(partialConfig) {
233
- console.error(`Updating memory config with: ${JSON.stringify(partialConfig, null, 2)}`);
234
- this.config = {
235
- ...this.config,
236
- ...partialConfig
237
- };
167
+ /**
168
+ * Reset configuration to defaults
169
+ */
170
+ async resetConfig() {
171
+ this.config = this.getDefaultConfig();
172
+ await this.saveConfig();
238
173
  return { ...this.config };
239
174
  }
240
175
  }
241
- // Export the appropriate manager based on the environment
176
+ // Export singleton instance
242
177
  export const configManager = new ConfigManager();
package/dist/config.d.ts CHANGED
@@ -1,4 +1,4 @@
1
+ export declare const USER_HOME: string;
1
2
  export declare const CONFIG_FILE: string;
2
- export declare const LOG_FILE: string;
3
- export declare const ERROR_LOG_FILE: string;
3
+ export declare const TOOL_CALL_FILE: string;
4
4
  export declare const DEFAULT_COMMAND_TIMEOUT = 1000;
package/dist/config.js CHANGED
@@ -1,6 +1,9 @@
1
1
  import path from 'path';
2
- import process from 'process';
3
- export const CONFIG_FILE = path.join(process.cwd(), 'config.json');
4
- export const LOG_FILE = path.join(process.cwd(), 'server.log');
5
- export const ERROR_LOG_FILE = path.join(process.cwd(), 'error.log');
2
+ import os from 'os';
3
+ // Use user's home directory for configuration files
4
+ export const USER_HOME = os.homedir();
5
+ const CONFIG_DIR = path.join(USER_HOME, '.claude-server-commander');
6
+ // Paths relative to the config directory
7
+ export const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
8
+ export const TOOL_CALL_FILE = path.join(CONFIG_DIR, 'claude_tool_call.log');
6
9
  export const DEFAULT_COMMAND_TIMEOUT = 1000; // milliseconds
@@ -1,9 +1,13 @@
1
+ import { capture } from "./utils/capture.js";
1
2
  /**
2
3
  * Creates a standard error response for tools
3
4
  * @param message The error message
4
5
  * @returns A ServerResult with the error message
5
6
  */
6
7
  export function createErrorResponse(message) {
8
+ capture('server_request_error', {
9
+ error: message
10
+ });
7
11
  return {
8
12
  content: [{ type: "text", text: `Error: ${message}` }],
9
13
  isError: true,
@@ -1,8 +1,10 @@
1
+ import { handleEditBlock } from '../tools/edit.js';
1
2
  import { ServerResult } from '../types.js';
2
3
  /**
3
4
  * Handle edit_block command
5
+ * Uses the enhanced implementation with multiple occurrence support and fuzzy matching
4
6
  */
5
- export declare function handleEditBlock(args: unknown): Promise<ServerResult>;
7
+ export { handleEditBlock };
6
8
  /**
7
9
  * Handle search_code command
8
10
  */
@@ -1,25 +1,13 @@
1
- import { parseEditBlock, performSearchReplace } from '../tools/edit.js';
2
1
  import { searchTextInFiles } from '../tools/search.js';
3
- import { EditBlockArgsSchema, SearchCodeArgsSchema } from '../tools/schemas.js';
4
- import { withTimeout } from '../utils.js';
5
- import { createErrorResponse } from '../error-handlers.js';
2
+ import { SearchCodeArgsSchema } from '../tools/schemas.js';
3
+ import { handleEditBlock } from '../tools/edit.js';
4
+ import { capture } from '../utils/capture.js';
5
+ import { withTimeout } from '../utils/withTimeout.js';
6
6
  /**
7
7
  * Handle edit_block command
8
+ * Uses the enhanced implementation with multiple occurrence support and fuzzy matching
8
9
  */
9
- export async function handleEditBlock(args) {
10
- try {
11
- const parsed = EditBlockArgsSchema.parse(args);
12
- const { filePath, searchReplace, error } = await parseEditBlock(parsed.blockContent);
13
- if (error) {
14
- return createErrorResponse(error);
15
- }
16
- return performSearchReplace(filePath, searchReplace);
17
- }
18
- catch (error) {
19
- const errorMessage = error instanceof Error ? error.message : String(error);
20
- return createErrorResponse(errorMessage);
21
- }
22
- }
10
+ export { handleEditBlock };
23
11
  /**
24
12
  * Handle search_code command
25
13
  */
@@ -50,7 +38,9 @@ export async function handleSearchCode(args) {
50
38
  delete globalThis.currentSearchProcess;
51
39
  }
52
40
  catch (error) {
53
- console.error('Error terminating search process:', error);
41
+ capture('server_request_error', {
42
+ error: 'Error terminating search process'
43
+ });
54
44
  }
55
45
  }
56
46
  if (results.length === 0) {
@@ -31,7 +31,3 @@ export declare function handleSearchFiles(args: unknown): Promise<ServerResult>;
31
31
  * Handle get_file_info command
32
32
  */
33
33
  export declare function handleGetFileInfo(args: unknown): Promise<ServerResult>;
34
- /**
35
- * Handle list_allowed_directories command
36
- */
37
- export declare function handleListAllowedDirectories(): ServerResult;
@@ -1,5 +1,5 @@
1
- import { readFile, readMultipleFiles, writeFile, createDirectory, listDirectory, moveFile, searchFiles, getFileInfo, listAllowedDirectories } from '../tools/filesystem.js';
2
- import { withTimeout } from '../utils.js';
1
+ import { readFile, readMultipleFiles, writeFile, createDirectory, listDirectory, moveFile, searchFiles, getFileInfo } from '../tools/filesystem.js';
2
+ import { withTimeout } from '../utils/withTimeout.js';
3
3
  import { createErrorResponse } from '../error-handlers.js';
4
4
  import { ReadFileArgsSchema, ReadMultipleFilesArgsSchema, WriteFileArgsSchema, CreateDirectoryArgsSchema, ListDirectoryArgsSchema, MoveFileArgsSchema, SearchFilesArgsSchema, GetFileInfoArgsSchema } from '../tools/schemas.js';
5
5
  /**
@@ -21,8 +21,7 @@ export async function handleReadFile(args) {
21
21
  const HANDLER_TIMEOUT = 60000; // 60 seconds total operation timeout
22
22
  const readFileOperation = async () => {
23
23
  const parsed = ReadFileArgsSchema.parse(args);
24
- // Explicitly cast the result to FileResult since we're passing true
25
- const fileResult = await readFile(parsed.path, true, parsed.isUrl);
24
+ const fileResult = await readFile(parsed.path, parsed.isUrl);
26
25
  if (fileResult.isImage) {
27
26
  // For image files, return as an image content type
28
27
  return {
@@ -47,9 +46,12 @@ export async function handleReadFile(args) {
47
46
  }
48
47
  };
49
48
  // Execute with timeout at the handler level
50
- return await withTimeout(readFileOperation(), HANDLER_TIMEOUT, 'Read file handler operation', {
51
- content: [{ type: "text", text: `Operation timed out after ${HANDLER_TIMEOUT / 1000} seconds. The file might be too large or on a slow/unresponsive storage device.` }],
52
- });
49
+ const result = await withTimeout(readFileOperation(), HANDLER_TIMEOUT, 'Read file handler operation', null);
50
+ if (result == null) {
51
+ // Handles the impossible case where withTimeout resolves to null instead of throwing
52
+ throw new Error('Failed to read the file');
53
+ }
54
+ return result;
53
55
  }
54
56
  /**
55
57
  * Handle read_multiple_files command
@@ -214,15 +216,5 @@ export async function handleGetFileInfo(args) {
214
216
  return createErrorResponse(errorMessage);
215
217
  }
216
218
  }
217
- /**
218
- * Handle list_allowed_directories command
219
- */
220
- export function handleListAllowedDirectories() {
221
- const directories = listAllowedDirectories();
222
- return {
223
- content: [{
224
- type: "text",
225
- text: `Allowed directories:\n${directories.join('\n')}`
226
- }],
227
- };
228
- }
219
+ // The listAllowedDirectories function has been removed
220
+ // Use get_config to retrieve the allowedDirectories configuration
@@ -1,5 +1,4 @@
1
1
  export * from './filesystem-handlers.js';
2
2
  export * from './terminal-handlers.js';
3
3
  export * from './process-handlers.js';
4
- export * from './command-handlers.js';
5
4
  export * from './edit-search-handlers.js';
@@ -2,5 +2,4 @@
2
2
  export * from './filesystem-handlers.js';
3
3
  export * from './terminal-handlers.js';
4
4
  export * from './process-handlers.js';
5
- export * from './command-handlers.js';
6
5
  export * from './edit-search-handlers.js';
package/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  import { FilteredStdioServerTransport } from './custom-stdio.js';
3
3
  import { server } from './server.js';
4
- import { commandManager } from './command-manager.js';
4
+ import { configManager } from './config-manager.js';
5
5
  import { join, dirname } from 'path';
6
6
  import { fileURLToPath, pathToFileURL } from 'url';
7
7
  import { platform } from 'os';
8
- import { capture } from './utils.js';
8
+ import { capture } from './utils/capture.js';
9
9
  const __filename = fileURLToPath(import.meta.url);
10
10
  const __dirname = dirname(__filename);
11
11
  const isWindows = platform() === 'win32';
@@ -81,12 +81,25 @@ async function runServer() {
81
81
  process.exit(1);
82
82
  });
83
83
  capture('run_server_start');
84
- // Load blocked commands from config file
85
- await commandManager.loadBlockedCommands();
84
+ try {
85
+ console.error("Loading configuration...");
86
+ await configManager.loadConfig();
87
+ console.error("Configuration loaded successfully");
88
+ }
89
+ catch (configError) {
90
+ console.error(`Failed to load configuration: ${configError instanceof Error ? configError.message : String(configError)}`);
91
+ console.error(configError instanceof Error && configError.stack ? configError.stack : 'No stack trace available');
92
+ console.error("Continuing with in-memory configuration only");
93
+ // Continue anyway - we'll use an in-memory config
94
+ }
95
+ console.error("Connecting server...");
86
96
  await server.connect(transport);
97
+ console.error("Server connected successfully");
87
98
  }
88
99
  catch (error) {
89
100
  const errorMessage = error instanceof Error ? error.message : String(error);
101
+ console.error(`FATAL ERROR: ${errorMessage}`);
102
+ console.error(error instanceof Error && error.stack ? error.stack : 'No stack trace available');
90
103
  process.stderr.write(JSON.stringify({
91
104
  type: 'error',
92
105
  timestamp: new Date().toISOString(),
@@ -100,6 +113,8 @@ async function runServer() {
100
113
  }
101
114
  runServer().catch(async (error) => {
102
115
  const errorMessage = error instanceof Error ? error.message : String(error);
116
+ console.error(`RUNTIME ERROR: ${errorMessage}`);
117
+ console.error(error instanceof Error && error.stack ? error.stack : 'No stack trace available');
103
118
  process.stderr.write(JSON.stringify({
104
119
  type: 'error',
105
120
  timestamp: new Date().toISOString(),
@@ -0,0 +1,15 @@
1
+ /**
2
+ * SPDX-License-Identifier: PolyForm-Small-Business-1.0.0
3
+ *
4
+ * Copyright (c) 2025 Desktope Commander MCP Contributors
5
+ *
6
+ * This file is licensed under the PolyForm Small Business License 1.0.0
7
+ * See the LICENSE file in the /src/polyform directory for the full license text.
8
+ */
9
+ import { ServerResult } from '../../types.js';
10
+ interface SearchReplace {
11
+ search: string;
12
+ replace: string;
13
+ }
14
+ export declare function performSearchReplace(filePath: string, block: SearchReplace, expectedReplacements?: number): Promise<ServerResult>;
15
+ export {};