polydev-ai 1.5.2 → 1.5.3

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 +101 -32
  2. package/package.json +1 -1
package/lib/cliManager.js CHANGED
@@ -675,27 +675,73 @@ This is a known issue with @google/gemini-cli@0.3.4 and older Node.js versions.`
675
675
  const parseCodexOutput = (output) => {
676
676
  if (!output || !output.trim()) return null;
677
677
 
678
+ // First, try to extract the response between "codex" marker and "tokens used"
679
+ // This is the most reliable pattern for Codex CLI output
680
+ const codexMarkerMatch = output.match(/\bcodex\s*\n([\s\S]*?)(?:\n\s*tokens used|\n\s*$)/i);
681
+ if (codexMarkerMatch && codexMarkerMatch[1]) {
682
+ const extracted = codexMarkerMatch[1].trim();
683
+ if (extracted.length > 0 && !extracted.startsWith('ERROR')) {
684
+ return extracted;
685
+ }
686
+ }
687
+
688
+ // Fallback: Try to find bullet point responses
689
+ const bulletMatches = output.match(/•\s*(.+)/g);
690
+ if (bulletMatches && bulletMatches.length > 0) {
691
+ const bulletContent = bulletMatches
692
+ .map(m => m.replace(/^•\s*/, '').trim())
693
+ .filter(s => s.length > 0)
694
+ .join('\n');
695
+ if (bulletContent.length > 0) {
696
+ return bulletContent;
697
+ }
698
+ }
699
+
700
+ // Last resort: Filter out known noise patterns line by line
678
701
  const lines = output.split('\n');
679
702
  const contentLines = [];
680
703
 
681
- // Filter out MCP protocol noise and collect actual content
704
+ // Patterns to skip (Codex-specific noise)
705
+ const noisePatterns = [
706
+ /^\s*$/, // Empty lines
707
+ /^\d{4}-\d{2}-\d{2}T[\d:]+.*?(ERROR|WARN|INFO)/i, // Timestamp logs
708
+ /^OpenAI Codex v[\d.]+/i, // Version banner
709
+ /^-{4,}$/, // Separator lines
710
+ /^workdir:/i, // Header fields
711
+ /^model:/i,
712
+ /^provider:/i,
713
+ /^approval:/i,
714
+ /^sandbox:/i,
715
+ /^reasoning effort:/i,
716
+ /^reasoning summaries:/i,
717
+ /^session id:/i,
718
+ /^user$/i, // "user" marker
719
+ /^thinking$/i, // "thinking" marker
720
+ /^codex$/i, // "codex" marker
721
+ /^tokens used$/i, // Token count header
722
+ /^[\d,]+$/, // Just numbers (token counts)
723
+ /^ERROR:\s*MCP/i, // MCP errors
724
+ /MCP client for .* failed/i, // MCP client failures
725
+ /handshake.*failed/i, // Handshake errors
726
+ /connection closed/i, // Connection errors
727
+ /\[MCP\]/i, // MCP tags
728
+ /^MCP\s/i, // MCP prefix
729
+ /rmcp::transport/i, // Rust MCP transport errors
730
+ /serde error/i, // Serde parsing errors
731
+ /^\*\*.*\*\*$/, // Bold status messages like **Awaiting next steps**
732
+ ];
733
+
682
734
  for (const line of lines) {
683
735
  const trimmedLine = line.trim();
684
- // Skip empty lines and MCP/protocol noise
685
- if (!trimmedLine) continue;
686
- if (trimmedLine.startsWith('MCP ')) continue;
687
- if (trimmedLine.includes('handshake') && trimmedLine.includes('error')) continue;
688
- if (trimmedLine.startsWith('[MCP]')) continue;
689
- if (trimmedLine.startsWith('Error:') && trimmedLine.includes('MCP')) continue;
690
736
 
691
- // Extract bullet content if present, otherwise keep the line
692
- const bulletMatch = trimmedLine.match(/^•\s*(.+)/);
693
- if (bulletMatch) {
694
- contentLines.push(bulletMatch[1].trim());
695
- } else if (!trimmedLine.startsWith('•')) {
696
- // Keep non-bullet content that isn't just whitespace
697
- contentLines.push(trimmedLine);
698
- }
737
+ // Check if line matches any noise pattern
738
+ const isNoise = noisePatterns.some(pattern => pattern.test(trimmedLine));
739
+ if (isNoise) continue;
740
+
741
+ // Skip if line looks like the echoed user prompt (heuristic: contains "?" and is long)
742
+ if (trimmedLine.includes('?') && trimmedLine.length > 20) continue;
743
+
744
+ contentLines.push(trimmedLine);
699
745
  }
700
746
 
701
747
  const result = contentLines.join('\n').trim();
@@ -730,26 +776,49 @@ This is a known issue with @google/gemini-cli@0.3.4 and older Node.js versions.`
730
776
 
731
777
  const trimmedStdout = stdout.trim();
732
778
  const trimmedStderr = stderr.trim();
779
+
780
+ // Combine stdout and stderr for parsing - Codex may output to either
781
+ const combinedOutput = trimmedStdout + '\n' + trimmedStderr;
782
+
783
+ // Always try to parse stdout first, regardless of exit code
784
+ // MCP handshake failures cause non-zero exit but don't prevent valid responses
785
+ const parsedStdout = parseCodexOutput(trimmedStdout);
786
+ if (parsedStdout) {
787
+ resolve(parsedStdout);
788
+ return;
789
+ }
790
+
791
+ // Try parsing combined output (some responses may appear in stderr)
792
+ const parsedCombined = parseCodexOutput(combinedOutput);
793
+ if (parsedCombined) {
794
+ resolve(parsedCombined);
795
+ return;
796
+ }
733
797
 
734
- if (code === 0 && trimmedStdout) {
735
- // Use the robust parser for consistent output handling
736
- const parsed = parseCodexOutput(trimmedStdout);
737
- if (parsed) {
738
- resolve(parsed);
739
- return;
740
- }
741
- // Fallback to raw output if parsing yields nothing
742
- resolve(trimmedStdout);
743
- } else if (code === 0) {
744
- // Code 0 but no stdout - check if stderr has useful info
745
- const parsedStderr = parseCodexOutput(trimmedStderr);
746
- if (parsedStderr) {
747
- resolve(parsedStderr);
748
- return;
798
+ // Only now consider it a failure
799
+ if (code === 0) {
800
+ // Successful exit but no parseable output
801
+ if (trimmedStdout) {
802
+ resolve(trimmedStdout); // Return raw output as fallback
803
+ } else {
804
+ reject(new Error('Codex completed but produced no output'));
749
805
  }
750
- reject(new Error('Codex completed but produced no output'));
751
806
  } else {
752
- reject(new Error(trimmedStderr || trimmedStdout || `Codex exited with code ${code}`));
807
+ // Non-zero exit and no parseable response - this is a real error
808
+ // Filter error message to remove MCP noise
809
+ const errorLines = (trimmedStderr || trimmedStdout).split('\n')
810
+ .filter(line => {
811
+ const l = line.trim().toLowerCase();
812
+ return l.length > 0 &&
813
+ !l.includes('mcp') &&
814
+ !l.includes('handshake') &&
815
+ !l.includes('rmcp::') &&
816
+ !l.includes('serde error');
817
+ })
818
+ .slice(0, 3); // Only first 3 relevant error lines
819
+
820
+ const cleanError = errorLines.join('; ') || `Codex exited with code ${code}`;
821
+ reject(new Error(cleanError));
753
822
  }
754
823
  });
755
824
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "polydev-ai",
3
- "version": "1.5.2",
3
+ "version": "1.5.3",
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",