polydev-ai 1.9.12 → 1.9.13

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 +156 -31
  2. package/package.json +1 -1
@@ -476,27 +476,37 @@ Token will be saved automatically after login.`
476
476
  async handleLoginTool(params, id) {
477
477
  const crypto = require('crypto');
478
478
 
479
- // Check if already authenticated
479
+ // Check if already authenticated - verify with server first
480
480
  if (this.isAuthenticated && this.userToken) {
481
- return {
482
- jsonrpc: '2.0',
483
- id,
484
- result: {
485
- content: [{
486
- type: 'text',
487
- text: `ALREADY AUTHENTICATED
481
+ console.error('[Polydev] Token exists locally, verifying with server...');
482
+ const isValid = await this.verifyTokenWithServer();
483
+
484
+ if (isValid) {
485
+ return {
486
+ jsonrpc: '2.0',
487
+ id,
488
+ result: {
489
+ content: [{
490
+ type: 'text',
491
+ text: `ALREADY AUTHENTICATED
488
492
  =====================
489
493
 
490
- Your token is configured and ready.
494
+ Your token is configured and verified.
491
495
 
492
496
  Available commands:
493
497
  /polydev:ask Query multiple AI models
494
498
  /polydev:auth Check status & credits
495
499
 
496
500
  To re-login: npx polydev-ai`
497
- }]
498
- }
499
- };
501
+ }]
502
+ }
503
+ };
504
+ }
505
+
506
+ // Token is invalid/expired - clear state and proceed with login
507
+ console.error('[Polydev] Token invalid/expired, proceeding with re-authentication...');
508
+ this.isAuthenticated = false;
509
+ this.userToken = null;
500
510
  }
501
511
 
502
512
  // Generate unique session ID for polling-based auth
@@ -620,6 +630,115 @@ Dashboard: https://polydev.ai/dashboard`
620
630
  }
621
631
  }
622
632
 
