polydev-ai 1.8.3 → 1.8.5
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 +168 -8
- package/package.json +2 -2
package/lib/cliManager.js
CHANGED
|
@@ -46,7 +46,7 @@ class CLIManager {
|
|
|
46
46
|
chat: [],
|
|
47
47
|
version: ['--version'],
|
|
48
48
|
auth_status: ['--print', 'test auth'], // Use --print to test auth
|
|
49
|
-
test_prompt: ['--print']
|
|
49
|
+
test_prompt: ['--print', '--output-format', 'json'] // Use JSON output to get model info
|
|
50
50
|
},
|
|
51
51
|
install_instructions: 'Install via: npm install -g @anthropic-ai/claude-code',
|
|
52
52
|
auth_instructions: 'Authenticate with Claude Code'
|
|
@@ -444,7 +444,18 @@ This is a known issue with @google/gemini-cli@0.3.4 and older Node.js versions.`
|
|
|
444
444
|
if (providerId === 'codex_cli') {
|
|
445
445
|
const execArgs = promptVariants.find(args => args.includes('exec')) || promptVariants[0];
|
|
446
446
|
try {
|
|
447
|
-
const
|
|
447
|
+
const result = await this.executeCodexExec(provider.command, execArgs, prompt, timeoutMs, model);
|
|
448
|
+
// executeCodexExec now returns { content, detectedModel, rawStdout, rawStderr }
|
|
449
|
+
const content = result.content;
|
|
450
|
+
const detectedModel = result.detectedModel;
|
|
451
|
+
|
|
452
|
+
// Use detected model if available, otherwise fall back to what was requested or 'cli_default'
|
|
453
|
+
const actualModel = detectedModel || model || 'cli_default';
|
|
454
|
+
|
|
455
|
+
if (detectedModel && detectedModel !== model) {
|
|
456
|
+
console.log(`[Polydev CLI] Codex CLI detected model: ${detectedModel} (requested: ${model || 'none'})`);
|
|
457
|
+
}
|
|
458
|
+
|
|
448
459
|
return {
|
|
449
460
|
success: true,
|
|
450
461
|
content,
|
|
@@ -452,7 +463,7 @@ This is a known issue with @google/gemini-cli@0.3.4 and older Node.js versions.`
|
|
|
452
463
|
latency_ms: Date.now() - startTime,
|
|
453
464
|
provider: providerId,
|
|
454
465
|
mode: 'args',
|
|
455
|
-
model_used:
|
|
466
|
+
model_used: actualModel,
|
|
456
467
|
timestamp: new Date()
|
|
457
468
|
};
|
|
458
469
|
} catch (error) {
|
|
@@ -499,7 +510,37 @@ This is a known issue with @google/gemini-cli@0.3.4 and older Node.js versions.`
|
|
|
499
510
|
);
|
|
500
511
|
|
|
501
512
|
if (!result.error) {
|
|
513
|
+
// Special handling for Claude Code JSON output
|
|
514
|
+
if (providerId === 'claude_code') {
|
|
515
|
+
const jsonResult = this.parseClaudeCodeJsonResponse(result.stdout || '');
|
|
516
|
+
if (jsonResult) {
|
|
517
|
+
console.log(`[Polydev CLI] Claude Code detected model: ${jsonResult.model_used} (from JSON output)`);
|
|
518
|
+
return {
|
|
519
|
+
success: true,
|
|
520
|
+
content: jsonResult.content,
|
|
521
|
+
tokens_used: jsonResult.tokens_used,
|
|
522
|
+
latency_ms: Date.now() - startTime,
|
|
523
|
+
provider: providerId,
|
|
524
|
+
mode: 'args',
|
|
525
|
+
model_used: jsonResult.model_used,
|
|
526
|
+
cost_usd: jsonResult.cost_usd,
|
|
527
|
+
model_usage: jsonResult.model_usage,
|
|
528
|
+
timestamp: new Date()
|
|
529
|
+
};
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
// Fallback: Standard text output handling
|
|
502
534
|
const content = this.cleanCliResponse(result.stdout || '');
|
|
535
|
+
|
|
536
|
+
// Detect actual model from CLI output
|
|
537
|
+
const detectedModel = this.detectModelFromOutput(providerId, result.stdout || '', result.stderr || '');
|
|
538
|
+
const actualModel = detectedModel || model || 'cli_default';
|
|
539
|
+
|
|
540
|
+
if (detectedModel && detectedModel !== model) {
|
|
541
|
+
console.log(`[Polydev CLI] ${providerId} detected model: ${detectedModel} (requested: ${model || 'none'})`);
|
|
542
|
+
}
|
|
543
|
+
|
|
503
544
|
return {
|
|
504
545
|
success: true,
|
|
505
546
|
content,
|
|
@@ -507,7 +548,7 @@ This is a known issue with @google/gemini-cli@0.3.4 and older Node.js versions.`
|
|
|
507
548
|
latency_ms: Date.now() - startTime,
|
|
508
549
|
provider: providerId,
|
|
509
550
|
mode: 'args',
|
|
510
|
-
model_used:
|
|
551
|
+
model_used: actualModel,
|
|
511
552
|
timestamp: new Date()
|
|
512
553
|
};
|
|
513
554
|
}
|
|
@@ -531,6 +572,15 @@ This is a known issue with @google/gemini-cli@0.3.4 and older Node.js versions.`
|
|
|
531
572
|
|
|
532
573
|
if (!fallbackResult.error) {
|
|
533
574
|
const content = this.cleanCliResponse(fallbackResult.stdout || '');
|
|
575
|
+
|
|
576
|
+
// Detect actual model from fallback output
|
|
577
|
+
const detectedModel = this.detectModelFromOutput(providerId, fallbackResult.stdout || '', fallbackResult.stderr || '');
|
|
578
|
+
const actualModel = detectedModel || 'cli_default_fallback';
|
|
579
|
+
|
|
580
|
+
if (detectedModel) {
|
|
581
|
+
console.log(`[Polydev CLI] ${providerId} fallback detected model: ${detectedModel}`);
|
|
582
|
+
}
|
|
583
|
+
|
|
534
584
|
return {
|
|
535
585
|
success: true,
|
|
536
586
|
content,
|
|
@@ -538,7 +588,7 @@ This is a known issue with @google/gemini-cli@0.3.4 and older Node.js versions.`
|
|
|
538
588
|
latency_ms: Date.now() - startTime,
|
|
539
589
|
provider: providerId,
|
|
540
590
|
mode: 'args',
|
|
541
|
-
model_used:
|
|
591
|
+
model_used: actualModel,
|
|
542
592
|
timestamp: new Date()
|
|
543
593
|
};
|
|
544
594
|
}
|
|
@@ -667,6 +717,113 @@ This is a known issue with @google/gemini-cli@0.3.4 and older Node.js versions.`
|
|
|
667
717
|
});
|
|
668
718
|
}
|
|
669
719
|
|
|
720
|
+
// Detect actual model from CLI output before parsing/cleaning
|
|
721
|
+
detectModelFromOutput(providerId, stdout, stderr) {
|
|
722
|
+
const combinedOutput = (stdout || '') + '\n' + (stderr || '');
|
|
723
|
+
|
|
724
|
+
// Different patterns for different CLI tools
|
|
725
|
+
switch (providerId) {
|
|
726
|
+
case 'claude_code': {
|
|
727
|
+
// Claude Code may output model info in various formats
|
|
728
|
+
// Look for patterns like "model: claude-sonnet-4-20250514" or "Using model: ..."
|
|
729
|
+
const claudeModelMatch = combinedOutput.match(/(?:model|using model)[:\s]+([a-zA-Z0-9_.-]+)/i);
|
|
730
|
+
if (claudeModelMatch && claudeModelMatch[1]) {
|
|
731
|
+
const model = claudeModelMatch[1].trim();
|
|
732
|
+
// Filter out invalid values
|
|
733
|
+
if (model && model !== 'undefined' && model !== 'null' && model.length > 2) {
|
|
734
|
+
return model;
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
break;
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
case 'codex_cli': {
|
|
741
|
+
// Codex CLI outputs configuration header like:
|
|
742
|
+
// model: gpt-4.1
|
|
743
|
+
// or: model: o4-mini
|
|
744
|
+
const codexModelMatch = combinedOutput.match(/^\s*model:\s*([a-zA-Z0-9_.-]+)/mi);
|
|
745
|
+
if (codexModelMatch && codexModelMatch[1]) {
|
|
746
|
+
const model = codexModelMatch[1].trim();
|
|
747
|
+
if (model && model !== 'undefined' && model !== 'null' && model.length > 2) {
|
|
748
|
+
return model;
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
break;
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
case 'gemini_cli': {
|
|
755
|
+
// Gemini CLI may output model info
|
|
756
|
+
// Look for patterns like "model: gemini-2.0-flash" or "Using gemini-..."
|
|
757
|
+
const geminiModelMatch = combinedOutput.match(/(?:model|using)[:\s]+(gemini[a-zA-Z0-9_.-]*)/i);
|
|
758
|
+
if (geminiModelMatch && geminiModelMatch[1]) {
|
|
759
|
+
const model = geminiModelMatch[1].trim();
|
|
760
|
+
if (model && model.length > 2) {
|
|
761
|
+
return model;
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
break;
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
return null; // Could not detect model from output
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
// Parse Claude Code JSON response to extract model and content
|
|
772
|
+
parseClaudeCodeJsonResponse(stdout) {
|
|
773
|
+
if (!stdout || !stdout.trim()) return null;
|
|
774
|
+
|
|
775
|
+
try {
|
|
776
|
+
// Try to parse as JSON
|
|
777
|
+
const json = JSON.parse(stdout.trim());
|
|
778
|
+
|
|
779
|
+
// Check if it's a valid Claude Code response
|
|
780
|
+
if (json.type !== 'result' || !json.result) {
|
|
781
|
+
return null;
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
// Extract content
|
|
785
|
+
const content = json.result;
|
|
786
|
+
|
|
787
|
+
// Extract primary model from modelUsage
|
|
788
|
+
// Priority: Opus > Sonnet > Haiku (prefer larger models as they do the main reasoning)
|
|
789
|
+
let primaryModel = 'cli_default';
|
|
790
|
+
const modelUsage = json.modelUsage || {};
|
|
791
|
+
const modelNames = Object.keys(modelUsage);
|
|
792
|
+
|
|
793
|
+
if (modelNames.length === 1) {
|
|
794
|
+
// Only one model used
|
|
795
|
+
primaryModel = modelNames[0];
|
|
796
|
+
} else if (modelNames.length > 1) {
|
|
797
|
+
// Multiple models - prefer Opus > Sonnet > Haiku
|
|
798
|
+
const opusModel = modelNames.find(m => m.includes('opus'));
|
|
799
|
+
const sonnetModel = modelNames.find(m => m.includes('sonnet'));
|
|
800
|
+
const haikuModel = modelNames.find(m => m.includes('haiku'));
|
|
801
|
+
|
|
802
|
+
primaryModel = opusModel || sonnetModel || haikuModel || modelNames[0];
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
// Calculate total tokens
|
|
806
|
+
let totalTokens = 0;
|
|
807
|
+
for (const usage of Object.values(modelUsage)) {
|
|
808
|
+
totalTokens += (usage.inputTokens || 0) + (usage.outputTokens || 0) +
|
|
809
|
+
(usage.cacheReadInputTokens || 0) + (usage.cacheCreationInputTokens || 0);
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
return {
|
|
813
|
+
content,
|
|
814
|
+
model_used: primaryModel,
|
|
815
|
+
tokens_used: totalTokens || json.usage?.input_tokens + json.usage?.output_tokens || 0,
|
|
816
|
+
cost_usd: json.total_cost_usd || 0,
|
|
817
|
+
model_usage: modelUsage,
|
|
818
|
+
session_id: json.session_id,
|
|
819
|
+
duration_ms: json.duration_ms
|
|
820
|
+
};
|
|
821
|
+
} catch (e) {
|
|
822
|
+
// Not valid JSON, return null to fall back to text parsing
|
|
823
|
+
return null;
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
|
|
670
827
|
async executeCodexExec(executable, commandArgs, prompt, timeoutMs, model = null) {
|
|
671
828
|
if (!executable) {
|
|
672
829
|
throw new Error('Missing Codex executable');
|
|
@@ -849,18 +1006,21 @@ This is a known issue with @google/gemini-cli@0.3.4 and older Node.js versions.`
|
|
|
849
1006
|
// Combine stdout and stderr for parsing - Codex may output to either
|
|
850
1007
|
const combinedOutput = trimmedStdout + '\n' + trimmedStderr;
|
|
851
1008
|
|
|
1009
|
+
// Detect the actual model used BEFORE parsing (model info is in the header)
|
|
1010
|
+
const detectedModel = this.detectModelFromOutput('codex_cli', trimmedStdout, trimmedStderr);
|
|
1011
|
+
|
|
852
1012
|
// Always try to parse stdout first, regardless of exit code
|
|
853
1013
|
// MCP handshake failures cause non-zero exit but don't prevent valid responses
|
|
854
1014
|
const parsedStdout = parseCodexOutput(trimmedStdout);
|
|
855
1015
|
if (parsedStdout) {
|
|
856
|
-
resolve(parsedStdout);
|
|
1016
|
+
resolve({ content: parsedStdout, detectedModel, rawStdout: trimmedStdout, rawStderr: trimmedStderr });
|
|
857
1017
|
return;
|
|
858
1018
|
}
|
|
859
1019
|
|
|
860
1020
|
// Try parsing combined output (some responses may appear in stderr)
|
|
861
1021
|
const parsedCombined = parseCodexOutput(combinedOutput);
|
|
862
1022
|
if (parsedCombined) {
|
|
863
|
-
resolve(parsedCombined);
|
|
1023
|
+
resolve({ content: parsedCombined, detectedModel, rawStdout: trimmedStdout, rawStderr: trimmedStderr });
|
|
864
1024
|
return;
|
|
865
1025
|
}
|
|
866
1026
|
|
|
@@ -868,7 +1028,7 @@ This is a known issue with @google/gemini-cli@0.3.4 and older Node.js versions.`
|
|
|
868
1028
|
if (code === 0) {
|
|
869
1029
|
// Successful exit but no parseable output
|
|
870
1030
|
if (trimmedStdout) {
|
|
871
|
-
resolve(trimmedStdout); // Return raw output as fallback
|
|
1031
|
+
resolve({ content: trimmedStdout, detectedModel, rawStdout: trimmedStdout, rawStderr: trimmedStderr }); // Return raw output as fallback
|
|
872
1032
|
} else {
|
|
873
1033
|
reject(new Error('Codex completed but produced no output'));
|
|
874
1034
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "polydev-ai",
|
|
3
|
-
"version": "1.8.
|
|
3
|
+
"version": "1.8.5",
|
|
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",
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"lucide-react": "^0.542.0",
|
|
68
68
|
"marked": "^16.2.1",
|
|
69
69
|
"next": "^15.5.7",
|
|
70
|
-
"polydev-ai": "
|
|
70
|
+
"polydev-ai": "^1.8.4",
|
|
71
71
|
"posthog-js": "^1.157.2",
|
|
72
72
|
"prismjs": "^1.30.0",
|
|
73
73
|
"react": "^18.3.1",
|