polydev-ai 1.6.1 → 1.7.0

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/lib/cliManager.js CHANGED
@@ -378,7 +378,7 @@ This is a known issue with @google/gemini-cli@0.3.4 and older Node.js versions.`
378
378
  }
379
379
  }
380
380
 
381
- async sendCliPrompt(providerId, prompt, mode = 'args', timeoutMs = null) {
381
+ async sendCliPrompt(providerId, prompt, mode = 'args', timeoutMs = null, model = null) {
382
382
  // Set provider-specific default timeouts (180s for all by default, complex prompts take time)
383
383
  if (timeoutMs === null) {
384
384
  timeoutMs = 180000; // 180 seconds default for all providers
@@ -424,6 +424,13 @@ This is a known issue with @google/gemini-cli@0.3.4 and older Node.js versions.`
424
424
  };
425
425
  }
426
426
 
427
+ // Log model being used
428
+ if (model) {
429
+ console.log(`[Polydev CLI] Using model for ${providerId}: ${model}`);
430
+ } else {
431
+ console.log(`[Polydev CLI] No model specified for ${providerId}, using CLI default`);
432
+ }
433
+
427
434
  const promptVariants = [
428
435
  provider.subcommands?.test_prompt ? [...provider.subcommands.test_prompt] : []
429
436
  ];
@@ -437,7 +444,7 @@ This is a known issue with @google/gemini-cli@0.3.4 and older Node.js versions.`
437
444
  if (providerId === 'codex_cli') {
438
445
  const execArgs = promptVariants.find(args => args.includes('exec')) || promptVariants[0];
439
446
  try {
440
- const content = await this.executeCodexExec(provider.command, execArgs, prompt, timeoutMs);
447
+ const content = await this.executeCodexExec(provider.command, execArgs, prompt, timeoutMs, model);
441
448
  return {
442
449
  success: true,
443
450
  content,
@@ -445,6 +452,7 @@ This is a known issue with @google/gemini-cli@0.3.4 and older Node.js versions.`
445
452
  latency_ms: Date.now() - startTime,
446
453
  provider: providerId,
447
454
  mode: 'args',
455
+ model_used: model || 'cli_default',
448
456
  timestamp: new Date()
449
457
  };
450
458
  } catch (error) {
@@ -462,7 +470,25 @@ This is a known issue with @google/gemini-cli@0.3.4 and older Node.js versions.`
462
470
  let lastErrorMessage = null;
463
471
 
464
472
  for (const promptArgs of promptVariants) {
465
- const args = Array.isArray(promptArgs) ? [...promptArgs, prompt] : [prompt];
473
+ // Build args with model flag if specified
474
+ let args = Array.isArray(promptArgs) ? [...promptArgs] : [];
475
+
476
+ // Add model flag based on CLI type
477
+ if (model) {
478
+ if (providerId === 'claude_code') {
479
+ // Claude Code uses --model flag
480
+ args = ['--model', model, ...args, prompt];
481
+ } else if (providerId === 'gemini_cli') {
482
+ // Gemini CLI uses -m flag
483
+ args = ['-m', model, ...args, prompt];
484
+ } else {
485
+ // Default: just append prompt
486
+ args = [...args, prompt];
487
+ }
488
+ } else {
489
+ args = [...args, prompt];
490
+ }
491
+
466
492
  try {
467
493
  const result = await this.executeCliCommand(
468
494
  provider.command,
@@ -481,6 +507,7 @@ This is a known issue with @google/gemini-cli@0.3.4 and older Node.js versions.`
481
507
  latency_ms: Date.now() - startTime,
482
508
  provider: providerId,
483
509
  mode: 'args',
510
+ model_used: model || 'cli_default',
484
511
  timestamp: new Date()
485
512
  };
486
513
  }