633
+ /**
634
+ * Verify the current token is valid by checking with the server
635
+ * Returns true if valid, false if invalid/expired
636
+ * On network error, returns true (don't block for transient issues)
637
+ */
638
+ async verifyTokenWithServer() {
639
+ if (!this.userToken) return false;
640
+ try {
641
+ const response = await fetch('https://www.polydev.ai/api/auth/status', {
642
+ method: 'POST',
643
+ headers: {
644
+ 'Content-Type': 'application/json',
645
+ 'Authorization': `Bearer ${this.userToken}`,
646
+ 'User-Agent': 'polydev-stdio-wrapper/1.0.0'
647
+ }
648
+ });
649
+ if (!response.ok) {
650
+ console.error(`[Polydev] Token verification failed: ${response.status}`);
651
+ return false;
652
+ }
653
+ return true;
654
+ } catch (error) {
655
+ // Network error - assume valid to avoid blocking on transient issues
656
+ console.error('[Polydev] Token verification network error (assuming valid):', error.message);
657
+ return true;
658
+ }
659
+ }
660
+
661
+ /**
662
+ * Trigger re-authentication by opening browser and starting polling
663
+ * Used when token is detected as invalid/expired
664
+ * @param {*} id - JSON-RPC request id
665
+ * @param {string} reason - Human-readable reason for re-auth
666
+ * @returns {object} JSON-RPC response
667
+ */
668
+ async triggerReAuth(id, reason = 'Token invalid or expired') {
669
+ const crypto = require('crypto');
670
+ const sessionId = crypto.randomBytes(32).toString('hex');
671
+
672
+ // Clear local auth state
673
+ this.isAuthenticated = false;
674
+ this.userToken = null;
675
+
676
+ try {
677
+ const createResponse = await fetch(`https://www.polydev.ai/api/auth/cli-session/${sessionId}`, {
678
+ method: 'POST',
679
+ headers: { 'Content-Type': 'application/json' }
680
+ });
681
+
682
+ if (!createResponse.ok) {
683
+ return {
684
+ jsonrpc: '2.0',
685
+ id,
686
+ result: {
687
+ content: [{
688
+ type: 'text',
689
+ text: `${reason}\n\nCould not initiate re-authentication. Please run:\n npx polydev-ai`
690
+ }],
691
+ isError: true
692
+ }
693
+ };
694
+ }
695
+
696
+ const authUrl = `https://polydev.ai/auth?session_id=${sessionId}&redirect=ide-plugin&auto=true`;
697
+
698
+ console.error(`[Polydev] Opening browser for re-authentication...`);
699
+ this.openBrowser(authUrl).catch(() => {
700
+ console.error('[Polydev] Could not open browser for re-authentication');
701
+ });
702
+
703
+ this.savePendingSession(sessionId);
704
+ this.startLoginPolling(sessionId);
705
+
706
+ return {
707
+ jsonrpc: '2.0',
708
+ id,
709
+ result: {
710
+ content: [{
711
+ type: 'text',
712
+ text: `RE-AUTHENTICATION REQUIRED
713
+ ==========================
714
+
715
+ ${reason}
716
+
717
+ A browser window is opening to re-authenticate.
718
+
719
+ If it doesn't open, visit:
720
+ ${authUrl}
721
+
722
+ Once you sign in, your token will be updated automatically.`
723
+ }]
724
+ }
725
+ };
726
+ } catch (error) {
727
+ const cause = error.cause ? ` (${error.cause.code || error.cause.message || error.cause})` : '';
728
+ return {
729
+ jsonrpc: '2.0',
730
+ id,
731
+ result: {
732
+ content: [{
733
+ type: 'text',
734
+ text: `${reason}\n\nCould not reach server: ${error.message}${cause}\nPlease run: npx polydev-ai`
735
+ }],
736
+ isError: true
737
+ }
738
+ };
739
+ }
740
+ }
741
+
623
742
  /**
624
743
  * Poll for login session completion
625
744
  * @param {string} sessionId - The session ID to poll
@@ -808,24 +927,9 @@ Configure: https://polydev.ai/dashboard/models`
808
927
  }
809
928
  };
810
929
  } else {
811
- return {
812
- jsonrpc: '2.0',
813
- id,
814
- result: {
815
- content: [{
816
- type: 'text',
817
- text: `POLYDEV STATUS
818
- ==============
819
-
820
- Token invalid or expired.
821
-
822
- Please re-login:
823
- 1. Use the "login" tool
824
- 2. Or run: npx polydev-ai login`
825
- }],
826
- isError: true
827
- }
828
- };
930
+ // Token invalid/expired - auto-trigger re-authentication
931
+ console.error('[Polydev] Auth status: token invalid/expired, auto-triggering re-auth...');
932
+ return await this.triggerReAuth(id, 'Token invalid or expired.');
829
933
  }
830
934
  } catch (error) {
831
935
  return {
@@ -1228,6 +1332,12 @@ Error: ${error.message}`
1228
1332
  const errorText = await response.text();
1229
1333
  console.error(`[Stdio Wrapper] Remote server error: ${response.status} - ${errorText}`);
1230
1334
 
1335
+ // Handle 401 specifically - token expired/invalid, trigger re-auth
1336
+ if (response.status === 401) {
1337
+ console.error('[Polydev] Remote API returned 401, auto-triggering re-authentication...');
1338
+ return await this.triggerReAuth(request.id, 'Authentication expired. Re-authenticating...');
1339
+ }
1340
+
1231
1341
  return {
1232
1342
  jsonrpc: '2.0',
1233
1343
  id: request.id,
@@ -1282,6 +1392,13 @@ Error: ${error.message}`
1282
1392
  // 3. Combines results
1283
1393
  const result = await this.localSendCliPrompt(params.arguments);
1284
1394
 
1395
+ // Check if result indicates auth failure (from forwardToRemoteServer 401 handling)
1396
+ const resultText = result.content || this.formatCliResponse(result);
1397
+ if (result.result?.content?.[0]?.text?.includes('RE-AUTHENTICATION REQUIRED')) {
1398
+ // Auth failure already handled with re-auth response - pass through
1399
+ return result;
1400
+ }
1401
+
1285
1402
  return {
1286
1403
  jsonrpc: '2.0',
1287
1404
  id,
@@ -1289,7 +1406,7 @@ Error: ${error.message}`
1289
1406
  content: [
1290
1407
  {
1291
1408
  type: 'text',
1292
- text: result.content || this.formatCliResponse(result)
1409
+ text: resultText
1293
1410
  }
1294
1411
  ]
1295
1412
  }
@@ -1297,6 +1414,14 @@ Error: ${error.message}`
1297
1414
 
1298
1415
  } catch (error) {
1299
1416
  console.error(`[Stdio Wrapper] get_perspectives error:`, error);
1417
+
1418
+ // Check if error is auth-related
1419
+ const errMsg = (error.message || '').toLowerCase();
1420
+ if (errMsg.includes('401') || errMsg.includes('unauthorized') || errMsg.includes('auth') || errMsg.includes('token')) {
1421
+ console.error('[Polydev] Perspectives auth error, auto-triggering re-authentication...');
1422
+ return await this.triggerReAuth(id, 'Authentication expired. Re-authenticating...');
1423
+ }
1424
+
1300
1425
  return {
1301
1426
  jsonrpc: '2.0',
1302
1427
  id,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "polydev-ai",
3
- "version": "1.9.12",
3
+ "version": "1.9.13",
4
4
  "engines": {
5
5
  "node": ">=20.x <=22.x"
6
6
  },