polydev-ai 1.8.22 → 1.8.24
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 +105 -44
- package/package.json +1 -1
package/mcp/stdio-wrapper.js
CHANGED
|
@@ -566,6 +566,7 @@ class StdioMCPWrapper {
|
|
|
566
566
|
/**
|
|
567
567
|
* Local CLI prompt sending with ALL available CLIs + remote perspectives
|
|
568
568
|
* Respects user's perspectives_per_message setting for total perspectives
|
|
569
|
+
* Uses allProviders from dashboard - tries CLI first, falls back to API
|
|
569
570
|
*/
|
|
570
571
|
async localSendCliPrompt(args) {
|
|
571
572
|
console.error(`[Stdio Wrapper] Local CLI prompt sending with perspectives`);
|
|
@@ -587,7 +588,7 @@ class StdioMCPWrapper {
|
|
|
587
588
|
const gracefulTimeout = Math.min(timeout_ms, 600000);
|
|
588
589
|
|
|
589
590
|
// Fetch user's model preferences (cached, non-blocking on failure)
|
|
590
|
-
// This also fetches perspectivesPerMessage setting
|
|
591
|
+
// This also fetches perspectivesPerMessage setting and allProviders list
|
|
591
592
|
let modelPreferences = {};
|
|
592
593
|
try {
|
|
593
594
|
modelPreferences = await this.fetchUserModelPreferences();
|
|
@@ -613,48 +614,85 @@ class StdioMCPWrapper {
|
|
|
613
614
|
const result = await this.cliManager.sendCliPrompt(provider_id, prompt, mode, gracefulTimeout, model);
|
|
614
615
|
localResults = [{ provider_id, ...result }];
|
|
615
616
|
} else {
|
|
616
|
-
// No specific provider - use
|
|
617
|
-
//
|
|
618
|
-
console.error(`[Stdio Wrapper] Using
|
|
619
|
-
const { available: availableClis, unavailable: unavailableClis } = await this.getAllAvailableProviders();
|
|
617
|
+
// No specific provider - use allProviders from dashboard in order
|
|
618
|
+
// For each provider: try CLI first if available, otherwise use API
|
|
619
|
+
console.error(`[Stdio Wrapper] Using allProviders from dashboard (max: ${maxPerspectives})`);
|
|
620
620
|
|
|
621
|
-
//
|
|
622
|
-
const
|
|
623
|
-
|
|
621
|
+
// Get available CLIs for checking
|
|
622
|
+
const { available: availableClis } = await this.getAllAvailableProviders();
|
|
623
|
+
console.error(`[Stdio Wrapper] Available CLIs: ${availableClis.join(', ') || 'none'}`);
|
|
624
624
|
|
|
625
|
-
//
|
|
626
|
-
|
|
627
|
-
const
|
|
625
|
+
// Use allProviders from API (full list including API-only providers)
|
|
626
|
+
// Falls back to CLI-only providers if allProviders not available
|
|
627
|
+
const allProviders = this.allProviders || [];
|
|
628
628
|
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
} else {
|
|
635
|
-
console.error(`[Stdio Wrapper] Using ${cliProviders.length} CLIs + ${apiProviders.length} API fallbacks`);
|
|
629
|
+
if (allProviders.length === 0) {
|
|
630
|
+
// Fallback: use legacy CLI-only flow
|
|
631
|
+
console.error(`[Stdio Wrapper] No allProviders, using legacy CLI-only flow`);
|
|
632
|
+
const userOrder = this.userProviderOrder || ['claude_code', 'codex_cli', 'gemini_cli'];
|
|
633
|
+
const cliProviders = userOrder.slice(0, maxPerspectives).filter(p => availableClis.includes(p));
|
|
636
634
|
|
|
637
|
-
// Run all CLI prompts concurrently
|
|
638
635
|
const cliPromises = cliProviders.map(async (providerId) => {
|
|
639
636
|
try {
|
|
640
637
|
const model = modelPreferences[providerId] || null;
|
|
641
|
-
if (model) {
|
|
642
|
-
console.error(`[Stdio Wrapper] Using user's preferred model for ${providerId}: ${model}`);
|
|
643
|
-
}
|
|
644
638
|
const result = await this.cliManager.sendCliPrompt(providerId, prompt, mode, gracefulTimeout, model);
|
|
645
639
|
return { provider_id: providerId, ...result };
|
|
646
640
|
} catch (error) {
|
|
647
|
-
|
|
648
|
-
return {
|
|
649
|
-
provider_id: providerId,
|
|
650
|
-
success: false,
|
|
651
|
-
error: error.message,
|
|
652
|
-
latency_ms: gracefulTimeout
|
|
653
|
-
};
|
|
641
|
+
return { provider_id: providerId, success: false, error: error.message };
|
|
654
642
|
}
|
|
655
643
|
});
|
|
656
|
-
|
|
657
644
|
localResults = await Promise.all(cliPromises);
|
|
645
|
+
} else {
|
|
646
|
+
// NEW: Use allProviders list (includes CLI + API-only providers)
|
|
647
|
+
const providersToUse = allProviders.slice(0, maxPerspectives);
|
|
648
|
+
console.error(`[Stdio Wrapper] Using ${providersToUse.length} providers from dashboard`);
|
|
649
|
+
|
|
650
|
+
// Separate into CLI providers vs API-only providers
|
|
651
|
+
const cliProviderEntries = [];
|
|
652
|
+
const apiOnlyProviders = [];
|
|
653
|
+
|
|
654
|
+
for (const p of providersToUse) {
|
|
655
|
+
if (p.cliId && availableClis.includes(p.cliId)) {
|
|
656
|
+
// Has CLI and CLI is available
|
|
657
|
+
cliProviderEntries.push(p);
|
|
658
|
+
} else {
|
|
659
|
+
// No CLI or CLI unavailable - needs API
|
|
660
|
+
apiOnlyProviders.push(p);
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
console.error(`[Stdio Wrapper] Provider breakdown: CLI=${cliProviderEntries.map(p => p.cliId).join(', ') || 'none'}, API-only=${apiOnlyProviders.map(p => p.provider).join(', ') || 'none'}`);
|
|
665
|
+
|
|
666
|
+
// Run all CLI prompts concurrently
|
|
667
|
+
if (cliProviderEntries.length > 0) {
|
|
668
|
+
const cliPromises = cliProviderEntries.map(async (providerEntry) => {
|
|
669
|
+
try {
|
|
670
|
+
const model = providerEntry.model || modelPreferences[providerEntry.cliId] || null;
|
|
671
|
+
if (model) {
|
|
672
|
+
console.error(`[Stdio Wrapper] Using model for ${providerEntry.cliId}: ${model}`);
|
|
673
|
+
}
|
|
674
|
+
const result = await this.cliManager.sendCliPrompt(providerEntry.cliId, prompt, mode, gracefulTimeout, model);
|
|
675
|
+
return {
|
|
676
|
+
provider_id: providerEntry.cliId,
|
|
677
|
+
original_provider: providerEntry.provider,
|
|
678
|
+
...result
|
|
679
|
+
};
|
|
680
|
+
} catch (error) {
|
|
681
|
+
console.error(`[Stdio Wrapper] CLI ${providerEntry.cliId} failed:`, error.message);
|
|
682
|
+
return {
|
|
683
|
+
provider_id: providerEntry.cliId,
|
|
684
|
+
original_provider: providerEntry.provider,
|
|
685
|
+
success: false,
|
|
686
|
+
error: error.message,
|
|
687
|
+
latency_ms: gracefulTimeout
|
|
688
|
+
};
|
|
689
|
+
}
|
|
690
|
+
});
|
|
691
|
+
localResults = await Promise.all(cliPromises);
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
// Store API-only providers info for remote API call
|
|
695
|
+
this._apiOnlyProviders = apiOnlyProviders;
|
|
658
696
|
}
|
|
659
697
|
}
|
|
660
698
|
|
|
@@ -665,15 +703,26 @@ class StdioMCPWrapper {
|
|
|
665
703
|
|
|
666
704
|
// Calculate how many successful local perspectives we got
|
|
667
705
|
const successfulLocalCount = localResults.filter(r => r.success).length;
|
|
668
|
-
const
|
|
706
|
+
const failedCliCount = localResults.filter(r => !r.success).length;
|
|
707
|
+
|
|
708
|
+
// Need API for: API-only providers + failed CLIs
|
|
709
|
+
const apiOnlyCount = (this._apiOnlyProviders || []).length;
|
|
710
|
+
const remainingPerspectives = apiOnlyCount + failedCliCount;
|
|
669
711
|
|
|
670
|
-
// Get remote perspectives only
|
|
712
|
+
// Get remote perspectives for API-only providers and failed CLIs
|
|
671
713
|
let perspectivesResult;
|
|
672
714
|
if (remainingPerspectives > 0) {
|
|
673
|
-
console.error(`[Stdio Wrapper] Need ${remainingPerspectives}
|
|
674
|
-
|
|
715
|
+
console.error(`[Stdio Wrapper] Need ${remainingPerspectives} perspectives from remote API (${apiOnlyCount} API-only + ${failedCliCount} failed CLIs)`);
|
|
716
|
+
|
|
717
|
+
// Pass API-only provider info to help remote API choose correct models
|
|
718
|
+
const apiProvidersInfo = (this._apiOnlyProviders || []).map(p => ({
|
|
719
|
+
provider: p.provider,
|
|
720
|
+
model: p.model
|
|
721
|
+
}));
|
|
722
|
+
|
|
723
|
+
perspectivesResult = await this.callPerspectivesForCli(args, localResults, remainingPerspectives, apiProvidersInfo);
|
|
675
724
|
} else {
|
|
676
|
-
console.error(`[Stdio Wrapper] Already have ${successfulLocalCount} perspectives, skipping remote call`);
|
|
725
|
+
console.error(`[Stdio Wrapper] Already have ${successfulLocalCount} perspectives from CLIs, skipping remote call`);
|
|
677
726
|
perspectivesResult = {
|
|
678
727
|
success: true,
|
|
679
728
|
content: '',
|
|
@@ -859,8 +908,9 @@ class StdioMCPWrapper {
|
|
|
859
908
|
* @param {Object} args - Original request arguments
|
|
860
909
|
* @param {Array} localResults - Results from local CLIs
|
|
861
910
|
* @param {number} maxPerspectives - Maximum number of remote perspectives to fetch
|
|
911
|
+
* @param {Array} apiProvidersInfo - Optional array of API-only providers to request (from allProviders)
|
|
862
912
|
*/
|
|
863
|
-
async callPerspectivesForCli(args, localResults, maxPerspectives = 2) {
|
|
913
|
+
async callPerspectivesForCli(args, localResults, maxPerspectives = 2, apiProvidersInfo = []) {
|
|
864
914
|
// Determine which providers succeeded locally
|
|
865
915
|
const successfulLocalProviders = localResults
|
|
866
916
|
.filter(r => r.success)
|
|
@@ -877,21 +927,25 @@ class StdioMCPWrapper {
|
|
|
877
927
|
.map(cli => cliToApiProvider[cli])
|
|
878
928
|
.filter(Boolean);
|
|
879
929
|
|
|
880
|
-
// If
|
|
881
|
-
if (maxPerspectives <= 0
|
|
882
|
-
|
|
883
|
-
(excludeProviders.includes('anthropic') && excludeProviders.includes('openai') && excludeProviders.includes('google'))) {
|
|
884
|
-
console.error(`[Stdio Wrapper] All providers covered by local CLIs or max perspectives reached, skipping remote perspectives`);
|
|
930
|
+
// If we don't need any perspectives, skip remote call
|
|
931
|
+
if (maxPerspectives <= 0) {
|
|
932
|
+
console.error(`[Stdio Wrapper] Max perspectives is 0, skipping remote perspectives`);
|
|
885
933
|
return {
|
|
886
934
|
success: true,
|
|
887
935
|
content: '',
|
|
888
936
|
skipped: true,
|
|
889
|
-
reason: '
|
|
937
|
+
reason: 'No perspectives needed',
|
|
890
938
|
timestamp: new Date().toISOString()
|
|
891
939
|
};
|
|
892
940
|
}
|
|
893
941
|
|
|
894
|
-
|
|
942
|
+
// Build list of specific providers to request (from API-only providers)
|
|
943
|
+
const requestProviders = apiProvidersInfo.map(p => ({
|
|
944
|
+
provider: p.provider,
|
|
945
|
+
model: p.model
|
|
946
|
+
}));
|
|
947
|
+
|
|
948
|
+
console.error(`[Stdio Wrapper] Calling remote perspectives (excluding: ${excludeProviders.join(', ') || 'none'}, requesting: ${requestProviders.map(p => p.provider).join(', ') || 'any'}, max: ${maxPerspectives})`);
|
|
895
949
|
|
|
896
950
|
// Format CLI responses for logging on the server
|
|
897
951
|
const cliResponses = localResults.map(result => ({
|
|
@@ -915,6 +969,8 @@ class StdioMCPWrapper {
|
|
|
915
969
|
user_token: this.userToken,
|
|
916
970
|
// Exclude providers that succeeded locally
|
|
917
971
|
exclude_providers: excludeProviders,
|
|
972
|
+
// NEW: Specific providers to request (from API-only list)
|
|
973
|
+
request_providers: requestProviders.length > 0 ? requestProviders : undefined,
|
|
918
974
|
// Pass CLI responses for dashboard logging
|
|
919
975
|
cli_responses: cliResponses,
|
|
920
976
|
// Limit remote perspectives to what we need
|
|
@@ -1387,7 +1443,7 @@ class StdioMCPWrapper {
|
|
|
1387
1443
|
/**
|
|
1388
1444
|
* Fetch user's model preferences from API keys
|
|
1389
1445
|
* Returns a map of CLI provider -> default_model
|
|
1390
|
-
* Also fetches and caches perspectivesPerMessage setting
|
|
1446
|
+
* Also fetches and caches perspectivesPerMessage setting and allProviders list
|
|
1391
1447
|
*/
|
|
1392
1448
|
async fetchUserModelPreferences() {
|
|
1393
1449
|
// Check cache first
|
|
@@ -1433,8 +1489,13 @@ class StdioMCPWrapper {
|
|
|
1433
1489
|
// IMPORTANT: This is cached alongside modelPreferences and restored when cache is used
|
|
1434
1490
|
this.userProviderOrder = result.providerOrder || ['claude_code', 'codex_cli', 'gemini_cli'];
|
|
1435
1491
|
|
|
1492
|
+
// NEW: Cache full list of all providers (CLI + API-only) from dashboard
|
|
1493
|
+
// Format: [{ provider: 'openai', model: 'gpt-52-codex', cliId: 'codex_cli' }, { provider: 'x-ai', model: 'grok-4', cliId: null }, ...]
|
|
1494
|
+
this.allProviders = result.allProviders || [];
|
|
1495
|
+
|
|
1436
1496
|
console.error('[Stdio Wrapper] Model preferences loaded:', JSON.stringify(result.modelPreferences));
|
|
1437
1497
|
console.error('[Stdio Wrapper] Provider order:', JSON.stringify(this.userProviderOrder));
|
|
1498
|
+
console.error('[Stdio Wrapper] All providers:', JSON.stringify(this.allProviders));
|
|
1438
1499
|
console.error('[Stdio Wrapper] Perspectives per message:', this.perspectivesPerMessage);
|
|
1439
1500
|
return result.modelPreferences;
|
|
1440
1501
|
} else {
|
package/package.json
CHANGED