starmux 0.12.0 → 0.13.1

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 (96) hide show
  1. package/README.md +2 -2
  2. package/dist/src/cli/mac-mcp-gateway.js +4 -3
  3. package/dist/src/cli/mac-mcp-gateway.js.map +1 -1
  4. package/dist/src/cli/starmux.js +1 -1
  5. package/dist/src/cli/starmux.js.map +1 -1
  6. package/dist/src/runtime-paths.js +3 -3
  7. package/dist/src/runtime-paths.js.map +1 -1
  8. package/dist/vendor/desktop-commander/LICENSE +21 -0
  9. package/dist/vendor/desktop-commander/dist/bootstrap.js +22 -0
  10. package/dist/vendor/desktop-commander/dist/command-manager.js +246 -0
  11. package/dist/vendor/desktop-commander/dist/config-field-definitions.js +37 -0
  12. package/dist/vendor/desktop-commander/dist/config-manager.js +634 -0
  13. package/dist/vendor/desktop-commander/dist/config-recovery.js +81 -0
  14. package/dist/vendor/desktop-commander/dist/config.js +19 -0
  15. package/dist/vendor/desktop-commander/dist/custom-stdio.js +358 -0
  16. package/dist/vendor/desktop-commander/dist/error-handlers.js +15 -0
  17. package/dist/vendor/desktop-commander/dist/handlers/edit-search-handlers.js +6 -0
  18. package/dist/vendor/desktop-commander/dist/handlers/filesystem-handlers.js +450 -0
  19. package/dist/vendor/desktop-commander/dist/handlers/history-handlers.js +67 -0
  20. package/dist/vendor/desktop-commander/dist/handlers/index.js +7 -0
  21. package/dist/vendor/desktop-commander/dist/handlers/process-handlers.js +15 -0
  22. package/dist/vendor/desktop-commander/dist/handlers/search-answers.js +172 -0
  23. package/dist/vendor/desktop-commander/dist/handlers/search-handlers.js +136 -0
  24. package/dist/vendor/desktop-commander/dist/handlers/terminal-handlers.js +35 -0
  25. package/dist/vendor/desktop-commander/dist/index.js +88 -0
  26. package/dist/vendor/desktop-commander/dist/search-manager.js +1262 -0
  27. package/dist/vendor/desktop-commander/dist/server.js +1414 -0
  28. package/dist/vendor/desktop-commander/dist/terminal-manager.js +757 -0
  29. package/dist/vendor/desktop-commander/dist/tools/config.js +211 -0
  30. package/dist/vendor/desktop-commander/dist/tools/edit.js +455 -0
  31. package/dist/vendor/desktop-commander/dist/tools/feedback.js +10 -0
  32. package/dist/vendor/desktop-commander/dist/tools/filesystem.js +1047 -0
  33. package/dist/vendor/desktop-commander/dist/tools/fuzzySearch.js +74 -0
  34. package/dist/vendor/desktop-commander/dist/tools/fuzzySearchCore.js +125 -0
  35. package/dist/vendor/desktop-commander/dist/tools/improved-process-tools.js +726 -0
  36. package/dist/vendor/desktop-commander/dist/tools/mime-types.js +28 -0
  37. package/dist/vendor/desktop-commander/dist/tools/pdf/extract-images.js +131 -0
  38. package/dist/vendor/desktop-commander/dist/tools/pdf/index.js +4 -0
  39. package/dist/vendor/desktop-commander/dist/tools/pdf/lib/pdf2md.js +78 -0
  40. package/dist/vendor/desktop-commander/dist/tools/pdf/manipulations.js +112 -0
  41. package/dist/vendor/desktop-commander/dist/tools/pdf/markdown.js +30 -0
  42. package/dist/vendor/desktop-commander/dist/tools/pdf/utils.js +45 -0
  43. package/dist/vendor/desktop-commander/dist/tools/process.js +90 -0
  44. package/dist/vendor/desktop-commander/dist/tools/prompts.js +259 -0
  45. package/dist/vendor/desktop-commander/dist/tools/schemas.js +242 -0
  46. package/dist/vendor/desktop-commander/dist/tools/usage.js +24 -0
  47. package/dist/vendor/desktop-commander/dist/types.js +1 -0
  48. package/dist/vendor/desktop-commander/dist/ui/config-editor/config-editor-runtime.js +150 -0
  49. package/dist/vendor/desktop-commander/dist/ui/config-editor/index.html +13 -0
  50. package/dist/vendor/desktop-commander/dist/ui/config-editor/styles.css +587 -0
  51. package/dist/vendor/desktop-commander/dist/ui/contracts.js +57 -0
  52. package/dist/vendor/desktop-commander/dist/ui/file-preview/index.html +16 -0
  53. package/dist/vendor/desktop-commander/dist/ui/file-preview/preview-runtime.js +471 -0
  54. package/dist/vendor/desktop-commander/dist/ui/file-preview/shared/preview-file-types.js +59 -0
  55. package/dist/vendor/desktop-commander/dist/ui/file-preview/styles.css +1631 -0
  56. package/dist/vendor/desktop-commander/dist/ui/resources.js +93 -0
  57. package/dist/vendor/desktop-commander/dist/utils/ab-test.js +122 -0
  58. package/dist/vendor/desktop-commander/dist/utils/atomic-write.js +80 -0
  59. package/dist/vendor/desktop-commander/dist/utils/capture.js +40 -0
  60. package/dist/vendor/desktop-commander/dist/utils/dockerPrompt.js +9 -0
  61. package/dist/vendor/desktop-commander/dist/utils/exit-process.js +31 -0
  62. package/dist/vendor/desktop-commander/dist/utils/feature-flags.js +18 -0
  63. package/dist/vendor/desktop-commander/dist/utils/files/base.js +5 -0
  64. package/dist/vendor/desktop-commander/dist/utils/files/binary.js +65 -0
  65. package/dist/vendor/desktop-commander/dist/utils/files/docx.js +694 -0
  66. package/dist/vendor/desktop-commander/dist/utils/files/excel.js +497 -0
  67. package/dist/vendor/desktop-commander/dist/utils/files/factory.js +168 -0
  68. package/dist/vendor/desktop-commander/dist/utils/files/image.js +89 -0
  69. package/dist/vendor/desktop-commander/dist/utils/files/index.js +14 -0
  70. package/dist/vendor/desktop-commander/dist/utils/files/pdf.js +124 -0
  71. package/dist/vendor/desktop-commander/dist/utils/files/text.js +423 -0
  72. package/dist/vendor/desktop-commander/dist/utils/fuzzySearchLogger.js +126 -0
  73. package/dist/vendor/desktop-commander/dist/utils/internal-facts.js +23 -0
  74. package/dist/vendor/desktop-commander/dist/utils/lazy-package.js +44 -0
  75. package/dist/vendor/desktop-commander/dist/utils/lineEndingHandler.js +77 -0
  76. package/dist/vendor/desktop-commander/dist/utils/logger.js +72 -0
  77. package/dist/vendor/desktop-commander/dist/utils/mcp-ui-ab-test.js +62 -0
  78. package/dist/vendor/desktop-commander/dist/utils/open-browser.js +2 -0
  79. package/dist/vendor/desktop-commander/dist/utils/process-detection.js +260 -0
  80. package/dist/vendor/desktop-commander/dist/utils/process-tree.js +223 -0
  81. package/dist/vendor/desktop-commander/dist/utils/rename.js +74 -0
  82. package/dist/vendor/desktop-commander/dist/utils/ripgrep-resolver.js +69 -0
  83. package/dist/vendor/desktop-commander/dist/utils/shell.js +187 -0
  84. package/dist/vendor/desktop-commander/dist/utils/system-info.js +727 -0
  85. package/dist/vendor/desktop-commander/dist/utils/terminal-timestamps.js +18 -0
  86. package/dist/vendor/desktop-commander/dist/utils/toolHistory.js +309 -0
  87. package/dist/vendor/desktop-commander/dist/utils/trackTools.js +55 -0
  88. package/dist/vendor/desktop-commander/dist/utils/unsupportedParams.js +66 -0
  89. package/dist/vendor/desktop-commander/dist/utils/usageTracker.js +225 -0
  90. package/dist/vendor/desktop-commander/dist/utils/welcome-onboarding.js +2 -0
  91. package/dist/vendor/desktop-commander/dist/utils/withTimeout.js +85 -0
  92. package/dist/vendor/desktop-commander/dist/version.js +1 -0
  93. package/dist/vendor/desktop-commander/package.json +15 -0
  94. package/package.json +22 -4
  95. package/docs/assets/starmux-app-en.png +0 -0
  96. package/docs/assets/starmux-architecture.svg +0 -315
