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 +76 -7
- package/mcp/stdio-wrapper.js +106 -2
- package/package.json +1 -1
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
|
-
|
|
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
|
-
|
|
623
|
-
|
|
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();
|
package/mcp/stdio-wrapper.js
CHANGED
|
@@ -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
|
|
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
|
|
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