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.
Files changed (2) hide show
  1. package/lib/cliManager.js +168 -8
  2. 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 content = await this.executeCodexExec(provider.command, execArgs, prompt, timeoutMs, model);
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: model || 'cli_default',
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: model || 'cli_default',
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: 'cli_default_fallback',
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",
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": "latest",
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",