diff --git a/.env.production b/.env.production new file mode 100644 index 0000000..7a5955a --- /dev/null +++ b/.env.production @@ -0,0 +1,38 @@ +# Production Environment Configuration +NODE_ENV=production +PORT=5000 + +# Database Configuration (will be set by deployment platform) +DATABASE_URL= + +# Security Configuration +SESSION_SECRET=your-production-session-secret-here +BCRYPT_ROUNDS=12 + +# API Keys (to be provided via deployment secrets) +ANTHROPIC_API_KEY= +OPENAI_API_KEY= + +# Application Configuration +APP_NAME=MenAssist +APP_VERSION=1.0.0 +CORS_ORIGIN=https://your-domain.replit.app + +# Voice Processing Configuration +VOICE_ENABLED=true +TTS_ENABLED=true +VOICE_TIMEOUT=30000 + +# AI Configuration +AI_ENABLED=true +AI_MODEL_PATH=./models/ai/base-llm +DAILY_JOKE_CACHE_TTL=86400 + +# Logging Configuration +LOG_LEVEL=info +LOG_FORMAT=json + +# Performance Configuration +CACHE_TTL=3600 +MAX_UPLOAD_SIZE=10mb +REQUEST_TIMEOUT=30000 \ No newline at end of file diff --git a/client/src/hooks/useEnhancedVoice.tsx b/client/src/hooks/useEnhancedVoice.tsx index b8be8de..a309198 100644 --- a/client/src/hooks/useEnhancedVoice.tsx +++ b/client/src/hooks/useEnhancedVoice.tsx @@ -79,7 +79,7 @@ export function useEnhancedVoice() { console.log('Voice recognition ended'); }; - recognition.onerror = (event) => { + recognition.onerror = (event: SpeechRecognitionErrorEvent) => { console.error('Voice recognition error:', event.error); setIsListening(false); if (event.error === 'no-speech') { @@ -91,17 +91,22 @@ export function useEnhancedVoice() { } }; - recognition.onresult = (event) => { + recognition.onresult = (event: SpeechRecognitionEvent) => { let finalTranscript = ''; let interimTranscript = ''; for (let i = event.resultIndex; i < event.results.length; i++) { const result = event.results[i]; - const transcript = result[0].transcript; + if (!result) continue; + + const alternative = result[0]; + if (!alternative) continue; + + const transcript = alternative.transcript; if (result.isFinal) { finalTranscript += transcript; - if (result[0].confidence >= settings.confidenceThreshold) { + if (alternative.confidence >= settings.confidenceThreshold) { processVoiceCommand(transcript, result[0].confidence); } } else { diff --git a/client/src/types/global.d.ts b/client/src/types/global.d.ts new file mode 100644 index 0000000..cf227d8 --- /dev/null +++ b/client/src/types/global.d.ts @@ -0,0 +1,79 @@ +// Global type declarations for production environment + +declare global { + interface Window { + SpeechRecognition: typeof SpeechRecognition; + webkitSpeechRecognition: typeof SpeechRecognition; + } + + interface SpeechRecognition extends EventTarget { + continuous: boolean; + grammars: SpeechGrammarList; + interimResults: boolean; + lang: string; + maxAlternatives: number; + serviceURI: string; + start(): void; + stop(): void; + abort(): void; + onaudiostart: ((this: SpeechRecognition, ev: Event) => any) | null; + onaudioend: ((this: SpeechRecognition, ev: Event) => any) | null; + onend: ((this: SpeechRecognition, ev: Event) => any) | null; + onerror: ((this: SpeechRecognition, ev: SpeechRecognitionErrorEvent) => any) | null; + onnomatch: ((this: SpeechRecognition, ev: SpeechRecognitionEvent) => any) | null; + onresult: ((this: SpeechRecognition, ev: SpeechRecognitionEvent) => any) | null; + onsoundstart: ((this: SpeechRecognition, ev: Event) => any) | null; + onsoundend: ((this: SpeechRecognition, ev: Event) => any) | null; + onspeechstart: ((this: SpeechRecognition, ev: Event) => any) | null; + onspeechend: ((this: SpeechRecognition, ev: Event) => any) | null; + onstart: ((this: SpeechRecognition, ev: Event) => any) | null; + } + + var SpeechRecognition: { + prototype: SpeechRecognition; + new(): SpeechRecognition; + }; + + interface SpeechRecognitionEvent extends Event { + readonly resultIndex: number; + readonly results: SpeechRecognitionResultList; + } + + interface SpeechRecognitionErrorEvent extends Event { + readonly error: string; + readonly message: string; + } + + interface SpeechRecognitionResult { + readonly isFinal: boolean; + readonly length: number; + item(index: number): SpeechRecognitionAlternative; + [index: number]: SpeechRecognitionAlternative; + } + + interface SpeechRecognitionResultList { + readonly length: number; + item(index: number): SpeechRecognitionResult; + [index: number]: SpeechRecognitionResult; + } + + interface SpeechRecognitionAlternative { + readonly transcript: string; + readonly confidence: number; + } + + interface SpeechGrammarList { + readonly length: number; + item(index: number): SpeechGrammar; + [index: number]: SpeechGrammar; + addFromURI(src: string, weight?: number): void; + addFromString(string: string, weight?: number): void; + } + + interface SpeechGrammar { + src: string; + weight: number; + } +} + +export {}; \ No newline at end of file diff --git a/production.config.js b/production.config.js new file mode 100644 index 0000000..322c480 --- /dev/null +++ b/production.config.js @@ -0,0 +1,79 @@ +// Production configuration for MenAssist +const config = { + // Server Configuration + server: { + port: process.env.PORT || 5000, + host: '0.0.0.0', + compression: true, + helmet: true, + rateLimit: { + windowMs: 15 * 60 * 1000, // 15 minutes + max: 100, // limit each IP to 100 requests per windowMs + }, + }, + + // Database Configuration + database: { + ssl: true, + connectionTimeout: 30000, + idleTimeout: 30000, + maxConnections: 20, + }, + + // Security Configuration + security: { + session: { + secure: true, + httpOnly: true, + sameSite: 'strict', + maxAge: 24 * 60 * 60 * 1000, // 24 hours + }, + cors: { + origin: process.env.CORS_ORIGIN || 'https://your-domain.replit.app', + credentials: true, + }, + }, + + // AI Configuration + ai: { + enabled: process.env.AI_ENABLED === 'true', + timeout: 30000, + maxTokens: 1024, + rateLimiting: { + requests: 50, + window: 60000, // 1 minute + }, + }, + + // Voice Configuration + voice: { + enabled: process.env.VOICE_ENABLED === 'true', + timeout: process.env.VOICE_TIMEOUT || 30000, + maxDuration: 60000, // 1 minute max recording + sampleRate: 16000, + }, + + // Logging Configuration + logging: { + level: process.env.LOG_LEVEL || 'info', + format: process.env.LOG_FORMAT || 'json', + enableAccessLogs: true, + enableErrorLogs: true, + }, + + // Cache Configuration + cache: { + ttl: process.env.CACHE_TTL || 3600, + maxSize: '100mb', + compression: true, + }, + + // File Upload Configuration + upload: { + maxSize: process.env.MAX_UPLOAD_SIZE || '10mb', + allowedTypes: ['image/jpeg', 'image/png', 'image/webp'], + destination: './uploads', + }, +}; + +module.exports = config; \ No newline at end of file