@@ -488,6 +515,37 @@ This is a known issue with @google/gemini-cli@0.3.4 and older Node.js versions.`
488
515
  lastErrorMessage = result.error;
489
516
  } catch (error) {
490
517
  lastErrorMessage = error instanceof Error ? error.message : String(error);
518
+
519
+ // If model was specified and command failed, retry without model (graceful fallback)
520
+ if (model && lastErrorMessage.includes('model')) {
521
+ console.log(`[Polydev CLI] Model ${model} may be invalid for ${providerId}, retrying without model flag`);
522
+ try {
523
+ const fallbackArgs = Array.isArray(promptArgs) ? [...promptArgs, prompt] : [prompt];
524
+ const fallbackResult = await this.executeCliCommand(
525
+ provider.command,
526
+ fallbackArgs,
527
+ 'args',
528
+ timeoutMs,
529
+ undefined
530
+ );
531
+
532
+ if (!fallbackResult.error) {
533
+ const content = this.cleanCliResponse(fallbackResult.stdout || '');
534
+ return {
535
+ success: true,
536
+ content,
537
+ tokens_used: this.estimateTokens(prompt + content),
538
+ latency_ms: Date.now() - startTime,
539
+ provider: providerId,
540
+ mode: 'args',
541
+ model_used: 'cli_default_fallback',
542
+ timestamp: new Date()
543
+ };
544
+ }
545
+ } catch (fallbackError) {
546
+ // Fallback also failed, continue with original error
547
+ }
548
+ }
491
549
  }
492
550
  }
493
551
 
@@ -609,7 +667,7 @@ This is a known issue with @google/gemini-cli@0.3.4 and older Node.js versions.`
609
667
  });
610
668
  }
611
669
 
