polydev-ai 1.4.2 → 1.4.4

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/package.json +1 -1
  2. package/stdio-wrapper.js +81 -13
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "polydev-ai",
3
- "version": "1.4.2",
3
+ "version": "1.4.4",
4
4
  "description": "Get diverse AI perspectives from multiple LLMs via MCP - supports Cline, Claude Code, and other MCP clients",
5
5
  "main": "stdio-wrapper.js",
6
6
  "bin": {
package/stdio-wrapper.js CHANGED
@@ -6,6 +6,69 @@ const path = require('path');
6
6
  const os = require('os');
7
7
  const { CLIManager } = require('./cliManager');
8
8
 
9
+ // Simple .env file loader (no external dependencies)
10
+ function loadEnvFile(filePath) {
11
+ try {
12
+ if (!fs.existsSync(filePath)) return false;
13
+
14
+ const content = fs.readFileSync(filePath, 'utf8');
15
+ const lines = content.split('\n');
16
+ let loaded = 0;
17
+
18
+ for (const line of lines) {
19
+ const trimmed = line.trim();
20
+ // Skip comments and empty lines
21
+ if (!trimmed || trimmed.startsWith('#')) continue;
22
+
23
+ const eqIndex = trimmed.indexOf('=');
24
+ if (eqIndex === -1) continue;
25
+
26
+ const key = trimmed.substring(0, eqIndex).trim();
27
+ let value = trimmed.substring(eqIndex + 1).trim();
28
+
29
+ // Remove surrounding quotes if present
30
+ if ((value.startsWith('"') && value.endsWith('"')) ||
31
+ (value.startsWith("'") && value.endsWith("'"))) {
32
+ value = value.slice(1, -1);
33
+ }
34
+
35
+ // Only set if not already defined (don't override existing env vars)
36
+ if (!process.env[key]) {
37
+ process.env[key] = value;
38
+ loaded++;
39
+ }
40
+ }
41
+
42
+ return loaded > 0;
43
+ } catch (error) {
44
+ return false;
45
+ }
46
+ }
47
+
48
+ // Load .env files from multiple locations (in priority order)
49
+ function loadEnvironment() {
50
+ const envPaths = [
51
+ path.join(process.cwd(), '.env'), // Current working directory
52
+ path.join(process.cwd(), '.env.local'), // Local overrides
53
+ path.join(os.homedir(), '.polydev.env'), // User home directory
54
+ path.join(os.homedir(), '.env'), // Home directory fallback
55
+ ];
56
+
57
+ const loaded = [];
58
+ for (const envPath of envPaths) {
59
+ if (loadEnvFile(envPath)) {
60
+ loaded.push(envPath);
61
+ }
62
+ }
63
+
64
+ if (loaded.length > 0) {
65
+ console.error(`[Stdio Wrapper] Loaded env from: ${loaded.join(', ')}`);
66
+ }
67
+ }
68
+
69
+ // Load environment variables FIRST, before any checks
70
+ loadEnvironment();
71
+
9
72
  function ensureWritableTmpDir() {
10
73
  const candidates = [
11
74
  process.env.POLYDEV_TMPDIR,
@@ -535,6 +598,9 @@ class StdioMCPWrapper {
535
598
  * Combine multiple CLI results and remote perspectives
536
599
  */
537
600
  combineAllCliAndPerspectives(localResults, perspectivesResult, args) {
601
+ // Ensure perspectivesResult is always an object to prevent undefined errors
602
+ const safePersp = perspectivesResult || { success: false, error: 'No response from perspectives server' };
603
+
538
604
  const combinedResult = {
539
605
  success: true,
540
606
  timestamp: new Date().toISOString(),
@@ -542,7 +608,7 @@ class StdioMCPWrapper {
542
608
  local_cli_count: localResults.length,
543
609
  sections: {
544
610
  local: localResults,
545
- remote: perspectivesResult
611
+ remote: safePersp
546
612
  }
547
613
  };
548
614
 
@@ -551,25 +617,25 @@ class StdioMCPWrapper {
551
617
  const hasSomeLocalSuccess = successfulClis.length > 0;
552
618
 
553
619
  // Determine overall success and content
554
- if (hasSomeLocalSuccess && perspectivesResult.success) {
555
- combinedResult.content = this.formatMultipleCliResponse(localResults, perspectivesResult, false);
620
+ if (hasSomeLocalSuccess && safePersp.success) {
621
+ combinedResult.content = this.formatMultipleCliResponse(localResults, safePersp, false);
556
622
  combinedResult.tokens_used = successfulClis.reduce((total, cli) => total + (cli.tokens_used || 0), 0);
557
623
  combinedResult.latency_ms = Math.max(...successfulClis.map(cli => cli.latency_ms || 0));
558
- } else if (!hasSomeLocalSuccess && perspectivesResult.success) {
624
+ } else if (!hasSomeLocalSuccess && safePersp.success) {
559
625
  // Complete fallback case - no local CLIs worked
560
- combinedResult.content = this.formatMultipleCliResponse(localResults, perspectivesResult, true);
626
+ combinedResult.content = this.formatMultipleCliResponse(localResults, safePersp, true);
561
627
  combinedResult.fallback_used = true;
562
628
  combinedResult.tokens_used = 0; // No local tokens used
563
- } else if (hasSomeLocalSuccess && !perspectivesResult.success) {
629
+ } else if (hasSomeLocalSuccess && !safePersp.success) {
564
630
  // Local CLIs succeeded, remote failed
565
- combinedResult.content = this.formatMultipleCliResponse(localResults, perspectivesResult, false);
631
+ combinedResult.content = this.formatMultipleCliResponse(localResults, safePersp, false);
566
632
  combinedResult.tokens_used = successfulClis.reduce((total, cli) => total + (cli.tokens_used || 0), 0);
567
633
  combinedResult.latency_ms = Math.max(...successfulClis.map(cli => cli.latency_ms || 0));
568
634
  } else {
569
635
  // Both failed
570
636
  combinedResult.success = false;
571
637
  const cliErrors = localResults.map(cli => `${cli.provider_id}: ${cli.error || 'Unknown error'}`).join('; ');
572
- const perspectivesError = perspectivesResult?.error || 'Unknown remote error';
638
+ const perspectivesError = safePersp.error || 'Unknown remote error';
573
639
  combinedResult.error = `All local CLIs failed: ${cliErrors}; Perspectives also failed: ${perspectivesError}`;
574
640
  }
575
641
 
@@ -580,6 +646,8 @@ class StdioMCPWrapper {
580
646
  * Format multiple CLI responses with remote perspectives
581
647
  */
582
648
  formatMultipleCliResponse(localResults, perspectivesResult, isFallback) {
649
+ // Safety check - ensure perspectivesResult is always an object
650
+ const safePersp = perspectivesResult || { success: false, error: 'No perspectives data' };
583
651
  let formatted = '';
584
652
 
585
653
  // Show all local CLI responses
@@ -614,19 +682,19 @@ class StdioMCPWrapper {
614
682
  }
615
683
 
616
684
  // Add remote perspectives
617
- if (perspectivesResult.success) {
618
- if (perspectivesResult.raw) {
685
+ if (safePersp.success) {
686
+ if (safePersp.raw) {
619
687
  // Raw content is already formatted - use as-is
620
- formatted += `${perspectivesResult.content}\n\n`;
688
+ formatted += `${safePersp.content}\n\n`;
621
689
  } else {
622
690
  // Legacy formatting
623
691
  const title = (successfulClis.length === 0) ? '🧠 **Perspectives Fallback**' : '🧠 **Supplemental Multi-Model Perspectives**';
624
692
  formatted += `${title}\n\n`;
625
- formatted += `${perspectivesResult.content}\n\n`;
693
+ formatted += `${safePersp.content}\n\n`;
626
694
  }
627
695
  } else if (successfulClis.length > 0) {
628
696
  // Show remote error only if we have local success
629
- formatted += `❌ **Perspectives request failed**: ${perspectivesResult.error}\n\n`;
697
+ formatted += `❌ **Perspectives request failed**: ${safePersp.error || 'Unknown error'}\n\n`;
630
698
  }
631
699
 
632
700
  return formatted.trim();