polydev-ai 1.9.15 → 1.9.17
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 +65 -3
- package/package.json +1 -1
package/mcp/stdio-wrapper.js
CHANGED
|
@@ -299,7 +299,11 @@ class StdioMCPWrapper {
|
|
|
299
299
|
|
|
300
300
|
// Pending session file for surviving restarts
|
|
301
301
|
this.PENDING_SESSION_FILE = path.join(os.homedir(), '.polydev-pending-session');
|
|
302
|
-
|
|
302
|
+
|
|
303
|
+
// MCP client info (set during initialize handshake)
|
|
304
|
+
// Used to detect which IDE is running us and exclude its CLI to avoid recursive calls
|
|
305
|
+
this.clientInfo = null;
|
|
306
|
+
|
|
303
307
|
// Initialize CLI Manager for local CLI functionality
|
|
304
308
|
// Disable StatusReporter - it's redundant (updateCliStatusInDatabase handles DB updates via /api/cli-status-update)
|
|
305
309
|
// and causes 401 errors because /api/mcp uses different auth than /api/cli-status-update
|
|
@@ -363,6 +367,12 @@ class StdioMCPWrapper {
|
|
|
363
367
|
try {
|
|
364
368
|
switch (method) {
|
|
365
369
|
case 'initialize':
|
|
370
|
+
// Capture client info to detect which IDE is running us
|
|
371
|
+
// This lets us exclude its CLI to avoid recursive calls (e.g., Claude Code → claude_code CLI)
|
|
372
|
+
this.clientInfo = params?.clientInfo || null;
|
|
373
|
+
if (this.clientInfo) {
|
|
374
|
+
console.error(`[Stdio Wrapper] IDE detected: ${this.clientInfo.name} v${this.clientInfo.version || 'unknown'}`);
|
|
375
|
+
}
|
|
366
376
|
return {
|
|
367
377
|
jsonrpc: '2.0',
|
|
368
378
|
id,
|
|
@@ -1679,6 +1689,47 @@ Error: ${error.message}`
|
|
|
1679
1689
|
}
|
|
1680
1690
|
}
|
|
1681
1691
|
|
|
1692
|
+
/**
|
|
1693
|
+
* Get the CLI ID to exclude based on the current IDE client.
|
|
1694
|
+
* Prevents recursive calls (e.g., Claude Code calling claude_code CLI which spawns another Claude Code).
|
|
1695
|
+
* Returns null if no CLI should be excluded.
|
|
1696
|
+
*/
|
|
1697
|
+
getExcludedCliForCurrentIDE() {
|
|
1698
|
+
if (!this.clientInfo?.name) return null;
|
|
1699
|
+
|
|
1700
|
+
const clientName = this.clientInfo.name.toLowerCase();
|
|
1701
|
+
|
|
1702
|
+
// Map known IDE client names to their corresponding CLI IDs
|
|
1703
|
+
// These are the clientInfo.name values sent during MCP initialize handshake
|
|
1704
|
+
const ideToCliMap = {
|
|
1705
|
+
// Claude Code variants
|
|
1706
|
+
'claude-code': 'claude_code',
|
|
1707
|
+
'claude_code': 'claude_code',
|
|
1708
|
+
'claude code': 'claude_code',
|
|
1709
|
+
'claudecode': 'claude_code',
|
|
1710
|
+
// Cursor uses Claude under the hood but is a separate IDE — don't exclude
|
|
1711
|
+
// Gemini CLI / Google IDX
|
|
1712
|
+
'gemini-cli': 'gemini_cli',
|
|
1713
|
+
'gemini_cli': 'gemini_cli',
|
|
1714
|
+
// Codex CLI / OpenAI
|
|
1715
|
+
'codex-cli': 'codex_cli',
|
|
1716
|
+
'codex_cli': 'codex_cli',
|
|
1717
|
+
'codex': 'codex_cli',
|
|
1718
|
+
};
|
|
1719
|
+
|
|
1720
|
+
// Direct match first
|
|
1721
|
+
if (ideToCliMap[clientName]) {
|
|
1722
|
+
return ideToCliMap[clientName];
|
|
1723
|
+
}
|
|
1724
|
+
|
|
1725
|
+
// Fuzzy match: check if client name contains known patterns
|
|
1726
|
+
if (clientName.includes('claude')) return 'claude_code';
|
|
1727
|
+
if (clientName.includes('gemini')) return 'gemini_cli';
|
|
1728
|
+
if (clientName.includes('codex')) return 'codex_cli';
|
|
1729
|
+
|
|
1730
|
+
return null;
|
|
1731
|
+
}
|
|
1732
|
+
|
|
1682
1733
|
/**
|
|
1683
1734
|
* Local CLI prompt sending with ALL available CLIs + remote perspectives
|
|
1684
1735
|
* Respects user's perspectives_per_message setting for total perspectives
|
|
@@ -1764,16 +1815,27 @@ Error: ${error.message}`
|
|
|
1764
1815
|
|
|
1765
1816
|
// CLI priority order: Claude Code first, then Gemini, then Codex
|
|
1766
1817
|
const cliPriorityOrder = ['claude_code', 'gemini_cli', 'codex_cli'];
|
|
1767
|
-
|
|
1818
|
+
|
|
1819
|
+
// Detect if we should exclude the current IDE's CLI to avoid recursive calls
|
|
1820
|
+
const excludedCli = this.getExcludedCliForCurrentIDE();
|
|
1821
|
+
if (excludedCli) {
|
|
1822
|
+
console.error(`[Stdio Wrapper] Excluding CLI '${excludedCli}' (current IDE: ${this.clientInfo?.name}) to avoid recursive calls`);
|
|
1823
|
+
}
|
|
1824
|
+
|
|
1768
1825
|
// Build merged provider list: CLIs first, then API-only
|
|
1769
1826
|
const finalProviders = [];
|
|
1770
1827
|
const usedProviderNames = new Set();
|
|
1771
|
-
|
|
1828
|
+
|
|
1772
1829
|
// STEP 1: Add ALL available CLIs (in priority order) - they're FREE
|
|
1773
1830
|
// Don't limit to maxPerspectives here — we run all CLIs in parallel
|
|
1774
1831
|
// and take the first maxPerspectives successes (fast-collect pattern)
|
|
1832
|
+
// Skip the CLI that matches the current IDE to avoid recursive calls
|
|
1775
1833
|
for (const cliId of cliPriorityOrder) {
|
|
1776
1834
|
if (!availableClis.includes(cliId)) continue;
|
|
1835
|
+
if (cliId === excludedCli) {
|
|
1836
|
+
console.error(`[Stdio Wrapper] [CLI-FIRST] Skipping ${cliId} (same as current IDE — would cause recursive call)`);
|
|
1837
|
+
continue;
|
|
1838
|
+
}
|
|
1777
1839
|
|
|
1778
1840
|
const providerName = cliToProviderMap[cliId];
|
|
1779
1841
|
usedProviderNames.add(providerName);
|