mstro-app 0.1.47

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 (213) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +177 -0
  3. package/bin/commands/config.js +145 -0
  4. package/bin/commands/login.js +313 -0
  5. package/bin/commands/logout.js +75 -0
  6. package/bin/commands/status.js +197 -0
  7. package/bin/commands/whoami.js +161 -0
  8. package/bin/configure-claude.js +298 -0
  9. package/bin/mstro.js +581 -0
  10. package/bin/postinstall.js +45 -0
  11. package/bin/release.sh +110 -0
  12. package/dist/server/cli/headless/claude-invoker.d.ts +17 -0
  13. package/dist/server/cli/headless/claude-invoker.d.ts.map +1 -0
  14. package/dist/server/cli/headless/claude-invoker.js +311 -0
  15. package/dist/server/cli/headless/claude-invoker.js.map +1 -0
  16. package/dist/server/cli/headless/index.d.ts +13 -0
  17. package/dist/server/cli/headless/index.d.ts.map +1 -0
  18. package/dist/server/cli/headless/index.js +10 -0
  19. package/dist/server/cli/headless/index.js.map +1 -0
  20. package/dist/server/cli/headless/mcp-config.d.ts +11 -0
  21. package/dist/server/cli/headless/mcp-config.d.ts.map +1 -0
  22. package/dist/server/cli/headless/mcp-config.js +76 -0
  23. package/dist/server/cli/headless/mcp-config.js.map +1 -0
  24. package/dist/server/cli/headless/output-utils.d.ts +33 -0
  25. package/dist/server/cli/headless/output-utils.d.ts.map +1 -0
  26. package/dist/server/cli/headless/output-utils.js +101 -0
  27. package/dist/server/cli/headless/output-utils.js.map +1 -0
  28. package/dist/server/cli/headless/prompt-utils.d.ts +21 -0
  29. package/dist/server/cli/headless/prompt-utils.d.ts.map +1 -0
  30. package/dist/server/cli/headless/prompt-utils.js +84 -0
  31. package/dist/server/cli/headless/prompt-utils.js.map +1 -0
  32. package/dist/server/cli/headless/runner.d.ts +24 -0
  33. package/dist/server/cli/headless/runner.d.ts.map +1 -0
  34. package/dist/server/cli/headless/runner.js +99 -0
  35. package/dist/server/cli/headless/runner.js.map +1 -0
  36. package/dist/server/cli/headless/types.d.ts +106 -0
  37. package/dist/server/cli/headless/types.d.ts.map +1 -0
  38. package/dist/server/cli/headless/types.js +4 -0
  39. package/dist/server/cli/headless/types.js.map +1 -0
  40. package/dist/server/cli/improvisation-session-manager.d.ts +155 -0
  41. package/dist/server/cli/improvisation-session-manager.d.ts.map +1 -0
  42. package/dist/server/cli/improvisation-session-manager.js +415 -0
  43. package/dist/server/cli/improvisation-session-manager.js.map +1 -0
  44. package/dist/server/index.d.ts +2 -0
  45. package/dist/server/index.d.ts.map +1 -0
  46. package/dist/server/index.js +386 -0
  47. package/dist/server/index.js.map +1 -0
  48. package/dist/server/mcp/bouncer-cli.d.ts +3 -0
  49. package/dist/server/mcp/bouncer-cli.d.ts.map +1 -0
  50. package/dist/server/mcp/bouncer-cli.js +99 -0
  51. package/dist/server/mcp/bouncer-cli.js.map +1 -0
  52. package/dist/server/mcp/bouncer-integration.d.ts +36 -0
  53. package/dist/server/mcp/bouncer-integration.d.ts.map +1 -0
  54. package/dist/server/mcp/bouncer-integration.js +301 -0
  55. package/dist/server/mcp/bouncer-integration.js.map +1 -0
  56. package/dist/server/mcp/security-audit.d.ts +52 -0
  57. package/dist/server/mcp/security-audit.d.ts.map +1 -0
  58. package/dist/server/mcp/security-audit.js +118 -0
  59. package/dist/server/mcp/security-audit.js.map +1 -0
  60. package/dist/server/mcp/security-patterns.d.ts +73 -0
  61. package/dist/server/mcp/security-patterns.d.ts.map +1 -0
  62. package/dist/server/mcp/security-patterns.js +247 -0
  63. package/dist/server/mcp/security-patterns.js.map +1 -0
  64. package/dist/server/mcp/server.d.ts +3 -0
  65. package/dist/server/mcp/server.d.ts.map +1 -0
  66. package/dist/server/mcp/server.js +146 -0
  67. package/dist/server/mcp/server.js.map +1 -0
  68. package/dist/server/routes/files.d.ts +9 -0
  69. package/dist/server/routes/files.d.ts.map +1 -0
  70. package/dist/server/routes/files.js +24 -0
  71. package/dist/server/routes/files.js.map +1 -0
  72. package/dist/server/routes/improvise.d.ts +3 -0
  73. package/dist/server/routes/improvise.d.ts.map +1 -0
  74. package/dist/server/routes/improvise.js +72 -0
  75. package/dist/server/routes/improvise.js.map +1 -0
  76. package/dist/server/routes/index.d.ts +10 -0
  77. package/dist/server/routes/index.d.ts.map +1 -0
  78. package/dist/server/routes/index.js +12 -0
  79. package/dist/server/routes/index.js.map +1 -0
  80. package/dist/server/routes/instances.d.ts +10 -0
  81. package/dist/server/routes/instances.d.ts.map +1 -0
  82. package/dist/server/routes/instances.js +47 -0
  83. package/dist/server/routes/instances.js.map +1 -0
  84. package/dist/server/routes/notifications.d.ts +3 -0
  85. package/dist/server/routes/notifications.d.ts.map +1 -0
  86. package/dist/server/routes/notifications.js +136 -0
  87. package/dist/server/routes/notifications.js.map +1 -0
  88. package/dist/server/services/analytics.d.ts +56 -0
  89. package/dist/server/services/analytics.d.ts.map +1 -0
  90. package/dist/server/services/analytics.js +240 -0
  91. package/dist/server/services/analytics.js.map +1 -0
  92. package/dist/server/services/auth.d.ts +26 -0
  93. package/dist/server/services/auth.d.ts.map +1 -0
  94. package/dist/server/services/auth.js +71 -0
  95. package/dist/server/services/auth.js.map +1 -0
  96. package/dist/server/services/client-id.d.ts +10 -0
  97. package/dist/server/services/client-id.d.ts.map +1 -0
  98. package/dist/server/services/client-id.js +61 -0
  99. package/dist/server/services/client-id.js.map +1 -0
  100. package/dist/server/services/credentials.d.ts +39 -0
  101. package/dist/server/services/credentials.d.ts.map +1 -0
  102. package/dist/server/services/credentials.js +110 -0
  103. package/dist/server/services/credentials.js.map +1 -0
  104. package/dist/server/services/files.d.ts +119 -0
  105. package/dist/server/services/files.d.ts.map +1 -0
  106. package/dist/server/services/files.js +560 -0
  107. package/dist/server/services/files.js.map +1 -0
  108. package/dist/server/services/instances.d.ts +52 -0
  109. package/dist/server/services/instances.d.ts.map +1 -0
  110. package/dist/server/services/instances.js +241 -0
  111. package/dist/server/services/instances.js.map +1 -0
  112. package/dist/server/services/pathUtils.d.ts +47 -0
  113. package/dist/server/services/pathUtils.d.ts.map +1 -0
  114. package/dist/server/services/pathUtils.js +124 -0
  115. package/dist/server/services/pathUtils.js.map +1 -0
  116. package/dist/server/services/platform.d.ts +72 -0
  117. package/dist/server/services/platform.d.ts.map +1 -0
  118. package/dist/server/services/platform.js +368 -0
  119. package/dist/server/services/platform.js.map +1 -0
  120. package/dist/server/services/sentry.d.ts +5 -0
  121. package/dist/server/services/sentry.d.ts.map +1 -0
  122. package/dist/server/services/sentry.js +71 -0
  123. package/dist/server/services/sentry.js.map +1 -0
  124. package/dist/server/services/terminal/pty-manager.d.ts +149 -0
  125. package/dist/server/services/terminal/pty-manager.d.ts.map +1 -0
  126. package/dist/server/services/terminal/pty-manager.js +377 -0
  127. package/dist/server/services/terminal/pty-manager.js.map +1 -0
  128. package/dist/server/services/terminal/tmux-manager.d.ts +82 -0
  129. package/dist/server/services/terminal/tmux-manager.d.ts.map +1 -0
  130. package/dist/server/services/terminal/tmux-manager.js +352 -0
  131. package/dist/server/services/terminal/tmux-manager.js.map +1 -0
  132. package/dist/server/services/websocket/autocomplete.d.ts +50 -0
  133. package/dist/server/services/websocket/autocomplete.d.ts.map +1 -0
  134. package/dist/server/services/websocket/autocomplete.js +361 -0
  135. package/dist/server/services/websocket/autocomplete.js.map +1 -0
  136. package/dist/server/services/websocket/file-utils.d.ts +44 -0
  137. package/dist/server/services/websocket/file-utils.d.ts.map +1 -0
  138. package/dist/server/services/websocket/file-utils.js +272 -0
  139. package/dist/server/services/websocket/file-utils.js.map +1 -0
  140. package/dist/server/services/websocket/handler.d.ts +246 -0
  141. package/dist/server/services/websocket/handler.d.ts.map +1 -0
  142. package/dist/server/services/websocket/handler.js +1771 -0
  143. package/dist/server/services/websocket/handler.js.map +1 -0
  144. package/dist/server/services/websocket/index.d.ts +11 -0
  145. package/dist/server/services/websocket/index.d.ts.map +1 -0
  146. package/dist/server/services/websocket/index.js +14 -0
  147. package/dist/server/services/websocket/index.js.map +1 -0
  148. package/dist/server/services/websocket/types.d.ts +214 -0
  149. package/dist/server/services/websocket/types.d.ts.map +1 -0
  150. package/dist/server/services/websocket/types.js +4 -0
  151. package/dist/server/services/websocket/types.js.map +1 -0
  152. package/dist/server/utils/agent-manager.d.ts +69 -0
  153. package/dist/server/utils/agent-manager.d.ts.map +1 -0
  154. package/dist/server/utils/agent-manager.js +269 -0
  155. package/dist/server/utils/agent-manager.js.map +1 -0
  156. package/dist/server/utils/paths.d.ts +25 -0
  157. package/dist/server/utils/paths.d.ts.map +1 -0
  158. package/dist/server/utils/paths.js +38 -0
  159. package/dist/server/utils/paths.js.map +1 -0
  160. package/dist/server/utils/port-manager.d.ts +10 -0
  161. package/dist/server/utils/port-manager.d.ts.map +1 -0
  162. package/dist/server/utils/port-manager.js +60 -0
  163. package/dist/server/utils/port-manager.js.map +1 -0
  164. package/dist/server/utils/port.d.ts +26 -0
  165. package/dist/server/utils/port.d.ts.map +1 -0
  166. package/dist/server/utils/port.js +83 -0
  167. package/dist/server/utils/port.js.map +1 -0
  168. package/hooks/bouncer.sh +138 -0
  169. package/package.json +74 -0
  170. package/server/README.md +191 -0
  171. package/server/cli/headless/claude-invoker.ts +415 -0
  172. package/server/cli/headless/index.ts +39 -0
  173. package/server/cli/headless/mcp-config.ts +87 -0
  174. package/server/cli/headless/output-utils.ts +109 -0
  175. package/server/cli/headless/prompt-utils.ts +108 -0
  176. package/server/cli/headless/runner.ts +133 -0
  177. package/server/cli/headless/types.ts +118 -0
  178. package/server/cli/improvisation-session-manager.ts +531 -0
  179. package/server/index.ts +456 -0
  180. package/server/mcp/README.md +122 -0
  181. package/server/mcp/bouncer-cli.ts +127 -0
  182. package/server/mcp/bouncer-integration.ts +430 -0
  183. package/server/mcp/security-audit.ts +180 -0
  184. package/server/mcp/security-patterns.ts +290 -0
  185. package/server/mcp/server.ts +174 -0
  186. package/server/routes/files.ts +29 -0
  187. package/server/routes/improvise.ts +82 -0
  188. package/server/routes/index.ts +13 -0
  189. package/server/routes/instances.ts +54 -0
  190. package/server/routes/notifications.ts +158 -0
  191. package/server/services/analytics.ts +277 -0
  192. package/server/services/auth.ts +80 -0
  193. package/server/services/client-id.ts +68 -0
  194. package/server/services/credentials.ts +134 -0
  195. package/server/services/files.ts +710 -0
  196. package/server/services/instances.ts +275 -0
  197. package/server/services/pathUtils.ts +158 -0
  198. package/server/services/platform.test.ts +1314 -0
  199. package/server/services/platform.ts +435 -0
  200. package/server/services/sentry.ts +81 -0
  201. package/server/services/terminal/pty-manager.ts +464 -0
  202. package/server/services/terminal/tmux-manager.ts +426 -0
  203. package/server/services/websocket/autocomplete.ts +438 -0
  204. package/server/services/websocket/file-utils.ts +305 -0
  205. package/server/services/websocket/handler.test.ts +20 -0
  206. package/server/services/websocket/handler.ts +2047 -0
  207. package/server/services/websocket/index.ts +40 -0
  208. package/server/services/websocket/types.ts +339 -0
  209. package/server/tsconfig.json +19 -0
  210. package/server/utils/agent-manager.ts +323 -0
  211. package/server/utils/paths.ts +45 -0
  212. package/server/utils/port-manager.ts +70 -0
  213. package/server/utils/port.ts +102 -0
