polydev-ai 1.0.1 → 1.2.0
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/mcp/manifest.json +1 -1
- package/mcp/stdio-wrapper.js +32 -182
- package/package.json +1 -2
package/mcp/manifest.json
CHANGED
package/mcp/stdio-wrapper.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// Lightweight stdio wrapper with local CLI functionality and remote Polydev MCP server fallback
|
|
4
4
|
const fs = require('fs');
|
|
5
5
|
const path = require('path');
|
|
6
|
-
const
|
|
6
|
+
const CLIManager = require('../lib/cliManager').default;
|
|
7
7
|
|
|
8
8
|
class StdioMCPWrapper {
|
|
9
9
|
constructor() {
|
|
@@ -204,7 +204,7 @@ class StdioMCPWrapper {
|
|
|
204
204
|
const providerId = args.provider_id; // Optional - detect specific provider
|
|
205
205
|
|
|
206
206
|
// Force detection using CLI Manager (no remote API calls)
|
|
207
|
-
const results = await this.cliManager.forceCliDetection(providerId);
|
|
207
|
+
const results = await this.cliManager.forceCliDetection(null, providerId);
|
|
208
208
|
|
|
209
209
|
// Save status locally to file-based cache
|
|
210
210
|
await this.saveLocalCliStatus(results);
|
|
@@ -241,13 +241,13 @@ class StdioMCPWrapper {
|
|
|
241
241
|
if (providerId) {
|
|
242
242
|
// Get specific provider status
|
|
243
243
|
const status = await this.cliManager.getCliStatus(providerId);
|
|
244
|
-
results = status;
|
|
244
|
+
results[providerId] = status;
|
|
245
245
|
} else {
|
|
246
246
|
// Get all providers status
|
|
247
|
-
const providers = this.cliManager.
|
|
247
|
+
const providers = this.cliManager.getProviders();
|
|
248
248
|
for (const provider of providers) {
|
|
249
249
|
const status = await this.cliManager.getCliStatus(provider.id);
|
|
250
|
-
results[provider.id] = status
|
|
250
|
+
results[provider.id] = status;
|
|
251
251
|
}
|
|
252
252
|
}
|
|
253
253
|
|
|
@@ -271,10 +271,10 @@ class StdioMCPWrapper {
|
|
|
271
271
|
}
|
|
272
272
|
|
|
273
273
|
/**
|
|
274
|
-
* Local CLI prompt sending
|
|
274
|
+
* Local CLI prompt sending
|
|
275
275
|
*/
|
|
276
276
|
async localSendCliPrompt(args) {
|
|
277
|
-
console.error(`[Stdio Wrapper] Local CLI prompt sending
|
|
277
|
+
console.error(`[Stdio Wrapper] Local CLI prompt sending`);
|
|
278
278
|
|
|
279
279
|
try {
|
|
280
280
|
const { provider_id, prompt, mode = 'args', timeout_ms = 30000 } = args;
|
|
@@ -283,174 +283,40 @@ class StdioMCPWrapper {
|
|
|
283
283
|
throw new Error('provider_id and prompt are required');
|
|
284
284
|
}
|
|
285
285
|
|
|
286
|
-
//
|
|
287
|
-
const
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
]);
|
|
294
|
-
|
|
295
|
-
// Process results
|
|
296
|
-
const localResponse = localResult.status === 'fulfilled' ? localResult.value : {
|
|
297
|
-
success: false,
|
|
298
|
-
error: `CLI check failed: ${localResult.reason?.message || 'Unknown error'}`,
|
|
299
|
-
latency_ms: gracefulTimeout,
|
|
300
|
-
timestamp: new Date().toISOString()
|
|
301
|
-
};
|
|
302
|
-
|
|
303
|
-
const perspectivesResponse = perspectivesResult.status === 'fulfilled' ? perspectivesResult.value : {
|
|
304
|
-
success: false,
|
|
305
|
-
error: `Perspectives failed: ${perspectivesResult.reason?.message || 'Unknown error'}`,
|
|
306
|
-
timestamp: new Date().toISOString()
|
|
307
|
-
};
|
|
308
|
-
|
|
309
|
-
// Record usage locally (file-based analytics) - non-blocking
|
|
310
|
-
this.recordLocalUsage(provider_id, prompt, localResponse).catch(err => {
|
|
311
|
-
console.error('[Stdio Wrapper] Usage recording failed (non-critical):', err.message);
|
|
312
|
-
});
|
|
286
|
+
// Send prompt using CLI Manager (local execution)
|
|
287
|
+
const response = await this.cliManager.sendCliPrompt(
|
|
288
|
+
provider_id,
|
|
289
|
+
prompt,
|
|
290
|
+
mode,
|
|
291
|
+
timeout_ms
|
|
292
|
+
);
|
|
313
293
|
|
|
314
|
-
//
|
|
315
|
-
|
|
294
|
+
// Record usage locally (file-based analytics)
|
|
295
|
+
await this.recordLocalUsage(provider_id, prompt, response);
|
|
316
296
|
|
|
317
|
-
} catch (error) {
|
|
318
|
-
console.error('[Stdio Wrapper] Local CLI prompt error:', error);
|
|
319
297
|
return {
|
|
320
|
-
success:
|
|
321
|
-
|
|
298
|
+
success: response.success,
|
|
299
|
+
content: response.content,
|
|
300
|
+
error: response.error,
|
|
301
|
+
tokens_used: response.tokensUsed,
|
|
302
|
+
latency_ms: response.latencyMs,
|
|
303
|
+
provider: provider_id,
|
|
304
|
+
mode,
|
|
322
305
|
timestamp: new Date().toISOString(),
|
|
323
306
|
local_only: true
|
|
324
307
|
};
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
308
|
|
|
328
|
-
/**
|
|
329
|
-
* Call remote perspectives for CLI prompts
|
|
330
|
-
*/
|
|
331
|
-
async callPerspectivesForCli(args, localResult) {
|
|
332
|
-
console.error(`[Stdio Wrapper] Calling remote perspectives for CLI prompt`);
|
|
333
|
-
|
|
334
|
-
try {
|
|
335
|
-
const perspectivesRequest = {
|
|
336
|
-
jsonrpc: '2.0',
|
|
337
|
-
method: 'tools/call',
|
|
338
|
-
params: {
|
|
339
|
-
name: 'get_perspectives',
|
|
340
|
-
arguments: {
|
|
341
|
-
prompt: args.prompt,
|
|
342
|
-
user_token: this.userToken,
|
|
343
|
-
// Let the remote server use user's configured preferences for models
|
|
344
|
-
// Don't specify models to use dashboard defaults
|
|
345
|
-
project_memory: 'none',
|
|
346
|
-
temperature: 0.7,
|
|
347
|
-
max_tokens: 2000
|
|
348
|
-
}
|
|
349
|
-
},
|
|
350
|
-
id: `perspectives-${Date.now()}`
|
|
351
|
-
};
|
|
352
|
-
|
|
353
|
-
const remoteResponse = await this.forwardToRemoteServer(perspectivesRequest);
|
|
354
|
-
|
|
355
|
-
if (remoteResponse.result && remoteResponse.result.content && remoteResponse.result.content[0]) {
|
|
356
|
-
return {
|
|
357
|
-
success: true,
|
|
358
|
-
content: remoteResponse.result.content[0].text,
|
|
359
|
-
timestamp: new Date().toISOString()
|
|
360
|
-
};
|
|
361
|
-
} else if (remoteResponse.error) {
|
|
362
|
-
return {
|
|
363
|
-
success: false,
|
|
364
|
-
error: remoteResponse.error.message || 'Remote perspectives failed',
|
|
365
|
-
timestamp: new Date().toISOString()
|
|
366
|
-
};
|
|
367
|
-
} else {
|
|
368
|
-
return {
|
|
369
|
-
success: false,
|
|
370
|
-
error: 'Unexpected remote response format',
|
|
371
|
-
timestamp: new Date().toISOString()
|
|
372
|
-
};
|
|
373
|
-
}
|
|
374
309
|
} catch (error) {
|
|
375
|
-
console.error('[Stdio Wrapper]
|
|
310
|
+
console.error('[Stdio Wrapper] Local CLI prompt error:', error);
|
|
376
311
|
return {
|
|
377
312
|
success: false,
|
|
378
|
-
error:
|
|
379
|
-
timestamp: new Date().toISOString()
|
|
313
|
+
error: error.message,
|
|
314
|
+
timestamp: new Date().toISOString(),
|
|
315
|
+
local_only: true
|
|
380
316
|
};
|
|
381
317
|
}
|
|
382
318
|
}
|
|
383
319
|
|
|
384
|
-
/**
|
|
385
|
-
* Combine local CLI and remote perspectives results
|
|
386
|
-
*/
|
|
387
|
-
combineCliAndPerspectives(localResult, perspectivesResult, args) {
|
|
388
|
-
const combinedResult = {
|
|
389
|
-
success: true,
|
|
390
|
-
timestamp: new Date().toISOString(),
|
|
391
|
-
provider: args.provider_id,
|
|
392
|
-
mode: args.mode,
|
|
393
|
-
sections: {
|
|
394
|
-
local: localResult,
|
|
395
|
-
remote: perspectivesResult
|
|
396
|
-
}
|
|
397
|
-
};
|
|
398
|
-
|
|
399
|
-
// Determine overall success and fallback status
|
|
400
|
-
if (localResult.success && perspectivesResult.success) {
|
|
401
|
-
combinedResult.content = this.formatCombinedResponse(localResult, perspectivesResult, false);
|
|
402
|
-
combinedResult.tokens_used = localResult.tokens_used || 0;
|
|
403
|
-
combinedResult.latency_ms = localResult.latency_ms || 0;
|
|
404
|
-
} else if (!localResult.success && perspectivesResult.success) {
|
|
405
|
-
// Fallback case
|
|
406
|
-
combinedResult.content = this.formatCombinedResponse(localResult, perspectivesResult, true);
|
|
407
|
-
combinedResult.fallback_used = true;
|
|
408
|
-
combinedResult.tokens_used = 0; // No local tokens used
|
|
409
|
-
} else if (localResult.success && !perspectivesResult.success) {
|
|
410
|
-
// Local succeeded, remote failed
|
|
411
|
-
combinedResult.content = this.formatCombinedResponse(localResult, perspectivesResult, false);
|
|
412
|
-
combinedResult.tokens_used = localResult.tokens_used || 0;
|
|
413
|
-
combinedResult.latency_ms = localResult.latency_ms || 0;
|
|
414
|
-
} else {
|
|
415
|
-
// Both failed
|
|
416
|
-
combinedResult.success = false;
|
|
417
|
-
combinedResult.error = `Local CLI failed: ${localResult.error}; Perspectives also failed: ${perspectivesResult.error}`;
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
return combinedResult;
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
/**
|
|
424
|
-
* Format combined response text
|
|
425
|
-
*/
|
|
426
|
-
formatCombinedResponse(localResult, perspectivesResult, isFallback) {
|
|
427
|
-
let formatted = '';
|
|
428
|
-
|
|
429
|
-
if (localResult.success) {
|
|
430
|
-
// Local CLI succeeded
|
|
431
|
-
formatted += `🟢 **Local CLI Response** (${localResult.provider} - ${localResult.mode} mode)\n\n`;
|
|
432
|
-
formatted += `${localResult.content}\n\n`;
|
|
433
|
-
formatted += `*Latency: ${localResult.latency_ms || 0}ms | Tokens: ${localResult.tokens_used || 0}*\n\n`;
|
|
434
|
-
formatted += `---\n\n`;
|
|
435
|
-
} else if (isFallback) {
|
|
436
|
-
// Local CLI failed, using fallback
|
|
437
|
-
formatted += `⚠️ **Local CLI unavailable**: ${localResult.error}\n`;
|
|
438
|
-
formatted += `Using perspectives fallback.\n\n`;
|
|
439
|
-
formatted += `---\n\n`;
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
if (perspectivesResult.success) {
|
|
443
|
-
const title = isFallback ? '🧠 **Perspectives Fallback**' : '🧠 **Supplemental Multi-Model Perspectives**';
|
|
444
|
-
formatted += `${title}\n\n`;
|
|
445
|
-
formatted += `${perspectivesResult.content}\n\n`;
|
|
446
|
-
} else if (!isFallback) {
|
|
447
|
-
// Show remote error only if not in fallback mode
|
|
448
|
-
formatted += `❌ **Perspectives request failed**: ${perspectivesResult.error}\n\n`;
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
return formatted.trim();
|
|
452
|
-
}
|
|
453
|
-
|
|
454
320
|
/**
|
|
455
321
|
* Save CLI status to local file cache
|
|
456
322
|
*/
|
|
@@ -488,20 +354,10 @@ class StdioMCPWrapper {
|
|
|
488
354
|
const polydevevDir = path.join(homeDir, '.polydev');
|
|
489
355
|
const usageFile = path.join(polydevevDir, 'cli-usage.json');
|
|
490
356
|
|
|
491
|
-
// Ensure directory exists
|
|
492
|
-
if (!fs.existsSync(polydevevDir)) {
|
|
493
|
-
fs.mkdirSync(polydevevDir, { recursive: true });
|
|
494
|
-
}
|
|
495
|
-
|
|
496
357
|
// Load existing usage data
|
|
497
358
|
let usageData = [];
|
|
498
359
|
if (fs.existsSync(usageFile)) {
|
|
499
|
-
|
|
500
|
-
usageData = JSON.parse(fs.readFileSync(usageFile, 'utf8'));
|
|
501
|
-
} catch (parseError) {
|
|
502
|
-
console.error('[Stdio Wrapper] Failed to parse existing usage file, starting fresh:', parseError);
|
|
503
|
-
usageData = [];
|
|
504
|
-
}
|
|
360
|
+
usageData = JSON.parse(fs.readFileSync(usageFile, 'utf8'));
|
|
505
361
|
}
|
|
506
362
|
|
|
507
363
|
// Add new usage record
|
|
@@ -510,8 +366,8 @@ class StdioMCPWrapper {
|
|
|
510
366
|
provider: providerId,
|
|
511
367
|
prompt_length: prompt.length,
|
|
512
368
|
success: response.success,
|
|
513
|
-
latency_ms: response.
|
|
514
|
-
tokens_used: response.
|
|
369
|
+
latency_ms: response.latencyMs,
|
|
370
|
+
tokens_used: response.tokensUsed || 0
|
|
515
371
|
});
|
|
516
372
|
|
|
517
373
|
// Keep only last 1000 records
|
|
@@ -523,8 +379,7 @@ class StdioMCPWrapper {
|
|
|
523
379
|
console.error(`[Stdio Wrapper] Usage recorded locally`);
|
|
524
380
|
|
|
525
381
|
} catch (error) {
|
|
526
|
-
console.error('[Stdio Wrapper] Failed to record local usage
|
|
527
|
-
// Don't throw - this is non-critical functionality
|
|
382
|
+
console.error('[Stdio Wrapper] Failed to record local usage:', error);
|
|
528
383
|
}
|
|
529
384
|
}
|
|
530
385
|
|
|
@@ -536,13 +391,8 @@ class StdioMCPWrapper {
|
|
|
536
391
|
return `❌ **CLI Error**\n\n${result.error}\n\n*Timestamp: ${result.timestamp}*`;
|
|
537
392
|
}
|
|
538
393
|
|
|
539
|
-
// Handle combined CLI + perspectives response
|
|
540
|
-
if (result.sections) {
|
|
541
|
-
return result.content;
|
|
542
|
-
}
|
|
543
|
-
|
|
544
394
|
if (result.content) {
|
|
545
|
-
//
|
|
395
|
+
// Prompt response
|
|
546
396
|
return `✅ **CLI Response** (${result.provider || 'Unknown'} - ${result.mode || 'unknown'} mode)\n\n${result.content}\n\n*Latency: ${result.latency_ms || 0}ms | Tokens: ${result.tokens_used || 0} | ${result.timestamp}*`;
|
|
547
397
|
} else {
|
|
548
398
|
// Status/detection response
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "polydev-ai",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.2.0",
|
|
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",
|
|
@@ -59,7 +59,6 @@
|
|
|
59
59
|
"lucide-react": "^0.542.0",
|
|
60
60
|
"marked": "^16.2.1",
|
|
61
61
|
"next": "15.0.0",
|
|
62
|
-
"polydev-ai": "^1.0.0",
|
|
63
62
|
"posthog-js": "^1.157.2",
|
|
64
63
|
"react": "^18.3.1",
|
|
65
64
|
"react-dom": "^18.3.1",
|