polydev-ai 1.8.99 → 1.9.1
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/stdio-wrapper.js +149 -116
- package/package.json +1 -1
package/mcp/stdio-wrapper.js
CHANGED
|
@@ -438,16 +438,14 @@ Token will be saved automatically after login.`
|
|
|
438
438
|
result: {
|
|
439
439
|
content: [{
|
|
440
440
|
type: 'text',
|
|
441
|
-
text:
|
|
442
|
-
|
|
443
|
-
╰─────────────────────────────────────────╯
|
|
441
|
+
text: `ALREADY AUTHENTICATED
|
|
442
|
+
=====================
|
|
444
443
|
|
|
445
|
-
|
|
444
|
+
Your token is configured and ready.
|
|
446
445
|
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
• get_perspectives - Direct tool call
|
|
446
|
+
Available commands:
|
|
447
|
+
/polydev:ask Query multiple AI models
|
|
448
|
+
/polydev:auth Check status & credits
|
|
451
449
|
|
|
452
450
|
To re-login: npx polydev-ai`
|
|
453
451
|
}]
|
|
@@ -507,19 +505,20 @@ To re-login: npx polydev-ai`
|
|
|
507
505
|
result: {
|
|
508
506
|
content: [{
|
|
509
507
|
type: 'text',
|
|
510
|
-
text:
|
|
511
|
-
|
|
512
|
-
╰─────────────────────────────────────────╯
|
|
508
|
+
text: `LOGIN SUCCESSFUL
|
|
509
|
+
================
|
|
513
510
|
|
|
514
|
-
|
|
511
|
+
Token saved to:
|
|
512
|
+
~/.polydev.env
|
|
513
|
+
~/.zshrc
|
|
515
514
|
|
|
516
|
-
|
|
517
|
-
• Token will be saved automatically
|
|
518
|
-
• You can safely reconnect MCP or restart IDE
|
|
519
|
-
• Use /polydev:auth to check status
|
|
515
|
+
IMPORTANT: Restart your IDE to activate.
|
|
520
516
|
|
|
521
|
-
|
|
522
|
-
|
|
517
|
+
After restart, you can:
|
|
518
|
+
/polydev:ask Query multiple AI models
|
|
519
|
+
/polydev:auth Check status & credits
|
|
520
|
+
|
|
521
|
+
Dashboard: https://polydev.ai/dashboard`
|
|
523
522
|
}]
|
|
524
523
|
}
|
|
525
524
|
};
|
|
@@ -569,7 +568,7 @@ After login:
|
|
|
569
568
|
this.isAuthenticated = true;
|
|
570
569
|
this._freshLogin = true;
|
|
571
570
|
|
|
572
|
-
console.error('[Polydev]
|
|
571
|
+
console.error('[Polydev] Login successful! Token saved.');
|
|
573
572
|
console.error('[Polydev] You can now use Polydev tools.');
|
|
574
573
|
console.error('[Polydev] No restart required - token is active immediately.');
|
|
575
574
|
return; // Stop polling
|
|
@@ -1096,7 +1095,7 @@ Error: ${error.message}`
|
|
|
1096
1095
|
</a>
|
|
1097
1096
|
<button onclick="window.close()" class="secondary-btn">Close Window</button>
|
|
1098
1097
|
|
|
1099
|
-
<p class="note"
|
|
1098
|
+
<p class="note">Token saved. Restart your IDE to activate.</p>
|
|
1100
1099
|
<div class="countdown" id="countdown">
|
|
1101
1100
|
<div class="countdown-spinner"></div>
|
|
1102
1101
|
<span>Closing in <strong id="seconds">5</strong>s...</span>
|
|
@@ -1407,93 +1406,129 @@ Error: ${error.message}`
|
|
|
1407
1406
|
const result = await this.cliManager.sendCliPrompt(provider_id, prompt, mode, gracefulTimeout, model);
|
|
1408
1407
|
localResults = [{ provider_id, ...result }];
|
|
1409
1408
|
} else {
|
|
1410
|
-
// No specific provider -
|
|
1411
|
-
//
|
|
1412
|
-
|
|
1409
|
+
// No specific provider - SMART ROUTING: CLIs first (free), then API/credits
|
|
1410
|
+
// Priority order: Available CLIs > User's API keys > Credits tier models
|
|
1411
|
+
// If a configured API/credits model can be accessed through an available CLI, use CLI
|
|
1412
|
+
console.error(`[Stdio Wrapper] Smart routing: CLIs first, then API/credits (max: ${maxPerspectives})`);
|
|
1413
1413
|
|
|
1414
1414
|
// Get available CLIs for checking
|
|
1415
1415
|
const { available: availableClis } = await this.getAllAvailableProviders();
|
|
1416
1416
|
console.error(`[Stdio Wrapper] Available CLIs: ${availableClis.join(', ') || 'none'}`);
|
|
1417
1417
|
|
|
1418
|
-
// Use allProviders from API (
|
|
1419
|
-
// Falls back to CLI-only providers if allProviders not available
|
|
1418
|
+
// Use allProviders from API (user's configured providers from dashboard)
|
|
1420
1419
|
const allProviders = this.allProviders || [];
|
|
1421
1420
|
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1421
|
+
// CLI to provider name mapping
|
|
1422
|
+
const cliToProviderMap = {
|
|
1423
|
+
'claude_code': 'anthropic',
|
|
1424
|
+
'gemini_cli': 'google',
|
|
1425
|
+
'codex_cli': 'openai'
|
|
1426
|
+
};
|
|
1427
|
+
|
|
1428
|
+
// Provider name normalization (matches model-preferences API)
|
|
1429
|
+
const normalizeProvider = (provider) => {
|
|
1430
|
+
const map = {
|
|
1431
|
+
'gemini': 'google',
|
|
1432
|
+
'google-ai': 'google',
|
|
1433
|
+
'x-ai': 'xai',
|
|
1434
|
+
'open-ai': 'openai',
|
|
1435
|
+
'anthropic-ai': 'anthropic'
|
|
1436
|
+
};
|
|
1437
|
+
const lower = provider.toLowerCase();
|
|
1438
|
+
return map[lower] || lower;
|
|
1439
|
+
};
|
|
1440
|
+
|
|
1441
|
+
// CLI priority order: Claude Code first, then Gemini, then Codex
|
|
1442
|
+
const cliPriorityOrder = ['claude_code', 'gemini_cli', 'codex_cli'];
|
|
1443
|
+
|
|
1444
|
+
// Build merged provider list: CLIs first, then API-only
|
|
1445
|
+
const finalProviders = [];
|
|
1446
|
+
const usedProviderNames = new Set();
|
|
1447
|
+
|
|
1448
|
+
// STEP 1: Add ALL available CLIs first (in priority order) - they're FREE
|
|
1449
|
+
for (const cliId of cliPriorityOrder) {
|
|
1450
|
+
if (finalProviders.length >= maxPerspectives) break;
|
|
1451
|
+
if (!availableClis.includes(cliId)) continue;
|
|
1452
|
+
|
|
1453
|
+
const providerName = cliToProviderMap[cliId];
|
|
1454
|
+
usedProviderNames.add(providerName);
|
|
1455
|
+
|
|
1456
|
+
// Check if user has a configured model for this provider (from API keys or credits)
|
|
1457
|
+
// If so, use that model through CLI instead of burning API credits
|
|
1458
|
+
const configuredProvider = allProviders.find(p => {
|
|
1459
|
+
const normalized = normalizeProvider(p.provider);
|
|
1460
|
+
return normalized === providerName;
|
|
1461
|
+
});
|
|
1462
|
+
|
|
1463
|
+
finalProviders.push({
|
|
1464
|
+
provider: providerName,
|
|
1465
|
+
model: configuredProvider?.model || null,
|
|
1466
|
+
cliId: cliId,
|
|
1467
|
+
source: 'cli',
|
|
1468
|
+
tier: configuredProvider?.tier || null
|
|
1469
|
+
});
|
|
1470
|
+
|
|
1471
|
+
console.error(`[Stdio Wrapper] [CLI-FIRST] Added CLI: ${cliId} (${providerName})${configuredProvider ? ` with configured model: ${configuredProvider.model}` : ' with CLI default'}`);
|
|
1472
|
+
}
|
|
1473
|
+
|
|
1474
|
+
// STEP 2: Fill remaining slots with API/credits providers (skip those already covered by CLI)
|
|
1475
|
+
for (const p of allProviders) {
|
|
1476
|
+
if (finalProviders.length >= maxPerspectives) break;
|
|
1477
|
+
|
|
1478
|
+
const normalizedProvider = normalizeProvider(p.provider);
|
|
1479
|
+
if (usedProviderNames.has(normalizedProvider)) {
|
|
1480
|
+
console.error(`[Stdio Wrapper] [CLI-FIRST] Skipping ${normalizedProvider} (already covered by CLI)`);
|
|
1481
|
+
continue;
|
|
1482
|
+
}
|
|
1483
|
+
|
|
1484
|
+
usedProviderNames.add(normalizedProvider);
|
|
1485
|
+
finalProviders.push({
|
|
1486
|
+
...p,
|
|
1487
|
+
provider: normalizedProvider,
|
|
1488
|
+
source: 'api'
|
|
1489
|
+
});
|
|
1430
1490
|
|
|
1431
|
-
|
|
1491
|
+
console.error(`[Stdio Wrapper] [CLI-FIRST] Added API/credits: ${normalizedProvider} (${p.model})${p.tier ? ` [${p.tier}]` : ''}`);
|
|
1492
|
+
}
|
|
1493
|
+
|
|
1494
|
+
console.error(`[Stdio Wrapper] Final provider list (${finalProviders.length}/${maxPerspectives}): ${finalProviders.map(p => `${p.provider}[${p.source}]`).join(', ')}`);
|
|
1495
|
+
|
|
1496
|
+
// Separate into CLI entries (local execution) vs API entries (remote execution)
|
|
1497
|
+
const cliProviderEntries = finalProviders.filter(p => p.source === 'cli');
|
|
1498
|
+
const apiOnlyProviders = finalProviders.filter(p => p.source === 'api');
|
|
1499
|
+
|
|
1500
|
+
console.error(`[Stdio Wrapper] Provider breakdown: CLI=${cliProviderEntries.map(p => p.cliId).join(', ') || 'none'}, API-only=${apiOnlyProviders.map(p => p.provider).join(', ') || 'none'}`);
|
|
1501
|
+
|
|
1502
|
+
// Run all CLI prompts concurrently
|
|
1503
|
+
if (cliProviderEntries.length > 0) {
|
|
1504
|
+
const cliPromises = cliProviderEntries.map(async (providerEntry) => {
|
|
1432
1505
|
try {
|
|
1433
|
-
const model = modelPreferences[
|
|
1434
|
-
|
|
1506
|
+
const model = providerEntry.model || modelPreferences[providerEntry.cliId] || null;
|
|
1507
|
+
if (model) {
|
|
1508
|
+
console.error(`[Stdio Wrapper] Using model for ${providerEntry.cliId}: ${model}`);
|
|
1509
|
+
}
|
|
1510
|
+
const result = await this.cliManager.sendCliPrompt(providerEntry.cliId, prompt, mode, gracefulTimeout, model);
|
|
1435
1511
|
return {
|
|
1436
|
-
provider_id:
|
|
1437
|
-
original_provider:
|
|
1512
|
+
provider_id: providerEntry.cliId,
|
|
1513
|
+
original_provider: providerEntry.provider,
|
|
1438
1514
|
...result
|
|
1439
1515
|
};
|
|
1440
1516
|
} catch (error) {
|
|
1441
|
-
|
|
1517
|
+
console.error(`[Stdio Wrapper] CLI ${providerEntry.cliId} failed:`, error.message);
|
|
1518
|
+
return {
|
|
1519
|
+
provider_id: providerEntry.cliId,
|
|
1520
|
+
original_provider: providerEntry.provider,
|
|
1521
|
+
success: false,
|
|
1522
|
+
error: error.message,
|
|
1523
|
+
latency_ms: gracefulTimeout
|
|
1524
|
+
};
|
|
1442
1525
|
}
|
|
1443
1526
|
});
|
|
1444
1527
|
localResults = await Promise.all(cliPromises);
|
|
1445
|
-
} else {
|
|
1446
|
-
// NEW: Use allProviders list (includes CLI + API-only providers)
|
|
1447
|
-
const providersToUse = allProviders.slice(0, maxPerspectives);
|
|
1448
|
-
console.error(`[Stdio Wrapper] Using ${providersToUse.length} providers from dashboard`);
|
|
1449
|
-
|
|
1450
|
-
// Separate into CLI providers vs API-only providers
|
|
1451
|
-
const cliProviderEntries = [];
|
|
1452
|
-
const apiOnlyProviders = [];
|
|
1453
|
-
|
|
1454
|
-
for (const p of providersToUse) {
|
|
1455
|
-
if (p.cliId && availableClis.includes(p.cliId)) {
|
|
1456
|
-
// Has CLI and CLI is available
|
|
1457
|
-
cliProviderEntries.push(p);
|
|
1458
|
-
} else {
|
|
1459
|
-
// No CLI or CLI unavailable - needs API
|
|
1460
|
-
apiOnlyProviders.push(p);
|
|
1461
|
-
}
|
|
1462
|
-
}
|
|
1463
|
-
|
|
1464
|
-
console.error(`[Stdio Wrapper] Provider breakdown: CLI=${cliProviderEntries.map(p => p.cliId).join(', ') || 'none'}, API-only=${apiOnlyProviders.map(p => p.provider).join(', ') || 'none'}`);
|
|
1465
|
-
|
|
1466
|
-
// Run all CLI prompts concurrently
|
|
1467
|
-
if (cliProviderEntries.length > 0) {
|
|
1468
|
-
const cliPromises = cliProviderEntries.map(async (providerEntry) => {
|
|
1469
|
-
try {
|
|
1470
|
-
const model = providerEntry.model || modelPreferences[providerEntry.cliId] || null;
|
|
1471
|
-
if (model) {
|
|
1472
|
-
console.error(`[Stdio Wrapper] Using model for ${providerEntry.cliId}: ${model}`);
|
|
1473
|
-
}
|
|
1474
|
-
const result = await this.cliManager.sendCliPrompt(providerEntry.cliId, prompt, mode, gracefulTimeout, model);
|
|
1475
|
-
return {
|
|
1476
|
-
provider_id: providerEntry.cliId,
|
|
1477
|
-
original_provider: providerEntry.provider,
|
|
1478
|
-
...result
|
|
1479
|
-
};
|
|
1480
|
-
} catch (error) {
|
|
1481
|
-
console.error(`[Stdio Wrapper] CLI ${providerEntry.cliId} failed:`, error.message);
|
|
1482
|
-
return {
|
|
1483
|
-
provider_id: providerEntry.cliId,
|
|
1484
|
-
original_provider: providerEntry.provider,
|
|
1485
|
-
success: false,
|
|
1486
|
-
error: error.message,
|
|
1487
|
-
latency_ms: gracefulTimeout
|
|
1488
|
-
};
|
|
1489
|
-
}
|
|
1490
|
-
});
|
|
1491
|
-
localResults = await Promise.all(cliPromises);
|
|
1492
|
-
}
|
|
1493
|
-
|
|
1494
|
-
// Store API-only providers info for remote API call
|
|
1495
|
-
this._apiOnlyProviders = apiOnlyProviders;
|
|
1496
1528
|
}
|
|
1529
|
+
|
|
1530
|
+
// Store API-only providers info for remote API call
|
|
1531
|
+
this._apiOnlyProviders = apiOnlyProviders;
|
|
1497
1532
|
}
|
|
1498
1533
|
|
|
1499
1534
|
// Calculate how many successful local perspectives we got
|
|
@@ -1957,16 +1992,16 @@ Error: ${error.message}`
|
|
|
1957
1992
|
const modelDisplay = cliResult.model_used && cliResult.model_used !== 'cli_default' && cliResult.model_used !== 'cli_default_fallback'
|
|
1958
1993
|
? cliResult.model_used
|
|
1959
1994
|
: cliResult.provider_id;
|
|
1960
|
-
formatted +=
|
|
1995
|
+
formatted += `Local CLI Response (${modelDisplay})\n\n`;
|
|
1961
1996
|
formatted += `${cleanCliResponse(cliResult.content)}\n\n`;
|
|
1962
|
-
formatted +=
|
|
1997
|
+
formatted += `Latency: ${cliResult.latency_ms || 0}ms | Tokens: ${cliResult.tokens_used || 0}\n\n`;
|
|
1963
1998
|
formatted += `---\n\n`;
|
|
1964
1999
|
}
|
|
1965
2000
|
}
|
|
1966
2001
|
|
|
1967
2002
|
if (failedClis.length > 0 && successfulClis.length === 0) {
|
|
1968
2003
|
// All local CLIs failed
|
|
1969
|
-
formatted +=
|
|
2004
|
+
formatted += `[Warning] All Local CLIs Unavailable\n`;
|
|
1970
2005
|
for (const cliResult of failedClis) {
|
|
1971
2006
|
formatted += `- ${cliResult.provider_id}: ${cliResult.error}\n`;
|
|
1972
2007
|
}
|
|
@@ -1974,7 +2009,7 @@ Error: ${error.message}`
|
|
|
1974
2009
|
formatted += `---\n\n`;
|
|
1975
2010
|
} else if (failedClis.length > 0) {
|
|
1976
2011
|
// Some CLIs failed, some succeeded
|
|
1977
|
-
formatted +=
|
|
2012
|
+
formatted += `[Warning] Some CLIs Failed\n`;
|
|
1978
2013
|
for (const cliResult of failedClis) {
|
|
1979
2014
|
formatted += `- ${cliResult.provider_id}: ${cliResult.error}\n`;
|
|
1980
2015
|
}
|
|
@@ -1988,13 +2023,13 @@ Error: ${error.message}`
|
|
|
1988
2023
|
formatted += `${safePersp.content}\n\n`;
|
|
1989
2024
|
} else {
|
|
1990
2025
|
// Legacy formatting
|
|
1991
|
-
const title = (successfulClis.length === 0) ? '
|
|
2026
|
+
const title = (successfulClis.length === 0) ? 'Perspectives Fallback' : 'Supplemental Multi-Model Perspectives';
|
|
1992
2027
|
formatted += `${title}\n\n`;
|
|
1993
2028
|
formatted += `${safePersp.content}\n\n`;
|
|
1994
2029
|
}
|
|
1995
2030
|
} else if (successfulClis.length > 0) {
|
|
1996
2031
|
// Show remote error only if we have local success
|
|
1997
|
-
formatted += `❌
|
|
2032
|
+
formatted += `❌ Perspectives request failed: ${safePersp.error || 'Unknown error'}\n\n`;
|
|
1998
2033
|
}
|
|
1999
2034
|
|
|
2000
2035
|
return formatted.trim();
|
|
@@ -2257,28 +2292,28 @@ Error: ${error.message}`
|
|
|
2257
2292
|
const cliCount = result.local_cli_count || 1;
|
|
2258
2293
|
|
|
2259
2294
|
if (cliCount > 1) {
|
|
2260
|
-
return
|
|
2295
|
+
return `Multi-CLI Response (${cliCount} local CLIs + perspectives)\n\n${result.content}\n\nTotal Latency: ${result.latency_ms || 0}ms | Total Tokens: ${result.tokens_used || 0} | ${result.timestamp}`;
|
|
2261
2296
|
} else {
|
|
2262
|
-
return
|
|
2297
|
+
return `CLI Response (${result.provider || 'Unknown'} - ${result.mode || 'unknown'} mode)\n\n${result.content}\n\nLatency: ${result.latency_ms || 0}ms | Tokens: ${result.tokens_used || 0} | ${result.timestamp}`;
|
|
2263
2298
|
}
|
|
2264
2299
|
} else {
|
|
2265
2300
|
// Status/detection response
|
|
2266
|
-
let formatted =
|
|
2301
|
+
let formatted = `CLI Operation Success\n\n`;
|
|
2267
2302
|
formatted += `${result.message}\n\n`;
|
|
2268
2303
|
|
|
2269
2304
|
if (result.results) {
|
|
2270
|
-
formatted +=
|
|
2305
|
+
formatted += `Results:\n`;
|
|
2271
2306
|
for (const [providerId, status] of Object.entries(result.results)) {
|
|
2272
|
-
const icon = status.available ? '
|
|
2273
|
-
const
|
|
2274
|
-
formatted += `- ${icon} ${
|
|
2307
|
+
const icon = status.available ? '[+]' : '[-]';
|
|
2308
|
+
const authStatus = status.authenticated ? '[auth]' : '[no-auth]';
|
|
2309
|
+
formatted += `- ${icon} ${authStatus} ${providerId}: ${status.available ? 'Available' : 'Not Available'}`;
|
|
2275
2310
|
if (status.version) formatted += ` (${status.version})`;
|
|
2276
2311
|
if (status.error) formatted += ` - ${status.error}`;
|
|
2277
2312
|
formatted += `\n`;
|
|
2278
2313
|
}
|
|
2279
2314
|
}
|
|
2280
2315
|
|
|
2281
|
-
formatted += `\n
|
|
2316
|
+
formatted += `\n${result.local_only ? 'Local execution' : 'Remote execution'} | ${result.timestamp}`;
|
|
2282
2317
|
return formatted;
|
|
2283
2318
|
}
|
|
2284
2319
|
}
|
|
@@ -2544,22 +2579,20 @@ Error: ${error.message}`
|
|
|
2544
2579
|
result: {
|
|
2545
2580
|
content: [{
|
|
2546
2581
|
type: 'text',
|
|
2547
|
-
text:
|
|
2548
|
-
|
|
2549
|
-
╰─────────────────────────────────────────╯
|
|
2582
|
+
text: `LOGIN SUCCESSFUL
|
|
2583
|
+
================
|
|
2550
2584
|
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2585
|
+
Token saved to:
|
|
2586
|
+
~/.polydev.env
|
|
2587
|
+
~/.zshrc
|
|
2554
2588
|
|
|
2555
|
-
|
|
2589
|
+
IMPORTANT: Restart your IDE to activate.
|
|
2556
2590
|
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
• Use get_perspectives tool directly
|
|
2591
|
+
After restart, you can:
|
|
2592
|
+
/polydev:ask Query multiple AI models
|
|
2593
|
+
/polydev:auth Check status & credits
|
|
2561
2594
|
|
|
2562
|
-
|
|
2595
|
+
Dashboard: https://polydev.ai/dashboard`
|
|
2563
2596
|
}]
|
|
2564
2597
|
}
|
|
2565
2598
|
});
|