UNPKG

ai-debug-local-mcp

Version:

🎯 ENHANCED AI GUIDANCE v4.1.2: Dramatically improved tool descriptions help AI users choose the right tools instead of 'close enough' options. Ultra-fast keyboard automation (10x speed), universal recording, multi-ecosystem debugging support, and compreh

212 lines (182 loc) • 5.37 kB
import { createHash } from 'crypto'; import fs from 'fs/promises'; import path from 'path'; export interface APIKeyInfo { key: string; tier: 'free' | 'pro' | 'enterprise'; usageLimit: number; usageCount: number; expiresAt?: Date; features: string[]; } export class APIKeyManager { private apiKeys: Map<string, APIKeyInfo> = new Map(); private configPath: string; constructor(configPath?: string) { this.configPath = configPath || path.join(process.env.HOME || '', '.ai-debug-mcp', 'keys.json'); } async initialize(): Promise<void> { try { const data = await fs.readFile(this.configPath, 'utf-8'); const keys = JSON.parse(data); for (const keyInfo of keys) { this.apiKeys.set(keyInfo.key, keyInfo); } } catch (error) { // File doesn't exist yet, that's okay await this.ensureConfigDir(); } } private async ensureConfigDir(): Promise<void> { const dir = path.dirname(this.configPath); await fs.mkdir(dir, { recursive: true }); } async validateKey(apiKey: string | undefined): Promise<APIKeyInfo | null> { if (!apiKey) { // Return free tier for no API key return { key: 'FREE_TIER', tier: 'free', usageLimit: 100, usageCount: 0, features: ['basic_debugging', 'state_inspection', 'dom_analysis'] }; } const keyInfo = this.apiKeys.get(apiKey); if (!keyInfo) { return null; } // Check expiration if (keyInfo.expiresAt && new Date() > keyInfo.expiresAt) { return null; } // Check usage limit if (keyInfo.usageCount >= keyInfo.usageLimit) { return null; } return keyInfo; } async incrementUsage(apiKey: string): Promise<void> { const keyInfo = this.apiKeys.get(apiKey); if (keyInfo && apiKey !== 'FREE_TIER') { keyInfo.usageCount++; await this.saveKeys(); } } private async saveKeys(): Promise<void> { await this.ensureConfigDir(); const keys = Array.from(this.apiKeys.values()); await fs.writeFile(this.configPath, JSON.stringify(keys, null, 2)); } getFeatureTiers(): Record<string, string[]> { return { free: [ 'basic_debugging', 'state_inspection', 'dom_analysis', 'console_monitoring', 'network_inspection' ], pro: [ 'ai_root_cause_analysis', 'ai_fix_suggestions', 'pattern_detection', 'performance_analysis', 'advanced_correlation', 'unlimited_sessions' ], enterprise: [ 'custom_ai_models', 'priority_support', 'team_collaboration', 'audit_logs', 'sso_integration', 'dedicated_infrastructure' ] }; } hasFeature(keyInfo: APIKeyInfo, feature: string): boolean { const tierFeatures = this.getFeatureTiers(); const allFeatures = [...tierFeatures.free]; if (keyInfo.tier === 'pro' || keyInfo.tier === 'enterprise') { allFeatures.push(...tierFeatures.pro); } if (keyInfo.tier === 'enterprise') { allFeatures.push(...tierFeatures.enterprise); } return allFeatures.includes(feature) || keyInfo.features.includes(feature); } hasValidKey(): boolean { const apiKey = process.env.AI_DEBUG_API_KEY; if (!apiKey) return false; const keyInfo = this.apiKeys.get(apiKey); if (!keyInfo) return false; // Check expiration if (keyInfo.expiresAt && new Date() > keyInfo.expiresAt) { return false; } // Check usage limit return keyInfo.usageCount < keyInfo.usageLimit; } getKeyStatus(): { valid: boolean; tier?: string; expiresAt?: string } { const apiKey = process.env.AI_DEBUG_API_KEY; if (!apiKey) { return { valid: false }; } const keyInfo = this.apiKeys.get(apiKey); if (!keyInfo) { return { valid: false }; } const valid = this.hasValidKey(); return { valid, tier: keyInfo.tier, expiresAt: keyInfo.expiresAt?.toISOString() }; } getUsageStats(): { aiAnalysis: number; aiReports: number; premiumFeatures: number; limits: { aiAnalysis: number; aiReports: number; premiumFeatures: number; }; } { const apiKey = process.env.AI_DEBUG_API_KEY; const keyInfo = apiKey ? this.apiKeys.get(apiKey) : null; // Default free tier limits const limits = { aiAnalysis: 0, aiReports: 0, premiumFeatures: 0 }; if (keyInfo) { switch (keyInfo.tier) { case 'pro': limits.aiAnalysis = 100; limits.aiReports = 50; limits.premiumFeatures = -1; // unlimited break; case 'enterprise': limits.aiAnalysis = -1; // unlimited limits.aiReports = -1; // unlimited limits.premiumFeatures = -1; // unlimited break; } } return { aiAnalysis: keyInfo?.usageCount || 0, aiReports: Math.floor((keyInfo?.usageCount || 0) / 2), // Rough estimate premiumFeatures: keyInfo?.usageCount || 0, limits }; } async recordUsage(feature: string): Promise<void> { const apiKey = process.env.AI_DEBUG_API_KEY; if (apiKey) { await this.incrementUsage(apiKey); } } }