@quantiya/codevibe-claude-plugin 1.0.11 → 1.0.12

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 (43) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/dist/server.js +16 -1162
  3. package/node_modules/@quantiya/codevibe-core/README.md +15 -6
  4. package/node_modules/@quantiya/codevibe-core/bin/codevibe.js +1 -1
  5. package/node_modules/@quantiya/codevibe-core/dist/index.js +216 -67
  6. package/node_modules/@quantiya/codevibe-core/package.json +12 -9
  7. package/node_modules/node-abi/abi_registry.json +7 -0
  8. package/node_modules/node-abi/package.json +1 -1
  9. package/package.json +6 -13
  10. package/dist/appsync-client.js +0 -858
  11. package/dist/auth-cli.js +0 -472
  12. package/dist/command-executor.js +0 -127
  13. package/dist/config.js +0 -106
  14. package/dist/crypto-service.js +0 -278
  15. package/dist/http-api.js +0 -334
  16. package/dist/key-manager.js +0 -287
  17. package/dist/logger.js +0 -18
  18. package/dist/prompt-responder.js +0 -132
  19. package/dist/token-storage.js +0 -169
  20. package/dist/types.js +0 -17
  21. package/node_modules/@quantiya/codevibe-core/dist/appsync/appsync-client.js +0 -576
  22. package/node_modules/@quantiya/codevibe-core/dist/appsync/index.js +0 -10
  23. package/node_modules/@quantiya/codevibe-core/dist/appsync/queries.js +0 -189
  24. package/node_modules/@quantiya/codevibe-core/dist/auth/auth-cli.js +0 -217
  25. package/node_modules/@quantiya/codevibe-core/dist/auth/auth-service.js +0 -464
  26. package/node_modules/@quantiya/codevibe-core/dist/auth/fetch-helpers.js +0 -165
  27. package/node_modules/@quantiya/codevibe-core/dist/auth/index.js +0 -9
  28. package/node_modules/@quantiya/codevibe-core/dist/config/config.js +0 -123
  29. package/node_modules/@quantiya/codevibe-core/dist/config/index.js +0 -8
  30. package/node_modules/@quantiya/codevibe-core/dist/crypto/crypto-service.js +0 -284
  31. package/node_modules/@quantiya/codevibe-core/dist/crypto/index.js +0 -9
  32. package/node_modules/@quantiya/codevibe-core/dist/keychain/index.js +0 -8
  33. package/node_modules/@quantiya/codevibe-core/dist/keychain/keychain-manager.js +0 -375
  34. package/node_modules/@quantiya/codevibe-core/dist/logger/index.js +0 -8
  35. package/node_modules/@quantiya/codevibe-core/dist/logger/logger.js +0 -142
  36. package/node_modules/@quantiya/codevibe-core/dist/prompt-parser.js +0 -236
  37. package/node_modules/@quantiya/codevibe-core/dist/session/index.js +0 -7
  38. package/node_modules/@quantiya/codevibe-core/dist/session/session-resume.js +0 -151
  39. package/node_modules/@quantiya/codevibe-core/dist/types/auth.js +0 -3
  40. package/node_modules/@quantiya/codevibe-core/dist/types/encryption.js +0 -3
  41. package/node_modules/@quantiya/codevibe-core/dist/types/events.js +0 -28
  42. package/node_modules/@quantiya/codevibe-core/dist/types/index.js +0 -22
  43. package/node_modules/@quantiya/codevibe-core/dist/types/session.js +0 -22
