starmux 0.12.0 → 0.13.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 (93) hide show
  1. package/dist/src/cli/mac-mcp-gateway.js +4 -3
  2. package/dist/src/cli/mac-mcp-gateway.js.map +1 -1
  3. package/dist/src/cli/starmux.js +1 -1
  4. package/dist/src/cli/starmux.js.map +1 -1
  5. package/dist/src/runtime-paths.js +3 -3
  6. package/dist/src/runtime-paths.js.map +1 -1
  7. package/dist/vendor/desktop-commander/LICENSE +21 -0
  8. package/dist/vendor/desktop-commander/dist/bootstrap.js +22 -0
  9. package/dist/vendor/desktop-commander/dist/command-manager.js +246 -0
  10. package/dist/vendor/desktop-commander/dist/config-field-definitions.js +37 -0
  11. package/dist/vendor/desktop-commander/dist/config-manager.js +634 -0
  12. package/dist/vendor/desktop-commander/dist/config-recovery.js +81 -0
  13. package/dist/vendor/desktop-commander/dist/config.js +19 -0
  14. package/dist/vendor/desktop-commander/dist/custom-stdio.js +358 -0
  15. package/dist/vendor/desktop-commander/dist/error-handlers.js +15 -0
  16. package/dist/vendor/desktop-commander/dist/handlers/edit-search-handlers.js +6 -0
  17. package/dist/vendor/desktop-commander/dist/handlers/filesystem-handlers.js +450 -0
  18. package/dist/vendor/desktop-commander/dist/handlers/history-handlers.js +67 -0
  19. package/dist/vendor/desktop-commander/dist/handlers/index.js +7 -0
  20. package/dist/vendor/desktop-commander/dist/handlers/process-handlers.js +15 -0
  21. package/dist/vendor/desktop-commander/dist/handlers/search-answers.js +172 -0
  22. package/dist/vendor/desktop-commander/dist/handlers/search-handlers.js +136 -0
  23. package/dist/vendor/desktop-commander/dist/handlers/terminal-handlers.js +35 -0
  24. package/dist/vendor/desktop-commander/dist/index.js +88 -0
  25. package/dist/vendor/desktop-commander/dist/search-manager.js +1262 -0
  26. package/dist/vendor/desktop-commander/dist/server.js +1414 -0
  27. package/dist/vendor/desktop-commander/dist/terminal-manager.js +757 -0
  28. package/dist/vendor/desktop-commander/dist/tools/config.js +211 -0
  29. package/dist/vendor/desktop-commander/dist/tools/edit.js +455 -0
  30. package/dist/vendor/desktop-commander/dist/tools/feedback.js +10 -0
  31. package/dist/vendor/desktop-commander/dist/tools/filesystem.js +1047 -0
  32. package/dist/vendor/desktop-commander/dist/tools/fuzzySearch.js +74 -0
  33. package/dist/vendor/desktop-commander/dist/tools/fuzzySearchCore.js +125 -0
  34. package/dist/vendor/desktop-commander/dist/tools/improved-process-tools.js +726 -0
  35. package/dist/vendor/desktop-commander/dist/tools/mime-types.js +28 -0
  36. package/dist/vendor/desktop-commander/dist/tools/pdf/extract-images.js +131 -0
  37. package/dist/vendor/desktop-commander/dist/tools/pdf/index.js +4 -0
  38. package/dist/vendor/desktop-commander/dist/tools/pdf/lib/pdf2md.js +78 -0
  39. package/dist/vendor/desktop-commander/dist/tools/pdf/manipulations.js +112 -0
  40. package/dist/vendor/desktop-commander/dist/tools/pdf/markdown.js +30 -0
  41. package/dist/vendor/desktop-commander/dist/tools/pdf/utils.js +45 -0
  42. package/dist/vendor/desktop-commander/dist/tools/process.js +90 -0
  43. package/dist/vendor/desktop-commander/dist/tools/prompts.js +259 -0
  44. package/dist/vendor/desktop-commander/dist/tools/schemas.js +242 -0
  45. package/dist/vendor/desktop-commander/dist/tools/usage.js +24 -0
  46. package/dist/vendor/desktop-commander/dist/types.js +1 -0
  47. package/dist/vendor/desktop-commander/dist/ui/config-editor/config-editor-runtime.js +150 -0
  48. package/dist/vendor/desktop-commander/dist/ui/config-editor/index.html +13 -0
  49. package/dist/vendor/desktop-commander/dist/ui/config-editor/styles.css +587 -0
  50. package/dist/vendor/desktop-commander/dist/ui/contracts.js +57 -0
  51. package/dist/vendor/desktop-commander/dist/ui/file-preview/index.html +16 -0
  52. package/dist/vendor/desktop-commander/dist/ui/file-preview/preview-runtime.js +471 -0
  53. package/dist/vendor/desktop-commander/dist/ui/file-preview/shared/preview-file-types.js +59 -0
  54. package/dist/vendor/desktop-commander/dist/ui/file-preview/styles.css +1631 -0
  55. package/dist/vendor/desktop-commander/dist/ui/resources.js +93 -0
  56. package/dist/vendor/desktop-commander/dist/utils/ab-test.js +122 -0
  57. package/dist/vendor/desktop-commander/dist/utils/atomic-write.js +80 -0
  58. package/dist/vendor/desktop-commander/dist/utils/capture.js +40 -0
  59. package/dist/vendor/desktop-commander/dist/utils/dockerPrompt.js +9 -0
  60. package/dist/vendor/desktop-commander/dist/utils/exit-process.js +31 -0
  61. package/dist/vendor/desktop-commander/dist/utils/feature-flags.js +18 -0
  62. package/dist/vendor/desktop-commander/dist/utils/files/base.js +5 -0
  63. package/dist/vendor/desktop-commander/dist/utils/files/binary.js +65 -0
  64. package/dist/vendor/desktop-commander/dist/utils/files/docx.js +694 -0
  65. package/dist/vendor/desktop-commander/dist/utils/files/excel.js +497 -0
  66. package/dist/vendor/desktop-commander/dist/utils/files/factory.js +168 -0
  67. package/dist/vendor/desktop-commander/dist/utils/files/image.js +89 -0
  68. package/dist/vendor/desktop-commander/dist/utils/files/index.js +14 -0
  69. package/dist/vendor/desktop-commander/dist/utils/files/pdf.js +124 -0
  70. package/dist/vendor/desktop-commander/dist/utils/files/text.js +423 -0
  71. package/dist/vendor/desktop-commander/dist/utils/fuzzySearchLogger.js +126 -0
  72. package/dist/vendor/desktop-commander/dist/utils/internal-facts.js +23 -0
  73. package/dist/vendor/desktop-commander/dist/utils/lazy-package.js +44 -0
  74. package/dist/vendor/desktop-commander/dist/utils/lineEndingHandler.js +77 -0
  75. package/dist/vendor/desktop-commander/dist/utils/logger.js +72 -0
  76. package/dist/vendor/desktop-commander/dist/utils/mcp-ui-ab-test.js +62 -0
  77. package/dist/vendor/desktop-commander/dist/utils/open-browser.js +2 -0
  78. package/dist/vendor/desktop-commander/dist/utils/process-detection.js +260 -0
  79. package/dist/vendor/desktop-commander/dist/utils/process-tree.js +223 -0
  80. package/dist/vendor/desktop-commander/dist/utils/rename.js +74 -0
  81. package/dist/vendor/desktop-commander/dist/utils/ripgrep-resolver.js +69 -0
  82. package/dist/vendor/desktop-commander/dist/utils/shell.js +187 -0
  83. package/dist/vendor/desktop-commander/dist/utils/system-info.js +727 -0
  84. package/dist/vendor/desktop-commander/dist/utils/terminal-timestamps.js +18 -0
  85. package/dist/vendor/desktop-commander/dist/utils/toolHistory.js +309 -0
  86. package/dist/vendor/desktop-commander/dist/utils/trackTools.js +55 -0
  87. package/dist/vendor/desktop-commander/dist/utils/unsupportedParams.js +66 -0
  88. package/dist/vendor/desktop-commander/dist/utils/usageTracker.js +225 -0
  89. package/dist/vendor/desktop-commander/dist/utils/welcome-onboarding.js +2 -0
  90. package/dist/vendor/desktop-commander/dist/utils/withTimeout.js +85 -0
  91. package/dist/vendor/desktop-commander/dist/version.js +1 -0
  92. package/dist/vendor/desktop-commander/package.json +15 -0
  93. package/package.json +14 -2
