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.
Files changed (2) hide show
  1. package/mcp/stdio-wrapper.js +120 -91
  2. package/package.json +1 -1
@@ -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 http = require('http');
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
- // Close any existing login server
440
- if (this._loginServer) {
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
- // Create and STORE the server at class level so it stays alive
446
- this._loginServer = http.createServer((req, res) => {
447
- const url = new URL(req.url, `http://localhost`);
448
-
449
- if (req.method === 'OPTIONS') {
450
- res.writeHead(204, {
451
- 'Access-Control-Allow-Origin': '*',
452
- 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
453
- 'Access-Control-Allow-Headers': 'Content-Type'
454
- });
455
- res.end();
456
- return;
457
- }
458
-
459
- if (url.pathname === '/callback') {
460
- const token = url.searchParams.get('token');
461
-
462
- if (token && token.startsWith('pd_')) {
463
- // Save token
464
- this.saveTokenToFiles(token);
465
- this.userToken = token;
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
- // Start listening
496
- this._loginServer.listen(0, 'localhost', () => {
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] Callback server listening on port ${port}`);
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
- // Timeout after 5 minutes
512
- this._loginServerTimeout = setTimeout(() => {
513
- if (this._loginServer) {
514
- console.error('[Polydev] Login timeout - closing server');
515
- this._loginServer.close();
516
- this._loginServer = null;
517
- }
518
- }, 5 * 60 * 1000);
519
-
520
- this._loginServer.on('error', (err) => {
521
- console.error('[Polydev] Login server error:', err.message);
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'll see a success page with auto-close
541
- Return here and the tools will be ready!
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
- ⏳ Waiting for authentication...
544
- (Server listening for up to 5 minutes)`
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
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "polydev-ai",
3
- "version": "1.8.92",
3
+ "version": "1.8.93",
4
4
  "engines": {
5
5
  "node": ">=20.x <=22.x"
6
6
  },