polydev-ai 1.6.0 → 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
@@ -42,9 +42,6 @@ class CLIManager {
42
42
  id: 'claude_code',
43
43
  name: 'Claude Code',
44
44
  command: process.env.CLAUDE_CODE_PATH || 'claude',
45
- // Model configuration: use env var or default to 'haiku' for speed
46
- // Options: haiku (fastest), sonnet (balanced), opus (most capable)
47
- model: process.env.POLYDEV_CLAUDE_MODEL || 'haiku',
48
45
  subcommands: {
49
46
  chat: [],
50
47
  version: ['--version'],
@@ -58,9 +55,6 @@ class CLIManager {
58
55
  id: 'codex_cli',
59
56
  name: 'Codex CLI',
60
57
  command: process.env.CODEX_CLI_PATH || 'codex',
61
- // Model configuration: use env var or default to 'gpt-4o-mini' for speed
62
- // Options: gpt-4o-mini (fastest), gpt-4o, o3-mini, o1, etc.
63
- model: process.env.POLYDEV_CODEX_MODEL || 'gpt-4o-mini',
64
58
  subcommands: {
65
59
  chat: ['chat'],
66
60
  version: ['--version'],
@@ -78,8 +72,6 @@ class CLIManager {
78
72
  id: 'gemini_cli',
79
73
  name: 'Gemini CLI',
80
74
  command: process.env.GEMINI_CLI_PATH || 'gemini',
81
- // Model configuration for Gemini
82
- model: process.env.POLYDEV_GEMINI_MODEL || 'gemini-2.0-flash',
83
75
  subcommands: {
84
76
  chat: ['chat'],
85
77
  version: ['--version'],
@@ -386,7 +378,7 @@ This is a known issue with @google/gemini-cli@0.3.4 and older Node.js versions.`
386
378
  }
387
379
  }
388
380
 
389
- async sendCliPrompt(providerId, prompt, mode = 'args', timeoutMs = null) {
381
+ async sendCliPrompt(providerId, prompt, mode = 'args', timeoutMs = null, model = null) {
390
382
  // Set provider-specific default timeouts (180s for all by default, complex prompts take time)
391
383
  if (timeoutMs === null) {
392
384
  timeoutMs = 180000; // 180 seconds default for all providers
@@ -432,6 +424,13 @@ This is a known issue with @google/gemini-cli@0.3.4 and older Node.js versions.`
432
424
  };
433
425
  }
434
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
+
435
434
  const promptVariants = [
436
435
  provider.subcommands?.test_prompt ? [...provider.subcommands.test_prompt] : []
437
436
  ];
@@ -445,16 +444,15 @@ This is a known issue with @google/gemini-cli@0.3.4 and older Node.js versions.`
445
444
  if (providerId === 'codex_cli') {
446
445
  const execArgs = promptVariants.find(args => args.includes('exec')) || promptVariants[0];
447
446
  try {
448
- // Pass model configuration to Codex
449
- const content = await this.executeCodexExec(provider.command, execArgs, prompt, timeoutMs, provider.model);
447
+ const content = await this.executeCodexExec(provider.command, execArgs, prompt, timeoutMs, model);
450
448
  return {
451
449
  success: true,
452
450
  content,
453
451
  tokens_used: this.estimateTokens(prompt + content),
454
452
  latency_ms: Date.now() - startTime,
455
453
  provider: providerId,
456
- model: provider.model,
457
454
  mode: 'args',
455
+ model_used: model || 'cli_default',
458
456
  timestamp: new Date()
459
457
  };
460
458
  } catch (error) {
@@ -463,7 +461,6 @@ This is a known issue with @google/gemini-cli@0.3.4 and older Node.js versions.`
463
461
  error: `CLI execution failed: ${error instanceof Error ? error.message : String(error)}`,
464
462
  latency_ms: Date.now() - startTime,
465
463
  provider: providerId,
466
- model: provider.model,
467
464
  mode,
468
465
  timestamp: new Date()
469
466
  };
@@ -473,9 +470,25 @@ This is a known issue with @google/gemini-cli@0.3.4 and older Node.js versions.`
473
470
  let lastErrorMessage = null;
474
471
 
475
472
  for (const promptArgs of promptVariants) {
476
- // Add model parameter for Claude Code
477
- const modelArgs = provider.model ? ['--model', provider.model] : [];
478
- const args = Array.isArray(promptArgs) ? [...promptArgs, ...modelArgs, prompt] : [...modelArgs, 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
+
479
492
  try {
480
493
  const result = await this.executeCliCommand(
481
494
  provider.command,
@@ -493,8 +506,8 @@ This is a known issue with @google/gemini-cli@0.3.4 and older Node.js versions.`
493
506
  tokens_used: this.estimateTokens(prompt + content),
494
507
  latency_ms: Date.now() - startTime,
495
508
  provider: providerId,
496
- model: provider.model,
497
509
  mode: 'args',
510
+ model_used: model || 'cli_default',
498
511
  timestamp: new Date()
499
512
  };
500
513
  }
@@ -502,6 +515,37 @@ This is a known issue with @google/gemini-cli@0.3.4 and older Node.js versions.`
502
515
  lastErrorMessage = result.error;
503
516
  } catch (error) {
504
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
+ }
505
549
  }
506
550
  }
507
551
 
@@ -623,7 +667,7 @@ This is a known issue with @google/gemini-cli@0.3.4 and older Node.js versions.`
623
667
  });
624
668
  }
625
669
 
626
- async executeCodexExec(executable, commandArgs, prompt, timeoutMs, model) {
670
+ async executeCodexExec(executable, commandArgs, prompt, timeoutMs, model = null) {
627
671
  if (!executable) {
628
672
  throw new Error('Missing Codex executable');
629
673
  }
@@ -634,18 +678,25 @@ This is a known issue with @google/gemini-cli@0.3.4 and older Node.js versions.`
634
678
 
635
679
  const workingDir = process.cwd();
636
680
 
637
- // Build args with model configuration if specified
638
- const modelArgs = model ? ['-c', `model="${model}"`] : [];
639
- const args = [
640
- ...commandArgs,
641
- ...modelArgs,
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(
642
693
  '--sandbox',
643
694
  'workspace-write',
644
695
  '--skip-git-repo-check',
645
696
  '--cd',
646
697
  workingDir,
647
698
  prompt
648
- ];
699
+ );
649
700
 
650
701
  return new Promise((resolve, reject) => {
651
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.0",
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",