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.
- package/LICENSE +21 -0
- package/README.md +177 -0
- package/bin/commands/config.js +145 -0
- package/bin/commands/login.js +313 -0
- package/bin/commands/logout.js +75 -0
- package/bin/commands/status.js +197 -0
- package/bin/commands/whoami.js +161 -0
- package/bin/configure-claude.js +298 -0
- package/bin/mstro.js +581 -0
- package/bin/postinstall.js +45 -0
- package/bin/release.sh +110 -0
- package/dist/server/cli/headless/claude-invoker.d.ts +17 -0
- package/dist/server/cli/headless/claude-invoker.d.ts.map +1 -0
- package/dist/server/cli/headless/claude-invoker.js +311 -0
- package/dist/server/cli/headless/claude-invoker.js.map +1 -0
- package/dist/server/cli/headless/index.d.ts +13 -0
- package/dist/server/cli/headless/index.d.ts.map +1 -0
- package/dist/server/cli/headless/index.js +10 -0
- package/dist/server/cli/headless/index.js.map +1 -0
- package/dist/server/cli/headless/mcp-config.d.ts +11 -0
- package/dist/server/cli/headless/mcp-config.d.ts.map +1 -0
- package/dist/server/cli/headless/mcp-config.js +76 -0
- package/dist/server/cli/headless/mcp-config.js.map +1 -0
- package/dist/server/cli/headless/output-utils.d.ts +33 -0
- package/dist/server/cli/headless/output-utils.d.ts.map +1 -0
- package/dist/server/cli/headless/output-utils.js +101 -0
- package/dist/server/cli/headless/output-utils.js.map +1 -0
- package/dist/server/cli/headless/prompt-utils.d.ts +21 -0
- package/dist/server/cli/headless/prompt-utils.d.ts.map +1 -0
- package/dist/server/cli/headless/prompt-utils.js +84 -0
- package/dist/server/cli/headless/prompt-utils.js.map +1 -0
- package/dist/server/cli/headless/runner.d.ts +24 -0
- package/dist/server/cli/headless/runner.d.ts.map +1 -0
- package/dist/server/cli/headless/runner.js +99 -0
- package/dist/server/cli/headless/runner.js.map +1 -0
- package/dist/server/cli/headless/types.d.ts +106 -0
- package/dist/server/cli/headless/types.d.ts.map +1 -0
- package/dist/server/cli/headless/types.js +4 -0
- package/dist/server/cli/headless/types.js.map +1 -0
- package/dist/server/cli/improvisation-session-manager.d.ts +155 -0
- package/dist/server/cli/improvisation-session-manager.d.ts.map +1 -0
- package/dist/server/cli/improvisation-session-manager.js +415 -0
- package/dist/server/cli/improvisation-session-manager.js.map +1 -0
- package/dist/server/index.d.ts +2 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +386 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/mcp/bouncer-cli.d.ts +3 -0
- package/dist/server/mcp/bouncer-cli.d.ts.map +1 -0
- package/dist/server/mcp/bouncer-cli.js +99 -0
- package/dist/server/mcp/bouncer-cli.js.map +1 -0
- package/dist/server/mcp/bouncer-integration.d.ts +36 -0
- package/dist/server/mcp/bouncer-integration.d.ts.map +1 -0
- package/dist/server/mcp/bouncer-integration.js +301 -0
- package/dist/server/mcp/bouncer-integration.js.map +1 -0
- package/dist/server/mcp/security-audit.d.ts +52 -0
- package/dist/server/mcp/security-audit.d.ts.map +1 -0
- package/dist/server/mcp/security-audit.js +118 -0
- package/dist/server/mcp/security-audit.js.map +1 -0
- package/dist/server/mcp/security-patterns.d.ts +73 -0
- package/dist/server/mcp/security-patterns.d.ts.map +1 -0
- package/dist/server/mcp/security-patterns.js +247 -0
- package/dist/server/mcp/security-patterns.js.map +1 -0
- package/dist/server/mcp/server.d.ts +3 -0
- package/dist/server/mcp/server.d.ts.map +1 -0
- package/dist/server/mcp/server.js +146 -0
- package/dist/server/mcp/server.js.map +1 -0
- package/dist/server/routes/files.d.ts +9 -0
- package/dist/server/routes/files.d.ts.map +1 -0
- package/dist/server/routes/files.js +24 -0
- package/dist/server/routes/files.js.map +1 -0
- package/dist/server/routes/improvise.d.ts +3 -0
- package/dist/server/routes/improvise.d.ts.map +1 -0
- package/dist/server/routes/improvise.js +72 -0
- package/dist/server/routes/improvise.js.map +1 -0
- package/dist/server/routes/index.d.ts +10 -0
- package/dist/server/routes/index.d.ts.map +1 -0
- package/dist/server/routes/index.js +12 -0
- package/dist/server/routes/index.js.map +1 -0
- package/dist/server/routes/instances.d.ts +10 -0
- package/dist/server/routes/instances.d.ts.map +1 -0
- package/dist/server/routes/instances.js +47 -0
- package/dist/server/routes/instances.js.map +1 -0
- package/dist/server/routes/notifications.d.ts +3 -0
- package/dist/server/routes/notifications.d.ts.map +1 -0
- package/dist/server/routes/notifications.js +136 -0
- package/dist/server/routes/notifications.js.map +1 -0
- package/dist/server/services/analytics.d.ts +56 -0
- package/dist/server/services/analytics.d.ts.map +1 -0
- package/dist/server/services/analytics.js +240 -0
- package/dist/server/services/analytics.js.map +1 -0
- package/dist/server/services/auth.d.ts +26 -0
- package/dist/server/services/auth.d.ts.map +1 -0
- package/dist/server/services/auth.js +71 -0
- package/dist/server/services/auth.js.map +1 -0
- package/dist/server/services/client-id.d.ts +10 -0
- package/dist/server/services/client-id.d.ts.map +1 -0
- package/dist/server/services/client-id.js +61 -0
- package/dist/server/services/client-id.js.map +1 -0
- package/dist/server/services/credentials.d.ts +39 -0
- package/dist/server/services/credentials.d.ts.map +1 -0
- package/dist/server/services/credentials.js +110 -0
- package/dist/server/services/credentials.js.map +1 -0
- package/dist/server/services/files.d.ts +119 -0
- package/dist/server/services/files.d.ts.map +1 -0
- package/dist/server/services/files.js +560 -0
- package/dist/server/services/files.js.map +1 -0
- package/dist/server/services/instances.d.ts +52 -0
- package/dist/server/services/instances.d.ts.map +1 -0
- package/dist/server/services/instances.js +241 -0
- package/dist/server/services/instances.js.map +1 -0
- package/dist/server/services/pathUtils.d.ts +47 -0
- package/dist/server/services/pathUtils.d.ts.map +1 -0
- package/dist/server/services/pathUtils.js +124 -0
- package/dist/server/services/pathUtils.js.map +1 -0
- package/dist/server/services/platform.d.ts +72 -0
- package/dist/server/services/platform.d.ts.map +1 -0
- package/dist/server/services/platform.js +368 -0
- package/dist/server/services/platform.js.map +1 -0
- package/dist/server/services/sentry.d.ts +5 -0
- package/dist/server/services/sentry.d.ts.map +1 -0
- package/dist/server/services/sentry.js +71 -0
- package/dist/server/services/sentry.js.map +1 -0
- package/dist/server/services/terminal/pty-manager.d.ts +149 -0
- package/dist/server/services/terminal/pty-manager.d.ts.map +1 -0
- package/dist/server/services/terminal/pty-manager.js +377 -0
- package/dist/server/services/terminal/pty-manager.js.map +1 -0
- package/dist/server/services/terminal/tmux-manager.d.ts +82 -0
- package/dist/server/services/terminal/tmux-manager.d.ts.map +1 -0
- package/dist/server/services/terminal/tmux-manager.js +352 -0
- package/dist/server/services/terminal/tmux-manager.js.map +1 -0
- package/dist/server/services/websocket/autocomplete.d.ts +50 -0
- package/dist/server/services/websocket/autocomplete.d.ts.map +1 -0
- package/dist/server/services/websocket/autocomplete.js +361 -0
- package/dist/server/services/websocket/autocomplete.js.map +1 -0
- package/dist/server/services/websocket/file-utils.d.ts +44 -0
- package/dist/server/services/websocket/file-utils.d.ts.map +1 -0
- package/dist/server/services/websocket/file-utils.js +272 -0
- package/dist/server/services/websocket/file-utils.js.map +1 -0
- package/dist/server/services/websocket/handler.d.ts +246 -0
- package/dist/server/services/websocket/handler.d.ts.map +1 -0
- package/dist/server/services/websocket/handler.js +1771 -0
- package/dist/server/services/websocket/handler.js.map +1 -0
- package/dist/server/services/websocket/index.d.ts +11 -0
- package/dist/server/services/websocket/index.d.ts.map +1 -0
- package/dist/server/services/websocket/index.js +14 -0
- package/dist/server/services/websocket/index.js.map +1 -0
- package/dist/server/services/websocket/types.d.ts +214 -0
- package/dist/server/services/websocket/types.d.ts.map +1 -0
- package/dist/server/services/websocket/types.js +4 -0
- package/dist/server/services/websocket/types.js.map +1 -0
- package/dist/server/utils/agent-manager.d.ts +69 -0
- package/dist/server/utils/agent-manager.d.ts.map +1 -0
- package/dist/server/utils/agent-manager.js +269 -0
- package/dist/server/utils/agent-manager.js.map +1 -0
- package/dist/server/utils/paths.d.ts +25 -0
- package/dist/server/utils/paths.d.ts.map +1 -0
- package/dist/server/utils/paths.js +38 -0
- package/dist/server/utils/paths.js.map +1 -0
- package/dist/server/utils/port-manager.d.ts +10 -0
- package/dist/server/utils/port-manager.d.ts.map +1 -0
- package/dist/server/utils/port-manager.js +60 -0
- package/dist/server/utils/port-manager.js.map +1 -0
- package/dist/server/utils/port.d.ts +26 -0
- package/dist/server/utils/port.d.ts.map +1 -0
- package/dist/server/utils/port.js +83 -0
- package/dist/server/utils/port.js.map +1 -0
- package/hooks/bouncer.sh +138 -0
- package/package.json +74 -0
- package/server/README.md +191 -0
- package/server/cli/headless/claude-invoker.ts +415 -0
- package/server/cli/headless/index.ts +39 -0
- package/server/cli/headless/mcp-config.ts +87 -0
- package/server/cli/headless/output-utils.ts +109 -0
- package/server/cli/headless/prompt-utils.ts +108 -0
- package/server/cli/headless/runner.ts +133 -0
- package/server/cli/headless/types.ts +118 -0
- package/server/cli/improvisation-session-manager.ts +531 -0
- package/server/index.ts +456 -0
- package/server/mcp/README.md +122 -0
- package/server/mcp/bouncer-cli.ts +127 -0
- package/server/mcp/bouncer-integration.ts +430 -0
- package/server/mcp/security-audit.ts +180 -0
- package/server/mcp/security-patterns.ts +290 -0
- package/server/mcp/server.ts +174 -0
- package/server/routes/files.ts +29 -0
- package/server/routes/improvise.ts +82 -0
- package/server/routes/index.ts +13 -0
- package/server/routes/instances.ts +54 -0
- package/server/routes/notifications.ts +158 -0
- package/server/services/analytics.ts +277 -0
- package/server/services/auth.ts +80 -0
- package/server/services/client-id.ts +68 -0
- package/server/services/credentials.ts +134 -0
- package/server/services/files.ts +710 -0
- package/server/services/instances.ts +275 -0
- package/server/services/pathUtils.ts +158 -0
- package/server/services/platform.test.ts +1314 -0
- package/server/services/platform.ts +435 -0
- package/server/services/sentry.ts +81 -0
- package/server/services/terminal/pty-manager.ts +464 -0
- package/server/services/terminal/tmux-manager.ts +426 -0
- package/server/services/websocket/autocomplete.ts +438 -0
- package/server/services/websocket/file-utils.ts +305 -0
- package/server/services/websocket/handler.test.ts +20 -0
- package/server/services/websocket/handler.ts +2047 -0
- package/server/services/websocket/index.ts +40 -0
- package/server/services/websocket/types.ts +339 -0
- package/server/tsconfig.json +19 -0
- package/server/utils/agent-manager.ts +323 -0
- package/server/utils/paths.ts +45 -0
- package/server/utils/port-manager.ts +70 -0
- package/server/utils/port.ts +102 -0
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
// Copyright (c) 2025-present Mstro, Inc. All rights reserved.
|
|
2
|
+
// Licensed under the MIT License. See LICENSE file for details.
|
|
3
|
+
/**
|
|
4
|
+
* File Utilities
|
|
5
|
+
*
|
|
6
|
+
* File type detection, gitignore parsing, and directory scanning utilities.
|
|
7
|
+
*/
|
|
8
|
+
import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
|
|
9
|
+
import { extname, join, relative, sep } from 'node:path';
|
|
10
|
+
// Directories always excluded from autocomplete scanning
|
|
11
|
+
const ALWAYS_IGNORE_DIRS = new Set([
|
|
12
|
+
'node_modules', 'dist', 'dist-ssr', '.git', '__pycache__',
|
|
13
|
+
'.next', '.turbo', 'build', '.cache', 'coverage',
|
|
14
|
+
'.parcel-cache', '.nuxt', '.output', '.vercel', '.netlify',
|
|
15
|
+
'.nyc_output', 'venv', '.venv'
|
|
16
|
+
]);
|
|
17
|
+
// File type categorization for icons
|
|
18
|
+
export const FILE_TYPE_MAP = {
|
|
19
|
+
// JavaScript/TypeScript
|
|
20
|
+
'.js': 'javascript',
|
|
21
|
+
'.jsx': 'javascript',
|
|
22
|
+
'.ts': 'typescript',
|
|
23
|
+
'.tsx': 'typescript',
|
|
24
|
+
'.mjs': 'javascript',
|
|
25
|
+
'.cjs': 'javascript',
|
|
26
|
+
// Web
|
|
27
|
+
'.html': 'html',
|
|
28
|
+
'.htm': 'html',
|
|
29
|
+
'.css': 'css',
|
|
30
|
+
'.scss': 'css',
|
|
31
|
+
'.sass': 'css',
|
|
32
|
+
'.less': 'css',
|
|
33
|
+
// Data
|
|
34
|
+
'.json': 'json',
|
|
35
|
+
'.yaml': 'yaml',
|
|
36
|
+
'.yml': 'yaml',
|
|
37
|
+
'.xml': 'xml',
|
|
38
|
+
'.toml': 'config',
|
|
39
|
+
// Config
|
|
40
|
+
'.env': 'config',
|
|
41
|
+
'.gitignore': 'config',
|
|
42
|
+
'.eslintrc': 'config',
|
|
43
|
+
'.prettierrc': 'config',
|
|
44
|
+
// Documentation
|
|
45
|
+
'.md': 'markdown',
|
|
46
|
+
'.mdx': 'markdown',
|
|
47
|
+
'.txt': 'text',
|
|
48
|
+
'.rst': 'text',
|
|
49
|
+
// Images
|
|
50
|
+
'.png': 'image',
|
|
51
|
+
'.jpg': 'image',
|
|
52
|
+
'.jpeg': 'image',
|
|
53
|
+
'.gif': 'image',
|
|
54
|
+
'.svg': 'image',
|
|
55
|
+
'.webp': 'image',
|
|
56
|
+
'.ico': 'image',
|
|
57
|
+
// Other languages
|
|
58
|
+
'.py': 'python',
|
|
59
|
+
'.rb': 'ruby',
|
|
60
|
+
'.go': 'go',
|
|
61
|
+
'.rs': 'rust',
|
|
62
|
+
'.java': 'java',
|
|
63
|
+
'.kt': 'kotlin',
|
|
64
|
+
'.swift': 'swift',
|
|
65
|
+
'.c': 'c',
|
|
66
|
+
'.cpp': 'cpp',
|
|
67
|
+
'.h': 'c',
|
|
68
|
+
'.hpp': 'cpp',
|
|
69
|
+
'.cs': 'csharp',
|
|
70
|
+
'.php': 'php',
|
|
71
|
+
'.sh': 'shell',
|
|
72
|
+
'.bash': 'shell',
|
|
73
|
+
'.zsh': 'shell',
|
|
74
|
+
'.fish': 'shell',
|
|
75
|
+
// Build/Package
|
|
76
|
+
'.lock': 'lock',
|
|
77
|
+
'.log': 'log',
|
|
78
|
+
};
|
|
79
|
+
// Directory cache
|
|
80
|
+
export const directoryCache = new Map();
|
|
81
|
+
export const CACHE_TTL_MS = 5000; // 5 second cache
|
|
82
|
+
/**
|
|
83
|
+
* Get file type from extension
|
|
84
|
+
*/
|
|
85
|
+
export function getFileType(filePath) {
|
|
86
|
+
const ext = extname(filePath).toLowerCase();
|
|
87
|
+
return FILE_TYPE_MAP[ext] || 'file';
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Parse .gitignore patterns
|
|
91
|
+
*/
|
|
92
|
+
export function parseGitignore(workingDir) {
|
|
93
|
+
const gitignorePath = join(workingDir, '.gitignore');
|
|
94
|
+
if (!existsSync(gitignorePath)) {
|
|
95
|
+
return [];
|
|
96
|
+
}
|
|
97
|
+
try {
|
|
98
|
+
const content = readFileSync(gitignorePath, 'utf-8');
|
|
99
|
+
const patterns = content
|
|
100
|
+
.split('\n')
|
|
101
|
+
.map(line => line.trim())
|
|
102
|
+
.filter(line => line && !line.startsWith('#') && !line.startsWith('!'));
|
|
103
|
+
return patterns;
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
console.error('[FileUtils] Error parsing .gitignore:', error);
|
|
107
|
+
return [];
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Check if path matches gitignore pattern
|
|
112
|
+
* Follows gitignore semantics:
|
|
113
|
+
* - Patterns without slashes match anywhere in the path (e.g., "node_modules" matches "foo/node_modules/bar")
|
|
114
|
+
* - Patterns with slashes are anchored to the root (e.g., "src/foo" only matches "src/foo")
|
|
115
|
+
* - Patterns ending with / match directories
|
|
116
|
+
*/
|
|
117
|
+
function matchesSinglePattern(normalizedPath, pathSegments, pattern) {
|
|
118
|
+
const normalizedPattern = pattern.replace(/\\/g, '/');
|
|
119
|
+
const isDirectoryPattern = normalizedPattern.endsWith('/');
|
|
120
|
+
const cleanPattern = isDirectoryPattern ? normalizedPattern.slice(0, -1) : normalizedPattern;
|
|
121
|
+
if (cleanPattern.includes('/')) {
|
|
122
|
+
return normalizedPath === cleanPattern || normalizedPath.startsWith(`${cleanPattern}/`);
|
|
123
|
+
}
|
|
124
|
+
if (pathSegments.includes(cleanPattern)) {
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
if (cleanPattern.includes('*')) {
|
|
128
|
+
const regexPattern = cleanPattern
|
|
129
|
+
.replace(/\./g, '\\.')
|
|
130
|
+
.replace(/\*\*/g, '.*')
|
|
131
|
+
.replace(/\*/g, '[^/]*');
|
|
132
|
+
return new RegExp(`(^|/)${regexPattern}($|/)`).test(normalizedPath);
|
|
133
|
+
}
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
export function isIgnored(path, patterns) {
|
|
137
|
+
const normalizedPath = path.replace(/\\/g, '/');
|
|
138
|
+
const pathSegments = normalizedPath.split('/');
|
|
139
|
+
return patterns.some(pattern => matchesSinglePattern(normalizedPath, pathSegments, pattern));
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Recursively scan directory with depth limit for performance
|
|
143
|
+
*/
|
|
144
|
+
function shouldScanEntry(entry, relativePath, gitignorePatterns) {
|
|
145
|
+
if (entry.name.startsWith('.'))
|
|
146
|
+
return false;
|
|
147
|
+
if (entry.isDirectory() && ALWAYS_IGNORE_DIRS.has(entry.name))
|
|
148
|
+
return false;
|
|
149
|
+
if (gitignorePatterns.length > 0 && isIgnored(relativePath, gitignorePatterns))
|
|
150
|
+
return false;
|
|
151
|
+
return true;
|
|
152
|
+
}
|
|
153
|
+
export function scanDirectoryRecursiveWithDepth(dir, baseDir, gitignorePatterns, results = [], maxResults = 1000, maxDepth = 10, currentDepth = 0) {
|
|
154
|
+
try {
|
|
155
|
+
if (results.length >= maxResults || currentDepth >= maxDepth) {
|
|
156
|
+
return results;
|
|
157
|
+
}
|
|
158
|
+
const entries = readdirSync(dir, { withFileTypes: true });
|
|
159
|
+
for (const entry of entries) {
|
|
160
|
+
if (results.length >= maxResults)
|
|
161
|
+
break;
|
|
162
|
+
const fullPath = join(dir, entry.name);
|
|
163
|
+
const relativePath = relative(baseDir, fullPath);
|
|
164
|
+
if (!shouldScanEntry(entry, relativePath, gitignorePatterns))
|
|
165
|
+
continue;
|
|
166
|
+
results.push({ relativePath, isDirectory: entry.isDirectory() });
|
|
167
|
+
if (entry.isDirectory() && results.length < maxResults && currentDepth + 1 < maxDepth) {
|
|
168
|
+
scanDirectoryRecursiveWithDepth(fullPath, baseDir, gitignorePatterns, results, maxResults, maxDepth, currentDepth + 1);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
catch {
|
|
173
|
+
// Skip directories we can't read
|
|
174
|
+
}
|
|
175
|
+
return results;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Check if a path is in a safe location for reading (outside working dir)
|
|
179
|
+
*/
|
|
180
|
+
export function isPathInSafeLocation(fullPath) {
|
|
181
|
+
const homeDir = process.env.HOME || process.env.USERPROFILE || '';
|
|
182
|
+
const safePatterns = [
|
|
183
|
+
join(homeDir, 'Desktop'),
|
|
184
|
+
join(homeDir, 'Downloads'),
|
|
185
|
+
join(homeDir, 'Pictures'),
|
|
186
|
+
join(homeDir, 'Documents'),
|
|
187
|
+
'/var/folders/', // macOS temp directories for screenshots
|
|
188
|
+
'/tmp/',
|
|
189
|
+
process.env.TMPDIR || '/tmp'
|
|
190
|
+
];
|
|
191
|
+
return safePatterns.some(safePath => fullPath.startsWith(safePath));
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Check if a file is an image based on extension
|
|
195
|
+
*/
|
|
196
|
+
export function isImageFile(filePath) {
|
|
197
|
+
const imageExtensions = ['.png', '.jpg', '.jpeg', '.gif', '.webp', '.bmp', '.tiff', '.ico', '.svg'];
|
|
198
|
+
const ext = filePath.toLowerCase().split('.').pop();
|
|
199
|
+
return ext ? imageExtensions.includes(`.${ext}`) : false;
|
|
200
|
+
}
|
|
201
|
+
function readDirectoryContent(fullPath, filePath, fileName) {
|
|
202
|
+
try {
|
|
203
|
+
const entries = readdirSync(fullPath, { withFileTypes: true });
|
|
204
|
+
const listing = entries
|
|
205
|
+
.filter(e => !e.name.startsWith('.'))
|
|
206
|
+
.sort((a, b) => {
|
|
207
|
+
if (a.isDirectory() && !b.isDirectory())
|
|
208
|
+
return -1;
|
|
209
|
+
if (!a.isDirectory() && b.isDirectory())
|
|
210
|
+
return 1;
|
|
211
|
+
return a.name.localeCompare(b.name);
|
|
212
|
+
})
|
|
213
|
+
.map(e => e.isDirectory() ? `${e.name}/` : e.name)
|
|
214
|
+
.join('\n');
|
|
215
|
+
return { path: filePath, fileName, content: listing, size: listing.length };
|
|
216
|
+
}
|
|
217
|
+
catch {
|
|
218
|
+
return { path: filePath, fileName, content: '', error: 'Cannot read directory' };
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
function readImageContent(fullPath, filePath, fileName, stats) {
|
|
222
|
+
const buffer = readFileSync(fullPath);
|
|
223
|
+
const ext = fullPath.toLowerCase().split('.').pop() || 'png';
|
|
224
|
+
const mimeType = ext === 'svg' ? 'image/svg+xml' : ext === 'jpg' ? 'image/jpeg' : `image/${ext}`;
|
|
225
|
+
return {
|
|
226
|
+
path: filePath, fileName,
|
|
227
|
+
content: buffer.toString('base64'),
|
|
228
|
+
size: stats.size, modifiedAt: stats.mtime.toISOString(),
|
|
229
|
+
isImage: true, mimeType
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
function readTextContent(fullPath, filePath, fileName, stats) {
|
|
233
|
+
return {
|
|
234
|
+
path: filePath, fileName,
|
|
235
|
+
content: readFileSync(fullPath, 'utf-8'),
|
|
236
|
+
size: stats.size, modifiedAt: stats.mtime.toISOString()
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Read file content for context injection
|
|
241
|
+
*/
|
|
242
|
+
export function readFileContent(filePath, workingDir) {
|
|
243
|
+
try {
|
|
244
|
+
const fullPath = filePath.startsWith('/') ? filePath : join(workingDir, filePath);
|
|
245
|
+
const fileName = fullPath.split(sep).pop() || filePath;
|
|
246
|
+
const normalizedPath = join(fullPath);
|
|
247
|
+
const isInWorkingDir = normalizedPath.startsWith(join(workingDir));
|
|
248
|
+
if (!isInWorkingDir && !isPathInSafeLocation(normalizedPath)) {
|
|
249
|
+
return { path: filePath, fileName, content: '', error: 'Access denied: path outside allowed locations' };
|
|
250
|
+
}
|
|
251
|
+
if (!existsSync(fullPath)) {
|
|
252
|
+
return { path: filePath, fileName, content: '', error: 'File not found' };
|
|
253
|
+
}
|
|
254
|
+
const stats = statSync(fullPath);
|
|
255
|
+
if (stats.isDirectory()) {
|
|
256
|
+
return readDirectoryContent(fullPath, filePath, fileName);
|
|
257
|
+
}
|
|
258
|
+
const isImage = isImageFile(fullPath);
|
|
259
|
+
const MAX_FILE_SIZE = isImage ? 10 * 1024 * 1024 : 1024 * 1024;
|
|
260
|
+
if (stats.size > MAX_FILE_SIZE) {
|
|
261
|
+
return { path: filePath, fileName, content: '', size: stats.size, error: `File too large (${Math.round(stats.size / 1024)}KB). Maximum is ${isImage ? '10MB' : '1MB'}.` };
|
|
262
|
+
}
|
|
263
|
+
return isImage
|
|
264
|
+
? readImageContent(fullPath, filePath, fileName, stats)
|
|
265
|
+
: readTextContent(fullPath, filePath, fileName, stats);
|
|
266
|
+
}
|
|
267
|
+
catch (error) {
|
|
268
|
+
console.error('[FileUtils] Error reading file:', error);
|
|
269
|
+
return { path: filePath, fileName: filePath.split(sep).pop() || filePath, content: '', error: error.message || 'Failed to read file' };
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
//# sourceMappingURL=file-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-utils.js","sourceRoot":"","sources":["../../../../server/services/websocket/file-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import type { WSContext } from './types.js';
|
|
2
|
+
export interface UsageReport {
|
|
3
|
+
tokensUsed: number;
|
|
4
|
+
sessionId?: string;
|
|
5
|
+
movementId?: string;
|
|
6
|
+
}
|
|
7
|
+
export type UsageReporter = (report: UsageReport) => void;
|
|
8
|
+
export declare class WebSocketImproviseHandler {
|
|
9
|
+
private sessions;
|
|
10
|
+
private connections;
|
|
11
|
+
private autocompleteService;
|
|
12
|
+
private frecencyPath;
|
|
13
|
+
private usageReporter;
|
|
14
|
+
/** Per-tab selected git directory (tabId -> directory path) */
|
|
15
|
+
private gitDirectories;
|
|
16
|
+
constructor();
|
|
17
|
+
/**
|
|
18
|
+
* Set the usage reporter callback for sending usage data to platform
|
|
19
|
+
*/
|
|
20
|
+
setUsageReporter(reporter: UsageReporter): void;
|
|
21
|
+
/**
|
|
22
|
+
* Load frecency data from disk
|
|
23
|
+
*/
|
|
24
|
+
private loadFrecencyData;
|
|
25
|
+
/**
|
|
26
|
+
* Save frecency data to disk
|
|
27
|
+
*/
|
|
28
|
+
private saveFrecencyData;
|
|
29
|
+
/**
|
|
30
|
+
* Record a file selection for frecency scoring
|
|
31
|
+
*/
|
|
32
|
+
recordFileSelection(filePath: string): void;
|
|
33
|
+
/**
|
|
34
|
+
* Handle new WebSocket connection
|
|
35
|
+
*/
|
|
36
|
+
handleConnection(ws: WSContext, _workingDir: string): void;
|
|
37
|
+
/**
|
|
38
|
+
* Handle incoming WebSocket message
|
|
39
|
+
*/
|
|
40
|
+
handleMessage(ws: WSContext, message: string, workingDir: string): Promise<void>;
|
|
41
|
+
/**
|
|
42
|
+
* Dispatch a parsed message to the appropriate handler
|
|
43
|
+
*/
|
|
44
|
+
private dispatchMessage;
|
|
45
|
+
/**
|
|
46
|
+
* Handle session-related messages (execute, cancel, history, new, approve, reject)
|
|
47
|
+
*/
|
|
48
|
+
private handleSessionMessage;
|
|
49
|
+
/**
|
|
50
|
+
* Handle history/session listing messages
|
|
51
|
+
*/
|
|
52
|
+
private handleHistoryMessage;
|
|
53
|
+
/**
|
|
54
|
+
* Handle file-related messages (autocomplete, readFile, recordSelection, notifications)
|
|
55
|
+
*/
|
|
56
|
+
private handleFileMessage;
|
|
57
|
+
/**
|
|
58
|
+
* Handle terminal messages
|
|
59
|
+
*/
|
|
60
|
+
private handleTerminalMessage;
|
|
61
|
+
/**
|
|
62
|
+
* Handle file explorer operations with success/error response pattern
|
|
63
|
+
*/
|
|
64
|
+
private sendFileResult;
|
|
65
|
+
private handleListDirectory;
|
|
66
|
+
private handleWriteFile;
|
|
67
|
+
private handleCreateFile;
|
|
68
|
+
private handleCreateDirectory;
|
|
69
|
+
private handleDeleteFile;
|
|
70
|
+
private handleRenameFile;
|
|
71
|
+
private handleFileExplorerMessage;
|
|
72
|
+
/**
|
|
73
|
+
* Get a session or throw
|
|
74
|
+
*/
|
|
75
|
+
private requireSession;
|
|
76
|
+
/**
|
|
77
|
+
* Set up event listeners for a session
|
|
78
|
+
*/
|
|
79
|
+
private setupSessionListeners;
|
|
80
|
+
/**
|
|
81
|
+
* Resume a historical session for conversation continuity
|
|
82
|
+
* Falls back to creating a new session if the historical session cannot be found
|
|
83
|
+
* (e.g., server restarted before the session was saved to disk)
|
|
84
|
+
*/
|
|
85
|
+
private resumeHistoricalSession;
|
|
86
|
+
/**
|
|
87
|
+
* Initialize a new tab with its own session
|
|
88
|
+
*/
|
|
89
|
+
private initializeTab;
|
|
90
|
+
/**
|
|
91
|
+
* Get session for a specific tab
|
|
92
|
+
*/
|
|
93
|
+
private getSession;
|
|
94
|
+
/**
|
|
95
|
+
* Handle connection close
|
|
96
|
+
*/
|
|
97
|
+
handleClose(ws: WSContext): void;
|
|
98
|
+
/**
|
|
99
|
+
* Send message to WebSocket client
|
|
100
|
+
*/
|
|
101
|
+
private send;
|
|
102
|
+
/**
|
|
103
|
+
* Get count of all historical sessions without reading file contents
|
|
104
|
+
*/
|
|
105
|
+
private getSessionsCount;
|
|
106
|
+
/**
|
|
107
|
+
* Get paginated list of historical sessions from disk
|
|
108
|
+
* Returns minimal metadata - movements are stripped to just userPrompt preview
|
|
109
|
+
*/
|
|
110
|
+
private getSessionsList;
|
|
111
|
+
/**
|
|
112
|
+
* Get a full session by ID (includes all movement data)
|
|
113
|
+
*/
|
|
114
|
+
private getSessionById;
|
|
115
|
+
/**
|
|
116
|
+
* Delete a single session from disk
|
|
117
|
+
*/
|
|
118
|
+
private deleteSession;
|
|
119
|
+
/**
|
|
120
|
+
* Clear all sessions from disk
|
|
121
|
+
*/
|
|
122
|
+
private clearAllSessions;
|
|
123
|
+
/**
|
|
124
|
+
* Search sessions using grep on the history directory
|
|
125
|
+
* Searches through session file contents for matching text
|
|
126
|
+
* Returns paginated results with minimal metadata
|
|
127
|
+
*/
|
|
128
|
+
private movementMatchesQuery;
|
|
129
|
+
private buildSessionSummary;
|
|
130
|
+
private searchSessions;
|
|
131
|
+
/**
|
|
132
|
+
* Cleanup session
|
|
133
|
+
*/
|
|
134
|
+
cleanupSession(sessionId: string): void;
|
|
135
|
+
/**
|
|
136
|
+
* Clean up stale sessions
|
|
137
|
+
*/
|
|
138
|
+
cleanupStaleSessions(): void;
|
|
139
|
+
/**
|
|
140
|
+
* Generate a notification summary using Claude Haiku
|
|
141
|
+
* Sends the result as a notificationSummary message
|
|
142
|
+
*/
|
|
143
|
+
private generateNotificationSummary;
|
|
144
|
+
/**
|
|
145
|
+
* Create a fallback summary when AI summarization fails
|
|
146
|
+
*/
|
|
147
|
+
private createFallbackSummary;
|
|
148
|
+
/**
|
|
149
|
+
* Handle git-related messages
|
|
150
|
+
*/
|
|
151
|
+
private handleGitMessage;
|
|
152
|
+
/**
|
|
153
|
+
* Execute a git command and return stdout
|
|
154
|
+
*/
|
|
155
|
+
private executeGitCommand;
|
|
156
|
+
/**
|
|
157
|
+
* Parse git status --porcelain output into structured format
|
|
158
|
+
*/
|
|
159
|
+
private parseGitStatus;
|
|
160
|
+
/**
|
|
161
|
+
* Handle git status request
|
|
162
|
+
*/
|
|
163
|
+
private handleGitStatus;
|
|
164
|
+
/**
|
|
165
|
+
* Handle git stage request
|
|
166
|
+
*/
|
|
167
|
+
private handleGitStage;
|
|
168
|
+
/**
|
|
169
|
+
* Handle git unstage request
|
|
170
|
+
*/
|
|
171
|
+
private handleGitUnstage;
|
|
172
|
+
/**
|
|
173
|
+
* Handle git commit request (with user-provided message)
|
|
174
|
+
*/
|
|
175
|
+
private handleGitCommit;
|
|
176
|
+
/**
|
|
177
|
+
* Handle git commit with AI-generated message
|
|
178
|
+
* Uses Claude Code to analyze staged changes and generate a commit message
|
|
179
|
+
*/
|
|
180
|
+
private handleGitCommitWithAI;
|
|
181
|
+
/**
|
|
182
|
+
* Extract the actual commit message from Claude's output.
|
|
183
|
+
* Sometimes Claude outputs reasoning before the actual message, so we need to parse it.
|
|
184
|
+
*/
|
|
185
|
+
private extractCommitMessage;
|
|
186
|
+
/**
|
|
187
|
+
* Handle git push request
|
|
188
|
+
*/
|
|
189
|
+
private handleGitPush;
|
|
190
|
+
/**
|
|
191
|
+
* Handle git log request
|
|
192
|
+
*/
|
|
193
|
+
private handleGitLog;
|
|
194
|
+
/** Directories to skip when scanning for git repos */
|
|
195
|
+
private static readonly SKIP_DIRS;
|
|
196
|
+
/** Get the current branch name for a git repository */
|
|
197
|
+
private getRepoBranch;
|
|
198
|
+
/** Check if a directory name should be skipped when scanning */
|
|
199
|
+
private shouldSkipDir;
|
|
200
|
+
/** Recursively scan directories for git repositories */
|
|
201
|
+
private scanForGitRepos;
|
|
202
|
+
/**
|
|
203
|
+
* Discover git repositories in the working directory and subdirectories
|
|
204
|
+
*/
|
|
205
|
+
private handleGitDiscoverRepos;
|
|
206
|
+
/**
|
|
207
|
+
* Set the git directory for operations
|
|
208
|
+
*/
|
|
209
|
+
private handleGitSetDirectory;
|
|
210
|
+
/**
|
|
211
|
+
* Initialize a new terminal session or reconnect to existing one
|
|
212
|
+
*/
|
|
213
|
+
private handleTerminalInit;
|
|
214
|
+
/**
|
|
215
|
+
* Reconnect to an existing terminal session
|
|
216
|
+
*/
|
|
217
|
+
private handleTerminalReconnect;
|
|
218
|
+
/**
|
|
219
|
+
* List all active terminal sessions
|
|
220
|
+
*/
|
|
221
|
+
private handleTerminalList;
|
|
222
|
+
/**
|
|
223
|
+
* Handle terminal input
|
|
224
|
+
*/
|
|
225
|
+
private handleTerminalInput;
|
|
226
|
+
/**
|
|
227
|
+
* Handle terminal resize
|
|
228
|
+
*/
|
|
229
|
+
private handleTerminalResize;
|
|
230
|
+
/**
|
|
231
|
+
* Handle terminal close
|
|
232
|
+
*/
|
|
233
|
+
private handleTerminalClose;
|
|
234
|
+
private persistentHandlers;
|
|
235
|
+
private terminalListenerCleanups;
|
|
236
|
+
/**
|
|
237
|
+
* Initialize a persistent (tmux-backed) terminal session
|
|
238
|
+
* These sessions survive server restarts
|
|
239
|
+
*/
|
|
240
|
+
private handleTerminalInitPersistent;
|
|
241
|
+
/**
|
|
242
|
+
* List all persistent terminal sessions (including those from previous server runs)
|
|
243
|
+
*/
|
|
244
|
+
private handleTerminalListPersistent;
|
|
245
|
+
}
|
|
246
|
+
//# sourceMappingURL=handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../../server/services/websocket/handler.ts"],"names":[],"mappings":"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"}
|