@@ -0,0 +1,246 @@
1
+ import path from 'path';
2
+ import { configManager } from './config-manager.js';
3
+ import { capture } from "./utils/capture.js";
4
+ class CommandManager {
5
+ getBaseCommand(command) {
6
+ return command.split(' ')[0].toLowerCase().trim();
7
+ }
8
+ /**
9
+ * The command name of each command in a command line (chained, piped, in $(), ...).
10
+ * asTyped: each first word as typed instead of its base name, for telemetry,
11
+ * which then replaces a path whole (a base name alone can't be told from one).
12
+ */
13
+ extractCommands(commandString, asTyped = false) {
14
+ try {
15
+ // Trim any leading/trailing whitespace
16
+ commandString = commandString.trim();
17
+ // Define command separators - these are the operators that can chain commands
18
+ const separators = [';', '&&', '||', '|', '&'];
19
+ // This will store our extracted commands
20
+ const commands = [];
21
+ // Split by common separators while preserving quotes
22
+ let inQuote = false;
23
+ let quoteChar = '';
24
+ let currentCmd = '';
25
+ let escaped = false;
26
+ for (let i = 0; i < commandString.length; i++) {
27
+ const char = commandString[i];
28
+ // Handle escape characters
29
+ if (char === '\\' && !escaped) {
30
+ escaped = true;
31
+ currentCmd += char;
32
+ continue;
33
+ }
34
+ // If this character is escaped, just add it
35
+ if (escaped) {
36
+ escaped = false;
37
+ currentCmd += char;
38
+ continue;
39
+ }
40
+ // Handle quotes (both single and double)
41
+ if ((char === '"' || char === "'") && !inQuote) {
42
+ inQuote = true;
43
+ quoteChar = char;
44
+ currentCmd += char;
45
+ continue;
46
+ }
47
+ else if (char === quoteChar && inQuote) {
48
+ inQuote = false;
49
+ quoteChar = '';
50
+ currentCmd += char;
51
+ continue;
52
+ }
53
+ // Handle $() command substitution even inside quotes (fixes blocklist bypass)
54
+ if (char === '$' && i + 1 < commandString.length && commandString[i + 1] === '(') {
55
+ const startIndex = i;
56
+ let openParens = 1;
57
+ let j = i + 2; // skip past $(
58
+ while (j < commandString.length && openParens > 0) {
59
+ if (commandString[j] === '(')
60
+ openParens++;
61
+ if (commandString[j] === ')')
62
+ openParens--;
63
+ j++;
64
+ }
65
+ if (j <= commandString.length && openParens === 0) {
66
+ const subContent = commandString.substring(i + 2, j - 1);
67
+ const subCommands = this.extractCommands(subContent, asTyped);
68
+ commands.push(...subCommands);
69
+ i = j - 1;
70
+ if (!inQuote) {
71
+ continue;
72
+ }
73
+ else {
74
+ currentCmd += commandString.substring(startIndex, j);
75
+ continue;
76
+ }
77
+ }
78
+ }
79
+ // Handle backtick command substitution even inside quotes
80
+ if (char === '`') {
81
+ const startIndex = i;
82
+ let j = i + 1;
83
+ while (j < commandString.length && commandString[j] !== '`') {
84
+ j++;
85
+ }
86
+ if (j < commandString.length) {
87
+ const subContent = commandString.substring(i + 1, j);
88
+ const subCommands = this.extractCommands(subContent, asTyped);
89
+ commands.push(...subCommands);
90
+ i = j;
91
+ if (!inQuote) {
92
+ continue;
93
+ }
94
+ else {
95
+ currentCmd += commandString.substring(startIndex, j + 1);
96
+ continue;
97
+ }
98
+ }
99
+ }
100
+ // If we're inside quotes, just add the character
101
+ if (inQuote) {
102
+ currentCmd += char;
103
+ continue;
104
+ }
105
+ // Handle subshells - if we see an opening parenthesis, we need to find its matching closing parenthesis
106
+ if (char === '(') {
107
+ // Find the matching closing parenthesis
108
+ let openParens = 1;
109
+ let j = i + 1;
110
+ while (j < commandString.length && openParens > 0) {
111
+ if (commandString[j] === '(')
112
+ openParens++;
113
+ if (commandString[j] === ')')
114
+ openParens--;
115
+ j++;
116
+ }
117
+ // Skip to after the closing parenthesis only if properly balanced
118
+ if (j <= commandString.length && openParens === 0) {
119
+ const subshellContent = commandString.substring(i + 1, j - 1);
120
+ // Recursively extract commands from the subshell
121
+ const subCommands = this.extractCommands(subshellContent, asTyped);
122
+ commands.push(...subCommands);
123
+ // Move position past the subshell
124
+ i = j - 1;
125
+ continue;
126
+ }
127
+ }
128
+ // Check for separators
129
+ let isSeparator = false;
130
+ for (const separator of separators) {
131
+ if (commandString.startsWith(separator, i)) {
132
+ // We found a separator - extract the command before it
133
+ if (currentCmd.trim()) {
134
+ const baseCommand = this.extractBaseCommand(currentCmd.trim(), asTyped);
135
+ if (baseCommand)
136
+ commands.push(baseCommand);
137
+ }
138
+ // Move past the separator
139
+ i += separator.length - 1;
140
+ currentCmd = '';
141
+ isSeparator = true;
142
+ break;
143
+ }
144
+ }
145
+ if (!isSeparator) {
146
+ currentCmd += char;
147
+ }
148
+ }
149
+ // Don't forget to add the last command
150
+ if (currentCmd.trim()) {
151
+ const baseCommand = this.extractBaseCommand(currentCmd.trim(), asTyped);
152
+ if (baseCommand)
153
+ commands.push(baseCommand);
154
+ }
155
+ // Remove duplicates and return
156
+ return [...new Set(commands)];
157
+ }
158
+ catch (error) {
159
+ // If anything goes wrong, log the error but return the basic command to not break execution
160
+ capture('server_request_error', {
161
+ error: 'Error extracting commands'
162
+ });
163
+ const baseCmd = this.extractBaseCommand(commandString, asTyped);
164
+ return baseCmd ? [baseCmd] : [];
165
+ }
166
+ }
167
+ // This extracts the actual command name from a command string (asTyped: see extractCommands)
168
+ extractBaseCommand(commandStr, asTyped = false) {
169
+ try {
170
+ // Remove environment variables (patterns like KEY=value)
171
+ const withoutEnvVars = commandStr.replace(/\w+=\S+\s*/g, '').trim();
172
+ // If nothing remains after removing env vars, return null
173
+ if (!withoutEnvVars)
174
+ return null;
175
+ // Get the first token (the command)
176
+ const tokens = withoutEnvVars.split(/\s+/);
177
+ let firstToken = null;
178
+ // Find the first valid token (skip variables)
179
+ for (let i = 0; i < tokens.length; i++) {
180
+ const token = tokens[i];
181
+ // Skip dollar-prefixed tokens (variables) but not $() command substitutions
182
+ if (token.startsWith('$') && !token.startsWith('$(')) {
183
+ continue;
184
+ }
185
+ // Check if it starts with special characters like ( that might indicate it's not a regular command
186
+ if (token[0] === '(') {
187
+ continue;
188
+ }
189
+ firstToken = token;
190
+ break;
191
+ }
192
+ // No valid command token found
193
+ if (!firstToken) {
194
+ return null;
195
+ }
196
+ // handle $() command substitution - extract the inner command
197
+ if (firstToken.startsWith('$(') && firstToken.endsWith(')')) {
198
+ const inner = firstToken.slice(2, -1).trim();
199
+ if (inner) {
200
+ const innerTokens = inner.split(/\s+/);
201
+ return (asTyped ? innerTokens[0] : path.basename(innerTokens[0])).toLowerCase();
202
+ }
203
+ return null;
204
+ }
205
+ // strip path prefix so /usr/bin/sudo gets caught as "sudo"
206
+ const baseName = asTyped ? firstToken : path.basename(firstToken);
207
+ return baseName.toLowerCase();
208
+ }
209
+ catch (error) {
210
+ capture('Error extracting base command');
211
+ return null;
212
+ }
213
+ }
214
+ async validateCommand(command) {
215
+ try {
216
+ // Get blocked commands from config
217
+ const config = await configManager.getConfig();
218
+ const blockedCommands = config.blockedCommands || [];
219
+ // Extract all commands from the command string
220
+ const allCommands = this.extractCommands(command);
221
+ // If there are no commands extracted, fall back to base command
222
+ if (allCommands.length === 0) {
223
+ const baseCommand = this.getBaseCommand(command);
224
+ return !blockedCommands.includes(baseCommand);
225
+ }
226
+ // Check if any of the extracted commands are in the blocked list
227
+ for (const cmd of allCommands) {
228
+ if (blockedCommands.includes(cmd)) {
229
+ return false; // Command is blocked
230
+ }
231
+ }
232
+ // No commands were blocked
233
+ return true;
234
+ }
235
+ catch (error) {
236
+ console.error('Error validating command:', error);
237
+ capture('server_validate_command_error', {
238
+ error: error instanceof Error ? error.message : String(error)
239
+ });
240
+ // Fail closed: deny the command if validation encounters an error.
241
+ // This prevents a config read failure from bypassing all command filtering.
242
+ return false;
243
+ }
244
+ }
245
+ }
246
+ export const commandManager = new CommandManager();
@@ -0,0 +1,37 @@
1
+ // Single source of truth for user-editable configuration fields.
2
+ export const CONFIG_FIELD_DEFINITIONS = {
3
+ blockedCommands: {
4
+ label: 'Blocked Commands',
5
+ description: 'This is your personal safety blocklist. If a command appears here, Desktop Commander will refuse to run it even if a prompt asks for it. Add risky commands you never want executed by mistake.',
6
+ valueType: 'array',
7
+ },
8
+ allowedDirectories: {
9
+ label: 'Allowed Folders',
10
+ description: 'These are the folders Desktop Commander is allowed to read and edit. Think of this as a permission list. Keeping it small is safer. If this list is empty, Desktop Commander can access your entire filesystem.',
11
+ valueType: 'array',
12
+ },
13
+ defaultShell: {
14
+ label: 'Default Shell',
15
+ description: 'This is the shell used for new command sessions (for example /bin/bash or /bin/zsh). Only change this if you know your environment requires a specific shell.',
16
+ valueType: 'string',
17
+ },
18
+ telemetryEnabled: {
19
+ label: 'Anonymous Telemetry',
20
+ description: 'When on, Desktop Commander sends anonymous usage information that helps improve product quality. When off, no telemetry data is sent.',
21
+ valueType: 'boolean',
22
+ },
23
+ fileReadLineLimit: {
24
+ label: 'File Read Limit',
25
+ description: 'Maximum number of lines returned from a file in one read action. Lower numbers keep responses short and safer; higher numbers return more text at once.',
26
+ valueType: 'number',
27
+ },
28
+ fileWriteLineLimit: {
29
+ label: 'File Write Limit',
30
+ description: 'Maximum number of lines that can be written in one edit operation. This helps prevent accidental oversized writes and keeps file changes predictable.',
31
+ valueType: 'number',
32
+ },
33
+ };
34
+ export const CONFIG_FIELD_KEYS = Object.keys(CONFIG_FIELD_DEFINITIONS);
35
+ export function isConfigFieldKey(value) {
36
+ return Object.prototype.hasOwnProperty.call(CONFIG_FIELD_DEFINITIONS, value);
37
+ }