polydev-ai 1.8.17 → 1.8.19
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 +83 -19
- package/package.json +1 -1
package/mcp/stdio-wrapper.js
CHANGED
|
@@ -245,6 +245,7 @@ class StdioMCPWrapper {
|
|
|
245
245
|
|
|
246
246
|
// Cache for user model preferences (provider -> model)
|
|
247
247
|
this.userModelPreferences = null;
|
|
248
|
+
this.perspectivesPerMessage = 2; // Default to 2 perspectives
|
|
248
249
|
this.modelPreferencesCacheTime = null;
|
|
249
250
|
this.MODEL_PREFERENCES_CACHE_TTL = 5 * 60 * 1000; // 5 minutes cache
|
|
250
251
|
}
|
|
@@ -564,6 +565,7 @@ class StdioMCPWrapper {
|
|
|
564
565
|
|
|
565
566
|
/**
|
|
566
567
|
* Local CLI prompt sending with ALL available CLIs + remote perspectives
|
|
568
|
+
* Respects user's perspectives_per_message setting for total perspectives
|
|
567
569
|
*/
|
|
568
570
|
async localSendCliPrompt(args) {
|
|
569
571
|
console.error(`[Stdio Wrapper] Local CLI prompt sending with perspectives`);
|
|
@@ -585,6 +587,7 @@ class StdioMCPWrapper {
|
|
|
585
587
|
const gracefulTimeout = Math.min(timeout_ms, 600000);
|
|
586
588
|
|
|
587
589
|
// Fetch user's model preferences (cached, non-blocking on failure)
|
|
590
|
+
// This also fetches perspectivesPerMessage setting
|
|
588
591
|
let modelPreferences = {};
|
|
589
592
|
try {
|
|
590
593
|
modelPreferences = await this.fetchUserModelPreferences();
|
|
@@ -592,6 +595,10 @@ class StdioMCPWrapper {
|
|
|
592
595
|
console.error('[Stdio Wrapper] Model preferences fetch failed (will use CLI defaults):', prefError.message);
|
|
593
596
|
}
|
|
594
597
|
|
|
598
|
+
// Get the user's perspectives_per_message setting (default 2)
|
|
599
|
+
const maxPerspectives = this.perspectivesPerMessage || 2;
|
|
600
|
+
console.error(`[Stdio Wrapper] Max perspectives per message: ${maxPerspectives}`);
|
|
601
|
+
|
|
595
602
|
let localResults = [];
|
|
596
603
|
|
|
597
604
|
if (provider_id) {
|
|
@@ -606,18 +613,29 @@ class StdioMCPWrapper {
|
|
|
606
613
|
const result = await this.cliManager.sendCliPrompt(provider_id, prompt, mode, gracefulTimeout, model);
|
|
607
614
|
localResults = [{ provider_id, ...result }];
|
|
608
615
|
} else {
|
|
609
|
-
// No specific provider - use
|
|
610
|
-
|
|
611
|
-
|
|
616
|
+
// No specific provider - use providers in user's preferred order
|
|
617
|
+
// Mix CLI (where available) + API fallback (where CLI unavailable)
|
|
618
|
+
console.error(`[Stdio Wrapper] Using providers in user's preferred order (max: ${maxPerspectives})`);
|
|
619
|
+
const { available: availableClis, unavailable: unavailableClis } = await this.getAllAvailableProviders();
|
|
620
|
+
|
|
621
|
+
// Build ordered list: use CLI if available, otherwise mark for API fallback
|
|
622
|
+
const userOrder = this.userProviderOrder || ['claude_code', 'codex_cli', 'gemini_cli'];
|
|
623
|
+
const providersToUse = userOrder.slice(0, maxPerspectives);
|
|
624
|
+
|
|
625
|
+
// Separate into CLI vs API fallback
|
|
626
|
+
const cliProviders = providersToUse.filter(p => availableClis.includes(p));
|
|
627
|
+
const apiProviders = providersToUse.filter(p => unavailableClis.includes(p));
|
|
628
|
+
|
|
629
|
+
console.error(`[Stdio Wrapper] Provider breakdown: CLI=${cliProviders.join(', ') || 'none'}, API fallback=${apiProviders.join(', ') || 'none'}`);
|
|
612
630
|
|
|
613
|
-
if (
|
|
614
|
-
console.error(`[Stdio Wrapper] No
|
|
631
|
+
if (cliProviders.length === 0 && apiProviders.length === 0) {
|
|
632
|
+
console.error(`[Stdio Wrapper] No providers available, will use remote perspectives only`);
|
|
615
633
|
localResults = [];
|
|
616
634
|
} else {
|
|
617
|
-
console.error(`[Stdio Wrapper]
|
|
635
|
+
console.error(`[Stdio Wrapper] Using ${cliProviders.length} CLIs + ${apiProviders.length} API fallbacks`);
|
|
618
636
|
|
|
619
637
|
// Run all CLI prompts concurrently
|
|
620
|
-
const cliPromises =
|
|
638
|
+
const cliPromises = cliProviders.map(async (providerId) => {
|
|
621
639
|
try {
|
|
622
640
|
const model = modelPreferences[providerId] || null;
|
|
623
641
|
if (model) {
|
|
@@ -645,8 +663,25 @@ class StdioMCPWrapper {
|
|
|
645
663
|
console.error('[Stdio Wrapper] CLI results reporting failed (non-critical):', err.message);
|
|
646
664
|
});
|
|
647
665
|
|
|
648
|
-
//
|
|
649
|
-
const
|
|
666
|
+
// Calculate how many successful local perspectives we got
|
|
667
|
+
const successfulLocalCount = localResults.filter(r => r.success).length;
|
|
668
|
+
const remainingPerspectives = maxPerspectives - successfulLocalCount;
|
|
669
|
+
|
|
670
|
+
// Get remote perspectives only if we need more perspectives to reach maxPerspectives
|
|
671
|
+
let perspectivesResult;
|
|
672
|
+
if (remainingPerspectives > 0) {
|
|
673
|
+
console.error(`[Stdio Wrapper] Need ${remainingPerspectives} more perspectives from remote`);
|
|
674
|
+
perspectivesResult = await this.callPerspectivesForCli(args, localResults, remainingPerspectives);
|
|
675
|
+
} else {
|
|
676
|
+
console.error(`[Stdio Wrapper] Already have ${successfulLocalCount} perspectives, skipping remote call`);
|
|
677
|
+
perspectivesResult = {
|
|
678
|
+
success: true,
|
|
679
|
+
content: '',
|
|
680
|
+
skipped: true,
|
|
681
|
+
reason: `Already have ${successfulLocalCount} perspectives (max: ${maxPerspectives})`,
|
|
682
|
+
timestamp: new Date().toISOString()
|
|
683
|
+
};
|
|
684
|
+
}
|
|
650
685
|
|
|
651
686
|
// Record usage for all CLI responses
|
|
652
687
|
for (const localResult of localResults) {
|
|
@@ -673,14 +708,19 @@ class StdioMCPWrapper {
|
|
|
673
708
|
|
|
674
709
|
/**
|
|
675
710
|
* Get all available and authenticated CLI providers
|
|
711
|
+
* Uses user's provider order from dashboard (display_order) instead of hardcoded order
|
|
712
|
+
* Falls back to API for providers where CLI is not available/authenticated
|
|
676
713
|
*/
|
|
677
714
|
async getAllAvailableProviders() {
|
|
678
715
|
try {
|
|
679
716
|
const results = await this.cliManager.forceCliDetection();
|
|
680
717
|
const availableProviders = [];
|
|
718
|
+
const unavailableProviders = [];
|
|
681
719
|
|
|
682
|
-
//
|
|
683
|
-
|
|
720
|
+
// Use user's provider order from dashboard (fetched via model-preferences API)
|
|
721
|
+
// Falls back to default order if not yet loaded
|
|
722
|
+
const priorityOrder = this.userProviderOrder || ['claude_code', 'codex_cli', 'gemini_cli'];
|
|
723
|
+
console.error(`[Stdio Wrapper] Using provider order: ${priorityOrder.join(' > ')}`);
|
|
684
724
|
|
|
685
725
|
for (const providerId of priorityOrder) {
|
|
686
726
|
const status = results[providerId];
|
|
@@ -688,17 +728,25 @@ class StdioMCPWrapper {
|
|
|
688
728
|
// Skip providers with quota exhausted - they'll use API fallback
|
|
689
729
|
if (status.quota_exhausted) {
|
|
690
730
|
console.error(`[Stdio Wrapper] Skipping ${providerId} - quota exhausted, will use API fallback`);
|
|
731
|
+
unavailableProviders.push(providerId);
|
|
691
732
|
continue;
|
|
692
733
|
}
|
|
693
734
|
availableProviders.push(providerId);
|
|
735
|
+
} else {
|
|
736
|
+
// CLI not available - will fall back to API for this provider
|
|
737
|
+
const reason = !status ? 'not detected' : (!status.available ? 'not installed' : 'not authenticated');
|
|
738
|
+
console.error(`[Stdio Wrapper] CLI ${providerId} ${reason}, will use API fallback`);
|
|
739
|
+
unavailableProviders.push(providerId);
|
|
694
740
|
}
|
|
695
741
|
}
|
|
696
742
|
|
|
697
|
-
|
|
743
|
+
// Return available CLIs first, then unavailable ones (for API fallback)
|
|
744
|
+
// The caller will handle mixing CLI + API based on availability
|
|
745
|
+
return { available: availableProviders, unavailable: unavailableProviders };
|
|
698
746
|
|
|
699
747
|
} catch (error) {
|
|
700
748
|
console.error('[Stdio Wrapper] Failed to get available providers:', error);
|
|
701
|
-
return [];
|
|
749
|
+
return { available: [], unavailable: [] };
|
|
702
750
|
}
|
|
703
751
|
}
|
|
704
752
|
|
|
@@ -782,8 +830,11 @@ class StdioMCPWrapper {
|
|
|
782
830
|
/**
|
|
783
831
|
* Call remote perspectives for CLI prompts
|
|
784
832
|
* Only calls remote APIs for providers NOT covered by successful local CLIs
|
|
833
|
+
* @param {Object} args - Original request arguments
|
|
834
|
+
* @param {Array} localResults - Results from local CLIs
|
|
835
|
+
* @param {number} maxPerspectives - Maximum number of remote perspectives to fetch
|
|
785
836
|
*/
|
|
786
|
-
async callPerspectivesForCli(args, localResults) {
|
|
837
|
+
async callPerspectivesForCli(args, localResults, maxPerspectives = 2) {
|
|
787
838
|
// Determine which providers succeeded locally
|
|
788
839
|
const successfulLocalProviders = localResults
|
|
789
840
|
.filter(r => r.success)
|
|
@@ -800,20 +851,21 @@ class StdioMCPWrapper {
|
|
|
800
851
|
.map(cli => cliToApiProvider[cli])
|
|
801
852
|
.filter(Boolean);
|
|
802
853
|
|
|
803
|
-
// If all major providers are covered locally, skip remote call
|
|
804
|
-
if (
|
|
854
|
+
// If all major providers are covered locally OR we don't need more perspectives, skip remote call
|
|
855
|
+
if (maxPerspectives <= 0 ||
|
|
856
|
+
excludeProviders.length >= 3 ||
|
|
805
857
|
(excludeProviders.includes('anthropic') && excludeProviders.includes('openai') && excludeProviders.includes('google'))) {
|
|
806
|
-
console.error(`[Stdio Wrapper] All providers covered by local CLIs, skipping remote perspectives`);
|
|
858
|
+
console.error(`[Stdio Wrapper] All providers covered by local CLIs or max perspectives reached, skipping remote perspectives`);
|
|
807
859
|
return {
|
|
808
860
|
success: true,
|
|
809
861
|
content: '',
|
|
810
862
|
skipped: true,
|
|
811
|
-
reason: 'All providers covered by local CLIs',
|
|
863
|
+
reason: 'All providers covered by local CLIs or max perspectives reached',
|
|
812
864
|
timestamp: new Date().toISOString()
|
|
813
865
|
};
|
|
814
866
|
}
|
|
815
867
|
|
|
816
|
-
console.error(`[Stdio Wrapper] Calling remote perspectives (excluding: ${excludeProviders.join(', ') || 'none'})`);
|
|
868
|
+
console.error(`[Stdio Wrapper] Calling remote perspectives (excluding: ${excludeProviders.join(', ') || 'none'}, max: ${maxPerspectives})`);
|
|
817
869
|
|
|
818
870
|
// Format CLI responses for logging on the server
|
|
819
871
|
const cliResponses = localResults.map(result => ({
|
|
@@ -839,6 +891,8 @@ class StdioMCPWrapper {
|
|
|
839
891
|
exclude_providers: excludeProviders,
|
|
840
892
|
// Pass CLI responses for dashboard logging
|
|
841
893
|
cli_responses: cliResponses,
|
|
894
|
+
// Limit remote perspectives to what we need
|
|
895
|
+
max_perspectives: maxPerspectives,
|
|
842
896
|
project_memory: 'none',
|
|
843
897
|
temperature: 0.7,
|
|
844
898
|
max_tokens: 20000
|
|
@@ -1307,6 +1361,7 @@ class StdioMCPWrapper {
|
|
|
1307
1361
|
/**
|
|
1308
1362
|
* Fetch user's model preferences from API keys
|
|
1309
1363
|
* Returns a map of CLI provider -> default_model
|
|
1364
|
+
* Also fetches and caches perspectivesPerMessage setting
|
|
1310
1365
|
*/
|
|
1311
1366
|
async fetchUserModelPreferences() {
|
|
1312
1367
|
// Check cache first
|
|
@@ -1342,7 +1397,16 @@ class StdioMCPWrapper {
|
|
|
1342
1397
|
this.userModelPreferences = result.modelPreferences;
|
|
1343
1398
|
this.modelPreferencesCacheTime = Date.now();
|
|
1344
1399
|
|
|
1400
|
+
// Also cache perspectives_per_message setting (default 2)
|
|
1401
|
+
this.perspectivesPerMessage = result.perspectivesPerMessage || 2;
|
|
1402
|
+
|
|
1403
|
+
// Cache provider order from user's dashboard (respects display_order)
|
|
1404
|
+
// This determines which CLIs/APIs to use first
|
|
1405
|
+
this.userProviderOrder = result.providerOrder || ['claude_code', 'codex_cli', 'gemini_cli'];
|
|
1406
|
+
|
|
1345
1407
|
console.error('[Stdio Wrapper] Model preferences loaded:', JSON.stringify(result.modelPreferences));
|
|
1408
|
+
console.error('[Stdio Wrapper] Provider order:', JSON.stringify(this.userProviderOrder));
|
|
1409
|
+
console.error('[Stdio Wrapper] Perspectives per message:', this.perspectivesPerMessage);
|
|
1346
1410
|
return result.modelPreferences;
|
|
1347
1411
|
} else {
|
|
1348
1412
|
console.error('[Stdio Wrapper] No model preferences in response');
|
package/package.json
CHANGED