polydev-ai 1.8.92 → 1.8.93
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/mcp/stdio-wrapper.js +120 -91
- package/package.json +1 -1
package/mcp/stdio-wrapper.js
CHANGED
|
@@ -407,9 +407,10 @@ class StdioMCPWrapper {
|
|
|
407
407
|
|
|
408
408
|
/**
|
|
409
409
|
* Handle login tool - opens browser for authentication
|
|
410
|
+
* Uses polling-based flow that survives MCP reconnections
|
|
410
411
|
*/
|
|
411
412
|
async handleLoginTool(params, id) {
|
|
412
|
-
const
|
|
413
|
+
const crypto = require('crypto');
|
|
413
414
|
|
|
414
415
|
// Check if already authenticated
|
|
415
416
|
if (this.isAuthenticated && this.userToken) {
|
|
@@ -436,100 +437,56 @@ To re-login: npx polydev-ai`
|
|
|
436
437
|
};
|
|
437
438
|
}
|
|
438
439
|
|
|
439
|
-
//
|
|
440
|
-
|
|
441
|
-
try { this._loginServer.close(); } catch (e) {}
|
|
442
|
-
this._loginServer = null;
|
|
443
|
-
}
|
|
440
|
+
// Generate unique session ID for polling-based auth
|
|
441
|
+
const sessionId = crypto.randomBytes(32).toString('hex');
|
|
444
442
|
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
const
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
this.isAuthenticated = true;
|
|
467
|
-
this._freshLogin = true;
|
|
468
|
-
|
|
469
|
-
res.writeHead(200, {
|
|
470
|
-
'Content-Type': 'text/html; charset=utf-8',
|
|
471
|
-
'Access-Control-Allow-Origin': '*'
|
|
472
|
-
});
|
|
473
|
-
res.end(this.getLoginSuccessHTML());
|
|
474
|
-
|
|
475
|
-
console.error('[Polydev] Login successful, token saved');
|
|
476
|
-
console.error('[Polydev] ✓ You can now use Polydev tools!');
|
|
477
|
-
|
|
478
|
-
// Wait 7 seconds before closing server (let browser render success page)
|
|
479
|
-
setTimeout(() => {
|
|
480
|
-
if (this._loginServer) {
|
|
481
|
-
this._loginServer.close();
|
|
482
|
-
this._loginServer = null;
|
|
483
|
-
}
|
|
484
|
-
}, 7000);
|
|
485
|
-
} else {
|
|
486
|
-
res.writeHead(400, { 'Content-Type': 'text/plain' });
|
|
487
|
-
res.end('Invalid or missing token');
|
|
488
|
-
}
|
|
489
|
-
} else {
|
|
490
|
-
res.writeHead(404);
|
|
491
|
-
res.end('Not found');
|
|
443
|
+
try {
|
|
444
|
+
// Create session on server
|
|
445
|
+
const createResponse = await fetch(`https://www.polydev.ai/api/auth/cli-session/${sessionId}`, {
|
|
446
|
+
method: 'POST',
|
|
447
|
+
headers: { 'Content-Type': 'application/json' }
|
|
448
|
+
});
|
|
449
|
+
|
|
450
|
+
if (!createResponse.ok) {
|
|
451
|
+
const error = await createResponse.text();
|
|
452
|
+
console.error('[Polydev] Failed to create login session:', error);
|
|
453
|
+
return {
|
|
454
|
+
jsonrpc: '2.0',
|
|
455
|
+
id,
|
|
456
|
+
result: {
|
|
457
|
+
content: [{
|
|
458
|
+
type: 'text',
|
|
459
|
+
text: `Login session creation failed. Please try again or run: npx polydev-ai`
|
|
460
|
+
}],
|
|
461
|
+
isError: true
|
|
462
|
+
}
|
|
463
|
+
};
|
|
492
464
|
}
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
const port = this._loginServer.address().port;
|
|
498
|
-
const callbackUrl = `http://localhost:${port}/callback`;
|
|
499
|
-
const authUrl = `https://polydev.ai/auth?callback=${encodeURIComponent(callbackUrl)}&redirect=ide-plugin&auto=true`;
|
|
500
|
-
|
|
465
|
+
|
|
466
|
+
// Open browser with session_id (no localhost callback needed)
|
|
467
|
+
const authUrl = `https://polydev.ai/auth?session_id=${sessionId}&redirect=ide-plugin&auto=true`;
|
|
468
|
+
|
|
501
469
|
console.error(`[Polydev] Opening browser for authentication...`);
|
|
502
|
-
console.error(`[Polydev]
|
|
470
|
+
console.error(`[Polydev] Session ID: ${sessionId.slice(0, 8)}...`);
|
|
503
471
|
console.error(`[Polydev] Auth URL: ${authUrl}`);
|
|
504
472
|
|
|
505
473
|
this.openBrowser(authUrl).catch(() => {
|
|
506
474
|
console.error('[Polydev] Could not open browser automatically');
|
|
507
475
|
console.error('[Polydev] Please open this URL manually:', authUrl);
|
|
508
476
|
});
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
this._loginServer = null;
|
|
523
|
-
});
|
|
524
|
-
|
|
525
|
-
// Return immediately - server stays alive at this._loginServer
|
|
526
|
-
return {
|
|
527
|
-
jsonrpc: '2.0',
|
|
528
|
-
id,
|
|
529
|
-
result: {
|
|
530
|
-
content: [{
|
|
531
|
-
type: 'text',
|
|
532
|
-
text: `╭─────────────────────────────────────────╮
|
|
477
|
+
|
|
478
|
+
// Start polling in background (survives reconnections because
|
|
479
|
+
// if this process dies, the new one can resume polling with same session)
|
|
480
|
+
this.startLoginPolling(sessionId);
|
|
481
|
+
|
|
482
|
+
// Return immediately
|
|
483
|
+
return {
|
|
484
|
+
jsonrpc: '2.0',
|
|
485
|
+
id,
|
|
486
|
+
result: {
|
|
487
|
+
content: [{
|
|
488
|
+
type: 'text',
|
|
489
|
+
text: `╭─────────────────────────────────────────╮
|
|
533
490
|
│ BROWSER OPENED FOR LOGIN 🌐 │
|
|
534
491
|
╰─────────────────────────────────────────╯
|
|
535
492
|
|
|
@@ -537,14 +494,86 @@ To re-login: npx polydev-ai`
|
|
|
537
494
|
|
|
538
495
|
After login:
|
|
539
496
|
• Token will be saved automatically
|
|
540
|
-
• You
|
|
541
|
-
•
|
|
497
|
+
• You can safely reconnect MCP or restart IDE
|
|
498
|
+
• Use /polydev:auth to check status
|
|
499
|
+
|
|
500
|
+
⏳ Polling for authentication completion...
|
|
501
|
+
(Session expires in 10 minutes)`
|
|
502
|
+
}]
|
|
503
|
+
}
|
|
504
|
+
};
|
|
505
|
+
|
|
506
|
+
} catch (error) {
|
|
507
|
+
console.error('[Polydev] Login error:', error);
|
|
508
|
+
return {
|
|
509
|
+
jsonrpc: '2.0',
|
|
510
|
+
id,
|
|
511
|
+
result: {
|
|
512
|
+
content: [{
|
|
513
|
+
type: 'text',
|
|
514
|
+
text: `Login failed: ${error.message}\n\nPlease try: npx polydev-ai`
|
|
515
|
+
}],
|
|
516
|
+
isError: true
|
|
517
|
+
}
|
|
518
|
+
};
|
|
519
|
+
}
|
|
520
|
+
}
|
|
542
521
|
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
522
|
+
/**
|
|
523
|
+
* Poll for login session completion
|
|
524
|
+
*/
|
|
525
|
+
async startLoginPolling(sessionId) {
|
|
526
|
+
const pollInterval = 2000; // 2 seconds
|
|
527
|
+
const maxPolls = 300; // 10 minutes max
|
|
528
|
+
let polls = 0;
|
|
529
|
+
|
|
530
|
+
const poll = async () => {
|
|
531
|
+
polls++;
|
|
532
|
+
|
|
533
|
+
try {
|
|
534
|
+
const response = await fetch(`https://www.polydev.ai/api/auth/cli-session/${sessionId}`);
|
|
535
|
+
const data = await response.json();
|
|
536
|
+
|
|
537
|
+
if (data.status === 'completed' && data.token) {
|
|
538
|
+
// Success! Save the token
|
|
539
|
+
this.saveTokenToFiles(data.token);
|
|
540
|
+
this.userToken = data.token;
|
|
541
|
+
this.isAuthenticated = true;
|
|
542
|
+
this._freshLogin = true;
|
|
543
|
+
|
|
544
|
+
console.error('[Polydev] ✓ Login successful! Token saved.');
|
|
545
|
+
console.error('[Polydev] You can now use Polydev tools.');
|
|
546
|
+
return; // Stop polling
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
if (data.status === 'expired' || response.status === 410) {
|
|
550
|
+
console.error('[Polydev] Login session expired. Please try again.');
|
|
551
|
+
return; // Stop polling
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
if (data.status === 'not_found' || response.status === 404) {
|
|
555
|
+
console.error('[Polydev] Login session not found.');
|
|
556
|
+
return; // Stop polling
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
// Still pending, continue polling
|
|
560
|
+
if (polls < maxPolls) {
|
|
561
|
+
setTimeout(poll, pollInterval);
|
|
562
|
+
} else {
|
|
563
|
+
console.error('[Polydev] Login polling timed out.');
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
} catch (error) {
|
|
567
|
+
console.error('[Polydev] Poll error:', error.message);
|
|
568
|
+
// Continue polling on network errors
|
|
569
|
+
if (polls < maxPolls) {
|
|
570
|
+
setTimeout(poll, pollInterval);
|
|
571
|
+
}
|
|
546
572
|
}
|
|
547
573
|
};
|
|
574
|
+
|
|
575
|
+
// Start polling
|
|
576
|
+
setTimeout(poll, pollInterval);
|
|
548
577
|
}
|
|
549
578
|
|
|
550
579
|
/**
|