package/dist/auth-cli.js DELETED
@@ -1,472 +0,0 @@
1
- #!/usr/bin/env node
2
- "use strict";
3
- /**
4
- * CLI OAuth Authentication for CodeVibe
5
- *
6
- * Usage:
7
- * node auth-cli.js login - Authenticate via browser OAuth
8
- * node auth-cli.js logout - Clear stored tokens
9
- * node auth-cli.js status - Show current authentication status
10
- */
11
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
12
- if (k2 === undefined) k2 = k;
13
- var desc = Object.getOwnPropertyDescriptor(m, k);
14
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
15
- desc = { enumerable: true, get: function() { return m[k]; } };
16
- }
17
- Object.defineProperty(o, k2, desc);
18
- }) : (function(o, m, k, k2) {
19
- if (k2 === undefined) k2 = k;
20
- o[k2] = m[k];
21
- }));
22
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
23
- Object.defineProperty(o, "default", { enumerable: true, value: v });
24
- }) : function(o, v) {
25
- o["default"] = v;
26
- });
27
- var __importStar = (this && this.__importStar) || (function () {
28
- var ownKeys = function(o) {
29
- ownKeys = Object.getOwnPropertyNames || function (o) {
30
- var ar = [];
31
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
32
- return ar;
33
- };
34
- return ownKeys(o);
35
- };
36
- return function (mod) {
37
- if (mod && mod.__esModule) return mod;
38
- var result = {};
39
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
40
- __setModuleDefault(result, mod);
41
- return result;
42
- };
43
- })();
44
- Object.defineProperty(exports, "__esModule", { value: true });
45
- exports.refreshTokens = refreshTokens;
46
- const crypto = __importStar(require("crypto"));
47
- const http = __importStar(require("http"));
48
- const path = __importStar(require("path"));
49
- const child_process_1 = require("child_process");
50
- const dotenv = __importStar(require("dotenv"));
51
- // Load environment-specific .env file from the plugin directory
52
- // Only load .env files if ENVIRONMENT is explicitly set (for development)
53
- // This ensures marketplace users get production defaults without needing .env files
54
- const pluginDir = path.resolve(__dirname, '..');
55
- const environment = process.env.ENVIRONMENT || 'production';
56
- if (process.env.ENVIRONMENT) {
57
- const envFile = `.env.${environment}`;
58
- dotenv.config({ path: path.join(pluginDir, envFile), debug: false });
59
- // Fallback to default .env if environment-specific file didn't load
60
- if (!process.env.APPSYNC_URL) {
61
- dotenv.config({ path: path.join(pluginDir, '.env'), debug: false });
62
- }
63
- }
64
- const config_1 = require("./config");
65
- const logger_1 = require("./logger");
66
- const token_storage_1 = require("./token-storage");
67
- // OAuth configuration
68
- const CALLBACK_PORT = 8080;
69
- const CALLBACK_PATH = '/callback';
70
- const REDIRECT_URI = `http://localhost:${CALLBACK_PORT}${CALLBACK_PATH}`;
71
- // Colors for terminal output
72
- const colors = {
73
- reset: '\x1b[0m',
74
- green: '\x1b[32m',
75
- red: '\x1b[31m',
76
- yellow: '\x1b[33m',
77
- cyan: '\x1b[36m',
78
- dim: '\x1b[2m',
79
- };
80
- /**
81
- * Open URL in default browser
82
- */
83
- function openBrowser(url) {
84
- // macOS
85
- (0, child_process_1.spawn)('open', [url], { detached: true, stdio: 'ignore' }).unref();
86
- }
87
- /**
88
- * Generate a random state parameter for CSRF protection
89
- */
90
- function generateState() {
91
- return crypto.randomBytes(32).toString('hex');
92
- }
93
- /**
94
- * Build the Cognito Hosted UI authorization URL
95
- */
96
- function buildAuthUrl(state) {
97
- const params = new URLSearchParams({
98
- client_id: config_1.config.aws.cognitoClientId,
99
- response_type: 'code',
100
- scope: 'email openid profile',
101
- redirect_uri: REDIRECT_URI,
102
- state: state,
103
- });
104
- return `https://${config_1.config.aws.cognitoDomain}/oauth2/authorize?${params.toString()}`;
105
- }
106
- /**
107
- * Exchange authorization code for tokens
108
- */
109
- async function exchangeCodeForTokens(code) {
110
- const tokenUrl = `https://${config_1.config.aws.cognitoDomain}/oauth2/token`;
111
- const params = new URLSearchParams({
112
- grant_type: 'authorization_code',
113
- client_id: config_1.config.aws.cognitoClientId,
114
- code: code,
115
- redirect_uri: REDIRECT_URI,
116
- });
117
- const response = await fetch(tokenUrl, {
118
- method: 'POST',
119
- headers: {
120
- 'Content-Type': 'application/x-www-form-urlencoded',
121
- },
122
- body: params.toString(),
123
- });
124
- if (!response.ok) {
125
- const errorText = await response.text();
126
- throw new Error(`Token exchange failed: ${response.status} ${errorText}`);
127
- }
128
- const data = await response.json();
129
- return {
130
- accessToken: data.access_token,
131
- idToken: data.id_token,
132
- refreshToken: data.refresh_token,
133
- expiresIn: data.expires_in,
134
- };
135
- }
136
- /**
137
- * Decode JWT to extract user info
138
- */
139
- function decodeJwt(token) {
140
- const parts = token.split('.');
141
- if (parts.length !== 3) {
142
- throw new Error('Invalid JWT format');
143
- }
144
- const payload = Buffer.from(parts[1], 'base64').toString('utf-8');
145
- return JSON.parse(payload);
146
- }
147
- /**
148
- * Refresh tokens using refresh token
149
- */
150
- async function refreshTokens(refreshToken) {
151
- const tokenUrl = `https://${config_1.config.aws.cognitoDomain}/oauth2/token`;
152
- const params = new URLSearchParams({
153
- grant_type: 'refresh_token',
154
- client_id: config_1.config.aws.cognitoClientId,
155
- refresh_token: refreshToken,
156
- });
157
- const response = await fetch(tokenUrl, {
158
- method: 'POST',
159
- headers: {
160
- 'Content-Type': 'application/x-www-form-urlencoded',
161
- },
162
- body: params.toString(),
163
- });
164
- if (!response.ok) {
165
- const errorText = await response.text();
166
- throw new Error(`Token refresh failed: ${response.status} ${errorText}`);
167
- }
168
- const data = await response.json();
169
- return {
170
- accessToken: data.access_token,
171
- idToken: data.id_token,
172
- expiresIn: data.expires_in,
173
- };
174
- }
175
- /**
176
- * Login command - OAuth browser flow
177
- */
178
- async function login() {
179
- console.log(`${colors.cyan}CodeVibe Login${colors.reset}\n`);
180
- // Check if already logged in
181
- const existingTokens = (0, token_storage_1.loadTokens)();
182
- if (existingTokens && !(0, token_storage_1.isTokenExpired)(existingTokens)) {
183
- console.log(`${colors.yellow}Already logged in as: ${existingTokens.email}${colors.reset}`);
184
- console.log(`Token expires: ${new Date(existingTokens.expiresAt).toLocaleString()}`);
185
- console.log(`\nRun '${colors.dim}codevibe-claude logout${colors.reset}' to sign out first.`);
186
- return;
187
- }
188
- // Generate state for CSRF protection
189
- const state = generateState();
190
- const authUrl = buildAuthUrl(state);
191
- console.log('Opening browser for authentication...');
192
- console.log(`${colors.dim}Waiting for callback on ${REDIRECT_URI}...${colors.reset}\n`);
193
- // Start local server to receive callback
194
- return new Promise((resolve, reject) => {
195
- const server = http.createServer(async (req, res) => {
196
- if (!req.url?.startsWith(CALLBACK_PATH)) {
197
- res.writeHead(404);
198
- res.end('Not found');
199
- return;
200
- }
201
- try {
202
- const url = new URL(req.url, `http://localhost:${CALLBACK_PORT}`);
203
- const code = url.searchParams.get('code');
204
- const returnedState = url.searchParams.get('state');
205
- const error = url.searchParams.get('error');
206
- const errorDescription = url.searchParams.get('error_description');
207
- // Check for errors
208
- if (error) {
209
- throw new Error(`OAuth error: ${error} - ${errorDescription}`);
210
- }
211
- // Verify state
212
- if (returnedState !== state) {
213
- throw new Error('State mismatch - possible CSRF attack');
214
- }
215
- if (!code) {
216
- throw new Error('No authorization code received');
217
- }
218
- // Exchange code for tokens
219
- console.log('Exchanging authorization code for tokens...');
220
- const tokens = await exchangeCodeForTokens(code);
221
- // Decode ID token to get user info
222
- const idTokenPayload = decodeJwt(tokens.idToken);
223
- const userId = idTokenPayload.sub;
224
- const email = idTokenPayload.email || 'unknown';
225
- // Calculate expiration
226
- const expiresAt = Date.now() + (tokens.expiresIn * 1000);
227
- // Save tokens
228
- const storedTokens = {
229
- accessToken: tokens.accessToken,
230
- idToken: tokens.idToken,
231
- refreshToken: tokens.refreshToken,
232
- expiresAt,
233
- userId,
234
- email,
235
- };
236
- (0, token_storage_1.saveTokens)(storedTokens);
237
- // Send success response to browser
238
- res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
239
- res.end(`
240
- <!DOCTYPE html>
241
- <html>
242
- <head>
243
- <meta charset="UTF-8">
244
- <title>Authentication Successful</title>
245
- <style>
246
- body { font-family: system-ui; max-width: 600px; margin: 50px auto; text-align: center; }
247
- .success { color: #22c55e; font-size: 48px; }
248
- .info { color: #6b7280; margin-top: 20px; }
249
- </style>
250
- </head>
251
- <body>
252
- <div class="success">&#10003;</div>
253
- <h1>Authentication Successful!</h1>
254
- <p>You are now signed in as <strong>${email}</strong></p>
255
- <p class="info">You can close this window and return to the terminal.</p>
256
- </body>
257
- </html>
258
- `);
259
- // Print success to terminal
260
- console.log(`\n${colors.green}✓ Authentication successful!${colors.reset}`);
261
- console.log(` User: ${email}`);
262
- console.log(` User ID: ${userId}`);
263
- console.log(` Tokens stored in: ${(0, token_storage_1.getTokenFilePath)()}`);
264
- console.log(` Expires: ${new Date(expiresAt).toLocaleString()}`);
265
- // Close server after a short delay and exit
266
- setTimeout(() => {
267
- server.close(() => {
268
- resolve();
269
- process.exit(0);
270
- });
271
- }, 1000);
272
- }
273
- catch (error) {
274
- logger_1.logger.error('OAuth callback error:', error);
275
- // Send error response to browser
276
- res.writeHead(400, { 'Content-Type': 'text/html; charset=utf-8' });
277
- res.end(`
278
- <!DOCTYPE html>
279
- <html>
280
- <head>
281
- <meta charset="UTF-8">
282
- <title>Authentication Failed</title>
283
- <style>
284
- body { font-family: system-ui; max-width: 600px; margin: 50px auto; text-align: center; }
285
- .error { color: #ef4444; font-size: 48px; }
286
- .info { color: #6b7280; margin-top: 20px; }
287
- </style>
288
- </head>
289
- <body>
290
- <div class="error">&#10007;</div>
291
- <h1>Authentication Failed</h1>
292
- <p>${error.message}</p>
293
- <p class="info">Please try again.</p>
294
- </body>
295
- </html>
296
- `);
297
- console.log(`\n${colors.red}✗ Authentication failed${colors.reset}`);
298
- console.log(` Error: ${error.message}`);
299
- setTimeout(() => {
300
- server.close(() => {
301
- reject(error);
302
- process.exit(1);
303
- });
304
- }, 1000);
305
- }
306
- });
307
- // Handle server errors
308
- server.on('error', (error) => {
309
- if (error.code === 'EADDRINUSE') {
310
- console.log(`${colors.red}Error: Port ${CALLBACK_PORT} is already in use.${colors.reset}`);
311
- console.log('Please close any other applications using this port and try again.');
312
- }
313
- else {
314
- console.log(`${colors.red}Server error: ${error.message}${colors.reset}`);
315
- }
316
- reject(error);
317
- });
318
- // Start server and open browser
319
- server.listen(CALLBACK_PORT, 'localhost', () => {
320
- logger_1.logger.info('OAuth callback server started', { port: CALLBACK_PORT });
321
- openBrowser(authUrl);
322
- });
323
- // Timeout after 2 minutes
324
- setTimeout(() => {
325
- console.log(`\n${colors.yellow}Login timed out. Please try again.${colors.reset}`);
326
- server.close(() => {
327
- reject(new Error('Login timed out'));
328
- process.exit(1);
329
- });
330
- }, 2 * 60 * 1000);
331
- });
332
- }
333
- /**
334
- * Logout command - clear stored tokens and browser session
335
- */
336
- async function logout() {
337
- console.log(`${colors.cyan}CodeVibe Logout${colors.reset}\n`);
338
- const tokens = (0, token_storage_1.loadTokens)();
339
- if (!tokens) {
340
- console.log(`${colors.yellow}Not logged in.${colors.reset}`);
341
- return;
342
- }
343
- const email = tokens.email;
344
- const deleted = (0, token_storage_1.deleteTokens)();
345
- if (!deleted) {
346
- console.log(`${colors.red}✗ Failed to log out.${colors.reset}`);
347
- return;
348
- }
349
- console.log(`${colors.green}✓ Local tokens cleared.${colors.reset}`);
350
- console.log(` Previous user: ${email}`);
351
- console.log(`\n${colors.dim}Clearing browser session...${colors.reset}`);
352
- // Start a temporary server to receive the logout callback
353
- return new Promise((resolve) => {
354
- const server = http.createServer((req, res) => {
355
- if (req.url?.startsWith('/signout')) {
356
- // Send success page
357
- res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
358
- res.end(`
359
- <!DOCTYPE html>
360
- <html>
361
- <head>
362
- <meta charset="UTF-8">
363
- <title>Logged Out</title>
364
- <style>
365
- body { font-family: system-ui; max-width: 600px; margin: 50px auto; text-align: center; }
366
- .success { color: #22c55e; font-size: 48px; }
367
- .info { color: #6b7280; margin-top: 20px; }
368
- </style>
369
- </head>
370
- <body>
371
- <div class="success">&#10003;</div>
372
- <h1>Logged Out Successfully</h1>
373
- <p>You have been signed out of CodeVibe.</p>
374
- <p class="info">You can close this window.</p>
375
- </body>
376
- </html>
377
- `);
378
- console.log(`${colors.green}✓ Browser session cleared.${colors.reset}`);
379
- // Close server and exit
380
- setTimeout(() => {
381
- server.close(() => {
382
- resolve();
383
- process.exit(0);
384
- });
385
- }, 500);
386
- }
387
- else {
388
- res.writeHead(404);
389
- res.end('Not found');
390
- }
391
- });
392
- server.on('error', (error) => {
393
- if (error.code === 'EADDRINUSE') {
394
- console.log(`${colors.yellow}Could not clear browser session (port in use).${colors.reset}`);
395
- }
396
- resolve();
397
- process.exit(0);
398
- });
399
- // Start server and open logout URL
400
- server.listen(CALLBACK_PORT, 'localhost', () => {
401
- const logoutUrl = `https://${config_1.config.aws.cognitoDomain}/logout?` +
402
- `client_id=${config_1.config.aws.cognitoClientId}&` +
403
- `logout_uri=${encodeURIComponent(REDIRECT_URI.replace('/callback', '/signout'))}`;
404
- openBrowser(logoutUrl);
405
- });
406
- // Timeout after 10 seconds
407
- setTimeout(() => {
408
- console.log(`${colors.yellow}Browser session clear timed out.${colors.reset}`);
409
- server.close(() => {
410
- resolve();
411
- process.exit(0);
412
- });
413
- }, 10000);
414
- });
415
- }
416
- /**
417
- * Status command - show current authentication status
418
- */
419
- async function status() {
420
- console.log(`${colors.cyan}CodeVibe Auth Status${colors.reset}\n`);
421
- const tokens = (0, token_storage_1.loadTokens)();
422
- if (!tokens) {
423
- console.log(`${colors.yellow}Not authenticated.${colors.reset}`);
424
- console.log(`\nRun '${colors.dim}codevibe-claude login${colors.reset}' to sign in.`);
425
- return;
426
- }
427
- const expired = (0, token_storage_1.isTokenExpired)(tokens);
428
- const expiresDate = new Date(tokens.expiresAt);
429
- if (expired) {
430
- console.log(`${colors.yellow}⚠ Token expired${colors.reset}`);
431
- }
432
- else {
433
- console.log(`${colors.green}✓ Authenticated${colors.reset}`);
434
- }
435
- console.log(` User: ${tokens.email}`);
436
- console.log(` User ID: ${tokens.userId}`);
437
- console.log(` Token expires: ${expiresDate.toLocaleString()}`);
438
- console.log(` Token file: ${(0, token_storage_1.getTokenFilePath)()}`);
439
- if (expired) {
440
- console.log(`\n${colors.dim}Note: Token will be automatically refreshed on next use.${colors.reset}`);
441
- }
442
- }
443
- /**
444
- * Main CLI entry point
445
- */
446
- async function main() {
447
- const command = process.argv[2];
448
- switch (command) {
449
- case 'login':
450
- await login();
451
- break;
452
- case 'logout':
453
- await logout();
454
- break;
455
- case 'status':
456
- await status();
457
- break;
458
- default:
459
- console.log('CodeVibe Authentication\n');
460
- console.log('Usage:');
461
- console.log(' codevibe-claude login - Sign in via browser');
462
- console.log(' codevibe-claude logout - Sign out');
463
- console.log(' codevibe-claude status - Show auth status');
464
- process.exit(1);
465
- }
466
- }
467
- // Run CLI
468
- main().catch((error) => {
469
- logger_1.logger.error('Auth CLI error:', error);
470
- process.exit(1);
471
- });
472
- //# sourceMappingURL=auth-cli.js.map
@@ -1,127 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.CommandExecutor = void 0;
4
- const child_process_1 = require("child_process");
5
- const codevibe_core_1 = require("@quantiya/codevibe-core");
6
- const logger_1 = require("./logger");
7
- class CommandExecutor {
8
- /**
9
- * Execute a prompt in a specific Claude Code session
10
- * @param sessionId The session ID to execute the prompt in
11
- * @param prompt The prompt text to execute
12
- * @returns Result of the command execution
13
- */
14
- async executePrompt(sessionId, prompt) {
15
- const config = (0, codevibe_core_1.getConfig)();
16
- const timeout = config.claude.defaultTimeout;
17
- logger_1.logger.info('Executing prompt from mobile', {
18
- sessionId,
19
- promptLength: prompt.length,
20
- timeout,
21
- });
22
- return new Promise((resolve) => {
23
- const args = [
24
- '--resume', sessionId,
25
- '--print',
26
- '--output-format', 'stream-json',
27
- prompt
28
- ];
29
- logger_1.logger.debug('Spawning Claude command', {
30
- command: config.claude.command,
31
- args,
32
- });
33
- const child = (0, child_process_1.spawn)(config.claude.command, args, {
34
- stdio: ['pipe', 'pipe', 'pipe'],
35
- shell: true,
36
- });
37
- let stdout = '';
38
- let stderr = '';
39
- let timedOut = false;
40
- // Set timeout
41
- const timer = setTimeout(() => {
42
- timedOut = true;
43
- logger_1.logger.warn('Command execution timed out', { sessionId, timeout });
44
- child.kill('SIGTERM');
45
- }, timeout);
46
- // Capture stdout
47
- child.stdout?.on('data', (data) => {
48
- const output = data.toString();
49
- stdout += output;
50
- logger_1.logger.debug('Command stdout', { output: output.slice(0, 200) });
51
- });
52
- // Capture stderr
53
- child.stderr?.on('data', (data) => {
54
- const output = data.toString();
55
- stderr += output;
56
- logger_1.logger.debug('Command stderr', { output: output.slice(0, 200) });
57
- });
58
- // Handle process exit
59
- child.on('close', (code) => {
60
- clearTimeout(timer);
61
- const result = {
62
- success: code === 0 && !timedOut,
63
- output: stdout,
64
- error: stderr,
65
- exitCode: code || undefined,
66
- timedOut,
67
- };
68
- if (result.success) {
69
- logger_1.logger.info('Command executed successfully', {
70
- sessionId,
71
- exitCode: code,
72
- outputLength: stdout.length,
73
- });
74
- }
75
- else {
76
- logger_1.logger.error('Command execution failed', {
77
- sessionId,
78
- exitCode: code,
79
- timedOut,
80
- error: stderr.slice(0, 500),
81
- });
82
- }
83
- resolve(result);
84
- });
85
- // Handle errors
86
- child.on('error', (error) => {
87
- clearTimeout(timer);
88
- logger_1.logger.error('Failed to spawn command', { error: error.message });
89
- resolve({
90
- success: false,
91
- error: error.message,
92
- timedOut: false,
93
- });
94
- });
95
- });
96
- }
97
- /**
98
- * Check if interactive prompt is present in output
99
- * This is a simple heuristic - looks for common prompt patterns
100
- */
101
- detectInteractivePrompt(output) {
102
- const patterns = [
103
- /\[Y\/n\]/i,
104
- /\[y\/N\]/i,
105
- /\(y\/n\)/i,
106
- /Continue\?/i,
107
- /Proceed\?/i,
108
- ];
109
- return patterns.some(pattern => pattern.test(output));
110
- }
111
- /**
112
- * Extract interactive prompt text from output
113
- */
114
- extractPromptText(output) {
115
- // Look for lines that end with prompt patterns
116
- const lines = output.split('\n');
117
- for (let i = lines.length - 1; i >= 0; i--) {
118
- const line = lines[i].trim();
119
- if (this.detectInteractivePrompt(line)) {
120
- return line;
121
- }
122
- }
123
- return null;
124
- }
125
- }
126
- exports.CommandExecutor = CommandExecutor;
127
- //# sourceMappingURL=command-executor.js.map