polydev-ai 1.8.13 → 1.8.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/lib/cliManager.js +37 -0
- package/mcp/stdio-wrapper.js +75 -1
- package/package.json +1 -1
package/lib/cliManager.js
CHANGED
|
@@ -183,6 +183,7 @@ class CLIManager {
|
|
|
183
183
|
}
|
|
184
184
|
|
|
185
185
|
let authenticated = false;
|
|
186
|
+
let quotaExhausted = false;
|
|
186
187
|
|
|
187
188
|
// For Claude Code, skip command-based auth check and use file-based detection directly
|
|
188
189
|
// This avoids the recursion issue when running from within Claude Code
|
|
@@ -211,6 +212,12 @@ class CLIManager {
|
|
|
211
212
|
|
|
212
213
|
authenticated = this.parseAuthenticationStatus(provider.id, authOutput);
|
|
213
214
|
|
|
215
|
+
// Check for quota exhaustion (authenticated but rate limited)
|
|
216
|
+
if (provider.id === 'gemini_cli') {
|
|
217
|
+
quotaExhausted = authOutput.includes('exhausted your daily quota') ||
|
|
218
|
+
authOutput.includes('quota') && authOutput.includes('exhausted');
|
|
219
|
+
}
|
|
220
|
+
|
|
214
221
|
} catch (authError) {
|
|
215
222
|
if (process.env.POLYDEV_CLI_DEBUG) {
|
|
216
223
|
console.log(`[CLI Debug] Auth check failed for ${provider.id}:`, authError);
|
|
@@ -262,6 +269,7 @@ This is a known issue with @google/gemini-cli@0.3.4 and older Node.js versions.`
|
|
|
262
269
|
return {
|
|
263
270
|
available: true,
|
|
264
271
|
authenticated,
|
|
272
|
+
quota_exhausted: quotaExhausted,
|
|
265
273
|
version,
|
|
266
274
|
path: cliPath,
|
|
267
275
|
last_checked: new Date(),
|
|
@@ -437,6 +445,19 @@ This is a known issue with @google/gemini-cli@0.3.4 and older Node.js versions.`
|
|
|
437
445
|
};
|
|
438
446
|
}
|
|
439
447
|
|
|
448
|
+
// Check if CLI has quota exhausted - skip and suggest API fallback
|
|
449
|
+
if (providerStatus.quota_exhausted) {
|
|
450
|
+
console.log(`[Polydev CLI] ${provider.name} has exhausted daily quota, skipping CLI (use API fallback)`);
|
|
451
|
+
return {
|
|
452
|
+
success: false,
|
|
453
|
+
error: `${provider.name} has exhausted daily quota. Use API fallback.`,
|
|
454
|
+
error_code: 'QUOTA_EXHAUSTED',
|
|
455
|
+
latency_ms: Date.now() - startTime,
|
|
456
|
+
provider: providerId,
|
|
457
|
+
timestamp: new Date()
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
|
|
440
461
|
// Log model being used
|
|
441
462
|
if (model) {
|
|
442
463
|
console.log(`[Polydev CLI] Using model for ${providerId}: ${model}`);
|
|
@@ -611,6 +632,22 @@ This is a known issue with @google/gemini-cli@0.3.4 and older Node.js versions.`
|
|
|
611
632
|
}
|
|
612
633
|
|
|
613
634
|
lastErrorMessage = result.error;
|
|
635
|
+
|
|
636
|
+
// Check for quota exhaustion error during execution
|
|
637
|
+
const combinedOutput = ((result.stdout || '') + ' ' + (result.stderr || '') + ' ' + (result.error || '')).toLowerCase();
|
|
638
|
+
if (combinedOutput.includes('exhausted') && combinedOutput.includes('quota') ||
|
|
639
|
+
combinedOutput.includes('rate limit') ||
|
|
640
|
+
combinedOutput.includes('too many requests')) {
|
|
641
|
+
console.log(`[Polydev CLI] ${providerId} quota/rate limit error detected during execution`);
|
|
642
|
+
return {
|
|
643
|
+
success: false,
|
|
644
|
+
error: `${provider.name} quota/rate limit exceeded. Use API fallback.`,
|
|
645
|
+
error_code: 'QUOTA_EXHAUSTED',
|
|
646
|
+
latency_ms: Date.now() - startTime,
|
|
647
|
+
provider: providerId,
|
|
648
|
+
timestamp: new Date()
|
|
649
|
+
};
|
|
650
|
+
}
|
|
614
651
|
} catch (error) {
|
|
615
652
|
lastErrorMessage = error instanceof Error ? error.message : String(error);
|
|
616
653
|
|
package/mcp/stdio-wrapper.js
CHANGED
|
@@ -100,6 +100,75 @@ if (writableTmp) {
|
|
|
100
100
|
console.error(`[Stdio Wrapper] Using TMP directory: ${writableTmp}`);
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
+
/**
|
|
104
|
+
* Clean CLI response by removing metadata and debug info
|
|
105
|
+
* Strips: provider info, approval, sandbox, reasoning, session id, MCP errors, etc.
|
|
106
|
+
*/
|
|
107
|
+
function cleanCliResponse(content) {
|
|
108
|
+
if (!content || typeof content !== 'string') {
|
|
109
|
+
return content || '';
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const lines = content.split('\n');
|
|
113
|
+
const cleanedLines = [];
|
|
114
|
+
let skipUntilContent = true;
|
|
115
|
+
let inThinkingSection = false;
|
|
116
|
+
|
|
117
|
+
for (const line of lines) {
|
|
118
|
+
const trimmed = line.trim();
|
|
119
|
+
|
|
120
|
+
// Skip metadata lines at the start
|
|
121
|
+
if (skipUntilContent) {
|
|
122
|
+
// Skip empty lines
|
|
123
|
+
if (!trimmed) continue;
|
|
124
|
+
|
|
125
|
+
// Skip known metadata patterns
|
|
126
|
+
if (trimmed.startsWith('provider:')) continue;
|
|
127
|
+
if (trimmed.startsWith('approval:')) continue;
|
|
128
|
+
if (trimmed.startsWith('sandbox:')) continue;
|
|
129
|
+
if (trimmed.startsWith('reasoning effort:')) continue;
|
|
130
|
+
if (trimmed.startsWith('reasoning summaries:')) continue;
|
|
131
|
+
if (trimmed.startsWith('session id:')) continue;
|
|
132
|
+
if (trimmed.match(/^-{4,}$/)) continue; // Skip separator lines like --------
|
|
133
|
+
if (trimmed === 'user') continue; // Skip role markers
|
|
134
|
+
if (trimmed === 'assistant') continue;
|
|
135
|
+
|
|
136
|
+
// Skip MCP client errors
|
|
137
|
+
if (trimmed.startsWith('ERROR: MCP client for')) continue;
|
|
138
|
+
if (trimmed.includes('failed to start')) continue;
|
|
139
|
+
|
|
140
|
+
// Found actual content - stop skipping
|
|
141
|
+
skipUntilContent = false;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Handle thinking sections (optional: can show or hide)
|
|
145
|
+
if (trimmed === 'thinking') {
|
|
146
|
+
inThinkingSection = true;
|
|
147
|
+
continue; // Skip the "thinking" marker
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// End of thinking section on empty line after content
|
|
151
|
+
if (inThinkingSection && !trimmed) {
|
|
152
|
+
inThinkingSection = false;
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Skip more MCP errors anywhere in output
|
|
157
|
+
if (trimmed.startsWith('ERROR: MCP client for')) continue;
|
|
158
|
+
if (trimmed.includes('failed to start') && trimmed.includes('MCP')) continue;
|
|
159
|
+
|
|
160
|
+
// Keep this line
|
|
161
|
+
cleanedLines.push(line);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Trim trailing empty lines and return
|
|
165
|
+
while (cleanedLines.length > 0 && !cleanedLines[cleanedLines.length - 1].trim()) {
|
|
166
|
+
cleanedLines.pop();
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return cleanedLines.join('\n');
|
|
170
|
+
}
|
|
171
|
+
|
|
103
172
|
class StdioMCPWrapper {
|
|
104
173
|
constructor() {
|
|
105
174
|
this.userToken = process.env.POLYDEV_USER_TOKEN;
|
|
@@ -559,6 +628,11 @@ class StdioMCPWrapper {
|
|
|
559
628
|
for (const providerId of priorityOrder) {
|
|
560
629
|
const status = results[providerId];
|
|
561
630
|
if (status && status.available && status.authenticated) {
|
|
631
|
+
// Skip providers with quota exhausted - they'll use API fallback
|
|
632
|
+
if (status.quota_exhausted) {
|
|
633
|
+
console.error(`[Stdio Wrapper] Skipping ${providerId} - quota exhausted, will use API fallback`);
|
|
634
|
+
continue;
|
|
635
|
+
}
|
|
562
636
|
availableProviders.push(providerId);
|
|
563
637
|
}
|
|
564
638
|
}
|
|
@@ -832,7 +906,7 @@ class StdioMCPWrapper {
|
|
|
832
906
|
? cliResult.model_used
|
|
833
907
|
: cliResult.provider_id;
|
|
834
908
|
formatted += `🟢 **Local CLI Response** (${modelDisplay})\n\n`;
|
|
835
|
-
formatted += `${cliResult.content}\n\n`;
|
|
909
|
+
formatted += `${cleanCliResponse(cliResult.content)}\n\n`;
|
|
836
910
|
formatted += `*Latency: ${cliResult.latency_ms || 0}ms | Tokens: ${cliResult.tokens_used || 0}*\n\n`;
|
|
837
911
|
formatted += `---\n\n`;
|
|
838
912
|
}
|
package/package.json
CHANGED