polydev-ai 1.8.18 → 1.8.20

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.
@@ -613,21 +613,29 @@ class StdioMCPWrapper {
613
613
  const result = await this.cliManager.sendCliPrompt(provider_id, prompt, mode, gracefulTimeout, model);
614
614
  localResults = [{ provider_id, ...result }];
615
615
  } else {
616
- // No specific provider - use available local CLIs up to maxPerspectives limit
617
- console.error(`[Stdio Wrapper] Using available local CLIs (max: ${maxPerspectives})`);
618
- const allAvailableProviders = await this.getAllAvailableProviders();
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();
619
620
 
620
- // Limit to maxPerspectives
621
- const availableProviders = allAvailableProviders.slice(0, maxPerspectives);
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);
622
624
 
623
- if (availableProviders.length === 0) {
624
- console.error(`[Stdio Wrapper] No local CLIs available, will use remote perspectives only`);
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'}`);
630
+
631
+ if (cliProviders.length === 0 && apiProviders.length === 0) {
632
+ console.error(`[Stdio Wrapper] No providers available, will use remote perspectives only`);
625
633
  localResults = [];
626
634
  } else {
627
- console.error(`[Stdio Wrapper] Found ${allAvailableProviders.length} available CLIs, using ${availableProviders.length}: ${availableProviders.join(', ')}`);
635
+ console.error(`[Stdio Wrapper] Using ${cliProviders.length} CLIs + ${apiProviders.length} API fallbacks`);
628
636
 
629
637
  // Run all CLI prompts concurrently
630
- const cliPromises = availableProviders.map(async (providerId) => {
638
+ const cliPromises = cliProviders.map(async (providerId) => {
631
639
  try {
632
640
  const model = modelPreferences[providerId] || null;
633
641
  if (model) {
@@ -700,14 +708,19 @@ class StdioMCPWrapper {
700
708
 
701
709
  /**
702
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
703
713
  */
704
714
  async getAllAvailableProviders() {
705
715
  try {
706
716
  const results = await this.cliManager.forceCliDetection();
707
717
  const availableProviders = [];
718
+ const unavailableProviders = [];
708
719
 
709
- // Priority order: claude_code > codex_cli > gemini_cli
710
- const priorityOrder = ['claude_code', 'codex_cli', 'gemini_cli'];
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(' > ')}`);
711
724
 
712
725
  for (const providerId of priorityOrder) {
713
726
  const status = results[providerId];
@@ -715,17 +728,25 @@ class StdioMCPWrapper {
715
728
  // Skip providers with quota exhausted - they'll use API fallback
716
729
  if (status.quota_exhausted) {
717
730
  console.error(`[Stdio Wrapper] Skipping ${providerId} - quota exhausted, will use API fallback`);
731
+ unavailableProviders.push(providerId);
718
732
  continue;
719
733
  }
720
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);
721
740
  }
722
741
  }
723
742
 
724
- return availableProviders;
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 };
725
746
 
726
747
  } catch (error) {
727
748
  console.error('[Stdio Wrapper] Failed to get available providers:', error);
728
- return [];
749
+ return { available: [], unavailable: [] };
729
750
  }
730
751
  }
731
752
 
@@ -1348,6 +1369,8 @@ class StdioMCPWrapper {
1348
1369
  const cacheAge = Date.now() - this.modelPreferencesCacheTime;
1349
1370
  if (cacheAge < this.MODEL_PREFERENCES_CACHE_TTL) {
1350
1371
  console.error('[Stdio Wrapper] Using cached model preferences');
1372
+ // Also restore cached userProviderOrder when using cache
1373
+ // (userProviderOrder was set during the initial API fetch)
1351
1374
  return this.userModelPreferences;
1352
1375
  }
1353
1376
  }
@@ -1379,7 +1402,13 @@ class StdioMCPWrapper {
1379
1402
  // Also cache perspectives_per_message setting (default 2)
1380
1403
  this.perspectivesPerMessage = result.perspectivesPerMessage || 2;
1381
1404
 
1405
+ // Cache provider order from user's dashboard (respects display_order)
1406
+ // This determines which CLIs/APIs to use first
1407
+ // IMPORTANT: This is cached alongside modelPreferences and restored when cache is used
1408
+ this.userProviderOrder = result.providerOrder || ['claude_code', 'codex_cli', 'gemini_cli'];
1409
+
1382
1410
  console.error('[Stdio Wrapper] Model preferences loaded:', JSON.stringify(result.modelPreferences));
1411
+ console.error('[Stdio Wrapper] Provider order:', JSON.stringify(this.userProviderOrder));
1383
1412
  console.error('[Stdio Wrapper] Perspectives per message:', this.perspectivesPerMessage);
1384
1413
  return result.modelPreferences;
1385
1414
  } else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "polydev-ai",
3
- "version": "1.8.18",
3
+ "version": "1.8.20",
4
4
  "description": "Agentic workflow assistant with CLI integration - get diverse perspectives from multiple LLMs when stuck or need enhanced reasoning",
5
5
  "keywords": [
6
6
  "mcp",