@@ -0,0 +1,560 @@
1
+ // Copyright (c) 2025-present Mstro, Inc. All rights reserved.
2
+ // Licensed under the MIT License. See LICENSE file for details.
3
+ /**
4
+ * File Service
5
+ *
6
+ * Handles file autocomplete, directory operations, and file explorer features.
7
+ */
8
+ import { existsSync, mkdirSync, readdirSync, renameSync, rmdirSync, statSync, unlinkSync, writeFileSync } from 'node:fs';
9
+ import { dirname, join } from 'node:path';
10
+ import { containsDangerousPatterns, validateBothPathsWithinWorkingDir, validatePathWithinWorkingDir } from './pathUtils.js';
11
+ export class FileService {
12
+ workingDirectory;
13
+ skipDirs = ['node_modules', '.git', '.mstro', 'dist', 'build', '.next', 'coverage', '.vscode', '.idea'];
14
+ constructor(workingDirectory) {
15
+ this.workingDirectory = workingDirectory;
16
+ }
17
+ /**
18
+ * Get all files recursively with optional filtering
19
+ */
20
+ getAllFiles(_baseDir = 'working', filter, limit = 10) {
21
+ // Note: 'scores' baseDir kept for API compatibility, but maps to working directory
22
+ const directory = this.workingDirectory;
23
+ let files = this.scanDirectory(directory, directory);
24
+ // Apply filter if provided
25
+ if (filter) {
26
+ files = this.filterAndScore(files, filter);
27
+ }
28
+ // Sort by score if filtered, otherwise by type and name
29
+ if (filter) {
30
+ files.sort((a, b) => (b.score || 0) - (a.score || 0));
31
+ }
32
+ else {
33
+ files.sort((a, b) => {
34
+ if (a.isDirectory && !b.isDirectory)
35
+ return -1;
36
+ if (!a.isDirectory && b.isDirectory)
37
+ return 1;
38
+ return a.name.localeCompare(b.name);
39
+ });
40
+ }
41
+ return files.slice(0, limit);
42
+ }
43
+ /**
44
+ * Recursively scan directory
45
+ */
46
+ scanDirectory(dir, baseDir, results = []) {
47
+ try {
48
+ // Skip common ignore directories
49
+ const dirName = dir.split('/').pop() || '';
50
+ if (this.skipDirs.includes(dirName)) {
51
+ return results;
52
+ }
53
+ const entries = readdirSync(dir, { withFileTypes: true });
54
+ for (const entry of entries) {
55
+ // Skip hidden files and ignore directories
56
+ if (entry.name.startsWith('.') || this.skipDirs.includes(entry.name)) {
57
+ continue;
58
+ }
59
+ const fullPath = join(dir, entry.name);
60
+ const relativePath = fullPath.replace(`${baseDir}/`, '');
61
+ results.push({
62
+ name: entry.name,
63
+ path: relativePath,
64
+ isDirectory: entry.isDirectory()
65
+ });
66
+ // Recursively search directories (with depth limit)
67
+ if (entry.isDirectory() && results.length < 1000) {
68
+ this.scanDirectory(fullPath, baseDir, results);
69
+ }
70
+ }
71
+ }
72
+ catch (_error) {
73
+ // Skip directories we can't read
74
+ }
75
+ return results;
76
+ }
77
+ /**
78
+ * Filter files and assign relevance scores
79
+ */
80
+ filterAndScore(files, filter) {
81
+ const filterLower = filter.toLowerCase();
82
+ const scoredFiles = [];
83
+ for (const file of files) {
84
+ const nameLower = file.name.toLowerCase();
85
+ const pathLower = file.path.toLowerCase();
86
+ let score = 0;
87
+ // Highest priority: starts with filter
88
+ if (nameLower.startsWith(filterLower)) {
89
+ score = 1000;
90
+ }
91
+ // High priority: word in path starts with filter
92
+ else if (pathLower.split('/').some(part => part.startsWith(filterLower))) {
93
+ score = 500;
94
+ }
95
+ // Medium priority: contains filter
96
+ else if (nameLower.includes(filterLower)) {
97
+ score = 100;
98
+ }
99
+ // Low priority: path contains filter
100
+ else if (pathLower.includes(filterLower)) {
101
+ score = 10;
102
+ }
103
+ else {
104
+ continue; // Doesn't match, skip
105
+ }
106
+ // Boost score for shorter paths (prefer files closer to root)
107
+ score += (50 - Math.min(50, file.path.split('/').length * 5));
108
+ scoredFiles.push({
109
+ name: file.name,
110
+ path: file.path,
111
+ isDirectory: file.isDirectory,
112
+ score
113
+ });
114
+ }
115
+ return scoredFiles;
116
+ }
117
+ /**
118
+ * Get file statistics
119
+ */
120
+ getFileStats(path, _baseDir = 'working') {
121
+ try {
122
+ // Note: 'scores' baseDir kept for API compatibility, but maps to working directory
123
+ const fullPath = join(this.workingDirectory, path);
124
+ const stats = statSync(fullPath);
125
+ return {
126
+ size: stats.size,
127
+ created: stats.birthtime,
128
+ modified: stats.mtime,
129
+ isDirectory: stats.isDirectory(),
130
+ isFile: stats.isFile()
131
+ };
132
+ }
133
+ catch (_error) {
134
+ return null;
135
+ }
136
+ }
137
+ }
138
+ // ============================================================================
139
+ // File Explorer Functions (standalone exports for WebSocket handler)
140
+ // ============================================================================
141
+ /**
142
+ * List immediate children of a directory.
143
+ * Returns entries sorted: directories first, then files, alphabetically.
144
+ *
145
+ * @param dirPath - Directory path (relative to workingDir or absolute)
146
+ * @param workingDir - Working directory boundary
147
+ * @param showHidden - Whether to show hidden files (starting with .)
148
+ * @returns ListDirectoryResult with entries array or error
149
+ */
150
+ export function listDirectory(dirPath, workingDir, showHidden = false) {
151
+ // Check for dangerous patterns first
152
+ if (containsDangerousPatterns(dirPath)) {
153
+ console.error(`[FileService] SECURITY: Dangerous pattern in path: "${dirPath}"`);
154
+ return {
155
+ success: false,
156
+ error: 'Invalid path: contains dangerous patterns'
157
+ };
158
+ }
159
+ // Validate path is within working directory
160
+ const validation = validatePathWithinWorkingDir(dirPath, workingDir);
161
+ if (!validation.valid) {
162
+ return {
163
+ success: false,
164
+ error: validation.error
165
+ };
166
+ }
167
+ const resolvedPath = validation.resolvedPath;
168
+ try {
169
+ // Check if path exists and is a directory
170
+ if (!existsSync(resolvedPath)) {
171
+ return {
172
+ success: false,
173
+ error: 'Directory not found'
174
+ };
175
+ }
176
+ const stats = statSync(resolvedPath);
177
+ if (!stats.isDirectory()) {
178
+ return {
179
+ success: false,
180
+ error: 'Path is not a directory'
181
+ };
182
+ }
183
+ // Read directory entries
184
+ const entries = readdirSync(resolvedPath, { withFileTypes: true });
185
+ // Map to DirectoryEntry objects
186
+ const directoryEntries = entries
187
+ .filter(entry => {
188
+ // Filter hidden files unless showHidden is true
189
+ if (!showHidden && entry.name.startsWith('.')) {
190
+ return false;
191
+ }
192
+ return true;
193
+ })
194
+ .map(entry => {
195
+ const entryPath = join(resolvedPath, entry.name);
196
+ const isDir = entry.isDirectory();
197
+ // Get stats for size and modification time
198
+ let size;
199
+ let modifiedAt;
200
+ try {
201
+ const entryStats = statSync(entryPath);
202
+ modifiedAt = entryStats.mtime.toISOString();
203
+ if (!isDir) {
204
+ size = entryStats.size;
205
+ }
206
+ }
207
+ catch {
208
+ // Skip stats if we can't read them
209
+ }
210
+ // Return path relative to workingDir for consistency
211
+ const relativePath = entryPath.replace(`${workingDir}/`, '');
212
+ return {
213
+ name: entry.name,
214
+ path: relativePath,
215
+ type: isDir ? 'directory' : 'file',
216
+ size,
217
+ modifiedAt
218
+ };
219
+ });
220
+ // Sort: directories first, then files, alphabetically within each group
221
+ directoryEntries.sort((a, b) => {
222
+ if (a.type === 'directory' && b.type === 'file')
223
+ return -1;
224
+ if (a.type === 'file' && b.type === 'directory')
225
+ return 1;
226
+ return a.name.localeCompare(b.name);
227
+ });
228
+ return {
229
+ success: true,
230
+ entries: directoryEntries
231
+ };
232
+ }
233
+ catch (error) {
234
+ // Handle permission errors gracefully
235
+ if (error.code === 'EACCES') {
236
+ return {
237
+ success: false,
238
+ error: 'Permission denied'
239
+ };
240
+ }
241
+ console.error('[FileService] Error listing directory:', error);
242
+ return {
243
+ success: false,
244
+ error: error.message || 'Failed to list directory'
245
+ };
246
+ }
247
+ }
248
+ /**
249
+ * Write content to a file.
250
+ * Creates parent directories if needed.
251
+ *
252
+ * @param filePath - File path (relative to workingDir or absolute)
253
+ * @param content - Content to write
254
+ * @param workingDir - Working directory boundary
255
+ * @returns FileOperationResult
256
+ */
257
+ export function writeFile(filePath, content, workingDir) {
258
+ // Check for dangerous patterns first
259
+ if (containsDangerousPatterns(filePath)) {
260
+ console.error(`[FileService] SECURITY: Dangerous pattern in path: "${filePath}"`);
261
+ return {
262
+ success: false,
263
+ error: 'Invalid path: contains dangerous patterns'
264
+ };
265
+ }
266
+ // Validate path is within working directory
267
+ const validation = validatePathWithinWorkingDir(filePath, workingDir);
268
+ if (!validation.valid) {
269
+ return {
270
+ success: false,
271
+ error: validation.error
272
+ };
273
+ }
274
+ const resolvedPath = validation.resolvedPath;
275
+ try {
276
+ // Create parent directories if they don't exist
277
+ const parentDir = dirname(resolvedPath);
278
+ if (!existsSync(parentDir)) {
279
+ mkdirSync(parentDir, { recursive: true });
280
+ }
281
+ // Check if target is a directory (can't write to directory)
282
+ if (existsSync(resolvedPath)) {
283
+ const stats = statSync(resolvedPath);
284
+ if (stats.isDirectory()) {
285
+ return {
286
+ success: false,
287
+ error: 'Cannot write to a directory'
288
+ };
289
+ }
290
+ }
291
+ // Write the file
292
+ writeFileSync(resolvedPath, content, 'utf-8');
293
+ return {
294
+ success: true,
295
+ path: resolvedPath.replace(`${workingDir}/`, '')
296
+ };
297
+ }
298
+ catch (error) {
299
+ console.error('[FileService] Error writing file:', error);
300
+ return {
301
+ success: false,
302
+ error: error.message || 'Failed to write file'
303
+ };
304
+ }
305
+ }
306
+ /**
307
+ * Create an empty file.
308
+ * Returns error if file already exists.
309
+ *
310
+ * @param filePath - File path (relative to workingDir or absolute)
311
+ * @param workingDir - Working directory boundary
312
+ * @returns FileOperationResult
313
+ */
314
+ export function createFile(filePath, workingDir) {
315
+ // Check for dangerous patterns first
316
+ if (containsDangerousPatterns(filePath)) {
317
+ console.error(`[FileService] SECURITY: Dangerous pattern in path: "${filePath}"`);
318
+ return {
319
+ success: false,
320
+ error: 'Invalid path: contains dangerous patterns'
321
+ };
322
+ }
323
+ // Validate path is within working directory
324
+ const validation = validatePathWithinWorkingDir(filePath, workingDir);
325
+ if (!validation.valid) {
326
+ return {
327
+ success: false,
328
+ error: validation.error
329
+ };
330
+ }
331
+ const resolvedPath = validation.resolvedPath;
332
+ try {
333
+ // Check if file already exists
334
+ if (existsSync(resolvedPath)) {
335
+ return {
336
+ success: false,
337
+ error: 'File already exists'
338
+ };
339
+ }
340
+ // Create parent directories if needed
341
+ const parentDir = dirname(resolvedPath);
342
+ if (!existsSync(parentDir)) {
343
+ mkdirSync(parentDir, { recursive: true });
344
+ }
345
+ // Create empty file
346
+ writeFileSync(resolvedPath, '', 'utf-8');
347
+ return {
348
+ success: true,
349
+ path: resolvedPath.replace(`${workingDir}/`, '')
350
+ };
351
+ }
352
+ catch (error) {
353
+ console.error('[FileService] Error creating file:', error);
354
+ return {
355
+ success: false,
356
+ error: error.message || 'Failed to create file'
357
+ };
358
+ }
359
+ }
360
+ /**
361
+ * Create a directory (recursively if needed).
362
+ * Returns error if directory already exists.
363
+ *
364
+ * @param dirPath - Directory path (relative to workingDir or absolute)
365
+ * @param workingDir - Working directory boundary
366
+ * @returns FileOperationResult
367
+ */
368
+ export function createDirectory(dirPath, workingDir) {
369
+ // Check for dangerous patterns first
370
+ if (containsDangerousPatterns(dirPath)) {
371
+ console.error(`[FileService] SECURITY: Dangerous pattern in path: "${dirPath}"`);
372
+ return {
373
+ success: false,
374
+ error: 'Invalid path: contains dangerous patterns'
375
+ };
376
+ }
377
+ // Validate path is within working directory
378
+ const validation = validatePathWithinWorkingDir(dirPath, workingDir);
379
+ if (!validation.valid) {
380
+ return {
381
+ success: false,
382
+ error: validation.error
383
+ };
384
+ }
385
+ const resolvedPath = validation.resolvedPath;
386
+ try {
387
+ // Check if path already exists
388
+ if (existsSync(resolvedPath)) {
389
+ const stats = statSync(resolvedPath);
390
+ if (stats.isDirectory()) {
391
+ return {
392
+ success: false,
393
+ error: 'Directory already exists'
394
+ };
395
+ }
396
+ else {
397
+ return {
398
+ success: false,
399
+ error: 'A file with that name already exists'
400
+ };
401
+ }
402
+ }
403
+ // Create directory recursively
404
+ mkdirSync(resolvedPath, { recursive: true });
405
+ return {
406
+ success: true,
407
+ path: resolvedPath.replace(`${workingDir}/`, '')
408
+ };
409
+ }
410
+ catch (error) {
411
+ console.error('[FileService] Error creating directory:', error);
412
+ return {
413
+ success: false,
414
+ error: error.message || 'Failed to create directory'
415
+ };
416
+ }
417
+ }
418
+ /**
419
+ * Delete a file or EMPTY directory.
420
+ * For safety, only deletes empty directories.
421
+ *
422
+ * CRITICAL: Validates path is within workingDir to prevent path traversal.
423
+ *
424
+ * @param targetPath - Path to delete (relative to workingDir or absolute)
425
+ * @param workingDir - Working directory boundary
426
+ * @returns FileOperationResult
427
+ */
428
+ export function deleteFile(targetPath, workingDir) {
429
+ // Check for dangerous patterns first
430
+ if (containsDangerousPatterns(targetPath)) {
431
+ console.error(`[FileService] SECURITY: Dangerous pattern in path: "${targetPath}"`);
432
+ return {
433
+ success: false,
434
+ error: 'Invalid path: contains dangerous patterns'
435
+ };
436
+ }
437
+ // Validate path is within working directory
438
+ const validation = validatePathWithinWorkingDir(targetPath, workingDir);
439
+ if (!validation.valid) {
440
+ return {
441
+ success: false,
442
+ error: validation.error
443
+ };
444
+ }
445
+ const resolvedPath = validation.resolvedPath;
446
+ // Additional safety: prevent deleting the working directory itself
447
+ if (resolvedPath === workingDir || resolvedPath === `${workingDir}/`) {
448
+ console.error(`[FileService] SECURITY: Attempted to delete working directory: "${resolvedPath}"`);
449
+ return {
450
+ success: false,
451
+ error: 'Cannot delete the working directory'
452
+ };
453
+ }
454
+ try {
455
+ // Check if path exists
456
+ if (!existsSync(resolvedPath)) {
457
+ return {
458
+ success: false,
459
+ error: 'File or directory not found'
460
+ };
461
+ }
462
+ const stats = statSync(resolvedPath);
463
+ if (stats.isDirectory()) {
464
+ // Only delete empty directories for safety
465
+ const contents = readdirSync(resolvedPath);
466
+ if (contents.length > 0) {
467
+ return {
468
+ success: false,
469
+ error: 'Directory is not empty. Only empty directories can be deleted.'
470
+ };
471
+ }
472
+ rmdirSync(resolvedPath);
473
+ }
474
+ else {
475
+ unlinkSync(resolvedPath);
476
+ }
477
+ return {
478
+ success: true,
479
+ path: resolvedPath.replace(`${workingDir}/`, '')
480
+ };
481
+ }
482
+ catch (error) {
483
+ console.error('[FileService] Error deleting file:', error);
484
+ return {
485
+ success: false,
486
+ error: error.message || 'Failed to delete'
487
+ };
488
+ }
489
+ }
490
+ /**
491
+ * Rename or move a file/directory.
492
+ * Both source and destination must be within workingDir.
493
+ *
494
+ * @param oldPath - Current path (relative to workingDir or absolute)
495
+ * @param newPath - New path (relative to workingDir or absolute)
496
+ * @param workingDir - Working directory boundary
497
+ * @returns FileOperationResult
498
+ */
499
+ export function renameFile(oldPath, newPath, workingDir) {
500
+ // Check for dangerous patterns in both paths
501
+ if (containsDangerousPatterns(oldPath)) {
502
+ console.error(`[FileService] SECURITY: Dangerous pattern in source path: "${oldPath}"`);
503
+ return {
504
+ success: false,
505
+ error: 'Invalid source path: contains dangerous patterns'
506
+ };
507
+ }
508
+ if (containsDangerousPatterns(newPath)) {
509
+ console.error(`[FileService] SECURITY: Dangerous pattern in destination path: "${newPath}"`);
510
+ return {
511
+ success: false,
512
+ error: 'Invalid destination path: contains dangerous patterns'
513
+ };
514
+ }
515
+ // Validate both paths are within working directory
516
+ const validation = validateBothPathsWithinWorkingDir(oldPath, newPath, workingDir);
517
+ if (!validation.valid) {
518
+ return {
519
+ success: false,
520
+ error: validation.error
521
+ };
522
+ }
523
+ const resolvedOldPath = validation.resolvedSourcePath;
524
+ const resolvedNewPath = validation.resolvedDestPath;
525
+ try {
526
+ // Check if source exists
527
+ if (!existsSync(resolvedOldPath)) {
528
+ return {
529
+ success: false,
530
+ error: 'Source file or directory not found'
531
+ };
532
+ }
533
+ // Check if destination already exists
534
+ if (existsSync(resolvedNewPath)) {
535
+ return {
536
+ success: false,
537
+ error: 'Destination already exists'
538
+ };
539
+ }
540
+ // Create parent directories for destination if needed
541
+ const parentDir = dirname(resolvedNewPath);
542
+ if (!existsSync(parentDir)) {
543
+ mkdirSync(parentDir, { recursive: true });
544
+ }
545
+ // Perform the rename
546
+ renameSync(resolvedOldPath, resolvedNewPath);
547
+ return {
548
+ success: true,
549
+ path: resolvedNewPath.replace(`${workingDir}/`, '')
550
+ };
551
+ }
552
+ catch (error) {
553
+ console.error('[FileService] Error renaming file:', error);
554
+ return {
555
+ success: false,
556
+ error: error.message || 'Failed to rename'
557
+ };
558
+ }
559
+ }
560
+ //# sourceMappingURL=files.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"files.js","sourceRoot":"","sources":["../../../server/services/files.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ export interface MstroInstance {
2
+ id: string;
3
+ port: number;
4
+ url: string;
5
+ workingDirectory: string;
6
+ startedAt: number;
7
+ lastHeartbeat: number;
8
+ pid: number;
9
+ }
10
+ export declare class InstanceRegistry {
11
+ private registryPath;
12
+ private currentInstance;
13
+ private heartbeatInterval;
14
+ constructor();
15
+ /**
16
+ * Register current instance
17
+ */
18
+ register(port: number, workingDirectory: string): MstroInstance;
19
+ /**
20
+ * Unregister current instance
21
+ */
22
+ unregister(): void;
23
+ /**
24
+ * Get current instance info
25
+ */
26
+ getCurrentInstance(): MstroInstance | null;
27
+ /**
28
+ * Get all instances (with file locking to prevent race conditions)
29
+ */
30
+ static getAllInstances(): MstroInstance[];
31
+ /**
32
+ * Get instance by ID
33
+ */
34
+ static getInstance(id: string): MstroInstance | null;
35
+ /**
36
+ * Save instance to registry (with file locking)
37
+ */
38
+ private saveInstance;
39
+ /**
40
+ * Remove instance from registry (with file locking)
41
+ */
42
+ private removeInstance;
43
+ /**
44
+ * Start heartbeat to keep instance alive
45
+ */
46
+ private startHeartbeat;
47
+ /**
48
+ * Stop heartbeat
49
+ */
50
+ private stopHeartbeat;
51
+ }
52
+ //# sourceMappingURL=instances.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instances.d.ts","sourceRoot":"","sources":["../../../server/services/instances.ts"],"names":[],"mappings":"AAuDA,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,MAAM,CAAA;IACX,gBAAgB,EAAE,MAAM,CAAA;IACxB,SAAS,EAAE,MAAM,CAAA;IACjB,aAAa,EAAE,MAAM,CAAA;IACrB,GAAG,EAAE,MAAM,CAAA;CACZ;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,YAAY,CAAQ;IAC5B,OAAO,CAAC,eAAe,CAA6B;IACpD,OAAO,CAAC,iBAAiB,CAA8C;;IAUvE;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,aAAa;IAkB/D;;OAEG;IACH,UAAU;IAQV;;OAEG;IACH,kBAAkB,IAAI,aAAa,GAAG,IAAI;IAI1C;;OAEG;IACH,MAAM,CAAC,eAAe,IAAI,aAAa,EAAE;IA6CzC;;OAEG;IACH,MAAM,CAAC,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI;IAKpD;;OAEG;IACH,OAAO,CAAC,YAAY;IA2CpB;;OAEG;IACH,OAAO,CAAC,cAAc;IA+BtB;;OAEG;IACH,OAAO,CAAC,cAAc;IAStB;;OAEG;IACH,OAAO,CAAC,aAAa;CAMtB"}