polydev-ai 1.9.14 → 1.9.15
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 +46 -53
- package/package.json +1 -1
package/mcp/stdio-wrapper.js
CHANGED
|
@@ -1769,9 +1769,10 @@ Error: ${error.message}`
|
|
|
1769
1769
|
const finalProviders = [];
|
|
1770
1770
|
const usedProviderNames = new Set();
|
|
1771
1771
|
|
|
1772
|
-
// STEP 1: Add ALL available CLIs
|
|
1772
|
+
// STEP 1: Add ALL available CLIs (in priority order) - they're FREE
|
|
1773
|
+
// Don't limit to maxPerspectives here — we run all CLIs in parallel
|
|
1774
|
+
// and take the first maxPerspectives successes (fast-collect pattern)
|
|
1773
1775
|
for (const cliId of cliPriorityOrder) {
|
|
1774
|
-
if (finalProviders.length >= maxPerspectives) break;
|
|
1775
1776
|
if (!availableClis.includes(cliId)) continue;
|
|
1776
1777
|
|
|
1777
1778
|
const providerName = cliToProviderMap[cliId];
|
|
@@ -1817,7 +1818,7 @@ Error: ${error.message}`
|
|
|
1817
1818
|
console.error(`[Stdio Wrapper] [CLI-FIRST] Added API/credits: ${normalizedProvider} (${p.model})${p.tier ? ` [${p.tier}]` : ''}`);
|
|
1818
1819
|
}
|
|
1819
1820
|
|
|
1820
|
-
console.error(`[Stdio Wrapper] Final provider list (${finalProviders.length}
|
|
1821
|
+
console.error(`[Stdio Wrapper] Final provider list (${finalProviders.length}, need ${maxPerspectives}): ${finalProviders.map(p => `${p.provider}[${p.source}]`).join(', ')}`);
|
|
1821
1822
|
|
|
1822
1823
|
// Separate into CLI entries (local execution) vs API entries (remote execution)
|
|
1823
1824
|
const cliProviderEntries = finalProviders.filter(p => p.source === 'cli');
|
|
@@ -1825,7 +1826,8 @@ Error: ${error.message}`
|
|
|
1825
1826
|
|
|
1826
1827
|
console.error(`[Stdio Wrapper] Provider breakdown: CLI=${cliProviderEntries.map(p => p.cliId).join(', ') || 'none'}, API-only=${apiOnlyProviders.map(p => p.provider).join(', ') || 'none'}`);
|
|
1827
1828
|
|
|
1828
|
-
// Run
|
|
1829
|
+
// Run ALL CLI prompts concurrently with fast-collect pattern
|
|
1830
|
+
// Resolves once we have maxPerspectives successes (don't wait for slow CLIs)
|
|
1829
1831
|
if (cliProviderEntries.length > 0) {
|
|
1830
1832
|
const cliPromises = cliProviderEntries.map(async (providerEntry) => {
|
|
1831
1833
|
try {
|
|
@@ -1866,7 +1868,10 @@ Error: ${error.message}`
|
|
|
1866
1868
|
};
|
|
1867
1869
|
}
|
|
1868
1870
|
});
|
|
1869
|
-
|
|
1871
|
+
|
|
1872
|
+
// Fast-collect: resolve once we have maxPerspectives successes OR all complete
|
|
1873
|
+
localResults = await this.collectFirstNSuccesses(cliPromises, maxPerspectives);
|
|
1874
|
+
console.error(`[Stdio Wrapper] Fast-collect: got ${localResults.filter(r => r.success).length} successful, ${localResults.filter(r => !r.success).length} failed out of ${cliPromises.length} CLIs`);
|
|
1870
1875
|
}
|
|
1871
1876
|
|
|
1872
1877
|
// Store API-only providers info for remote API call
|
|
@@ -1941,6 +1946,42 @@ Error: ${error.message}`
|
|
|
1941
1946
|
}
|
|
1942
1947
|
}
|
|
1943
1948
|
|
|
1949
|
+
/**
|
|
1950
|
+
* Collect results from parallel promises, resolving early once we have N successes
|
|
1951
|
+
* This avoids waiting for slow/timed-out CLIs when we already have enough results
|
|
1952
|
+
* @param {Promise[]} promises - Array of promises to collect from
|
|
1953
|
+
* @param {number} needed - Number of successful results needed
|
|
1954
|
+
* @returns {Promise<Array>} Array of results (may include failures if not enough successes)
|
|
1955
|
+
*/
|
|
1956
|
+
collectFirstNSuccesses(promises, needed) {
|
|
1957
|
+
return new Promise((resolve) => {
|
|
1958
|
+
const results = [];
|
|
1959
|
+
let successCount = 0;
|
|
1960
|
+
let completedCount = 0;
|
|
1961
|
+
let resolved = false;
|
|
1962
|
+
|
|
1963
|
+
if (promises.length === 0) {
|
|
1964
|
+
resolve([]);
|
|
1965
|
+
return;
|
|
1966
|
+
}
|
|
1967
|
+
|
|
1968
|
+
for (const promise of promises) {
|
|
1969
|
+
promise.then(result => {
|
|
1970
|
+
if (resolved) return;
|
|
1971
|
+
results.push(result);
|
|
1972
|
+
if (result.success) successCount++;
|
|
1973
|
+
completedCount++;
|
|
1974
|
+
|
|
1975
|
+
// Resolve early if we have enough successes OR all promises done
|
|
1976
|
+
if (successCount >= needed || completedCount >= promises.length) {
|
|
1977
|
+
resolved = true;
|
|
1978
|
+
resolve([...results]); // Copy to prevent mutation from late arrivals
|
|
1979
|
+
}
|
|
1980
|
+
});
|
|
1981
|
+
}
|
|
1982
|
+
});
|
|
1983
|
+
}
|
|
1984
|
+
|
|
1944
1985
|
/**
|
|
1945
1986
|
* Get all available and authenticated CLI providers
|
|
1946
1987
|
* Uses user's provider order from dashboard (display_order) instead of hardcoded order
|
|
@@ -2278,54 +2319,6 @@ Error: ${error.message}`
|
|
|
2278
2319
|
combineAllCliAndPerspectives(localResults, perspectivesResult, args) {
|
|
2279
2320
|
// Ensure perspectivesResult is always an object to prevent undefined errors
|
|
2280
2321
|
const safePersp = perspectivesResult || { success: false, error: 'No response from perspectives server' };
|
|
2281
|
-
|
|
2282
|
-
const combinedResult = {
|
|
2283
|
-
success: true,
|
|
2284
|
-
timestamp: new Date().toISOString(),
|
|
2285
|
-
mode: args.mode,
|
|
2286
|
-
local_cli_count: localResults.length,
|
|
2287
|
-
sections: {
|
|
2288
|
-
local: localResults,
|
|
2289
|
-
remote: safePersp
|
|
2290
|
-
}
|
|
2291
|
-
};
|
|
2292
|
-
|
|
2293
|
-
// Check if any local CLIs succeeded
|
|
2294
|
-
const successfulClis = localResults.filter(result => result.success);
|
|
2295
|
-
const hasSomeLocalSuccess = successfulClis.length > 0;
|
|
2296
|
-
|
|
2297
|
-
// Determine overall success and content
|
|
2298
|
-
if (hasSomeLocalSuccess && safePersp.success) {
|
|
2299
|
-
combinedResult.content = this.formatMultipleCliResponse(localResults, safePersp, false);
|
|
2300
|
-
combinedResult.tokens_used = successfulClis.reduce((total, cli) => total + (cli.tokens_used || 0), 0);
|
|
2301
|
-
combinedResult.latency_ms = Math.max(...successfulClis.map(cli => cli.latency_ms || 0));
|
|
2302
|
-
} else if (!hasSomeLocalSuccess && safePersp.success) {
|
|
2303
|
-
// Complete fallback case - no local CLIs worked
|
|
2304
|
-
combinedResult.content = this.formatMultipleCliResponse(localResults, safePersp, true);
|
|
2305
|
-
combinedResult.fallback_used = true;
|
|
2306
|
-
combinedResult.tokens_used = 0; // No local tokens used
|
|
2307
|
-
} else if (hasSomeLocalSuccess && !safePersp.success) {
|
|
2308
|
-
// Local CLIs succeeded, remote failed
|
|
2309
|
-
combinedResult.content = this.formatMultipleCliResponse(localResults, safePersp, false);
|
|
2310
|
-
combinedResult.tokens_used = successfulClis.reduce((total, cli) => total + (cli.tokens_used || 0), 0);
|
|
2311
|
-
combinedResult.latency_ms = Math.max(...successfulClis.map(cli => cli.latency_ms || 0));
|
|
2312
|
-
} else {
|
|
2313
|
-
// Both failed
|
|
2314
|
-
combinedResult.success = false;
|
|
2315
|
-
const cliErrors = localResults.map(cli => `${cli.provider_id}: ${cli.error || 'Unknown error'}`).join('; ');
|
|
2316
|
-
const perspectivesError = safePersp.error || 'Unknown remote error';
|
|
2317
|
-
combinedResult.error = `All local CLIs failed: ${cliErrors}; Perspectives also failed: ${perspectivesError}`;
|
|
2318
|
-
}
|
|
2319
|
-
|
|
2320
|
-
return combinedResult;
|
|
2321
|
-
}
|
|
2322
|
-
|
|
2323
|
-
/**
|
|
2324
|
-
* Format multiple CLI responses with remote perspectives
|
|
2325
|
-
*/
|
|
2326
|
-
formatMultipleCliResponse(localResults, perspectivesResult, isFallback) {
|
|
2327
|
-
// Safety check - ensure perspectivesResult is always an object
|
|
2328
|
-
const safePersp = perspectivesResult || { success: false, error: 'No perspectives data' };
|
|
2329
2322
|
let formatted = '';
|
|
2330
2323
|
|
|
2331
2324
|
// Show all local CLI responses
|