@@ -0,0 +1,81 @@
1
+ import fs from 'fs/promises';
2
+ import path from 'path';
3
+ import { existsSync } from 'fs';
4
+ /**
5
+ * The settings still readable in a corrupt config.json: the longest beginning
6
+ * of it that is a JSON object once closed, so every complete top-level setting
7
+ * before the first error. {} when there is none.
8
+ */
9
+ export function salvageSettings(text) {
10
+ const body = text.charCodeAt(0) === 0xfeff ? text.slice(1) : text;
11
+ // A readable beginning can end at each comma between top-level settings, or at
12
+ // the brace that closes the object (anything after it is ignored)
13
+ const ends = [];
14
+ let depth = 0;
15
+ let inString = false;
16
+ let escaped = false;
17
+ for (let i = 0; i < body.length; i++) {
18
+ const char = body[i];
19
+ if (inString) {
20
+ if (escaped)
21
+ escaped = false;
22
+ else if (char === '\\')
23
+ escaped = true;
24
+ else if (char === '"')
25
+ inString = false;
26
+ }
27
+ else if (char === '"') {
28
+ inString = true;
29
+ }
30
+ else if (char === '{' || char === '[') {
31
+ depth++;
32
+ }
33
+ else if (char === '}' || char === ']') {
34
+ if (--depth === 0) {
35
+ ends.push(i);
36
+ break;
37
+ }
38
+ }
39
+ else if (char === ',' && depth === 1) {
40
+ ends.push(i);
41
+ }
42
+ }
43
+ for (const end of ends.reverse()) {
44
+ try {
45
+ return JSON.parse(body.slice(0, end) + '}');
46
+ }
47
+ catch {
48
+ // Not valid JSON up to here either, so try a shorter beginning
49
+ }
50
+ }
51
+ return {};
52
+ }
53
+ /**
54
+ * What a corrupt config.json is recovered as: the defaults, then the settings
55
+ * last read (while running), then the settings salvaged from it. The welcome
56
+ * page stays off, as for any existing install.
57
+ */
58
+ export function buildRecoveredConfig(defaults, lastRead, text) {
59
+ const { version: _version, ...settings } = lastRead ?? {};
60
+ return { ...defaults, ...settings, ...salvageSettings(text), welcomeOnboardingEligible: false, pendingWelcomeOnboarding: false };
61
+ }
62
+ /**
63
+ * Backs up a corrupt config.json as config.json.corrupt.<ms>.<pid>, unless the
64
+ * newest backup already holds `bytes` (a recovery tried again after its write
65
+ * failed). Returns the backup's name, or null when there is no config.json.
66
+ */
67
+ export async function backupCorruptConfig(configPath, bytes) {
68
+ if (!existsSync(configPath))
69
+ return null;
70
+ const folder = path.dirname(configPath);
71
+ const prefix = `${path.basename(configPath)}.corrupt.`;
72
+ const newest = (await fs.readdir(folder).catch(() => []))
73
+ .filter((name) => name.startsWith(prefix))
74
+ .sort((a, b) => parseInt(a.slice(prefix.length), 10) - parseInt(b.slice(prefix.length), 10))
75
+ .pop();
76
+ if (newest && (await fs.readFile(path.join(folder, newest)).catch(() => null))?.equals(bytes))
77
+ return newest;
78
+ const name = `${prefix}${Date.now()}.${process.pid}`;
79
+ await fs.copyFile(configPath, path.join(folder, name));
80
+ return name;
81
+ }
@@ -0,0 +1,19 @@
1
+ import path from 'path';
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');
9
+ export const TOOL_CALL_FILE_MAX_SIZE = 1024 * 1024 * 10; // 10 MB
10
+ export const DEFAULT_COMMAND_TIMEOUT = 1000; // milliseconds
11
+ // Longest one process call (start_process, interact_with_process,
12
+ // read_process_output) blocks, whatever timeout_ms asks for; the process keeps
13
+ // running and the caller reads the rest with read_process_output. It stays well
14
+ // under 60 s: that is the MCP SDK's default request timeout
15
+ // (DEFAULT_REQUEST_TIMEOUT_MSEC), which Claude Desktop and the remote device's
16
+ // own client use, and an answer capped at 60 s arrived just after the client had
17
+ // given up (-32001 "Request timed out", #447). The margin leaves time to build
18
+ // and deliver the answer.
19
+ export const MAX_PROCESS_WAIT_MS = 50000;
@@ -0,0 +1,358 @@
1
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
2
+ import process from "node:process";
3
+ /**
4
+ * Enhanced StdioServerTransport that wraps console output in valid JSON-RPC structures
5
+ * instead of filtering them out. This prevents crashes while maintaining debug visibility.
6
+ */
7
+ export class FilteredStdioServerTransport extends StdioServerTransport {
8
+ constructor() {
9
+ super();
10
+ this.isInitialized = false;
11
+ this.messageBuffer = [];
12
+ this.clientName = 'unknown';
13
+ this.disableNotifications = false;
14
+ // Store original methods
15
+ this.originalConsole = {
16
+ log: console.log,
17
+ warn: console.warn,
18
+ error: console.error,
19
+ debug: console.debug,
20
+ info: console.info,
21
+ };
22
+ this.originalStdoutWrite = process.stdout.write;
23
+ // Setup console redirection
24
+ this.setupConsoleRedirection();
25
+ // Setup stdout filtering for any other output
26
+ this.setupStdoutFiltering();
27
+ // Note: We defer the initialization notification until enableNotifications() is called
28
+ // to ensure MCP protocol compliance - notifications must not be sent before initialization
29
+ }
30
+ /**
31
+ * Call this method after MCP initialization is complete to enable JSON-RPC notifications
32
+ */
33
+ enableNotifications() {
34
+ this.isInitialized = true;
35
+ // Check if notifications should be disabled based on client
36
+ if (this.disableNotifications) {
37
+ // Clear buffer without sending - just log to stderr instead
38
+ if (this.messageBuffer.length > 0) {
39
+ process.stderr.write(`[INFO] ${this.messageBuffer.length} buffered messages suppressed for ${this.clientName}\n`);
40
+ }
41
+ this.messageBuffer = [];
42
+ return;
43
+ }
44
+ // Send the deferred initialization notification first
45
+ this.sendLogNotification('info', ['Enhanced FilteredStdioServerTransport initialized']);
46
+ // Replay all buffered messages in chronological order
47
+ if (this.messageBuffer.length > 0) {
48
+ this.sendLogNotification('info', [`Replaying ${this.messageBuffer.length} buffered initialization messages`]);
49
+ this.messageBuffer
50
+ .sort((a, b) => a.timestamp - b.timestamp)
51
+ .forEach(msg => {
52
+ this.sendLogNotification(msg.level, msg.args);
53
+ });
54
+ // Clear the buffer
55
+ this.messageBuffer = [];
56
+ }
57
+ this.sendLogNotification('info', ['JSON-RPC notifications enabled']);
58
+ }
59
+ /**
60
+ * Configure client-specific behavior
61
+ * Call this BEFORE enableNotifications()
62
+ */
63
+ configureForClient(clientName) {
64
+ this.clientName = clientName.toLowerCase();
65
+ // Detect Cline and disable notifications
66
+ if (this.clientName.includes('cline') ||
67
+ this.clientName.includes('vscode') ||
68
+ this.clientName === 'claude-dev') {
69
+ this.disableNotifications = true;
70
+ process.stderr.write(`[INFO] Desktop Commander: Notifications disabled for ${clientName}\n`);
71
+ }
72
+ }
73
+ /**
74
+ * Check if notifications are enabled
75
+ */
76
+ get isNotificationsEnabled() {
77
+ return this.isInitialized;
78
+ }
79
+ /**
80
+ * Get the current count of buffered messages
81
+ */
82
+ get bufferedMessageCount() {
83
+ return this.messageBuffer.length;
84
+ }
85
+ setupConsoleRedirection() {
86
+ console.log = (...args) => {
87
+ if (this.isInitialized) {
88
+ this.sendLogNotification("info", args);
89
+ }
90
+ else {
91
+ // Buffer for later replay to client
92
+ this.messageBuffer.push({
93
+ level: "info",
94
+ args,
95
+ timestamp: Date.now()
96
+ });
97
+ }
98
+ };
99
+ console.info = (...args) => {
100
+ if (this.isInitialized) {
101
+ this.sendLogNotification("info", args);
102
+ }
103
+ else {
104
+ this.messageBuffer.push({
105
+ level: "info",
106
+ args,
107
+ timestamp: Date.now()
108
+ });
109
+ }
110
+ };
111
+ console.warn = (...args) => {
112
+ if (this.isInitialized) {
113
+ this.sendLogNotification("warning", args);
114
+ }
115
+ else {
116
+ this.messageBuffer.push({
117
+ level: "warning",
118
+ args,
119
+ timestamp: Date.now()
120
+ });
121
+ }
122
+ };
123
+ console.error = (...args) => {
124
+ if (this.isInitialized) {
125
+ this.sendLogNotification("error", args);
126
+ }
127
+ else {
128
+ this.messageBuffer.push({
129
+ level: "error",
130
+ args,
131
+ timestamp: Date.now()
132
+ });
133
+ }
134
+ };
135
+ console.debug = (...args) => {
136
+ if (this.isInitialized) {
137
+ this.sendLogNotification("debug", args);
138
+ }
139
+ else {
140
+ this.messageBuffer.push({
141
+ level: "debug",
142
+ args,
143
+ timestamp: Date.now()
144
+ });
145
+ }
146
+ };
147
+ }
148
+ setupStdoutFiltering() {
149
+ process.stdout.write = (buffer, encoding, callback) => {
150
+ // Handle different call signatures
151
+ if (typeof buffer === 'string') {
152
+ const trimmed = buffer.trim();
153
+ // Check if this looks like a valid JSON-RPC message
154
+ if (trimmed.startsWith('{') && (trimmed.includes('"jsonrpc"') ||
155
+ trimmed.includes('"method"') ||
156
+ trimmed.includes('"id"'))) {
157
+ // This looks like a valid JSON-RPC message, allow it
158
+ return this.originalStdoutWrite.call(process.stdout, buffer, encoding, callback);
159
+ }
160
+ else if (trimmed.length > 0) {
161
+ // Non-JSON-RPC output, wrap it in a log notification
162
+ if (this.isInitialized) {
163
+ this.sendLogNotification("info", [buffer.replace(/\n$/, '')]);
164
+ }
165
+ else {
166
+ // Buffer for later replay to client
167
+ this.messageBuffer.push({
168
+ level: "info",
169
+ args: [buffer.replace(/\n$/, '')],
170
+ timestamp: Date.now()
171
+ });
172
+ }
173
+ if (callback)
174
+ callback();
175
+ return true;
176
+ }
177
+ }
178
+ // For non-string buffers or empty strings, let them through
179
+ return this.originalStdoutWrite.call(process.stdout, buffer, encoding, callback);
180
+ };
181
+ }
182
+ sendLogNotification(level, args) {
183
+ // Skip if notifications are disabled (e.g., for Cline)
184
+ if (this.disableNotifications) {
185
+ return;
186
+ }
187
+ try {
188
+ // For data, we can send structured data or string according to MCP spec
189
+ let data;
190
+ if (args.length === 1 && typeof args[0] === 'object' && args[0] !== null) {
191
+ // Single object - send as structured data
192
+ data = args[0];
193
+ }
194
+ else {
195
+ // Multiple args or primitives - convert to string
196
+ data = args.map(arg => {
197
+ if (typeof arg === 'object') {
198
+ try {
199
+ return JSON.stringify(arg, null, 2);
200
+ }
201
+ catch {
202
+ return String(arg);
203
+ }
204
+ }
205
+ return String(arg);
206
+ }).join(' ');
207
+ }
208
+ const notification = {
209
+ jsonrpc: "2.0",
210
+ method: "notifications/message",
211
+ params: {
212
+ level: level,
213
+ logger: "desktop-commander",
214
+ data: data
215
+ }
216
+ };
217
+ // Send as valid JSON-RPC notification
218
+ this.originalStdoutWrite.call(process.stdout, JSON.stringify(notification) + '\n');
219
+ }
220
+ catch (error) {
221
+ // Fallback to a simple JSON-RPC error notification if JSON serialization fails
222
+ const fallbackNotification = {
223
+ jsonrpc: "2.0",
224
+ method: "notifications/message",
225
+ params: {
226
+ level: "error",
227
+ logger: "desktop-commander",
228
+ data: `Log serialization failed: ${args.join(' ')}`
229
+ }
230
+ };
231
+ this.originalStdoutWrite.call(process.stdout, JSON.stringify(fallbackNotification) + '\n');
232
+ }
233
+ }
234
+ /**
235
+ * Public method to send log notifications from anywhere in the application
236
+ * Now properly buffers messages before MCP initialization to avoid breaking stdio protocol
237
+ */
238
+ sendLog(level, message, data) {
239
+ // Skip if notifications are disabled (e.g., for Cline)
240
+ if (this.disableNotifications) {
241
+ return;
242
+ }
243
+ // Buffer messages before initialization to avoid breaking MCP protocol
244
+ // MCP requires client to send first message - server cannot write to stdout before that
245
+ if (!this.isInitialized) {
246
+ this.messageBuffer.push({
247
+ level,
248
+ args: [data ? { message, ...data } : message],
249
+ timestamp: Date.now()
250
+ });
251
+ return;
252
+ }
253
+ try {
254
+ const notification = {
255
+ jsonrpc: "2.0",
256
+ method: "notifications/message",
257
+ params: {
258
+ level: level,
259
+ logger: "desktop-commander",
260
+ data: data ? { message, ...data } : message
261
+ }
262
+ };
263
+ this.originalStdoutWrite.call(process.stdout, JSON.stringify(notification) + '\n');
264
+ }
265
+ catch (error) {
266
+ // Fallback to basic JSON-RPC notification
267
+ const fallbackNotification = {
268
+ jsonrpc: "2.0",
269
+ method: "notifications/message",
270
+ params: {
271
+ level: "error",
272
+ logger: "desktop-commander",
273
+ data: `sendLog failed: ${message}`
274
+ }
275
+ };
276
+ this.originalStdoutWrite.call(process.stdout, JSON.stringify(fallbackNotification) + '\n');
277
+ }
278
+ }
279
+ /**
280
+ * Send a progress notification (useful for long-running operations)
281
+ */
282
+ sendProgress(token, value, total) {
283
+ // Don't send progress before initialization - would break MCP protocol
284
+ if (!this.isInitialized) {
285
+ return;
286
+ }
287
+ try {
288
+ const notification = {
289
+ jsonrpc: "2.0",
290
+ method: "notifications/progress",
291
+ params: {
292
+ progressToken: token,
293
+ value: value,
294
+ ...(total && { total })
295
+ }
296
+ };
297
+ this.originalStdoutWrite.call(process.stdout, JSON.stringify(notification) + '\n');
298
+ }
299
+ catch (error) {
300
+ // Fallback to basic JSON-RPC notification for progress
301
+ const fallbackNotification = {
302
+ jsonrpc: "2.0",
303
+ method: "notifications/message",
304
+ params: {
305
+ level: "info",
306
+ logger: "desktop-commander",
307
+ data: `Progress ${token}: ${value}${total ? `/${total}` : ''}`
308
+ }
309
+ };
310
+ this.originalStdoutWrite.call(process.stdout, JSON.stringify(fallbackNotification) + '\n');
311
+ }
312
+ }
313
+ /**
314
+ * Send a custom notification with any method name
315
+ */
316
+ sendCustomNotification(method, params) {
317
+ // Don't send custom notifications before initialization - would break MCP protocol
318
+ if (!this.isInitialized) {
319
+ return;
320
+ }
321
+ try {
322
+ const notification = {
323
+ jsonrpc: "2.0",
324
+ method: method,
325
+ params: params
326
+ };
327
+ this.originalStdoutWrite.call(process.stdout, JSON.stringify(notification) + '\n');
328
+ }
329
+ catch (error) {
330
+ // Fallback to basic JSON-RPC notification for custom notifications
331
+ const fallbackNotification = {
332
+ jsonrpc: "2.0",
333
+ method: "notifications/message",
334
+ params: {
335
+ level: "error",
336
+ logger: "desktop-commander",
337
+ data: `Custom notification failed: ${method}: ${JSON.stringify(params)}`
338
+ }
339
+ };
340
+ this.originalStdoutWrite.call(process.stdout, JSON.stringify(fallbackNotification) + '\n');
341
+ }
342
+ }
343
+ /**
344
+ * Cleanup method to restore original console methods if needed
345
+ */
346
+ cleanup() {
347
+ if (this.originalConsole) {
348
+ console.log = this.originalConsole.log;
349
+ console.warn = this.originalConsole.warn;
350
+ console.error = this.originalConsole.error;
351
+ console.debug = this.originalConsole.debug;
352
+ console.info = this.originalConsole.info;
353
+ }
354
+ if (this.originalStdoutWrite) {
355
+ process.stdout.write = this.originalStdoutWrite;
356
+ }
357
+ }
358
+ }
@@ -0,0 +1,15 @@
1
+ import { capture } from "./utils/capture.js";
2
+ /**
3
+ * Creates a standard error response for tools
4
+ * @param message The error message
5
+ * @returns A ServerResult with the error message
6
+ */
7
+ export function createErrorResponse(message) {
8
+ capture('server_request_error', {
9
+ error: message
10
+ });
11
+ return {
12
+ content: [{ type: "text", text: `Error: ${message}` }],
13
+ isError: true,
14
+ };
15
+ }
@@ -0,0 +1,6 @@
1
+ import { handleEditBlock } from '../tools/edit.js';
2
+ /**
3
+ * Handle edit_block command
4
+ * Uses the enhanced implementation with multiple occurrence support and fuzzy matching
5
+ */
6
+ export { handleEditBlock };