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.
- package/mcp/stdio-wrapper.js +156 -31
- package/package.json +1 -1
package/mcp/stdio-wrapper.js
CHANGED
|
@@ -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
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
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
|
|
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
|
-
|
|
812
|
-
|
|
813
|
-
|
|
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:
|
|
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,
|