polydev-ai 1.2.12 → 1.2.14

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 CHANGED
@@ -100,7 +100,7 @@ class CLIManager {
100
100
  * Updates status cache and reports to MCP server via Supabase
101
101
  */
102
102
  async forceCliDetection(userId, providerId) {
103
- console.log(`[CLI Manager] Force detection started for ${providerId || 'all providers'}`);
103
+ console.error(`[CLI Manager] Force detection started for ${providerId || 'all providers'}`);
104
104
  const results = {};
105
105
  const providersToCheck = providerId ? [providerId] : Array.from(this.providers.keys());
106
106
  for (const id of providersToCheck) {
@@ -115,7 +115,7 @@ class CLIManager {
115
115
  if (userId) {
116
116
  await this.updateCliStatusInDatabase(userId, id, status);
117
117
  }
118
- console.log(`[CLI Manager] ${provider.name}: ${status.available ? 'Available' : 'Not Available'}`);
118
+ console.error(`[CLI Manager] ${provider.name}: ${status.available ? 'Available' : 'Not Available'}`);
119
119
  }
120
120
  catch (error) {
121
121
  console.error(`[CLI Manager] Error detecting ${provider.name}:`, error);
@@ -363,7 +363,7 @@ class CLIManager {
363
363
  throw new Error(`Failed to update CLI status: ${response.status}`);
364
364
  }
365
365
  const result = await response.json();
366
- console.log(`[CLI Manager] Updated database via MCP Supabase for ${providerId}: ${status.available}`);
366
+ console.error(`[CLI Manager] Updated database via MCP Supabase for ${providerId}: ${status.available}`);
367
367
  }
368
368
  catch (error) {
369
369
  console.error(`[CLI Manager] Failed to update database via MCP Supabase:`, error);
@@ -81,7 +81,7 @@ class ZeroKnowledgeEncryption {
81
81
  const keyData = cursor.value;
82
82
  // Check if key needs rotation
83
83
  if (new Date() > new Date(keyData.rotationDue)) {
84
- console.log('[ZK Encryption] Key rotation needed, generating new key');
84
+ console.error('[ZK Encryption] Key rotation needed, generating new key');
85
85
  await this.createAndStoreKey();
86
86
  }
87
87
  else {
@@ -214,7 +214,7 @@ class ZeroKnowledgeEncryption {
214
214
  */
215
215
  async rotateKeys() {
216
216
  await this.createAndStoreKey();
217
- console.log('[ZK Encryption] Key rotation completed');
217
+ console.error('[ZK Encryption] Key rotation completed');
218
218
  }
219
219
  /**
220
220
  * Generate unique key ID
@@ -274,7 +274,7 @@ class ZeroKnowledgeEncryption {
274
274
  await transaction.objectStore('keys').clear();
275
275
  await transaction.objectStore('cache').clear();
276
276
  this.activeKey = null;
277
- console.log('[ZK Encryption] All keys cleared');
277
+ console.error('[ZK Encryption] All keys cleared');
278
278
  }
279
279
  }
280
280
  exports.ZeroKnowledgeEncryption = ZeroKnowledgeEncryption;
package/mcp/manifest.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "polydev-perspectives",
3
- "version": "1.2.0",
3
+ "version": "1.2.14",
4
4
  "description": "Agentic workflow assistant - get diverse perspectives from multiple LLMs when stuck or need enhanced reasoning",
5
5
  "author": "Polydev AI",
6
6
  "license": "MIT",
@@ -0,0 +1,169 @@
1
+ #!/usr/bin/env node
2
+
3
+ // MINIMAL MCP stdio wrapper - NO stdout pollution, JSON only
4
+ const fs = require('fs');
5
+ const path = require('path');
6
+
7
+ class MinimalStdioWrapper {
8
+ constructor() {
9
+ this.userToken = process.env.POLYDEV_USER_TOKEN;
10
+
11
+ // Load manifest
12
+ try {
13
+ const manifestPath = path.join(__dirname, 'manifest.json');
14
+ this.manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
15
+ } catch (error) {
16
+ // Use stderr for errors
17
+ console.error('Failed to load manifest:', error);
18
+ process.exit(1);
19
+ }
20
+ }
21
+
22
+ async handleRequest(request) {
23
+ const { method, params, id } = request;
24
+
25
+ try {
26
+ switch (method) {
27
+ case 'initialize':
28
+ return {
29
+ jsonrpc: '2.0',
30
+ id,
31
+ result: {
32
+ protocolVersion: '2024-11-05',
33
+ capabilities: { tools: {} },
34
+ serverInfo: {
35
+ name: 'polydev-ai',
36
+ version: '1.2.13'
37
+ }
38
+ }
39
+ };
40
+
41
+ case 'tools/list':
42
+ const tools = this.manifest.tools.map(tool => ({
43
+ name: tool.name,
44
+ description: tool.description,
45
+ inputSchema: tool.inputSchema
46
+ }));
47
+
48
+ return {
49
+ jsonrpc: '2.0',
50
+ id,
51
+ result: { tools }
52
+ };
53
+
54
+ case 'tools/call':
55
+ // Check token
56
+ if (!this.userToken) {
57
+ return {
58
+ jsonrpc: '2.0',
59
+ id,
60
+ error: {
61
+ code: -32603,
62
+ message: 'POLYDEV_USER_TOKEN environment variable is required'
63
+ }
64
+ };
65
+ }
66
+
67
+ // Forward to remote server
68
+ const response = await fetch('https://www.polydev.ai/api/mcp', {
69
+ method: 'POST',
70
+ headers: {
71
+ 'Content-Type': 'application/json',
72
+ 'Authorization': `Bearer ${this.userToken}`
73
+ },
74
+ body: JSON.stringify(request)
75
+ });
76
+
77
+ if (!response.ok) {
78
+ const errorText = await response.text();
79
+ return {
80
+ jsonrpc: '2.0',
81
+ id: request.id,
82
+ error: {
83
+ code: -32603,
84
+ message: `Remote server error: ${response.status}`
85
+ }
86
+ };
87
+ }
88
+
89
+ return await response.json();
90
+
91
+ default:
92
+ return {
93
+ jsonrpc: '2.0',
94
+ id,
95
+ error: {
96
+ code: -32601,
97
+ message: 'Method not found'
98
+ }
99
+ };
100
+ }
101
+ } catch (error) {
102
+ return {
103
+ jsonrpc: '2.0',
104
+ id,
105
+ error: {
106
+ code: -32603,
107
+ message: error.message
108
+ }
109
+ };
110
+ }
111
+ }
112
+
113
+ async start() {
114
+ // NO console.log to stdout!
115
+ // Use stderr for debug messages if needed
116
+ console.error('[MCP] Starting...');
117
+
118
+ process.stdin.setEncoding('utf8');
119
+ let buffer = '';
120
+
121
+ process.stdin.on('data', async (chunk) => {
122
+ buffer += chunk;
123
+
124
+ const lines = buffer.split('\n');
125
+ buffer = lines.pop() || '';
126
+
127
+ for (const line of lines) {
128
+ if (line.trim()) {
129
+ try {
130
+ const request = JSON.parse(line);
131
+ const response = await this.handleRequest(request);
132
+ // ONLY output JSON to stdout
133
+ process.stdout.write(JSON.stringify(response) + '\n');
134
+ } catch (error) {
135
+ console.error('Failed to process request:', error);
136
+ }
137
+ }
138
+ }
139
+ });
140
+
141
+ process.stdin.on('end', () => {
142
+ console.error('[MCP] Shutting down...');
143
+ process.exit(0);
144
+ });
145
+
146
+ process.on('SIGINT', () => {
147
+ console.error('[MCP] SIGINT received');
148
+ process.exit(0);
149
+ });
150
+
151
+ process.on('SIGTERM', () => {
152
+ console.error('[MCP] SIGTERM received');
153
+ process.exit(0);
154
+ });
155
+
156
+ console.error('[MCP] Ready');
157
+ }
158
+ }
159
+
160
+ // Start the server
161
+ if (require.main === module) {
162
+ const wrapper = new MinimalStdioWrapper();
163
+ wrapper.start().catch(error => {
164
+ console.error('Failed to start:', error);
165
+ process.exit(1);
166
+ });
167
+ }
168
+
169
+ module.exports = MinimalStdioWrapper;
@@ -20,6 +20,10 @@ class StdioMCPWrapper {
20
20
 
21
21
  // Smart refresh scheduler (will be started after initialization)
22
22
  this.refreshScheduler = null;
23
+
24
+ // Track if initial CLI detection has been done
25
+ this.initialDetectionDone = false;
26
+ this.initialDetectionPromise = null;
23
27
  }
24
28
 
25
29
  loadManifest() {
@@ -226,6 +230,10 @@ class StdioMCPWrapper {
226
230
  // Update database with CLI status
227
231
  await this.updateCliStatusInDatabase(results);
228
232
 
233
+ // Mark initial detection as done
234
+ this.initialDetectionDone = true;
235
+ this.initialDetectionPromise = null;
236
+
229
237
  return {
230
238
  success: true,
231
239
  results,
@@ -236,6 +244,10 @@ class StdioMCPWrapper {
236
244
 
237
245
  } catch (error) {
238
246
  console.error('[Stdio Wrapper] Local CLI detection error:', error);
247
+ // Mark as done even on error to prevent blocking
248
+ this.initialDetectionDone = true;
249
+ this.initialDetectionPromise = null;
250
+
239
251
  return {
240
252
  success: false,
241
253
  error: error.message,
@@ -297,6 +309,16 @@ class StdioMCPWrapper {
297
309
  console.error(`[Stdio Wrapper] Local CLI prompt sending with perspectives`);
298
310
 
299
311
  try {
312
+ // Ensure initial CLI detection has completed before sending prompts
313
+ if (!this.initialDetectionDone && this.initialDetectionPromise) {
314
+ console.error('[Stdio Wrapper] Waiting for initial CLI detection to complete...');
315
+ await this.initialDetectionPromise;
316
+ } else if (!this.initialDetectionDone && !this.initialDetectionPromise) {
317
+ console.error('[Stdio Wrapper] Running initial CLI detection before sending prompt...');
318
+ this.initialDetectionPromise = this.localForceCliDetection({});
319
+ await this.initialDetectionPromise;
320
+ }
321
+
300
322
  let { provider_id, prompt, mode = 'args', timeout_ms = 30000 } = args;
301
323
 
302
324
  // Ensure timeout_ms is valid (not undefined, null, Infinity, or negative)
@@ -380,7 +402,18 @@ class StdioMCPWrapper {
380
402
  */
381
403
  async getAllAvailableProviders() {
382
404
  try {
383
- const results = await this.cliManager.forceCliDetection();
405
+ // Try to load from cache first to avoid re-detection
406
+ const cachedStatus = await this.loadLocalCliStatus();
407
+ let results;
408
+
409
+ if (cachedStatus && Object.keys(cachedStatus).length > 0) {
410
+ console.error('[Stdio Wrapper] Using cached CLI status');
411
+ results = cachedStatus;
412
+ } else {
413
+ console.error('[Stdio Wrapper] No cached status, running detection');
414
+ results = await this.cliManager.forceCliDetection();
415
+ }
416
+
384
417
  const availableProviders = [];
385
418
 
386
419
  // Priority order: claude_code > codex_cli > gemini_cli
@@ -863,22 +896,6 @@ class StdioMCPWrapper {
863
896
  async start() {
864
897
  console.error('[Stdio Wrapper] Starting Polydev Stdio MCP Wrapper...');
865
898
 
866
- // Only run initial CLI detection if we have a token
867
- if (this.userToken && this.cliManager) {
868
- console.error('[Stdio Wrapper] Running initial CLI detection...');
869
- try {
870
- await this.localForceCliDetection({});
871
- console.error('[Stdio Wrapper] Initial CLI detection completed');
872
- } catch (error) {
873
- console.error('[Stdio Wrapper] Initial CLI detection failed:', error);
874
- }
875
-
876
- // Start smart refresh scheduler for automatic updates
877
- this.startSmartRefreshScheduler();
878
- } else {
879
- console.error('[Stdio Wrapper] No token provided - CLI detection disabled');
880
- }
881
-
882
899
  process.stdin.setEncoding('utf8');
883
900
  let buffer = '';
884
901
 
@@ -921,6 +938,27 @@ class StdioMCPWrapper {
921
938
  });
922
939
 
923
940
  console.error('[Stdio Wrapper] Ready and listening on stdin...');
941
+
942
+ // Run initial CLI detection AFTER stdin handler is set up
943
+ if (this.userToken && this.cliManager) {
944
+ console.error('[Stdio Wrapper] Scheduling initial CLI detection...');
945
+ // Run asynchronously after a short delay to not block initialization
946
+ setTimeout(async () => {
947
+ console.error('[Stdio Wrapper] Running initial CLI detection...');
948
+ try {
949
+ this.initialDetectionPromise = this.localForceCliDetection({});
950
+ await this.initialDetectionPromise;
951
+ console.error('[Stdio Wrapper] Initial CLI detection completed');
952
+ } catch (error) {
953
+ console.error('[Stdio Wrapper] Initial CLI detection failed:', error);
954
+ }
955
+
956
+ // Start smart refresh scheduler for automatic updates
957
+ this.startSmartRefreshScheduler();
958
+ }, 100);
959
+ } else {
960
+ console.error('[Stdio Wrapper] No token provided - CLI detection disabled');
961
+ }
924
962
  }
925
963
  }
926
964
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "polydev-ai",
3
- "version": "1.2.12",
3
+ "version": "1.2.14",
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",