polydev-ai 1.8.91 → 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 +127 -94
  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,96 +437,56 @@ To re-login: npx polydev-ai`
436
437
  };
437
438
  }
438
439
 
439
- // Start login server in background (don't block the tool response)
440
- const loginPromise = new Promise((resolve) => {
441
- const server = http.createServer((req, res) => {
442
- const url = new URL(req.url, `http://localhost`);
443
-
444
- if (req.method === 'OPTIONS') {
445
- res.writeHead(204, {
446
- 'Access-Control-Allow-Origin': '*',
447
- 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
448
- 'Access-Control-Allow-Headers': 'Content-Type'
449
- });
450
- res.end();
451
- return;
452
- }
453
-
454
- if (url.pathname === '/callback') {
455
- const token = url.searchParams.get('token');
456
-
457
- if (token && token.startsWith('pd_')) {
458
- // Save token
459
- this.saveTokenToFiles(token);
460
- this.userToken = token;
461
- this.isAuthenticated = true;
462
- this._freshLogin = true;
463
-
464
- res.writeHead(200, {
465
- 'Content-Type': 'text/html; charset=utf-8',
466
- 'Access-Control-Allow-Origin': '*'
467
- });
468
- res.end(this.getLoginSuccessHTML());
469
-
470
- console.error('[Polydev] Login successful, token saved');
471
- console.error('[Polydev] ✓ You can now use Polydev tools!');
472
-
473
- // Wait 7 seconds before closing server
474
- setTimeout(() => {
475
- server.close();
476
- resolve(true);
477
- }, 7000);
478
- } else {
479
- res.writeHead(400, { 'Content-Type': 'text/plain' });
480
- res.end('Invalid or missing token');
481
- }
482
- } else {
483
- res.writeHead(404);
484
- res.end('Not found');
485
- }
486
- });
487
-
488
- server.listen(0, 'localhost', () => {
489
- const port = server.address().port;
490
- const callbackUrl = `http://localhost:${port}/callback`;
491
- const authUrl = `https://polydev.ai/auth?callback=${encodeURIComponent(callbackUrl)}&redirect=ide-plugin&auto=true`;
492
-
493
- console.error(`[Polydev] Opening browser for authentication...`);
494
- console.error(`[Polydev] Auth URL: ${authUrl}`);
495
-
496
- this.openBrowser(authUrl).catch(() => {
497
- console.error('[Polydev] Could not open browser automatically');
498
- console.error('[Polydev] Please open this URL manually:', authUrl);
499
- });
500
- });
501
-
502
- // Timeout after 5 minutes
503
- setTimeout(() => {
504
- server.close();
505
- resolve(false);
506
- }, 5 * 60 * 1000);
507
-
508
- server.on('error', (err) => {
509
- console.error('[Polydev] Login server error:', err.message);
510
- resolve(false);
440
+ // Generate unique session ID for polling-based auth
441
+ const sessionId = crypto.randomBytes(32).toString('hex');
442
+
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' }
511
448
  });
512
- });
513
-
514
- // Don't await - let it run in background
515
- loginPromise.then((success) => {
516
- if (success) {
517
- console.error('[Polydev] Authentication completed successfully!');
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
+ };
518
464
  }
519
- });
520
-
521
- // Return immediately - don't wait for auth to complete
522
- return {
523
- jsonrpc: '2.0',
524
- id,
525
- result: {
526
- content: [{
527
- type: 'text',
528
- text: `╭─────────────────────────────────────────╮
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
+
469
+ console.error(`[Polydev] Opening browser for authentication...`);
470
+ console.error(`[Polydev] Session ID: ${sessionId.slice(0, 8)}...`);
471
+ console.error(`[Polydev] Auth URL: ${authUrl}`);
472
+
473
+ this.openBrowser(authUrl).catch(() => {
474
+ console.error('[Polydev] Could not open browser automatically');
475
+ console.error('[Polydev] Please open this URL manually:', authUrl);
476
+ });
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: `╭─────────────────────────────────────────╮
529
490
  │ BROWSER OPENED FOR LOGIN 🌐 │
530
491
  ╰─────────────────────────────────────────╯
531
492
 
@@ -533,14 +494,86 @@ To re-login: npx polydev-ai`
533
494
 
534
495
  After login:
535
496
  • Token will be saved automatically
536
- • You'll see a success page with auto-close
537
- 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
+ }
538
521
 
539
- ⏳ Waiting for authentication...
540
- (Server listening for up to 5 minutes)`
541
- }]
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
+ }
542
572
  }
543
573
  };
574
+
575
+ // Start polling
576
+ setTimeout(poll, pollInterval);
544
577
  }
545
578
 
546
579
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "polydev-ai",
3
- "version": "1.8.91",
3
+ "version": "1.8.93",
4
4
  "engines": {
5
5
  "node": ">=20.x <=22.x"
6
6
  },