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.
- package/package.json +1 -1
- package/stdio-wrapper.js +81 -13
package/package.json
CHANGED
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:
|
|
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 &&
|
|
555
|
-
combinedResult.content = this.formatMultipleCliResponse(localResults,
|
|
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 &&
|
|
624
|
+
} else if (!hasSomeLocalSuccess && safePersp.success) {
|
|
559
625
|
// Complete fallback case - no local CLIs worked
|
|
560
|
-
combinedResult.content = this.formatMultipleCliResponse(localResults,
|
|
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 && !
|
|
629
|
+
} else if (hasSomeLocalSuccess && !safePersp.success) {
|
|
564
630
|
// Local CLIs succeeded, remote failed
|
|
565
|
-
combinedResult.content = this.formatMultipleCliResponse(localResults,
|
|
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 =
|
|
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 (
|
|
618
|
-
if (
|
|
685
|
+
if (safePersp.success) {
|
|
686
|
+
if (safePersp.raw) {
|
|
619
687
|
// Raw content is already formatted - use as-is
|
|
620
|
-
formatted += `${
|
|
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 += `${
|
|
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**: ${
|
|
697
|
+
formatted += `❌ **Perspectives request failed**: ${safePersp.error || 'Unknown error'}\n\n`;
|
|
630
698
|
}
|
|
631
699
|
|
|
632
700
|
return formatted.trim();
|