612
- async executeCodexExec(executable, commandArgs, prompt, timeoutMs) {
670
+ async executeCodexExec(executable, commandArgs, prompt, timeoutMs, model = null) {
613
671
  if (!executable) {
614
672
  throw new Error('Missing Codex executable');
615
673
  }
@@ -619,15 +677,26 @@ This is a known issue with @google/gemini-cli@0.3.4 and older Node.js versions.`
619
677
  }
620
678
 
621
679
  const workingDir = process.cwd();
622
- const args = [
623
- ...commandArgs,
680
+
681
+ // Build args with optional model flag
682
+ // Codex CLI uses -m or --model flag
683
+ let args = [...commandArgs];
684
+
685
+ // Add model flag if specified
686
+ if (model) {
687
+ args.push('-m', model);
688
+ console.log(`[CLI Debug] Codex using model: ${model}`);
689
+ }
690
+
691
+ // Add standard flags and prompt
692
+ args.push(
624
693
  '--sandbox',
625
694
  'workspace-write',
626
695
  '--skip-git-repo-check',
627
696
  '--cd',
628
697
  workingDir,
629
698
  prompt
630
- ];
699
+ );
631
700
 
632
701
  return new Promise((resolve, reject) => {
633
702
  const baseTmp = process.env.POLYDEV_CLI_TMPDIR || process.env.TMPDIR || os.tmpdir();
@@ -116,6 +116,11 @@ class StdioMCPWrapper {
116
116
 
117
117
  // Smart refresh scheduler (will be started after initialization)
118
118
  this.refreshScheduler = null;
119
+
120
+ // Cache for user model preferences (provider -> model)
121
+ this.userModelPreferences = null;
122
+ this.modelPreferencesCacheTime = null;
123
+ this.MODEL_PREFERENCES_CACHE_TTL = 5 * 60 * 1000; // 5 minutes cache
119
124
  }
120
125
 
121
126
  loadManifest() {
@@ -452,12 +457,26 @@ class StdioMCPWrapper {
452
457
  // Use reasonable timeout for CLI responses (180 seconds for complex prompts)
453
458
  const gracefulTimeout = Math.min(timeout_ms, 180000);
454
459
 
460
+ // Fetch user's model preferences (cached, non-blocking on failure)
461
+ let modelPreferences = {};
462
+ try {
463
+ modelPreferences = await this.fetchUserModelPreferences();
464
+ } catch (prefError) {
465
+ console.error('[Stdio Wrapper] Model preferences fetch failed (will use CLI defaults):', prefError.message);
466
+ }
467
+
455
468
  let localResults = [];
456
469
 
457
470
  if (provider_id) {
458
471
  // Specific provider requested - use only that one
459
472
  console.error(`[Stdio Wrapper] Using specific provider: ${provider_id}`);
460
- const result = await this.cliManager.sendCliPrompt(provider_id, prompt, mode, gracefulTimeout);
473
+ const model = modelPreferences[provider_id] || null;
474
+ if (model) {
475
+ console.error(`[Stdio Wrapper] Using user's preferred model for ${provider_id}: ${model}`);
476
+ } else {
477
+ console.error(`[Stdio Wrapper] No model preference for ${provider_id}, using CLI default`);
478
+ }
479
+ const result = await this.cliManager.sendCliPrompt(provider_id, prompt, mode, gracefulTimeout, model);
461
480
  localResults = [{ provider_id, ...result }];
462
481
  } else {
463
482
  // No specific provider - use ALL available local CLIs
@@ -473,7 +492,11 @@ class StdioMCPWrapper {
473
492
  // Run all CLI prompts concurrently
474
493
  const cliPromises = availableProviders.map(async (providerId) => {
475
494
  try {
476
- const result = await this.cliManager.sendCliPrompt(providerId, prompt, mode, gracefulTimeout);
495
+ const model = modelPreferences[providerId] || null;
496
+ if (model) {
497
+ console.error(`[Stdio Wrapper] Using user's preferred model for ${providerId}: ${model}`);
498
+ }
499
+ const result = await this.cliManager.sendCliPrompt(providerId, prompt, mode, gracefulTimeout, model);
477
500
  return { provider_id: providerId, ...result };
478
501
  } catch (error) {
479
502
  console.error(`[Stdio Wrapper] CLI ${providerId} failed:`, error.message);
@@ -1020,6 +1043,87 @@ class StdioMCPWrapper {
1020
1043
  }
1021
1044
  }
1022
1045
 
1046
+ /**
1047
+ * Fetch user's model preferences from API keys
1048
+ * Returns a map of CLI provider -> default_model
1049
+ */
1050
+ async fetchUserModelPreferences() {
1051
+ // Check cache first
1052
+ if (this.userModelPreferences && this.modelPreferencesCacheTime) {
1053
+ const cacheAge = Date.now() - this.modelPreferencesCacheTime;
1054
+ if (cacheAge < this.MODEL_PREFERENCES_CACHE_TTL) {
1055
+ console.error('[Stdio Wrapper] Using cached model preferences');
1056
+ return this.userModelPreferences;
1057
+ }
1058
+ }
1059
+
1060
+ console.error('[Stdio Wrapper] Fetching user model preferences from API...');
1061
+
1062
+ try {
1063
+ // Call the dedicated model-preferences endpoint
1064
+ const response = await fetch('https://www.polydev.ai/api/model-preferences', {
1065
+ method: 'GET',
1066
+ headers: {
1067
+ 'Authorization': `Bearer ${this.userToken}`,
1068
+ 'User-Agent': 'polydev-stdio-wrapper/1.0.0'
1069
+ }
1070
+ });
1071
+
1072
+ if (!response.ok) {
1073
+ console.error('[Stdio Wrapper] Failed to fetch model preferences:', response.status);
1074
+ return this.userModelPreferences || {};
1075
+ }
1076
+
1077
+ const result = await response.json();
1078
+
1079
+ if (result.success && result.modelPreferences) {
1080
+ // Cache the preferences
1081
+ this.userModelPreferences = result.modelPreferences;
1082
+ this.modelPreferencesCacheTime = Date.now();
1083
+
1084
+ console.error('[Stdio Wrapper] Model preferences loaded:', JSON.stringify(result.modelPreferences));
1085
+ return result.modelPreferences;
1086
+ } else {
1087
+ console.error('[Stdio Wrapper] No model preferences in response');
1088
+ return this.userModelPreferences || {};
1089
+ }
1090
+
1091
+ } catch (error) {
1092
+ console.error('[Stdio Wrapper] Error fetching model preferences:', error.message);
1093
+ return this.userModelPreferences || {};
1094
+ }
1095
+ }
1096
+
1097
+ /**
1098
+ * Map provider name to CLI provider ID
1099
+ */
1100
+ mapProviderToCli(provider) {
1101
+ const providerLower = (provider || '').toLowerCase().trim();
1102
+
1103
+ // Map provider names to CLI tool IDs
1104
+ const providerMap = {
1105
+ 'anthropic': 'claude_code',
1106
+ 'anthropic-ai': 'claude_code',
1107
+ 'claude': 'claude_code',
1108
+ 'openai': 'codex_cli',
1109
+ 'open-ai': 'codex_cli',
1110
+ 'gpt': 'codex_cli',
1111
+ 'google': 'gemini_cli',
1112
+ 'google-ai': 'gemini_cli',
1113
+ 'gemini': 'gemini_cli'
1114
+ };
1115
+
1116
+ return providerMap[providerLower] || null;
1117
+ }
1118
+
1119
+ /**
1120
+ * Get model for a specific CLI provider
1121
+ */
1122
+ async getModelForProvider(providerId) {
1123
+ const preferences = await this.fetchUserModelPreferences();
1124
+ return preferences[providerId] || null;
1125
+ }
1126
+
1023
1127
  async start() {
1024
1128
  console.log('Starting Polydev Stdio MCP Wrapper...');
1025
1129
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "polydev-ai",
3
- "version": "1.6.1",
3
+ "version": "1.7.0",
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",