mobilecoder-mcp 2.1.2 → 2.1.4
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/dist/agent.d.ts +28 -28
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +350 -322
- package/dist/agent.js.map +1 -1
- package/dist/cli.d.ts +2 -2
- package/dist/cli.js +39 -34
- package/dist/cli.js.map +1 -1
- package/package.json +3 -3
- package/publish_error.txt +0 -0
- package/dist/adapters/cli-adapter.d.ts +0 -13
- package/dist/adapters/cli-adapter.d.ts.map +0 -1
- package/dist/adapters/cli-adapter.js +0 -58
- package/dist/adapters/cli-adapter.js.map +0 -1
- package/dist/index.d.ts +0 -3
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -152
- package/dist/index.js.map +0 -1
- package/dist/mcp-handler.d.ts +0 -3
- package/dist/mcp-handler.d.ts.map +0 -1
- package/dist/mcp-handler.js +0 -322
- package/dist/mcp-handler.js.map +0 -1
- package/dist/security.d.ts +0 -54
- package/dist/security.d.ts.map +0 -1
- package/dist/security.js +0 -307
- package/dist/security.js.map +0 -1
- package/dist/tool-detector.d.ts +0 -18
- package/dist/tool-detector.d.ts.map +0 -1
- package/dist/tool-detector.js +0 -93
- package/dist/tool-detector.js.map +0 -1
- package/dist/webrtc.d.ts +0 -23
- package/dist/webrtc.d.ts.map +0 -1
- package/dist/webrtc.js +0 -143
- package/dist/webrtc.js.map +0 -1
package/dist/security.js
DELETED
|
@@ -1,307 +0,0 @@
|
|
|
1
|
-
import * as crypto from 'crypto';
|
|
2
|
-
import * as fs from 'fs';
|
|
3
|
-
import * as path from 'path';
|
|
4
|
-
// Security configuration
|
|
5
|
-
export const SECURITY_CONFIG = {
|
|
6
|
-
maxFileSize: 10 * 1024 * 1024, // 10MB
|
|
7
|
-
maxRequestsPerMinute: 60,
|
|
8
|
-
maxRequestsPerHour: 1000,
|
|
9
|
-
allowedFileExtensions: ['.ts', '.js', '.jsx', '.tsx', '.json', '.md', '.txt', '.yml', '.yaml', '.env.example'],
|
|
10
|
-
blockedPaths: [
|
|
11
|
-
'.git',
|
|
12
|
-
'node_modules',
|
|
13
|
-
'.env',
|
|
14
|
-
'.env.local',
|
|
15
|
-
'.env.development',
|
|
16
|
-
'.env.production',
|
|
17
|
-
'dist',
|
|
18
|
-
'build',
|
|
19
|
-
'.next',
|
|
20
|
-
'.nuxt',
|
|
21
|
-
'.cache',
|
|
22
|
-
'tmp',
|
|
23
|
-
'temp'
|
|
24
|
-
],
|
|
25
|
-
blockedFilePatterns: [
|
|
26
|
-
/\.key$/,
|
|
27
|
-
/\.pem$/,
|
|
28
|
-
/\.crt$/,
|
|
29
|
-
/\.p12$/,
|
|
30
|
-
/private/i,
|
|
31
|
-
/secret/i,
|
|
32
|
-
/password/i,
|
|
33
|
-
/token/i,
|
|
34
|
-
/\.log$/,
|
|
35
|
-
/\.pid$/,
|
|
36
|
-
/\.lock$/,
|
|
37
|
-
]
|
|
38
|
-
};
|
|
39
|
-
// Rate limiting
|
|
40
|
-
class RateLimiter {
|
|
41
|
-
maxRequests;
|
|
42
|
-
windowMs;
|
|
43
|
-
requests = new Map();
|
|
44
|
-
constructor(maxRequests, windowMs) {
|
|
45
|
-
this.maxRequests = maxRequests;
|
|
46
|
-
this.windowMs = windowMs;
|
|
47
|
-
}
|
|
48
|
-
isAllowed(identifier) {
|
|
49
|
-
const now = Date.now();
|
|
50
|
-
const entry = this.requests.get(identifier);
|
|
51
|
-
if (!entry) {
|
|
52
|
-
this.requests.set(identifier, {
|
|
53
|
-
count: 1,
|
|
54
|
-
resetTime: now + this.windowMs,
|
|
55
|
-
lastReset: now
|
|
56
|
-
});
|
|
57
|
-
return true;
|
|
58
|
-
}
|
|
59
|
-
// Reset if window expired
|
|
60
|
-
if (now > entry.resetTime) {
|
|
61
|
-
entry.count = 1;
|
|
62
|
-
entry.resetTime = now + this.windowMs;
|
|
63
|
-
entry.lastReset = now;
|
|
64
|
-
return true;
|
|
65
|
-
}
|
|
66
|
-
if (entry.count >= this.maxRequests) {
|
|
67
|
-
return false;
|
|
68
|
-
}
|
|
69
|
-
entry.count++;
|
|
70
|
-
return true;
|
|
71
|
-
}
|
|
72
|
-
cleanup() {
|
|
73
|
-
const now = Date.now();
|
|
74
|
-
for (const [key, entry] of this.requests.entries()) {
|
|
75
|
-
if (now > entry.resetTime) {
|
|
76
|
-
this.requests.delete(key);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
export const rateLimiters = {
|
|
82
|
-
perMinute: new RateLimiter(SECURITY_CONFIG.maxRequestsPerMinute, 60 * 1000),
|
|
83
|
-
perHour: new RateLimiter(SECURITY_CONFIG.maxRequestsPerHour, 60 * 60 * 1000),
|
|
84
|
-
fileOperations: new RateLimiter(30, 60 * 1000),
|
|
85
|
-
commands: new RateLimiter(10, 60 * 1000)
|
|
86
|
-
};
|
|
87
|
-
// Allowed commands for MCP agent
|
|
88
|
-
export const ALLOWED_COMMANDS = new Set([
|
|
89
|
-
'npm', 'yarn', 'pnpm', 'git', 'docker', 'docker-compose', 'claude-code', 'claude', 'gemini', 'gemini-cli', 'qoder', 'qoder-cli',
|
|
90
|
-
'node', 'python', 'python3', 'pip', 'pipx', 'cargo', 'brew', 'echo', 'ls', 'pwd',
|
|
91
|
-
'cat', 'mkdir', 'touch', 'rmdir', 'mv', 'cp', 'test', 'grep', 'find'
|
|
92
|
-
]);
|
|
93
|
-
// Input validation
|
|
94
|
-
export async function safeResolvePath(base, userInput) {
|
|
95
|
-
const resolved = path.resolve(base, userInput);
|
|
96
|
-
// Follow symlinks and get the real absolute path
|
|
97
|
-
try {
|
|
98
|
-
const realPath = fs.realpathSync(resolved);
|
|
99
|
-
const realBase = fs.realpathSync(path.resolve(base));
|
|
100
|
-
if (!realPath.startsWith(realBase)) {
|
|
101
|
-
securityLogger.logPathTraversal(userInput, realPath);
|
|
102
|
-
throw new Error('Path traversal attempt detected');
|
|
103
|
-
}
|
|
104
|
-
return realPath;
|
|
105
|
-
}
|
|
106
|
-
catch (err) {
|
|
107
|
-
if (err.code === 'ENOENT') {
|
|
108
|
-
// If path doesn't exist yet (e.g. creating a new file), just check the parent
|
|
109
|
-
const parentDir = path.dirname(resolved);
|
|
110
|
-
try {
|
|
111
|
-
const realParent = fs.realpathSync(parentDir);
|
|
112
|
-
const realBase = fs.realpathSync(path.resolve(base));
|
|
113
|
-
if (!realParent.startsWith(realBase)) {
|
|
114
|
-
throw new Error('Path traversal attempt detected (parent)');
|
|
115
|
-
}
|
|
116
|
-
return resolved;
|
|
117
|
-
}
|
|
118
|
-
catch (parentErr) {
|
|
119
|
-
throw new Error(`Invalid path: ${err.message}`);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
throw err;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
export function validatePath(filePath, cwd) {
|
|
126
|
-
// Normalize path
|
|
127
|
-
const normalizedPath = path.normalize(filePath);
|
|
128
|
-
// Check for blocked paths in components
|
|
129
|
-
const pathParts = normalizedPath.split(path.sep);
|
|
130
|
-
for (const part of pathParts) {
|
|
131
|
-
if (SECURITY_CONFIG.blockedPaths.includes(part)) {
|
|
132
|
-
return { valid: false, error: `Access to ${part} is not allowed` };
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
// Check for blocked file patterns
|
|
136
|
-
for (const pattern of SECURITY_CONFIG.blockedFilePatterns) {
|
|
137
|
-
if (pattern.test(normalizedPath)) {
|
|
138
|
-
return { valid: false, error: 'Access to sensitive files is not allowed' };
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
return { valid: true };
|
|
142
|
-
}
|
|
143
|
-
export function validateFile(filePath, cwd) {
|
|
144
|
-
const pathValidation = validatePath(filePath, cwd);
|
|
145
|
-
if (!pathValidation.valid) {
|
|
146
|
-
return pathValidation;
|
|
147
|
-
}
|
|
148
|
-
// Check file extension
|
|
149
|
-
const ext = path.extname(filePath).toLowerCase();
|
|
150
|
-
if (!ext || !SECURITY_CONFIG.allowedFileExtensions.includes(ext)) {
|
|
151
|
-
// Also allow files without extension if they are in the allowed list (like .gitignore)
|
|
152
|
-
const basename = path.basename(filePath);
|
|
153
|
-
if (!['.gitignore', '.mcprules', 'package.json', 'README.md'].includes(basename)) {
|
|
154
|
-
return { valid: false, error: `File type ${ext} or name ${basename} is not allowed` };
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
// Check file size if exists
|
|
158
|
-
const fullPath = path.resolve(cwd, filePath);
|
|
159
|
-
try {
|
|
160
|
-
const stats = fs.statSync(fullPath);
|
|
161
|
-
if (stats.size > SECURITY_CONFIG.maxFileSize) {
|
|
162
|
-
return { valid: false, error: 'File too large' };
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
catch {
|
|
166
|
-
// File doesn't exist, that's ok
|
|
167
|
-
}
|
|
168
|
-
return { valid: true };
|
|
169
|
-
}
|
|
170
|
-
export function validateCommand(command) {
|
|
171
|
-
const trimmedCmd = command.trim();
|
|
172
|
-
const firstWord = trimmedCmd.split(/\s+/)[0].toLowerCase();
|
|
173
|
-
// Check against allow-list
|
|
174
|
-
if (!ALLOWED_COMMANDS.has(firstWord)) {
|
|
175
|
-
return { valid: false, error: `Command '${firstWord}' is not in the allow-list` };
|
|
176
|
-
}
|
|
177
|
-
// Check for command injection/chaining characters
|
|
178
|
-
const forbiddenChars = [';', '&', '|', '`', '$('];
|
|
179
|
-
for (const char of forbiddenChars) {
|
|
180
|
-
if (trimmedCmd.includes(char)) {
|
|
181
|
-
return { valid: false, error: `Forbidden character detected: ${char}` };
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
// Check for dangerous patterns as a second layer
|
|
185
|
-
const dangerousPatterns = [
|
|
186
|
-
/\brm\s+-rf\b/i,
|
|
187
|
-
/\bsudo\b/i,
|
|
188
|
-
/\bsu\s/i,
|
|
189
|
-
/\bchmod\s+777\b/i,
|
|
190
|
-
/\bwget\b|\bcurl\b/i,
|
|
191
|
-
/\bnc\s|\bnetcat\b/i,
|
|
192
|
-
/\bssh\b/i,
|
|
193
|
-
/\bscp\b/i,
|
|
194
|
-
/\brsync\b/i,
|
|
195
|
-
/\bdd\s+if=/i,
|
|
196
|
-
/\bmkfs\b/i,
|
|
197
|
-
/\bfdisk\b/i,
|
|
198
|
-
/\bmount\b/i,
|
|
199
|
-
/\bumount\b/i,
|
|
200
|
-
/\bpasswd\b/i,
|
|
201
|
-
/\bshadow\b/i,
|
|
202
|
-
/\bcrontab\b/i,
|
|
203
|
-
/\bsystemctl\b/i,
|
|
204
|
-
/\bservice\s/i,
|
|
205
|
-
/\bkill\s+-9\b/i,
|
|
206
|
-
/\bkillall\b/i,
|
|
207
|
-
/>\s*\/dev\/null/,
|
|
208
|
-
/>\s*\/dev\/(zero|random|urandom)/,
|
|
209
|
-
];
|
|
210
|
-
for (const pattern of dangerousPatterns) {
|
|
211
|
-
if (pattern.test(command)) {
|
|
212
|
-
return { valid: false, error: 'Dangerous command detected' };
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
return { valid: true };
|
|
216
|
-
}
|
|
217
|
-
// Sanitization
|
|
218
|
-
export function sanitizeInput(input) {
|
|
219
|
-
return input
|
|
220
|
-
.replace(/[<>]/g, '') // Remove HTML tags
|
|
221
|
-
.replace(/[\x00-\x1f\x7f]/g, '') // Remove control characters
|
|
222
|
-
.replace(/[\r\n\t]/g, ' ') // Replace newlines and tabs
|
|
223
|
-
.trim()
|
|
224
|
-
.substring(0, 5000); // Increased limit slightly for large diffs
|
|
225
|
-
}
|
|
226
|
-
export function sanitizePath(input) {
|
|
227
|
-
return input
|
|
228
|
-
.replace(/\.\./g, '') // Basic protection, safeResolvePath does the heavy lifting
|
|
229
|
-
.replace(/[<>:"|?*]/g, '') // Remove invalid characters
|
|
230
|
-
.trim();
|
|
231
|
-
}
|
|
232
|
-
// Security logging
|
|
233
|
-
export class SecurityLogger {
|
|
234
|
-
static instance;
|
|
235
|
-
logFile;
|
|
236
|
-
constructor() {
|
|
237
|
-
this.logFile = path.join(process.cwd(), '.security.log');
|
|
238
|
-
}
|
|
239
|
-
static getInstance() {
|
|
240
|
-
if (!SecurityLogger.instance) {
|
|
241
|
-
SecurityLogger.instance = new SecurityLogger();
|
|
242
|
-
}
|
|
243
|
-
return SecurityLogger.instance;
|
|
244
|
-
}
|
|
245
|
-
log(event, details, severity = 'medium') {
|
|
246
|
-
const logEntry = {
|
|
247
|
-
timestamp: new Date().toISOString(),
|
|
248
|
-
event,
|
|
249
|
-
details,
|
|
250
|
-
severity,
|
|
251
|
-
pid: process.pid,
|
|
252
|
-
user: process.env.USER || 'unknown'
|
|
253
|
-
};
|
|
254
|
-
const logLine = JSON.stringify(logEntry) + '\n';
|
|
255
|
-
try {
|
|
256
|
-
fs.appendFileSync(this.logFile, logLine);
|
|
257
|
-
}
|
|
258
|
-
catch (error) {
|
|
259
|
-
console.error('Failed to write security log:', error);
|
|
260
|
-
}
|
|
261
|
-
// Only log high and medium severity to console
|
|
262
|
-
if (severity === 'high') {
|
|
263
|
-
console.error('🚨 SECURITY ALERT:', logEntry);
|
|
264
|
-
}
|
|
265
|
-
else if (severity === 'medium') {
|
|
266
|
-
console.warn('⚠️ SECURITY WARNING:', logEntry);
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
logBlockedCommand(command, reason) {
|
|
270
|
-
this.log('blocked_command', { command, reason }, 'high');
|
|
271
|
-
}
|
|
272
|
-
logPathTraversal(attemptedPath, resolvedPath) {
|
|
273
|
-
this.log('path_traversal', { attemptedPath, resolvedPath }, 'high');
|
|
274
|
-
}
|
|
275
|
-
logRateLimitExceeded(identifier, operation) {
|
|
276
|
-
this.log('rate_limit_exceeded', { identifier, operation }, 'medium');
|
|
277
|
-
}
|
|
278
|
-
logSuspiciousActivity(activity, details) {
|
|
279
|
-
this.log('suspicious_activity', { activity, details }, 'medium');
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
export const securityLogger = SecurityLogger.getInstance();
|
|
283
|
-
// Cleanup old rate limit entries periodically
|
|
284
|
-
setInterval(() => {
|
|
285
|
-
rateLimiters.perMinute.cleanup();
|
|
286
|
-
rateLimiters.perHour.cleanup();
|
|
287
|
-
rateLimiters.fileOperations.cleanup();
|
|
288
|
-
rateLimiters.commands.cleanup();
|
|
289
|
-
}, 5 * 60 * 1000); // Every 5 minutes
|
|
290
|
-
// Generate secure tokens
|
|
291
|
-
export function generateSecureToken(length = 32) {
|
|
292
|
-
return crypto.randomBytes(length).toString('hex');
|
|
293
|
-
}
|
|
294
|
-
// Validate session tokens
|
|
295
|
-
export function validateSessionToken(token) {
|
|
296
|
-
// Basic token validation
|
|
297
|
-
if (!token || typeof token !== 'string') {
|
|
298
|
-
return false;
|
|
299
|
-
}
|
|
300
|
-
// Check length
|
|
301
|
-
if (token.length < 16 || token.length > 128) {
|
|
302
|
-
return false;
|
|
303
|
-
}
|
|
304
|
-
// Check format (hex)
|
|
305
|
-
return /^[a-f0-9]+$/.test(token);
|
|
306
|
-
}
|
|
307
|
-
//# sourceMappingURL=security.js.map
|
package/dist/security.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"security.js","sourceRoot":"","sources":["../src/security.ts"],"names":[],"mappings":"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"}
|
package/dist/tool-detector.d.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
export interface DetectedTool {
|
|
2
|
-
id: string;
|
|
3
|
-
name: string;
|
|
4
|
-
version: string;
|
|
5
|
-
path: string;
|
|
6
|
-
isInstalled: boolean;
|
|
7
|
-
}
|
|
8
|
-
export declare class ToolDetector {
|
|
9
|
-
detectAll(): Promise<DetectedTool[]>;
|
|
10
|
-
private checkCommand;
|
|
11
|
-
private checkClaude;
|
|
12
|
-
private checkGemini;
|
|
13
|
-
private checkQoder;
|
|
14
|
-
private checkKiro;
|
|
15
|
-
private checkAider;
|
|
16
|
-
private checkCursor;
|
|
17
|
-
}
|
|
18
|
-
//# sourceMappingURL=tool-detector.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tool-detector.d.ts","sourceRoot":"","sources":["../src/tool-detector.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,YAAY;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,OAAO,CAAC;CACxB;AAED,qBAAa,YAAY;IACf,SAAS,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;YAc5B,YAAY;YASZ,WAAW;YAWX,WAAW;YAWX,UAAU;YAWV,SAAS;YAWT,UAAU;YAWV,WAAW;CAc5B"}
|
package/dist/tool-detector.js
DELETED
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
import { exec } from 'child_process';
|
|
2
|
-
import { promisify } from 'util';
|
|
3
|
-
import * as fs from 'fs';
|
|
4
|
-
import * as path from 'path';
|
|
5
|
-
import * as os from 'os';
|
|
6
|
-
const execAsync = promisify(exec);
|
|
7
|
-
export class ToolDetector {
|
|
8
|
-
async detectAll() {
|
|
9
|
-
const tools = [
|
|
10
|
-
this.checkClaude(),
|
|
11
|
-
this.checkGemini(),
|
|
12
|
-
this.checkQoder(),
|
|
13
|
-
this.checkKiro(),
|
|
14
|
-
this.checkAider(),
|
|
15
|
-
this.checkCursor()
|
|
16
|
-
];
|
|
17
|
-
const results = await Promise.all(tools);
|
|
18
|
-
return results.filter(t => t.isInstalled);
|
|
19
|
-
}
|
|
20
|
-
async checkCommand(command) {
|
|
21
|
-
try {
|
|
22
|
-
const { stdout } = await execAsync(`${command} --version`);
|
|
23
|
-
return stdout.trim();
|
|
24
|
-
}
|
|
25
|
-
catch {
|
|
26
|
-
return null;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
async checkClaude() {
|
|
30
|
-
const version = await this.checkCommand('claude');
|
|
31
|
-
return {
|
|
32
|
-
id: 'claude',
|
|
33
|
-
name: 'Claude Code',
|
|
34
|
-
version: version || '',
|
|
35
|
-
path: '',
|
|
36
|
-
isInstalled: !!version
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
async checkGemini() {
|
|
40
|
-
const version = await this.checkCommand('gemini');
|
|
41
|
-
return {
|
|
42
|
-
id: 'gemini',
|
|
43
|
-
name: 'Gemini CLI',
|
|
44
|
-
version: version || '',
|
|
45
|
-
path: '',
|
|
46
|
-
isInstalled: !!version
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
async checkQoder() {
|
|
50
|
-
const version = await this.checkCommand('qoder');
|
|
51
|
-
return {
|
|
52
|
-
id: 'qoder',
|
|
53
|
-
name: 'Qoder',
|
|
54
|
-
version: version || '',
|
|
55
|
-
path: '',
|
|
56
|
-
isInstalled: !!version
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
async checkKiro() {
|
|
60
|
-
const version = await this.checkCommand('kiro');
|
|
61
|
-
return {
|
|
62
|
-
id: 'kiro',
|
|
63
|
-
name: 'Kiro',
|
|
64
|
-
version: version || '',
|
|
65
|
-
path: '',
|
|
66
|
-
isInstalled: !!version
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
async checkAider() {
|
|
70
|
-
const version = await this.checkCommand('aider');
|
|
71
|
-
return {
|
|
72
|
-
id: 'aider',
|
|
73
|
-
name: 'Aider',
|
|
74
|
-
version: version || '',
|
|
75
|
-
path: '',
|
|
76
|
-
isInstalled: !!version
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
async checkCursor() {
|
|
80
|
-
// Cursor is an app, not typically a CLI command for version checking in the same way
|
|
81
|
-
// We check for config file existence as a proxy for "installed/configured"
|
|
82
|
-
const configPath = path.join(os.homedir(), '.cursor', 'mcp.json');
|
|
83
|
-
const isInstalled = fs.existsSync(configPath);
|
|
84
|
-
return {
|
|
85
|
-
id: 'mcp', // Maps to 'mcp' in ToolSelector
|
|
86
|
-
name: 'Cursor',
|
|
87
|
-
version: 'App',
|
|
88
|
-
path: configPath,
|
|
89
|
-
isInstalled
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
//# sourceMappingURL=tool-detector.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tool-detector.js","sourceRoot":"","sources":["../src/tool-detector.ts"],"names":[],"mappings":"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"}
|
package/dist/webrtc.d.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
export declare class WebRTCConnection {
|
|
2
|
-
private socket;
|
|
3
|
-
private code;
|
|
4
|
-
private signalingUrl;
|
|
5
|
-
private isConnected;
|
|
6
|
-
private debug;
|
|
7
|
-
private onMessageCallback?;
|
|
8
|
-
private onConnectCallback?;
|
|
9
|
-
private onDisconnectCallback?;
|
|
10
|
-
private messageNonce;
|
|
11
|
-
constructor(code: string, signalingUrl: string, debug?: boolean);
|
|
12
|
-
getDebug(): boolean;
|
|
13
|
-
private detectEnvironment;
|
|
14
|
-
connect(): Promise<void>;
|
|
15
|
-
send(message: any): void;
|
|
16
|
-
onMessage(callback: (message: any) => void): void;
|
|
17
|
-
onConnect(callback: () => void): void;
|
|
18
|
-
onDisconnect(callback: () => void): void;
|
|
19
|
-
disconnect(): void;
|
|
20
|
-
destroy(): void;
|
|
21
|
-
getConnected(): boolean;
|
|
22
|
-
}
|
|
23
|
-
//# sourceMappingURL=webrtc.d.ts.map
|
package/dist/webrtc.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"webrtc.d.ts","sourceRoot":"","sources":["../src/webrtc.ts"],"names":[],"mappings":"AAKA,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,KAAK,CAAU;IACvB,OAAO,CAAC,iBAAiB,CAAC,CAAyB;IACnD,OAAO,CAAC,iBAAiB,CAAC,CAAa;IACvC,OAAO,CAAC,oBAAoB,CAAC,CAAa;IAC1C,OAAO,CAAC,YAAY,CAAqB;gBAE7B,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,KAAK,GAAE,OAAe;IAM/D,QAAQ,IAAI,OAAO;IAI1B,OAAO,CAAC,iBAAiB;IAuBnB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAqE9B,IAAI,CAAC,OAAO,EAAE,GAAG,GAAG,IAAI;IAWxB,SAAS,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,IAAI,GAAG,IAAI;IAIjD,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI;IAIrC,YAAY,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI;IAIxC,UAAU,IAAI,IAAI;IAQlB,OAAO,IAAI,IAAI;IAIf,YAAY,IAAI,OAAO;CAGxB"}
|
package/dist/webrtc.js
DELETED
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
import { io } from 'socket.io-client';
|
|
2
|
-
import os from 'os';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
export class WebRTCConnection {
|
|
5
|
-
socket = null;
|
|
6
|
-
code;
|
|
7
|
-
signalingUrl;
|
|
8
|
-
isConnected = false;
|
|
9
|
-
debug;
|
|
10
|
-
onMessageCallback;
|
|
11
|
-
onConnectCallback;
|
|
12
|
-
onDisconnectCallback;
|
|
13
|
-
messageNonce = new Set();
|
|
14
|
-
constructor(code, signalingUrl, debug = false) {
|
|
15
|
-
this.code = code;
|
|
16
|
-
this.signalingUrl = signalingUrl.replace(/\/api$/, ''); // Ensure clean base URL
|
|
17
|
-
this.debug = debug;
|
|
18
|
-
}
|
|
19
|
-
getDebug() {
|
|
20
|
-
return this.debug;
|
|
21
|
-
}
|
|
22
|
-
detectEnvironment() {
|
|
23
|
-
let editor = 'Terminal';
|
|
24
|
-
if (process.env.CURSOR_SESSION_ID)
|
|
25
|
-
editor = 'Cursor';
|
|
26
|
-
else if (process.env.VSCODE_PID)
|
|
27
|
-
editor = 'VS Code';
|
|
28
|
-
else if (process.env.WINDSURF_SESSION)
|
|
29
|
-
editor = 'Windsurf';
|
|
30
|
-
else if (process.env.TERM_PROGRAM === 'vscode')
|
|
31
|
-
editor = 'VS Code Terminal';
|
|
32
|
-
else if (process.env.TERM_PROGRAM === 'Apple_Terminal')
|
|
33
|
-
editor = 'Terminal';
|
|
34
|
-
else if (process.env.TERM_PROGRAM === 'iTerm.app')
|
|
35
|
-
editor = 'iTerm2';
|
|
36
|
-
const projectPath = process.cwd();
|
|
37
|
-
const projectName = path.basename(projectPath);
|
|
38
|
-
return {
|
|
39
|
-
type: 'environment_info',
|
|
40
|
-
editor,
|
|
41
|
-
projectName,
|
|
42
|
-
projectPath,
|
|
43
|
-
platform: process.platform,
|
|
44
|
-
hostname: os.hostname(),
|
|
45
|
-
timestamp: Date.now()
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
async connect() {
|
|
49
|
-
return new Promise((resolve, reject) => {
|
|
50
|
-
const timestamp = new Date().toLocaleTimeString();
|
|
51
|
-
console.log(`[${timestamp}] 🔌 [MCP] Initializing Zero-Trust Relay Tunnel...`);
|
|
52
|
-
this.socket = io(this.signalingUrl, {
|
|
53
|
-
path: '/terminal/socket.io',
|
|
54
|
-
transports: ['websocket', 'polling'],
|
|
55
|
-
reconnection: true,
|
|
56
|
-
reconnectionAttempts: Infinity,
|
|
57
|
-
reconnectionDelay: 1000,
|
|
58
|
-
// Zero-Trust: Sessions are ephemeral
|
|
59
|
-
});
|
|
60
|
-
const relay = this.socket.io.on('packet', (packet) => {
|
|
61
|
-
// Internal monitoring if needed
|
|
62
|
-
});
|
|
63
|
-
this.socket.on('connect', () => {
|
|
64
|
-
const timestamp = new Date().toLocaleTimeString();
|
|
65
|
-
console.log(`[${timestamp}] 🛡️ [MCP] Connected to Relay Server. Joining room [${this.code}]...`);
|
|
66
|
-
this.socket?.emit('join_room', { code: this.code, type: 'agent' });
|
|
67
|
-
});
|
|
68
|
-
this.socket.on('peer_joined', (data) => {
|
|
69
|
-
const timestamp = new Date().toLocaleTimeString();
|
|
70
|
-
if (data.type === 'client') {
|
|
71
|
-
console.log(`\n[${timestamp}] 🟢 [MCP] [ONLINE] Mobile client linked via Relay!`);
|
|
72
|
-
this.isConnected = true;
|
|
73
|
-
// Send environment info immediately
|
|
74
|
-
const envInfo = this.detectEnvironment();
|
|
75
|
-
this.send(envInfo);
|
|
76
|
-
if (this.onConnectCallback)
|
|
77
|
-
this.onConnectCallback();
|
|
78
|
-
resolve();
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
this.socket.on('term_data', (data) => {
|
|
82
|
-
if (this.onMessageCallback) {
|
|
83
|
-
this.onMessageCallback({ type: 'data', data });
|
|
84
|
-
}
|
|
85
|
-
});
|
|
86
|
-
this.socket.on('meta_data', (payload) => {
|
|
87
|
-
if (this.onMessageCallback) {
|
|
88
|
-
this.onMessageCallback(payload);
|
|
89
|
-
}
|
|
90
|
-
});
|
|
91
|
-
this.socket.on('peer_disconnected', () => {
|
|
92
|
-
const timestamp = new Date().toLocaleTimeString();
|
|
93
|
-
console.log(`[${timestamp}] 🔴 [MCP] Mobile client disconnected.`);
|
|
94
|
-
this.isConnected = false;
|
|
95
|
-
if (this.onDisconnectCallback)
|
|
96
|
-
this.onDisconnectCallback();
|
|
97
|
-
});
|
|
98
|
-
this.socket.on('connect_error', (error) => {
|
|
99
|
-
if (this.debug)
|
|
100
|
-
console.error('[Relay] Connection Error:', error.message);
|
|
101
|
-
});
|
|
102
|
-
this.socket.on('disconnect', () => {
|
|
103
|
-
this.isConnected = false;
|
|
104
|
-
if (this.onDisconnectCallback)
|
|
105
|
-
this.onDisconnectCallback();
|
|
106
|
-
});
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
send(message) {
|
|
110
|
-
if (!this.socket || !this.socket.connected)
|
|
111
|
-
return;
|
|
112
|
-
// Map internal types to relay events
|
|
113
|
-
if (message.type === 'data' || message.type === 'input') {
|
|
114
|
-
this.socket.emit('term_data', { code: this.code, data: message.data });
|
|
115
|
-
}
|
|
116
|
-
else {
|
|
117
|
-
this.socket.emit('meta_data', { code: this.code, payload: message });
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
onMessage(callback) {
|
|
121
|
-
this.onMessageCallback = callback;
|
|
122
|
-
}
|
|
123
|
-
onConnect(callback) {
|
|
124
|
-
this.onConnectCallback = callback;
|
|
125
|
-
}
|
|
126
|
-
onDisconnect(callback) {
|
|
127
|
-
this.onDisconnectCallback = callback;
|
|
128
|
-
}
|
|
129
|
-
disconnect() {
|
|
130
|
-
if (this.socket) {
|
|
131
|
-
this.socket.disconnect();
|
|
132
|
-
this.socket = null;
|
|
133
|
-
}
|
|
134
|
-
this.isConnected = false;
|
|
135
|
-
}
|
|
136
|
-
destroy() {
|
|
137
|
-
this.disconnect();
|
|
138
|
-
}
|
|
139
|
-
getConnected() {
|
|
140
|
-
return this.isConnected;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
//# sourceMappingURL=webrtc.js.map
|
package/dist/webrtc.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"webrtc.js","sourceRoot":"","sources":["../src/webrtc.ts"],"names":[],"mappings":"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"}
|