chore: remove unused code and suppress noisy Claude Code logs
- Delete unused files: retry.js, app-init.js, model-manager.js - Remove duplicate error helpers from helpers.js (exist in errors.js) - Remove unused exports from signature-cache.js, logger.js - Remove unused frontend code: ErrorHandler methods, validators, canDelete, destroy - Make internal functions private in thinking-utils.js - Remove commented-out code from constants.js - Remove deprecated .glass-panel CSS class - Add silent handler for Claude Code event logging (/api/event_logging/batch) - Suppress logging for /v1/messages/count_tokens (501 responses) - Fix catch-all to use originalUrl (wildcard strips req.path) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -67,17 +67,7 @@ export const LOAD_CODE_ASSIST_ENDPOINTS = [
|
||||
// Endpoint order for onboardUser (same as generateContent fallbacks)
|
||||
export const ONBOARD_USER_ENDPOINTS = ANTIGRAVITY_ENDPOINT_FALLBACKS;
|
||||
|
||||
// Hybrid headers specifically for loadCodeAssist
|
||||
// Uses google-api-nodejs-client User-Agent (required for project discovery on some accounts)
|
||||
// export const LOAD_CODE_ASSIST_HEADERS = {
|
||||
// 'User-Agent': 'google-api-nodejs-client/9.15.1',
|
||||
// 'X-Goog-Api-Client': 'google-cloud-sdk vscode_cloudshelleditor/0.1',
|
||||
// 'Client-Metadata': JSON.stringify({
|
||||
// ideType: 'IDE_UNSPECIFIED',
|
||||
// platform: 'PLATFORM_UNSPECIFIED',
|
||||
// pluginType: 'GEMINI'
|
||||
// })
|
||||
// };
|
||||
// Headers for loadCodeAssist API
|
||||
export const LOAD_CODE_ASSIST_HEADERS = ANTIGRAVITY_HEADERS;
|
||||
|
||||
// Default project ID if none can be discovered
|
||||
|
||||
@@ -47,32 +47,6 @@ export function getCachedSignature(toolUseId) {
|
||||
return entry.signature;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear expired entries from the cache
|
||||
* Can be called periodically to prevent memory buildup
|
||||
*/
|
||||
export function cleanupCache() {
|
||||
const now = Date.now();
|
||||
for (const [key, entry] of signatureCache) {
|
||||
if (now - entry.timestamp > GEMINI_SIGNATURE_CACHE_TTL_MS) {
|
||||
signatureCache.delete(key);
|
||||
}
|
||||
}
|
||||
for (const [key, entry] of thinkingSignatureCache) {
|
||||
if (now - entry.timestamp > GEMINI_SIGNATURE_CACHE_TTL_MS) {
|
||||
thinkingSignatureCache.delete(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current cache size (for debugging)
|
||||
* @returns {number} Number of entries in the cache
|
||||
*/
|
||||
export function getCacheSize() {
|
||||
return signatureCache.size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cache a thinking block signature with its model family
|
||||
* @param {string} signature - The thinking signature to cache
|
||||
@@ -105,14 +79,6 @@ export function getCachedSignatureFamily(signature) {
|
||||
return entry.modelFamily;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current thinking signature cache size (for debugging)
|
||||
* @returns {number} Number of entries in the thinking signature cache
|
||||
*/
|
||||
export function getThinkingCacheSize() {
|
||||
return thinkingSignatureCache.size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all entries from the thinking signature cache.
|
||||
* Used for testing cold cache scenarios.
|
||||
|
||||
@@ -12,7 +12,7 @@ import { logger } from '../utils/logger.js';
|
||||
* @param {Object} part - Content part to check
|
||||
* @returns {boolean} True if the part is a thinking block
|
||||
*/
|
||||
export function isThinkingPart(part) {
|
||||
function isThinkingPart(part) {
|
||||
return part.type === 'thinking' ||
|
||||
part.type === 'redacted_thinking' ||
|
||||
part.thinking !== undefined ||
|
||||
@@ -22,7 +22,7 @@ export function isThinkingPart(part) {
|
||||
/**
|
||||
* Check if a thinking part has a valid signature (>= MIN_SIGNATURE_LENGTH chars)
|
||||
*/
|
||||
export function hasValidSignature(part) {
|
||||
function hasValidSignature(part) {
|
||||
const signature = part.thought === true ? part.thoughtSignature : part.signature;
|
||||
return typeof signature === 'string' && signature.length >= MIN_SIGNATURE_LENGTH;
|
||||
}
|
||||
@@ -61,7 +61,7 @@ export function hasUnsignedThinkingBlocks(messages) {
|
||||
/**
|
||||
* Sanitize a thinking part by keeping only allowed fields
|
||||
*/
|
||||
export function sanitizeThinkingPart(part) {
|
||||
function sanitizeThinkingPart(part) {
|
||||
// Gemini-style thought blocks: { thought: true, text, thoughtSignature }
|
||||
if (part.thought === true) {
|
||||
const sanitized = { thought: true };
|
||||
@@ -85,7 +85,7 @@ export function sanitizeThinkingPart(part) {
|
||||
* Sanitize a thinking block by removing extra fields like cache_control.
|
||||
* Only keeps: type, thinking, signature (for thinking) or type, data (for redacted_thinking)
|
||||
*/
|
||||
export function sanitizeAnthropicThinkingBlock(block) {
|
||||
function sanitizeAnthropicThinkingBlock(block) {
|
||||
if (!block) return block;
|
||||
|
||||
if (block.type === 'thinking') {
|
||||
@@ -366,7 +366,7 @@ function isPlainUserMessage(message) {
|
||||
* @param {Array<Object>} messages - Array of messages
|
||||
* @returns {Object} State object with inToolLoop, interruptedTool, turnHasThinking, etc.
|
||||
*/
|
||||
export function analyzeConversationState(messages) {
|
||||
function analyzeConversationState(messages) {
|
||||
if (!Array.isArray(messages) || messages.length === 0) {
|
||||
return { inToolLoop: false, interruptedTool: false, turnHasThinking: false, toolResultCount: 0 };
|
||||
}
|
||||
|
||||
@@ -103,6 +103,23 @@ app.use('/v1', (req, res, next) => {
|
||||
// Setup usage statistics middleware
|
||||
usageStats.setupMiddleware(app);
|
||||
|
||||
/**
|
||||
* Silent handler for Claude Code CLI root POST requests
|
||||
* Claude Code sends heartbeat/event requests to POST / which we don't need
|
||||
* Using app.use instead of app.post for earlier middleware interception
|
||||
*/
|
||||
app.use((req, res, next) => {
|
||||
// Handle Claude Code event logging requests silently
|
||||
if (req.method === 'POST' && req.path === '/api/event_logging/batch') {
|
||||
return res.status(200).json({ status: 'ok' });
|
||||
}
|
||||
// Handle Claude Code root POST requests silently
|
||||
if (req.method === 'POST' && req.path === '/') {
|
||||
return res.status(200).json({ status: 'ok' });
|
||||
}
|
||||
next();
|
||||
});
|
||||
|
||||
// Mount WebUI (optional web interface for account management)
|
||||
mountWebUI(app, __dirname, accountManager);
|
||||
|
||||
@@ -162,7 +179,7 @@ app.use((req, res, next) => {
|
||||
const logMsg = `[${req.method}] ${req.path} ${status} (${duration}ms)`;
|
||||
|
||||
// Skip standard logging for event logging batch unless in debug mode
|
||||
if (req.path === '/api/event_logging/batch') {
|
||||
if (req.path === '/api/event_logging/batch' || req.path === '/v1/messages/count_tokens') {
|
||||
if (logger.isDebugEnabled) {
|
||||
logger.debug(logMsg);
|
||||
}
|
||||
@@ -181,6 +198,14 @@ app.use((req, res, next) => {
|
||||
next();
|
||||
});
|
||||
|
||||
/**
|
||||
* Silent handler for Claude Code CLI root POST requests
|
||||
* Claude Code sends heartbeat/event requests to POST / which we don't need
|
||||
*/
|
||||
app.post('/', (req, res) => {
|
||||
res.status(200).json({ status: 'ok' });
|
||||
});
|
||||
|
||||
/**
|
||||
* Test endpoint - Clear thinking signature cache
|
||||
* Used for testing cold cache scenarios in cross-model tests
|
||||
@@ -810,6 +835,7 @@ app.post('/v1/messages', async (req, res) => {
|
||||
usageStats.setupRoutes(app);
|
||||
|
||||
app.use('*', (req, res) => {
|
||||
// Log 404s (use originalUrl since wildcard strips req.path)
|
||||
if (logger.isDebugEnabled) {
|
||||
logger.debug(`[API] 404 Not Found: ${req.method} ${req.originalUrl}`);
|
||||
}
|
||||
|
||||
@@ -49,32 +49,3 @@ export function isNetworkError(error) {
|
||||
msg.includes('timeout')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an error is an authentication error (permanent until fixed)
|
||||
* @param {Error} error - The error to check
|
||||
* @returns {boolean} True if it is an auth error
|
||||
*/
|
||||
export function isAuthError(error) {
|
||||
const msg = error.message.toLowerCase();
|
||||
return (
|
||||
msg.includes('401') ||
|
||||
msg.includes('unauthenticated') ||
|
||||
msg.includes('invalid_grant') ||
|
||||
msg.includes('invalid_client')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an error is a rate limit error
|
||||
* @param {Error} error - The error to check
|
||||
* @returns {boolean} True if it is a rate limit error
|
||||
*/
|
||||
export function isRateLimitError(error) {
|
||||
const msg = error.message.toLowerCase();
|
||||
return (
|
||||
msg.includes('429') ||
|
||||
msg.includes('resource_exhausted') ||
|
||||
msg.includes('quota_exhausted')
|
||||
);
|
||||
}
|
||||
|
||||
@@ -140,6 +140,3 @@ class Logger extends EventEmitter {
|
||||
|
||||
// Export a singleton instance
|
||||
export const logger = new Logger();
|
||||
|
||||
// Export class if needed for multiple instances
|
||||
export { Logger };
|
||||
|
||||
@@ -1,161 +0,0 @@
|
||||
/**
|
||||
* Retry Utilities with Exponential Backoff
|
||||
*
|
||||
* Provides retry logic with exponential backoff and jitter
|
||||
* to prevent thundering herd and optimize API quota usage.
|
||||
*/
|
||||
|
||||
import { sleep } from './helpers.js';
|
||||
import { logger } from './logger.js';
|
||||
|
||||
/**
|
||||
* Calculate exponential backoff delay with jitter
|
||||
*
|
||||
* @param {number} attempt - Current attempt number (0-based)
|
||||
* @param {number} baseMs - Base delay in milliseconds
|
||||
* @param {number} maxMs - Maximum delay in milliseconds
|
||||
* @returns {number} Delay in milliseconds
|
||||
*/
|
||||
export function calculateBackoff(attempt, baseMs = 1000, maxMs = 30000) {
|
||||
// Exponential: baseMs * 2^attempt
|
||||
const exponential = baseMs * Math.pow(2, attempt);
|
||||
|
||||
// Cap at max
|
||||
const capped = Math.min(exponential, maxMs);
|
||||
|
||||
// Add random jitter (±25%) to prevent thundering herd
|
||||
const jitter = capped * 0.25 * (Math.random() * 2 - 1);
|
||||
|
||||
return Math.floor(capped + jitter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retry a function with exponential backoff
|
||||
*
|
||||
* @param {Function} fn - Async function to retry (receives attempt number)
|
||||
* @param {Object} options - Retry options
|
||||
* @param {number} options.maxAttempts - Maximum number of attempts (default: 5)
|
||||
* @param {number} options.baseMs - Base delay in milliseconds (default: 1000)
|
||||
* @param {number} options.maxMs - Maximum delay in milliseconds (default: 30000)
|
||||
* @param {Function} options.shouldRetry - Function to determine if error is retryable
|
||||
* @param {Function} options.onRetry - Callback before each retry (error, attempt, backoffMs)
|
||||
* @returns {Promise<any>} Result from fn
|
||||
* @throws {Error} Last error if all attempts fail
|
||||
*/
|
||||
export async function retryWithBackoff(fn, options = {}) {
|
||||
const {
|
||||
maxAttempts = 5,
|
||||
baseMs = 1000,
|
||||
maxMs = 30000,
|
||||
shouldRetry = () => true,
|
||||
onRetry = null
|
||||
} = options;
|
||||
|
||||
let lastError;
|
||||
|
||||
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
||||
try {
|
||||
return await fn(attempt);
|
||||
} catch (error) {
|
||||
lastError = error;
|
||||
|
||||
// Check if this is the last attempt
|
||||
if (attempt === maxAttempts - 1) {
|
||||
logger.debug(`[Retry] All ${maxAttempts} attempts exhausted`);
|
||||
throw error;
|
||||
}
|
||||
|
||||
// Check if error is retryable
|
||||
if (!shouldRetry(error, attempt)) {
|
||||
logger.debug(`[Retry] Error not retryable, aborting: ${error.message}`);
|
||||
throw error;
|
||||
}
|
||||
|
||||
// Calculate backoff
|
||||
const backoffMs = calculateBackoff(attempt, baseMs, maxMs);
|
||||
logger.debug(`[Retry] Attempt ${attempt + 1}/${maxAttempts} failed, retrying in ${backoffMs}ms`);
|
||||
|
||||
// Call onRetry callback
|
||||
if (onRetry) {
|
||||
await onRetry(error, attempt, backoffMs);
|
||||
}
|
||||
|
||||
// Wait before retrying
|
||||
await sleep(backoffMs);
|
||||
}
|
||||
}
|
||||
|
||||
// Should never reach here, but just in case
|
||||
throw lastError;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an error is retryable (5xx errors or network issues)
|
||||
*
|
||||
* @param {Error} error - Error to check
|
||||
* @returns {boolean} True if error is retryable
|
||||
*/
|
||||
export function isRetryableError(error) {
|
||||
const message = error.message?.toLowerCase() || '';
|
||||
|
||||
// Network errors
|
||||
if (message.includes('econnrefused') ||
|
||||
message.includes('econnreset') ||
|
||||
message.includes('etimedout') ||
|
||||
message.includes('network') ||
|
||||
message.includes('fetch failed')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 5xx server errors
|
||||
if (message.includes('500') ||
|
||||
message.includes('502') ||
|
||||
message.includes('503') ||
|
||||
message.includes('504')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Rate limits (429) are retryable
|
||||
if (message.includes('429') || message.includes('rate limit')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an error is NOT retryable (4xx client errors except 429)
|
||||
*
|
||||
* @param {Error} error - Error to check
|
||||
* @returns {boolean} True if error should not be retried
|
||||
*/
|
||||
export function isNonRetryableError(error) {
|
||||
const message = error.message?.toLowerCase() || '';
|
||||
|
||||
// Authentication errors (401, 403)
|
||||
if (message.includes('401') ||
|
||||
message.includes('403') ||
|
||||
message.includes('unauthorized') ||
|
||||
message.includes('forbidden')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Bad request (400)
|
||||
if (message.includes('400') || message.includes('bad request')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Not found (404)
|
||||
if (message.includes('404') || message.includes('not found')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
export default {
|
||||
calculateBackoff,
|
||||
retryWithBackoff,
|
||||
isRetryableError,
|
||||
isNonRetryableError
|
||||
};
|
||||
Reference in New Issue
Block a user