mobilcoder-mcp 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/cli-adapter.d.ts +13 -0
- package/dist/adapters/cli-adapter.d.ts.map +1 -0
- package/dist/adapters/cli-adapter.js +62 -0
- package/dist/adapters/cli-adapter.js.map +1 -0
- package/dist/agent.d.ts +10 -0
- package/dist/agent.d.ts.map +1 -0
- package/dist/agent.js +63 -0
- package/dist/agent.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +175 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp-handler.d.ts +3 -0
- package/dist/mcp-handler.d.ts.map +1 -0
- package/dist/mcp-handler.js +317 -0
- package/dist/mcp-handler.js.map +1 -0
- package/dist/security.d.ts +52 -0
- package/dist/security.d.ts.map +1 -0
- package/dist/security.js +307 -0
- package/dist/security.js.map +1 -0
- package/dist/tool-detector.d.ts +18 -0
- package/dist/tool-detector.d.ts.map +1 -0
- package/dist/tool-detector.js +130 -0
- package/dist/tool-detector.js.map +1 -0
- package/dist/webrtc.d.ts +20 -0
- package/dist/webrtc.d.ts.map +1 -0
- package/dist/webrtc.js +152 -0
- package/dist/webrtc.js.map +1 -0
- package/package.json +35 -0
- package/src/adapters/cli-adapter.ts +73 -0
- package/src/agent.ts +71 -0
- package/src/index.ts +162 -0
- package/src/mcp-handler.ts +324 -0
- package/src/security.ts +294 -0
- package/src/tool-detector.ts +110 -0
- package/src/webrtc.ts +156 -0
- package/tsconfig.json +21 -0
package/dist/security.js
ADDED
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.securityLogger = exports.SecurityLogger = exports.rateLimiters = exports.SECURITY_CONFIG = void 0;
|
|
37
|
+
exports.validatePath = validatePath;
|
|
38
|
+
exports.validateFile = validateFile;
|
|
39
|
+
exports.validateCommand = validateCommand;
|
|
40
|
+
exports.sanitizeInput = sanitizeInput;
|
|
41
|
+
exports.sanitizePath = sanitizePath;
|
|
42
|
+
exports.generateSecureToken = generateSecureToken;
|
|
43
|
+
exports.validateSessionToken = validateSessionToken;
|
|
44
|
+
const crypto = __importStar(require("crypto"));
|
|
45
|
+
const fs = __importStar(require("fs"));
|
|
46
|
+
const path = __importStar(require("path"));
|
|
47
|
+
// Security configuration
|
|
48
|
+
exports.SECURITY_CONFIG = {
|
|
49
|
+
maxFileSize: 10 * 1024 * 1024, // 10MB
|
|
50
|
+
maxRequestsPerMinute: 60,
|
|
51
|
+
maxRequestsPerHour: 1000,
|
|
52
|
+
allowedFileExtensions: ['.ts', '.js', '.jsx', '.tsx', '.json', '.md', '.txt', '.yml', '.yaml', '.env.example'],
|
|
53
|
+
blockedPaths: [
|
|
54
|
+
'.git',
|
|
55
|
+
'node_modules',
|
|
56
|
+
'.env',
|
|
57
|
+
'.env.local',
|
|
58
|
+
'.env.development',
|
|
59
|
+
'.env.production',
|
|
60
|
+
'dist',
|
|
61
|
+
'build',
|
|
62
|
+
'.next',
|
|
63
|
+
'.nuxt',
|
|
64
|
+
'.cache',
|
|
65
|
+
'tmp',
|
|
66
|
+
'temp'
|
|
67
|
+
],
|
|
68
|
+
blockedFilePatterns: [
|
|
69
|
+
/\.key$/,
|
|
70
|
+
/\.pem$/,
|
|
71
|
+
/\.crt$/,
|
|
72
|
+
/\.p12$/,
|
|
73
|
+
/private/i,
|
|
74
|
+
/secret/i,
|
|
75
|
+
/password/i,
|
|
76
|
+
/token/i,
|
|
77
|
+
/\.log$/,
|
|
78
|
+
/\.pid$/,
|
|
79
|
+
/\.lock$/,
|
|
80
|
+
]
|
|
81
|
+
};
|
|
82
|
+
// Rate limiting
|
|
83
|
+
class RateLimiter {
|
|
84
|
+
maxRequests;
|
|
85
|
+
windowMs;
|
|
86
|
+
requests = new Map();
|
|
87
|
+
constructor(maxRequests, windowMs) {
|
|
88
|
+
this.maxRequests = maxRequests;
|
|
89
|
+
this.windowMs = windowMs;
|
|
90
|
+
}
|
|
91
|
+
isAllowed(identifier) {
|
|
92
|
+
const now = Date.now();
|
|
93
|
+
const entry = this.requests.get(identifier);
|
|
94
|
+
if (!entry) {
|
|
95
|
+
this.requests.set(identifier, {
|
|
96
|
+
count: 1,
|
|
97
|
+
resetTime: now + this.windowMs,
|
|
98
|
+
lastReset: now
|
|
99
|
+
});
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
// Reset if window expired
|
|
103
|
+
if (now > entry.resetTime) {
|
|
104
|
+
entry.count = 1;
|
|
105
|
+
entry.resetTime = now + this.windowMs;
|
|
106
|
+
entry.lastReset = now;
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
if (entry.count >= this.maxRequests) {
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
entry.count++;
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
cleanup() {
|
|
116
|
+
const now = Date.now();
|
|
117
|
+
for (const [key, entry] of this.requests.entries()) {
|
|
118
|
+
if (now > entry.resetTime) {
|
|
119
|
+
this.requests.delete(key);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
exports.rateLimiters = {
|
|
125
|
+
perMinute: new RateLimiter(exports.SECURITY_CONFIG.maxRequestsPerMinute, 60 * 1000),
|
|
126
|
+
perHour: new RateLimiter(exports.SECURITY_CONFIG.maxRequestsPerHour, 60 * 60 * 1000),
|
|
127
|
+
fileOperations: new RateLimiter(30, 60 * 1000),
|
|
128
|
+
commands: new RateLimiter(10, 60 * 1000)
|
|
129
|
+
};
|
|
130
|
+
// Input validation
|
|
131
|
+
function validatePath(filePath, cwd) {
|
|
132
|
+
// Normalize path
|
|
133
|
+
const normalizedPath = path.normalize(filePath);
|
|
134
|
+
const fullPath = path.resolve(cwd, normalizedPath);
|
|
135
|
+
// Check for path traversal
|
|
136
|
+
if (!fullPath.startsWith(path.resolve(cwd))) {
|
|
137
|
+
return { valid: false, error: 'Path traversal detected' };
|
|
138
|
+
}
|
|
139
|
+
// Check for blocked paths
|
|
140
|
+
const pathParts = normalizedPath.split(path.sep);
|
|
141
|
+
for (const part of pathParts) {
|
|
142
|
+
if (exports.SECURITY_CONFIG.blockedPaths.includes(part)) {
|
|
143
|
+
return { valid: false, error: `Access to ${part} is not allowed` };
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// Check for blocked file patterns
|
|
147
|
+
for (const pattern of exports.SECURITY_CONFIG.blockedFilePatterns) {
|
|
148
|
+
if (pattern.test(normalizedPath)) {
|
|
149
|
+
return { valid: false, error: 'Access to sensitive files is not allowed' };
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return { valid: true };
|
|
153
|
+
}
|
|
154
|
+
function validateFile(filePath, cwd) {
|
|
155
|
+
const pathValidation = validatePath(filePath, cwd);
|
|
156
|
+
if (!pathValidation.valid) {
|
|
157
|
+
return pathValidation;
|
|
158
|
+
}
|
|
159
|
+
// Check file extension
|
|
160
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
161
|
+
if (!exports.SECURITY_CONFIG.allowedFileExtensions.includes(ext)) {
|
|
162
|
+
return { valid: false, error: `File type ${ext} is not allowed` };
|
|
163
|
+
}
|
|
164
|
+
// Check file size if exists
|
|
165
|
+
const fullPath = path.resolve(cwd, filePath);
|
|
166
|
+
try {
|
|
167
|
+
const stats = fs.statSync(fullPath);
|
|
168
|
+
if (stats.size > exports.SECURITY_CONFIG.maxFileSize) {
|
|
169
|
+
return { valid: false, error: 'File too large' };
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
catch {
|
|
173
|
+
// File doesn't exist, that's ok
|
|
174
|
+
}
|
|
175
|
+
return { valid: true };
|
|
176
|
+
}
|
|
177
|
+
function validateCommand(command) {
|
|
178
|
+
// Check for dangerous commands
|
|
179
|
+
const dangerousPatterns = [
|
|
180
|
+
/\brm\s+-rf\b/i,
|
|
181
|
+
/\bsudo\b/i,
|
|
182
|
+
/\bsu\s/i,
|
|
183
|
+
/\bchmod\s+777\b/i,
|
|
184
|
+
/\bwget\b|\bcurl\b/i,
|
|
185
|
+
/\bnc\s|\bnetcat\b/i,
|
|
186
|
+
/\bssh\b/i,
|
|
187
|
+
/\bscp\b/i,
|
|
188
|
+
/\brsync\b/i,
|
|
189
|
+
/\bdd\s+if=/i,
|
|
190
|
+
/\bmkfs\b/i,
|
|
191
|
+
/\bfdisk\b/i,
|
|
192
|
+
/\bmount\b/i,
|
|
193
|
+
/\bumount\b/i,
|
|
194
|
+
/\bpasswd\b/i,
|
|
195
|
+
/\bshadow\b/i,
|
|
196
|
+
/\bcrontab\b/i,
|
|
197
|
+
/\bsystemctl\b/i,
|
|
198
|
+
/\bservice\s/i,
|
|
199
|
+
/\bkill\s+-9\b/i,
|
|
200
|
+
/\bkillall\b/i,
|
|
201
|
+
/>\s*\/dev\/null/,
|
|
202
|
+
/>\s*\/dev\/(zero|random|urandom)/,
|
|
203
|
+
];
|
|
204
|
+
for (const pattern of dangerousPatterns) {
|
|
205
|
+
if (pattern.test(command)) {
|
|
206
|
+
return { valid: false, error: 'Dangerous command detected' };
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return { valid: true };
|
|
210
|
+
}
|
|
211
|
+
// Sanitization
|
|
212
|
+
function sanitizeInput(input) {
|
|
213
|
+
return input
|
|
214
|
+
.replace(/[<>]/g, '') // Remove HTML tags
|
|
215
|
+
.replace(/[\x00-\x1f\x7f]/g, '') // Remove control characters
|
|
216
|
+
.replace(/[\r\n\t]/g, ' ') // Replace newlines and tabs
|
|
217
|
+
.trim()
|
|
218
|
+
.substring(0, 1000); // Limit length
|
|
219
|
+
}
|
|
220
|
+
function sanitizePath(input) {
|
|
221
|
+
return input
|
|
222
|
+
.replace(/\.\./g, '') // Remove parent directory references
|
|
223
|
+
.replace(/^\//, '') // Remove leading slashes
|
|
224
|
+
.replace(/\/$/, '') // Remove trailing slashes
|
|
225
|
+
.replace(/[<>:"|?*]/g, '') // Remove invalid characters
|
|
226
|
+
.trim();
|
|
227
|
+
}
|
|
228
|
+
// Security logging
|
|
229
|
+
class SecurityLogger {
|
|
230
|
+
static instance;
|
|
231
|
+
logFile;
|
|
232
|
+
constructor() {
|
|
233
|
+
this.logFile = path.join(process.cwd(), '.security.log');
|
|
234
|
+
}
|
|
235
|
+
static getInstance() {
|
|
236
|
+
if (!SecurityLogger.instance) {
|
|
237
|
+
SecurityLogger.instance = new SecurityLogger();
|
|
238
|
+
}
|
|
239
|
+
return SecurityLogger.instance;
|
|
240
|
+
}
|
|
241
|
+
log(event, details, severity = 'medium') {
|
|
242
|
+
const logEntry = {
|
|
243
|
+
timestamp: new Date().toISOString(),
|
|
244
|
+
event,
|
|
245
|
+
details,
|
|
246
|
+
severity,
|
|
247
|
+
pid: process.pid,
|
|
248
|
+
user: process.env.USER || 'unknown'
|
|
249
|
+
};
|
|
250
|
+
const logLine = JSON.stringify(logEntry) + '\n';
|
|
251
|
+
try {
|
|
252
|
+
fs.appendFileSync(this.logFile, logLine);
|
|
253
|
+
}
|
|
254
|
+
catch (error) {
|
|
255
|
+
console.error('Failed to write security log:', error);
|
|
256
|
+
}
|
|
257
|
+
// Also log to console for immediate visibility
|
|
258
|
+
if (severity === 'high') {
|
|
259
|
+
console.error('🚨 SECURITY ALERT:', logEntry);
|
|
260
|
+
}
|
|
261
|
+
else if (severity === 'medium') {
|
|
262
|
+
console.warn('⚠️ SECURITY WARNING:', logEntry);
|
|
263
|
+
}
|
|
264
|
+
else {
|
|
265
|
+
console.log('ℹ️ SECURITY INFO:', logEntry);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
logBlockedCommand(command, reason) {
|
|
269
|
+
this.log('blocked_command', { command, reason }, 'high');
|
|
270
|
+
}
|
|
271
|
+
logPathTraversal(attemptedPath, resolvedPath) {
|
|
272
|
+
this.log('path_traversal', { attemptedPath, resolvedPath }, 'high');
|
|
273
|
+
}
|
|
274
|
+
logRateLimitExceeded(identifier, operation) {
|
|
275
|
+
this.log('rate_limit_exceeded', { identifier, operation }, 'medium');
|
|
276
|
+
}
|
|
277
|
+
logSuspiciousActivity(activity, details) {
|
|
278
|
+
this.log('suspicious_activity', { activity, details }, 'medium');
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
exports.SecurityLogger = SecurityLogger;
|
|
282
|
+
exports.securityLogger = SecurityLogger.getInstance();
|
|
283
|
+
// Cleanup old rate limit entries periodically
|
|
284
|
+
setInterval(() => {
|
|
285
|
+
exports.rateLimiters.perMinute.cleanup();
|
|
286
|
+
exports.rateLimiters.perHour.cleanup();
|
|
287
|
+
exports.rateLimiters.fileOperations.cleanup();
|
|
288
|
+
exports.rateLimiters.commands.cleanup();
|
|
289
|
+
}, 5 * 60 * 1000); // Every 5 minutes
|
|
290
|
+
// Generate secure tokens
|
|
291
|
+
function generateSecureToken(length = 32) {
|
|
292
|
+
return crypto.randomBytes(length).toString('hex');
|
|
293
|
+
}
|
|
294
|
+
// Validate session tokens
|
|
295
|
+
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
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security.js","sourceRoot":"","sources":["../src/security.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.ToolDetector = void 0;
|
|
37
|
+
const child_process_1 = require("child_process");
|
|
38
|
+
const util_1 = require("util");
|
|
39
|
+
const fs = __importStar(require("fs"));
|
|
40
|
+
const path = __importStar(require("path"));
|
|
41
|
+
const os = __importStar(require("os"));
|
|
42
|
+
const execAsync = (0, util_1.promisify)(child_process_1.exec);
|
|
43
|
+
class ToolDetector {
|
|
44
|
+
async detectAll() {
|
|
45
|
+
const tools = [
|
|
46
|
+
this.checkClaude(),
|
|
47
|
+
this.checkGemini(),
|
|
48
|
+
this.checkQoder(),
|
|
49
|
+
this.checkKiro(),
|
|
50
|
+
this.checkAider(),
|
|
51
|
+
this.checkCursor()
|
|
52
|
+
];
|
|
53
|
+
const results = await Promise.all(tools);
|
|
54
|
+
return results.filter(t => t.isInstalled);
|
|
55
|
+
}
|
|
56
|
+
async checkCommand(command) {
|
|
57
|
+
try {
|
|
58
|
+
const { stdout } = await execAsync(`${command} --version`);
|
|
59
|
+
return stdout.trim();
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
async checkClaude() {
|
|
66
|
+
const version = await this.checkCommand('claude');
|
|
67
|
+
return {
|
|
68
|
+
id: 'claude',
|
|
69
|
+
name: 'Claude Code',
|
|
70
|
+
version: version || '',
|
|
71
|
+
path: '',
|
|
72
|
+
isInstalled: !!version
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
async checkGemini() {
|
|
76
|
+
const version = await this.checkCommand('gemini');
|
|
77
|
+
return {
|
|
78
|
+
id: 'gemini',
|
|
79
|
+
name: 'Gemini CLI',
|
|
80
|
+
version: version || '',
|
|
81
|
+
path: '',
|
|
82
|
+
isInstalled: !!version
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
async checkQoder() {
|
|
86
|
+
const version = await this.checkCommand('qoder');
|
|
87
|
+
return {
|
|
88
|
+
id: 'qoder',
|
|
89
|
+
name: 'Qoder',
|
|
90
|
+
version: version || '',
|
|
91
|
+
path: '',
|
|
92
|
+
isInstalled: !!version
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
async checkKiro() {
|
|
96
|
+
const version = await this.checkCommand('kiro');
|
|
97
|
+
return {
|
|
98
|
+
id: 'kiro',
|
|
99
|
+
name: 'Kiro',
|
|
100
|
+
version: version || '',
|
|
101
|
+
path: '',
|
|
102
|
+
isInstalled: !!version
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
async checkAider() {
|
|
106
|
+
const version = await this.checkCommand('aider');
|
|
107
|
+
return {
|
|
108
|
+
id: 'aider',
|
|
109
|
+
name: 'Aider',
|
|
110
|
+
version: version || '',
|
|
111
|
+
path: '',
|
|
112
|
+
isInstalled: !!version
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
async checkCursor() {
|
|
116
|
+
// Cursor is an app, not typically a CLI command for version checking in the same way
|
|
117
|
+
// We check for config file existence as a proxy for "installed/configured"
|
|
118
|
+
const configPath = path.join(os.homedir(), '.cursor', 'mcp.json');
|
|
119
|
+
const isInstalled = fs.existsSync(configPath);
|
|
120
|
+
return {
|
|
121
|
+
id: 'mcp', // Maps to 'mcp' in ToolSelector
|
|
122
|
+
name: 'Cursor',
|
|
123
|
+
version: 'App',
|
|
124
|
+
path: configPath,
|
|
125
|
+
isInstalled
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
exports.ToolDetector = ToolDetector;
|
|
130
|
+
//# sourceMappingURL=tool-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-detector.js","sourceRoot":"","sources":["../src/tool-detector.ts"],"names":[],"mappings":"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"}
|
package/dist/webrtc.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export declare class WebRTCConnection {
|
|
2
|
+
private peer;
|
|
3
|
+
private code;
|
|
4
|
+
private signalingUrl;
|
|
5
|
+
private onMessageCallback?;
|
|
6
|
+
private onConnectCallback?;
|
|
7
|
+
private onDisconnectCallback?;
|
|
8
|
+
private isConnected;
|
|
9
|
+
private pollingInterval?;
|
|
10
|
+
constructor(code: string, signalingUrl: string);
|
|
11
|
+
connect(): Promise<void>;
|
|
12
|
+
private startPollingForOffer;
|
|
13
|
+
send(message: any): void;
|
|
14
|
+
onMessage(callback: (message: any) => void): void;
|
|
15
|
+
onConnect(callback: () => void): void;
|
|
16
|
+
onDisconnect(callback: () => void): void;
|
|
17
|
+
disconnect(): void;
|
|
18
|
+
getConnected(): boolean;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=webrtc.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webrtc.d.ts","sourceRoot":"","sources":["../src/webrtc.ts"],"names":[],"mappings":"AAEA,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,IAAI,CAAoC;IAChD,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,iBAAiB,CAAC,CAAyB;IACnD,OAAO,CAAC,iBAAiB,CAAC,CAAa;IACvC,OAAO,CAAC,oBAAoB,CAAC,CAAa;IAC1C,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,eAAe,CAAC,CAAiB;gBAE7B,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM;IAKxC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;YAyEhB,oBAAoB;IA0BlC,IAAI,CAAC,OAAO,EAAE,GAAG,GAAG,IAAI;IAYxB,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;IAWlB,YAAY,IAAI,OAAO;CAGxB"}
|
package/dist/webrtc.js
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.WebRTCConnection = void 0;
|
|
7
|
+
const simple_peer_1 = __importDefault(require("simple-peer"));
|
|
8
|
+
class WebRTCConnection {
|
|
9
|
+
peer = null;
|
|
10
|
+
code;
|
|
11
|
+
signalingUrl;
|
|
12
|
+
onMessageCallback;
|
|
13
|
+
onConnectCallback;
|
|
14
|
+
onDisconnectCallback;
|
|
15
|
+
isConnected = false;
|
|
16
|
+
pollingInterval;
|
|
17
|
+
constructor(code, signalingUrl) {
|
|
18
|
+
this.code = code;
|
|
19
|
+
this.signalingUrl = signalingUrl;
|
|
20
|
+
}
|
|
21
|
+
async connect() {
|
|
22
|
+
return new Promise((resolve, reject) => {
|
|
23
|
+
try {
|
|
24
|
+
// Desktop acts as answerer (not initiator)
|
|
25
|
+
this.peer = new simple_peer_1.default({
|
|
26
|
+
initiator: false,
|
|
27
|
+
trickle: false,
|
|
28
|
+
config: {
|
|
29
|
+
iceServers: [
|
|
30
|
+
{ urls: 'stun:stun.l.google.com:19302' },
|
|
31
|
+
{ urls: 'stun:stun1.l.google.com:19302' }
|
|
32
|
+
]
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
this.peer.on('signal', async (signal) => {
|
|
36
|
+
// Send answer to signaling server
|
|
37
|
+
try {
|
|
38
|
+
await fetch(`${this.signalingUrl}/answer`, {
|
|
39
|
+
method: 'POST',
|
|
40
|
+
headers: { 'Content-Type': 'application/json' },
|
|
41
|
+
body: JSON.stringify({ code: this.code, signal })
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
console.error('Failed to send answer:', error);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
this.peer.on('connect', () => {
|
|
49
|
+
console.log('✅ Connected to mobile device!');
|
|
50
|
+
this.isConnected = true;
|
|
51
|
+
if (this.onConnectCallback) {
|
|
52
|
+
this.onConnectCallback();
|
|
53
|
+
}
|
|
54
|
+
resolve();
|
|
55
|
+
});
|
|
56
|
+
this.peer.on('data', (data) => {
|
|
57
|
+
try {
|
|
58
|
+
const message = JSON.parse(data.toString());
|
|
59
|
+
if (this.onMessageCallback) {
|
|
60
|
+
this.onMessageCallback(message);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
console.error('Failed to parse message:', error);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
this.peer.on('error', (error) => {
|
|
68
|
+
console.error('WebRTC error:', error);
|
|
69
|
+
this.isConnected = false;
|
|
70
|
+
if (this.onDisconnectCallback) {
|
|
71
|
+
this.onDisconnectCallback();
|
|
72
|
+
}
|
|
73
|
+
reject(error);
|
|
74
|
+
});
|
|
75
|
+
this.peer.on('close', () => {
|
|
76
|
+
console.log('❌ Connection closed');
|
|
77
|
+
this.isConnected = false;
|
|
78
|
+
if (this.onDisconnectCallback) {
|
|
79
|
+
this.onDisconnectCallback();
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
// Start polling for offer from mobile
|
|
83
|
+
this.startPollingForOffer();
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
reject(error);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
async startPollingForOffer() {
|
|
91
|
+
const poll = async () => {
|
|
92
|
+
try {
|
|
93
|
+
const response = await fetch(`${this.signalingUrl}/poll?code=${this.code}`);
|
|
94
|
+
if (response.ok) {
|
|
95
|
+
const data = await response.json();
|
|
96
|
+
if (data.signal && this.peer) {
|
|
97
|
+
// Received offer from mobile, signal the peer
|
|
98
|
+
this.peer.signal(data.signal);
|
|
99
|
+
// Stop polling once we got the offer
|
|
100
|
+
if (this.pollingInterval) {
|
|
101
|
+
clearInterval(this.pollingInterval);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
// Silently handle polling errors
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
// Poll every 2 seconds
|
|
111
|
+
this.pollingInterval = setInterval(poll, 2000);
|
|
112
|
+
// Initial poll
|
|
113
|
+
await poll();
|
|
114
|
+
}
|
|
115
|
+
send(message) {
|
|
116
|
+
if (this.peer && this.isConnected) {
|
|
117
|
+
try {
|
|
118
|
+
this.peer.send(JSON.stringify(message));
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
console.error('Failed to send message:', error);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
console.warn('Cannot send message: not connected');
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
onMessage(callback) {
|
|
129
|
+
this.onMessageCallback = callback;
|
|
130
|
+
}
|
|
131
|
+
onConnect(callback) {
|
|
132
|
+
this.onConnectCallback = callback;
|
|
133
|
+
}
|
|
134
|
+
onDisconnect(callback) {
|
|
135
|
+
this.onDisconnectCallback = callback;
|
|
136
|
+
}
|
|
137
|
+
disconnect() {
|
|
138
|
+
if (this.pollingInterval) {
|
|
139
|
+
clearInterval(this.pollingInterval);
|
|
140
|
+
}
|
|
141
|
+
if (this.peer) {
|
|
142
|
+
this.peer.destroy();
|
|
143
|
+
this.peer = null;
|
|
144
|
+
}
|
|
145
|
+
this.isConnected = false;
|
|
146
|
+
}
|
|
147
|
+
getConnected() {
|
|
148
|
+
return this.isConnected;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
exports.WebRTCConnection = WebRTCConnection;
|
|
152
|
+
//# sourceMappingURL=webrtc.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webrtc.js","sourceRoot":"","sources":["../src/webrtc.ts"],"names":[],"mappings":"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"}
|