UNPKG

@neuroequality/neuroadapt-ai

Version:

AI-powered accessibility personalization for neurodivergent users

1 lines 220 kB
{"version":3,"file":"index.cjs","sources":["../src/adapters/base-adapter.ts","../src/adapters/openai-adapter.ts","../src/adapters/claude-adapter.ts","../src/adapters/ollama-adapter.ts","../src/predictable/predictable-ai.ts","../src/advanced/adaptive-engine.ts","../src/advanced/neural-adaptation.ts","../src/advanced/real-time-optimization.ts","../src/enterprise/sso-integration.ts","../src/enterprise/analytics-dashboard.ts","../src/enterprise/deployment-tools.ts","../src/index.ts"],"sourcesContent":["import type { AIAdapter, AIAdapterConfig, AIMessage, AIResponse, AICompletionOptions, AIStreamChunk } from '../types/index.js';\n\nexport abstract class BaseAIAdapter implements AIAdapter {\n protected config: AIAdapterConfig;\n protected currentModel: string;\n\n constructor(config: AIAdapterConfig) {\n this.config = config;\n this.currentModel = config.model || this.getDefaultModel();\n }\n\n abstract get name(): string;\n abstract get models(): string[];\n protected abstract getDefaultModel(): string;\n\n abstract complete(messages: AIMessage[], options?: AICompletionOptions): Promise<AIResponse>;\n abstract stream?(messages: AIMessage[], options?: AICompletionOptions): AsyncIterable<AIStreamChunk>;\n abstract isAvailable(): Promise<boolean>;\n\n getModel(): string {\n return this.currentModel;\n }\n\n setModel(model: string): void {\n if (!this.models.includes(model)) {\n throw new Error(`Model ${model} is not supported by ${this.name}`);\n }\n this.currentModel = model;\n }\n\n protected async retry<T>(\n operation: () => Promise<T>,\n attempts = this.config.retryAttempts || 3,\n delay = this.config.retryDelay || 1000\n ): Promise<T> {\n let lastError: Error;\n\n for (let attempt = 1; attempt <= attempts; attempt++) {\n try {\n return await operation();\n } catch (error) {\n lastError = error as Error;\n \n if (attempt === attempts) {\n throw lastError;\n }\n\n if (this.isRetryableError(error)) {\n await this.sleep(delay * Math.pow(2, attempt - 1));\n } else {\n throw lastError;\n }\n }\n }\n\n throw lastError!;\n }\n\n protected isRetryableError(error: unknown): boolean {\n if (error instanceof Error) {\n const message = error.message.toLowerCase();\n return (\n message.includes('timeout') ||\n message.includes('rate limit') ||\n message.includes('503') ||\n message.includes('502') ||\n message.includes('500')\n );\n }\n return false;\n }\n\n protected sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n }\n\n protected formatMessages(messages: AIMessage[]): unknown[] {\n return messages.map(msg => ({\n role: msg.role,\n content: msg.content,\n }));\n }\n\n protected createAbortController(signal?: AbortSignal, timeout?: number): AbortController {\n const controller = new AbortController();\n \n if (signal) {\n signal.addEventListener('abort', () => controller.abort());\n }\n \n if (timeout) {\n setTimeout(() => controller.abort(), timeout);\n }\n \n return controller;\n }\n}","import { BaseAIAdapter } from './base-adapter.js';\nimport type { AIMessage, AIResponse, AICompletionOptions, AIStreamChunk, AIAdapterConfig } from '../types/index.js';\n\nexport interface OpenAIAdapterConfig extends AIAdapterConfig {\n organization?: string;\n}\n\nexport class OpenAIAdapter extends BaseAIAdapter {\n private openai: any; // Will be dynamically imported\n\n constructor(config: OpenAIAdapterConfig) {\n super(config);\n this.initializeOpenAI();\n }\n\n get name(): string {\n return 'OpenAI';\n }\n\n get models(): string[] {\n return [\n 'gpt-4',\n 'gpt-4-turbo',\n 'gpt-4-turbo-preview',\n 'gpt-3.5-turbo',\n 'gpt-3.5-turbo-16k',\n ];\n }\n\n protected getDefaultModel(): string {\n return 'gpt-4-turbo-preview';\n }\n\n async complete(messages: AIMessage[], options: AICompletionOptions = {}): Promise<AIResponse> {\n if (!this.openai) {\n throw new Error('OpenAI client not initialized. Make sure to install the openai package.');\n }\n\n return this.retry(async () => {\n const controller = this.createAbortController(options.abortSignal, this.config.timeout);\n\n const response = await this.openai.chat.completions.create({\n model: this.currentModel,\n messages: this.formatMessages(messages),\n max_tokens: options.maxTokens,\n temperature: options.temperature,\n top_p: options.topP,\n stop: options.stop,\n stream: false,\n }, {\n signal: controller.signal,\n });\n\n return {\n content: response.choices[0]?.message?.content || '',\n usage: {\n promptTokens: response.usage?.prompt_tokens || 0,\n completionTokens: response.usage?.completion_tokens || 0,\n totalTokens: response.usage?.total_tokens || 0,\n },\n finishReason: response.choices[0]?.finish_reason as AIResponse['finishReason'],\n metadata: {\n model: response.model,\n created: response.created,\n },\n };\n });\n }\n\n async *stream(messages: AIMessage[], options: AICompletionOptions = {}): AsyncIterable<AIStreamChunk> {\n if (!this.openai) {\n throw new Error('OpenAI client not initialized. Make sure to install the openai package.');\n }\n\n const controller = this.createAbortController(options.abortSignal, this.config.timeout);\n\n const stream = await this.openai.chat.completions.create({\n model: this.currentModel,\n messages: this.formatMessages(messages),\n max_tokens: options.maxTokens,\n temperature: options.temperature,\n top_p: options.topP,\n stop: options.stop,\n stream: true,\n }, {\n signal: controller.signal,\n });\n\n for await (const chunk of stream) {\n const delta = chunk.choices[0]?.delta?.content || '';\n const done = chunk.choices[0]?.finish_reason !== null;\n\n yield {\n delta,\n done,\n usage: chunk.usage ? {\n promptTokens: chunk.usage.prompt_tokens || 0,\n completionTokens: chunk.usage.completion_tokens || 0,\n totalTokens: chunk.usage.total_tokens || 0,\n } : undefined,\n };\n\n if (done) break;\n }\n }\n\n async isAvailable(): Promise<boolean> {\n try {\n if (!this.openai) {\n return false;\n }\n await this.openai.models.list();\n return true;\n } catch (error) {\n return false;\n }\n }\n\n private async initializeOpenAI(): Promise<void> {\n try {\n const { default: OpenAI } = await import('openai');\n this.openai = new OpenAI({\n apiKey: this.config.apiKey,\n baseURL: this.config.baseURL,\n organization: (this.config as OpenAIAdapterConfig).organization,\n });\n } catch (error) {\n console.warn('OpenAI package not found. Install it to use OpenAI adapter.');\n }\n }\n}","import { BaseAIAdapter } from './base-adapter.js';\nimport type { AIMessage, AIResponse, AICompletionOptions, AIStreamChunk, AIAdapterConfig } from '../types/index.js';\n\nexport class ClaudeAdapter extends BaseAIAdapter {\n private anthropic: any; // Will be dynamically imported\n\n constructor(config: AIAdapterConfig) {\n super(config);\n this.initializeAnthropic();\n }\n\n get name(): string {\n return 'Claude';\n }\n\n get models(): string[] {\n return [\n 'claude-3-5-sonnet-20241022',\n 'claude-3-5-haiku-20241022',\n 'claude-3-opus-20240229',\n 'claude-3-sonnet-20240229',\n 'claude-3-haiku-20240307',\n ];\n }\n\n protected getDefaultModel(): string {\n return 'claude-3-5-sonnet-20241022';\n }\n\n async complete(messages: AIMessage[], options: AICompletionOptions = {}): Promise<AIResponse> {\n if (!this.anthropic) {\n throw new Error('Anthropic SDK not initialized. Make sure to install @anthropic-ai/sdk package.');\n }\n\n return this.retry(async () => {\n const { system, messages: formattedMessages } = this.formatClaudeMessages(messages);\n\n const response = await this.anthropic.messages.create({\n model: this.currentModel,\n max_tokens: options.maxTokens || 4096,\n temperature: options.temperature,\n top_p: options.topP,\n stop_sequences: options.stop,\n system,\n messages: formattedMessages,\n stream: false,\n });\n\n return {\n content: response.content[0]?.text || '',\n usage: {\n promptTokens: response.usage?.input_tokens || 0,\n completionTokens: response.usage?.output_tokens || 0,\n totalTokens: (response.usage?.input_tokens || 0) + (response.usage?.output_tokens || 0),\n },\n finishReason: response.stop_reason as AIResponse['finishReason'],\n metadata: {\n model: response.model,\n role: response.role,\n },\n };\n });\n }\n\n async *stream(messages: AIMessage[], options: AICompletionOptions = {}): AsyncIterable<AIStreamChunk> {\n if (!this.anthropic) {\n throw new Error('Anthropic SDK not initialized. Make sure to install @anthropic-ai/sdk package.');\n }\n\n const { system, messages: formattedMessages } = this.formatClaudeMessages(messages);\n\n const stream = await this.anthropic.messages.create({\n model: this.currentModel,\n max_tokens: options.maxTokens || 4096,\n temperature: options.temperature,\n top_p: options.topP,\n stop_sequences: options.stop,\n system,\n messages: formattedMessages,\n stream: true,\n });\n\n for await (const event of stream) {\n if (event.type === 'content_block_delta') {\n yield {\n delta: event.delta?.text || '',\n done: false,\n };\n } else if (event.type === 'message_stop') {\n yield {\n delta: '',\n done: true,\n usage: event.message?.usage ? {\n promptTokens: event.message.usage.input_tokens || 0,\n completionTokens: event.message.usage.output_tokens || 0,\n totalTokens: (event.message.usage.input_tokens || 0) + (event.message.usage.output_tokens || 0),\n } : undefined,\n };\n break;\n }\n }\n }\n\n async isAvailable(): Promise<boolean> {\n try {\n if (!this.anthropic) {\n return false;\n }\n // Simple test to check if the API key is valid\n await this.anthropic.messages.create({\n model: this.currentModel,\n max_tokens: 1,\n messages: [{ role: 'user', content: 'test' }],\n });\n return true;\n } catch (error) {\n // If it's an auth error but the SDK is working, return false\n // If it's a network error, also return false\n return false;\n }\n }\n\n private formatClaudeMessages(messages: AIMessage[]): { system?: string; messages: Array<{ role: string; content: string }> } {\n let system: string | undefined;\n const formattedMessages: Array<{ role: string; content: string }> = [];\n\n for (const message of messages) {\n if (message.role === 'system') {\n system = message.content;\n } else {\n formattedMessages.push({\n role: message.role,\n content: message.content,\n });\n }\n }\n\n return { system, messages: formattedMessages };\n }\n\n private async initializeAnthropic(): Promise<void> {\n try {\n const { default: Anthropic } = await import('@anthropic-ai/sdk');\n this.anthropic = new Anthropic({\n apiKey: this.config.apiKey,\n baseURL: this.config.baseURL,\n });\n } catch (error) {\n console.warn('Anthropic SDK not found. Install @anthropic-ai/sdk to use Claude adapter.');\n }\n }\n}","import { BaseAIAdapter } from './base-adapter.js';\nimport type { AIMessage, AIResponse, AICompletionOptions, AIStreamChunk, AIAdapterConfig } from '../types/index.js';\n\nexport interface OllamaAdapterConfig extends AIAdapterConfig {\n baseURL?: string;\n}\n\nexport class OllamaAdapter extends BaseAIAdapter {\n private baseURL: string;\n\n constructor(config: OllamaAdapterConfig) {\n super(config);\n this.baseURL = config.baseURL || 'http://localhost:11434';\n }\n\n get name(): string {\n return 'Ollama';\n }\n\n get models(): string[] {\n return [\n 'deepseek-r1:32b',\n 'llama3.2:3b',\n 'llama3.2:1b',\n 'phi3:mini',\n 'mistral:7b',\n 'codellama:7b',\n 'gemma2:2b',\n ];\n }\n\n protected getDefaultModel(): string {\n return 'deepseek-r1:32b';\n }\n\n async complete(messages: AIMessage[], options: AICompletionOptions = {}): Promise<AIResponse> {\n return this.retry(async () => {\n const controller = this.createAbortController(options.abortSignal, this.config.timeout);\n\n const response = await fetch(`${this.baseURL}/api/chat`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n model: this.currentModel,\n messages: this.formatMessages(messages),\n stream: false,\n options: {\n temperature: options.temperature,\n top_p: options.topP,\n stop: options.stop,\n num_predict: options.maxTokens,\n },\n }),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n throw new Error(`Ollama API error: ${response.status} ${response.statusText}`);\n }\n\n const data = await response.json();\n\n return {\n content: data.message?.content || '',\n usage: {\n promptTokens: data.prompt_eval_count || 0,\n completionTokens: data.eval_count || 0,\n totalTokens: (data.prompt_eval_count || 0) + (data.eval_count || 0),\n },\n finishReason: data.done ? 'stop' : 'length',\n metadata: {\n model: data.model,\n created_at: data.created_at,\n total_duration: data.total_duration,\n load_duration: data.load_duration,\n prompt_eval_duration: data.prompt_eval_duration,\n eval_duration: data.eval_duration,\n },\n };\n });\n }\n\n async *stream(messages: AIMessage[], options: AICompletionOptions = {}): AsyncIterable<AIStreamChunk> {\n const controller = this.createAbortController(options.abortSignal, this.config.timeout);\n\n const response = await fetch(`${this.baseURL}/api/chat`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n model: this.currentModel,\n messages: this.formatMessages(messages),\n stream: true,\n options: {\n temperature: options.temperature,\n top_p: options.topP,\n stop: options.stop,\n num_predict: options.maxTokens,\n },\n }),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n throw new Error(`Ollama API error: ${response.status} ${response.statusText}`);\n }\n\n const reader = response.body?.getReader();\n if (!reader) {\n throw new Error('No response body');\n }\n\n const decoder = new TextDecoder();\n let buffer = '';\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() || '';\n\n for (const line of lines) {\n if (line.trim()) {\n try {\n const chunk = JSON.parse(line);\n const delta = chunk.message?.content || '';\n const isDone = chunk.done || false;\n\n yield {\n delta,\n done: isDone,\n usage: isDone ? {\n promptTokens: chunk.prompt_eval_count || 0,\n completionTokens: chunk.eval_count || 0,\n totalTokens: (chunk.prompt_eval_count || 0) + (chunk.eval_count || 0),\n } : undefined,\n };\n\n if (isDone) return;\n } catch (parseError) {\n console.warn('Failed to parse Ollama chunk:', line);\n }\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n }\n\n async isAvailable(): Promise<boolean> {\n try {\n const response = await fetch(`${this.baseURL}/api/tags`, {\n method: 'GET',\n signal: AbortSignal.timeout(5000),\n });\n return response.ok;\n } catch (error) {\n return false;\n }\n }\n\n async getAvailableModels(): Promise<string[]> {\n try {\n const response = await fetch(`${this.baseURL}/api/tags`);\n if (!response.ok) {\n throw new Error('Failed to fetch models');\n }\n\n const data = await response.json();\n return data.models?.map((model: { name: string }) => model.name) || [];\n } catch (error) {\n console.warn('Failed to fetch available models from Ollama:', error);\n return this.models;\n }\n }\n\n async pullModel(model: string): Promise<void> {\n const response = await fetch(`${this.baseURL}/api/pull`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ name: model }),\n });\n\n if (!response.ok) {\n throw new Error(`Failed to pull model ${model}: ${response.statusText}`);\n }\n\n // Stream the pull progress\n const reader = response.body?.getReader();\n if (!reader) return;\n\n const decoder = new TextDecoder();\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n const chunk = decoder.decode(value);\n console.log('Pull progress:', chunk);\n }\n } finally {\n reader.releaseLock();\n }\n }\n}","import { EventEmitter } from 'eventemitter3';\nimport type { CognitivePreferences } from '@neuroadapt/core';\nimport type {\n AIAdapter,\n AIMessage,\n AIResponse,\n AIStreamChunk,\n PredictableAIConfig,\n PredictableAIEvents,\n UndoState,\n AICompletionOptions,\n} from '../types/index.js';\n\nexport class PredictableAI extends EventEmitter<PredictableAIEvents> {\n private adapter: AIAdapter;\n private config: PredictableAIConfig;\n private undoHistory: UndoState[] = [];\n private currentStep = 0;\n private cache = new Map<string, AIResponse>();\n\n constructor(adapter: AIAdapter, config: Partial<PredictableAIConfig> = {}) {\n super();\n this.adapter = adapter;\n this.config = this.mergeDefaultConfig(config);\n }\n\n async complete(prompt: string, options: AICompletionOptions = {}): Promise<AIResponse> {\n this.emit('response:start', { prompt });\n\n try {\n const messages = this.prepareMessages(prompt);\n const cacheKey = this.getCacheKey(messages);\n\n // Check cache for consistent responses\n if (this.config.consistencyLevel === 'high' && this.cache.has(cacheKey)) {\n const cachedResponse = this.cache.get(cacheKey)!;\n this.emit('response:complete', { response: cachedResponse });\n return cachedResponse;\n }\n\n const completionOptions = this.enhanceOptions(options);\n const response = await this.adapter.complete(messages, completionOptions);\n \n // Cache the response\n if (this.config.consistencyLevel !== 'low') {\n this.cache.set(cacheKey, response);\n }\n\n // Store in undo history\n if (this.config.allowUndo) {\n this.addToUndoHistory(prompt, response);\n }\n\n // Apply pacing if needed\n await this.applyPacing();\n\n this.emit('response:complete', { response });\n return response;\n } catch (error) {\n this.emit('response:error', { error: error as Error });\n throw error;\n }\n }\n\n async *stream(prompt: string, options: AICompletionOptions = {}): AsyncIterable<AIStreamChunk> {\n if (!this.adapter.stream) {\n throw new Error(`${this.adapter.name} adapter does not support streaming`);\n }\n\n this.emit('response:start', { prompt });\n\n try {\n const messages = this.prepareMessages(prompt);\n const completionOptions = this.enhanceOptions(options);\n \n let fullResponse = '';\n const startTime = Date.now();\n\n for await (const chunk of this.adapter.stream(messages, completionOptions)) {\n fullResponse += chunk.delta;\n this.emit('response:chunk', { chunk });\n yield chunk;\n\n if (chunk.done) {\n const response: AIResponse = {\n content: fullResponse,\n usage: chunk.usage,\n finishReason: 'stop',\n metadata: {\n streamDuration: Date.now() - startTime,\n },\n };\n\n // Store in undo history\n if (this.config.allowUndo) {\n this.addToUndoHistory(prompt, response);\n }\n\n this.emit('response:complete', { response });\n break;\n }\n }\n } catch (error) {\n this.emit('response:error', { error: error as Error });\n throw error;\n }\n }\n\n updateConfig(newConfig: Partial<PredictableAIConfig>): void {\n const previousConfig = { ...this.config };\n this.config = { ...this.config, ...newConfig };\n \n // Clear cache if consistency level changed\n if (newConfig.consistencyLevel && newConfig.consistencyLevel !== previousConfig.consistencyLevel) {\n this.cache.clear();\n }\n\n this.emit('config:changed', { config: newConfig });\n }\n\n updateFromCognitivePreferences(preferences: CognitivePreferences): void {\n const configUpdate: Partial<PredictableAIConfig> = {};\n\n // Map reading speed to pacing\n if (preferences.readingSpeed !== undefined) {\n const pacingMap = {\n slow: 'slow' as const,\n medium: 'normal' as const,\n fast: 'quick' as const,\n };\n configUpdate.pacing = pacingMap[preferences.readingSpeed];\n }\n\n // Map explanation level\n if (preferences.explanationLevel !== undefined) {\n const explanationMap = {\n simple: 'simple' as const,\n moderate: 'moderate' as const,\n detailed: 'detailed' as const,\n };\n configUpdate.explanationLevel = explanationMap[preferences.explanationLevel];\n }\n\n // Map processing pace to consistency\n if (preferences.processingPace !== undefined) {\n const consistencyMap = {\n relaxed: 'high' as const,\n standard: 'moderate' as const,\n quick: 'low' as const,\n };\n configUpdate.consistencyLevel = consistencyMap[preferences.processingPace];\n }\n\n this.updateConfig(configUpdate);\n }\n\n undo(): UndoState | null {\n if (!this.config.allowUndo || this.undoHistory.length === 0) {\n return null;\n }\n\n if (this.currentStep > 0) {\n this.currentStep--;\n const state = this.undoHistory[this.currentStep];\n this.emit('undo:performed', { step: this.currentStep, state });\n return state;\n }\n\n return null;\n }\n\n redo(): UndoState | null {\n if (!this.config.allowUndo || this.currentStep >= this.undoHistory.length - 1) {\n return null;\n }\n\n this.currentStep++;\n const state = this.undoHistory[this.currentStep];\n this.emit('undo:performed', { step: this.currentStep, state });\n return state;\n }\n\n canUndo(): boolean {\n return this.config.allowUndo && this.currentStep > 0;\n }\n\n canRedo(): boolean {\n return this.config.allowUndo && this.currentStep < this.undoHistory.length - 1;\n }\n\n getUndoHistory(): UndoState[] {\n return [...this.undoHistory];\n }\n\n clearUndoHistory(): void {\n this.undoHistory = [];\n this.currentStep = 0;\n }\n\n clearCache(): void {\n this.cache.clear();\n }\n\n getConfig(): PredictableAIConfig {\n return { ...this.config };\n }\n\n private prepareMessages(prompt: string): AIMessage[] {\n const systemPrompt = this.createSystemPrompt();\n const messages: AIMessage[] = [];\n\n if (systemPrompt) {\n messages.push({\n role: 'system',\n content: systemPrompt,\n timestamp: Date.now(),\n });\n }\n\n messages.push({\n role: 'user',\n content: prompt,\n timestamp: Date.now(),\n });\n\n return messages;\n }\n\n private createSystemPrompt(): string {\n const prompts: string[] = [];\n\n // Tone guidance\n const toneInstructions = {\n 'calm-supportive': 'Respond in a calm, supportive manner. Use gentle language and provide reassurance.',\n 'encouraging': 'Be encouraging and positive. Focus on possibilities and strengths.',\n 'neutral': 'Maintain a neutral, professional tone. Be clear and objective.',\n 'clinical': 'Use precise, clinical language. Be factual and methodical.',\n 'friendly': 'Be warm and friendly. Use conversational language while remaining helpful.',\n };\n prompts.push(toneInstructions[this.config.tone]);\n\n // Explanation level guidance\n const explanationInstructions = {\n simple: 'Use simple language and basic concepts. Avoid jargon and complex terms.',\n moderate: 'Provide balanced explanations with some detail. Use accessible language.',\n detailed: 'Give comprehensive explanations with examples and context.',\n technical: 'Use precise technical language and detailed explanations.',\n };\n prompts.push(explanationInstructions[this.config.explanationLevel]);\n\n // Analogy guidance\n if (this.config.useAnalogies) {\n prompts.push('When helpful, use analogies and real-world examples to clarify concepts.');\n }\n\n // Pacing guidance\n const pacingInstructions = {\n slow: 'Take time to explain each step. Break down complex ideas into smaller parts.',\n normal: 'Provide clear explanations at a steady pace.',\n quick: 'Be concise and direct. Focus on key points.',\n };\n prompts.push(pacingInstructions[this.config.pacing]);\n\n return prompts.join(' ');\n }\n\n private enhanceOptions(options: AICompletionOptions): AICompletionOptions {\n const enhanced = { ...options };\n\n // Set consistent temperature based on consistency level\n if (enhanced.temperature === undefined) {\n const temperatureMap = {\n low: 0.8,\n moderate: 0.5,\n high: 0.2,\n };\n enhanced.temperature = temperatureMap[this.config.consistencyLevel];\n }\n\n return enhanced;\n }\n\n private addToUndoHistory(prompt: string, response: AIResponse): void {\n const state: UndoState = {\n step: this.currentStep + 1,\n prompt,\n response,\n timestamp: Date.now(),\n };\n\n // Remove any redo steps when adding new state\n if (this.currentStep < this.undoHistory.length - 1) {\n this.undoHistory = this.undoHistory.slice(0, this.currentStep + 1);\n }\n\n this.undoHistory.push(state);\n this.currentStep = this.undoHistory.length - 1;\n\n // Limit undo history size\n if (this.undoHistory.length > this.config.maxUndoSteps) {\n this.undoHistory.shift();\n this.currentStep--;\n }\n }\n\n private getCacheKey(messages: AIMessage[]): string {\n const content = messages.map(m => `${m.role}:${m.content}`).join('|');\n const configKey = `${this.config.tone}:${this.config.explanationLevel}:${this.config.pacing}`;\n return `${this.adapter.name}:${this.adapter.getModel()}:${configKey}:${content}`;\n }\n\n private async applyPacing(): Promise<void> {\n if (this.config.pacing === 'slow') {\n await new Promise(resolve => setTimeout(resolve, 500));\n } else if (this.config.pacing === 'normal') {\n await new Promise(resolve => setTimeout(resolve, 200));\n }\n // No delay for quick pacing\n }\n\n private mergeDefaultConfig(config: Partial<PredictableAIConfig>): PredictableAIConfig {\n return {\n tone: 'neutral',\n explanationLevel: 'moderate',\n pacing: 'normal',\n consistencyLevel: 'moderate',\n useAnalogies: true,\n allowUndo: true,\n maxUndoSteps: 10,\n ...config,\n };\n }\n}","/**\n * Advanced Adaptive Engine - Real-time ML-powered personalization for neurodivergent users\n * @fileoverview Implements advanced machine learning algorithms for personalized accessibility adaptations\n */\n\nimport { EventEmitter } from 'eventemitter3';\nimport type { Preferences } from '@neuroadapt/core';\n\n// Define local interfaces for missing types\nexport interface CognitiveLoadMetrics {\n cognitiveLoad: number;\n taskComplexity: number;\n memoryLoad: number;\n distractorImpact: number;\n}\n\nexport interface SensoryData {\n audioSensitivity?: number;\n vibrationTolerance?: number;\n lightSensitivity?: number;\n temperaturePreference?: number;\n}\n\nexport interface AdaptationPattern {\n id: string;\n userId: string;\n patterns: {\n visual: VisualPattern;\n cognitive: CognitivePattern;\n motor: MotorPattern;\n sensory: SensoryPattern;\n };\n confidence: number;\n lastUpdated: Date;\n effectivenessScore: number;\n}\n\nexport interface VisualPattern {\n preferredContrast: number;\n colorSensitivity: string[];\n motionTolerance: number;\n fontSizePreference: number;\n brightnessAdaptation: number;\n}\n\nexport interface CognitivePattern {\n processingSpeed: number;\n workingMemoryCapacity: number;\n attentionSpan: number;\n preferredInformationDensity: number;\n distractionSensitivity: number;\n}\n\nexport interface MotorPattern {\n clickAccuracy: number;\n hoverDuration: number;\n keyboardSpeed: number;\n preferredTargetSize: number;\n gestureComplexity: number;\n}\n\nexport interface SensoryPattern {\n soundSensitivity: number;\n vibrationTolerance: number;\n lightSensitivity: number;\n temperaturePreference: number;\n texturePreference: string[];\n}\n\nexport interface AdaptationEvent {\n type: 'visual_adjustment' | 'cognitive_load_change' | 'motor_assistance' | 'sensory_calibration';\n data: any;\n confidence: number;\n timestamp: Date;\n}\n\nexport interface MLModelConfig {\n modelType: 'neural_network' | 'decision_tree' | 'random_forest' | 'svm';\n parameters: Record<string, any>;\n trainingDataSize: number;\n accuracy: number;\n lastTrained: Date;\n}\n\n/**\n * Advanced Adaptive Engine using Machine Learning for real-time personalization\n */\nexport class AdaptiveEngine extends EventEmitter {\n private patterns: Map<string, AdaptationPattern> = new Map();\n private mlModels: Map<string, MLModelConfig> = new Map();\n private realTimeMetrics: Map<string, any[]> = new Map();\n private adaptationHistory: AdaptationEvent[] = [];\n private isLearning: boolean = true;\n \n constructor(\n private config: {\n learningRate: number;\n confidenceThreshold: number;\n maxPatternAge: number;\n realTimeAdaptation: boolean;\n } = {\n learningRate: 0.1,\n confidenceThreshold: 0.8,\n maxPatternAge: 30 * 24 * 60 * 60 * 1000, // 30 days\n realTimeAdaptation: true\n }\n ) {\n super();\n this.initializeModels();\n }\n\n /**\n * Initialize machine learning models for different adaptation types\n */\n private initializeModels(): void {\n // Visual adaptation model\n this.mlModels.set('visual', {\n modelType: 'neural_network',\n parameters: {\n layers: [64, 32, 16],\n activation: 'relu',\n learningRate: 0.001,\n epochs: 100\n },\n trainingDataSize: 0,\n accuracy: 0,\n lastTrained: new Date()\n });\n\n // Cognitive load prediction model\n this.mlModels.set('cognitive', {\n modelType: 'random_forest',\n parameters: {\n n_estimators: 100,\n max_depth: 10,\n min_samples_split: 5\n },\n trainingDataSize: 0,\n accuracy: 0,\n lastTrained: new Date()\n });\n\n // Motor assistance model\n this.mlModels.set('motor', {\n modelType: 'svm',\n parameters: {\n kernel: 'rbf',\n C: 1.0,\n gamma: 'scale'\n },\n trainingDataSize: 0,\n accuracy: 0,\n lastTrained: new Date()\n });\n\n // Sensory adaptation model\n this.mlModels.set('sensory', {\n modelType: 'decision_tree',\n parameters: {\n max_depth: 15,\n min_samples_leaf: 3,\n criterion: 'gini'\n },\n trainingDataSize: 0,\n accuracy: 0,\n lastTrained: new Date()\n });\n }\n\n /**\n * Analyze user behavior and generate adaptation patterns\n */\n async analyzeUserBehavior(\n userId: string,\n interactions: any[],\n preferences: Preferences,\n cognitiveMetrics: CognitiveLoadMetrics,\n sensoryData: SensoryData\n ): Promise<AdaptationPattern> {\n const existingPattern = this.patterns.get(userId);\n \n // Analyze visual patterns\n const visualPattern = await this.analyzeVisualPatterns(interactions, preferences);\n \n // Analyze cognitive patterns\n const cognitivePattern = await this.analyzeCognitivePatterns(cognitiveMetrics, interactions);\n \n // Analyze motor patterns\n const motorPattern = await this.analyzeMotorPatterns(interactions);\n \n // Analyze sensory patterns\n const sensoryPattern = await this.analyzeSensoryPatterns(sensoryData, preferences);\n \n // Calculate confidence based on data quality and consistency\n const confidence = this.calculatePatternConfidence(\n visualPattern,\n cognitivePattern,\n motorPattern,\n sensoryPattern,\n interactions.length\n );\n \n // Calculate effectiveness score\n const effectivenessScore = await this.calculateEffectivenessScore(\n userId,\n { visual: visualPattern, cognitive: cognitivePattern, motor: motorPattern, sensory: sensoryPattern }\n );\n \n const pattern: AdaptationPattern = {\n id: `pattern_${userId}_${Date.now()}`,\n userId,\n patterns: {\n visual: visualPattern,\n cognitive: cognitivePattern,\n motor: motorPattern,\n sensory: sensoryPattern\n },\n confidence,\n lastUpdated: new Date(),\n effectivenessScore\n };\n \n this.patterns.set(userId, pattern);\n \n // Trigger real-time adaptations if enabled\n if (this.config.realTimeAdaptation && confidence > this.config.confidenceThreshold) {\n await this.applyRealTimeAdaptations(pattern);\n }\n \n this.emit('pattern_updated', pattern);\n return pattern;\n }\n\n /**\n * Analyze visual interaction patterns\n */\n private async analyzeVisualPatterns(interactions: any[], preferences: Preferences): Promise<VisualPattern> {\n const visualInteractions = interactions.filter(i => i.type === 'visual');\n \n // ML-based analysis of visual preferences\n const contrastAnalysis = this.analyzeContrastPreferences(visualInteractions);\n const colorAnalysis = this.analyzeColorSensitivity(visualInteractions, preferences);\n const motionAnalysis = this.analyzeMotionTolerance(visualInteractions);\n const fontAnalysis = this.analyzeFontPreferences(visualInteractions);\n const brightnessAnalysis = this.analyzeBrightnessAdaptation(visualInteractions);\n \n return {\n preferredContrast: contrastAnalysis.optimal,\n colorSensitivity: colorAnalysis.sensitivities,\n motionTolerance: motionAnalysis.tolerance,\n fontSizePreference: fontAnalysis.optimalSize,\n brightnessAdaptation: brightnessAnalysis.adaptation\n };\n }\n\n /**\n * Analyze cognitive load patterns using ML\n */\n private async analyzeCognitivePatterns(metrics: CognitiveLoadMetrics, interactions: any[]): Promise<CognitivePattern> {\n const cognitiveModel = this.mlModels.get('cognitive');\n \n // Process cognitive metrics through ML model\n const processingSpeed = this.predictProcessingSpeed(metrics, interactions);\n const workingMemory = this.assessWorkingMemoryCapacity(metrics, interactions);\n const attentionSpan = this.calculateAttentionSpan(interactions);\n const informationDensity = this.optimizeInformationDensity(metrics, interactions);\n const distractionSensitivity = this.assessDistractionSensitivity(metrics, interactions);\n \n return {\n processingSpeed,\n workingMemoryCapacity: workingMemory,\n attentionSpan,\n preferredInformationDensity: informationDensity,\n distractionSensitivity\n };\n }\n\n /**\n * Analyze motor interaction patterns\n */\n private async analyzeMotorPatterns(interactions: any[]): Promise<MotorPattern> {\n const motorInteractions = interactions.filter(i => i.type === 'motor');\n \n return {\n clickAccuracy: this.calculateClickAccuracy(motorInteractions),\n hoverDuration: this.calculateOptimalHoverDuration(motorInteractions),\n keyboardSpeed: this.calculateKeyboardSpeed(motorInteractions),\n preferredTargetSize: this.calculateOptimalTargetSize(motorInteractions),\n gestureComplexity: this.assessGestureComplexity(motorInteractions)\n };\n }\n\n /**\n * Analyze sensory adaptation patterns\n */\n private async analyzeSensoryPatterns(sensoryData: SensoryData, preferences: Preferences): Promise<SensoryPattern> {\n return {\n soundSensitivity: sensoryData.audioSensitivity || 0.5,\n vibrationTolerance: sensoryData.vibrationTolerance || 0.5,\n lightSensitivity: sensoryData.lightSensitivity || 0.5,\n temperaturePreference: sensoryData.temperaturePreference || 22,\n texturePreference: preferences.sensory?.texturePreferences || []\n };\n }\n\n /**\n * Apply real-time adaptations based on patterns\n */\n private async applyRealTimeAdaptations(pattern: AdaptationPattern): Promise<void> {\n const adaptations: AdaptationEvent[] = [];\n \n // Visual adaptations\n if (pattern.patterns.visual.motionTolerance < 0.3) {\n adaptations.push({\n type: 'visual_adjustment',\n data: { reduceMotion: true, animationDuration: 0 },\n confidence: pattern.confidence,\n timestamp: new Date()\n });\n }\n \n // Cognitive load adaptations\n if (pattern.patterns.cognitive.processingSpeed < 0.5) {\n adaptations.push({\n type: 'cognitive_load_change',\n data: { \n simplifyInterface: true, \n reduceInformationDensity: 0.3,\n increasePausesBetweenActions: 500 \n },\n confidence: pattern.confidence,\n timestamp: new Date()\n });\n }\n \n // Motor assistance adaptations\n if (pattern.patterns.motor.clickAccuracy < 0.7) {\n adaptations.push({\n type: 'motor_assistance',\n data: { \n increaseTargetSize: 1.5,\n enableClickAssistance: true,\n reduceFineMotorRequirements: true \n },\n confidence: pattern.confidence,\n timestamp: new Date()\n });\n }\n \n // Sensory calibrations\n if (pattern.patterns.sensory.soundSensitivity > 0.8) {\n adaptations.push({\n type: 'sensory_calibration',\n data: { \n muteNonEssentialSounds: true,\n reduceAudioVolume: 0.3,\n enableVisualAlternatives: true \n },\n confidence: pattern.confidence,\n timestamp: new Date()\n });\n }\n \n // Apply adaptations\n for (const adaptation of adaptations) {\n this.adaptationHistory.push(adaptation);\n this.emit('adaptation_applied', adaptation);\n }\n }\n\n /**\n * Train ML models with new data\n */\n async trainModels(trainingData: any[]): Promise<void> {\n for (const [modelName, model] of this.mlModels.entries()) {\n const modelData = trainingData.filter(d => d.type === modelName);\n \n if (modelData.length > 10) { // Minimum data requirement\n // Simulate ML training (in real implementation, this would use actual ML libraries)\n const accuracy = await this.simulateModelTraining(model, modelData);\n \n model.accuracy = accuracy;\n model.trainingDataSize = modelData.length;\n model.lastTrained = new Date();\n \n this.emit('model_trained', { modelName, accuracy, dataSize: modelData.length });\n }\n }\n }\n\n /**\n * Predict optimal adaptations for new user interactions\n */\n async predictAdaptations(\n userId: string,\n currentContext: any\n ): Promise<AdaptationEvent[]> {\n const pattern = this.patterns.get(userId);\n if (!pattern || pattern.confidence < this.config.confidenceThreshold) {\n return [];\n }\n \n const predictions: AdaptationEvent[] = [];\n \n // Use ML models to predict needed adaptations\n for (const [modelType, model] of this.mlModels.entries()) {\n if (model.accuracy > 0.7) {\n const prediction = await this.runModelPrediction(model, currentContext, pattern);\n if (prediction.confidence > this.config.confidenceThreshold) {\n predictions.push(prediction);\n }\n }\n }\n \n return predictions;\n }\n\n /**\n * Get adaptation effectiveness metrics\n */\n getAdaptationMetrics(userId: string): {\n totalAdaptations: number;\n averageConfidence: number;\n effectivenessScore: number;\n lastAdaptation: Date | null;\n } {\n const userAdaptations = this.adaptationHistory.filter(a => \n this.patterns.get(userId)?.id === a.data?.patternId\n );\n \n const pattern = this.patterns.get(userId);\n \n return {\n totalAdaptations: userAdaptations.length,\n averageConfidence: userAdaptations.reduce((sum, a) => sum + a.confidence, 0) / userAdaptations.length || 0,\n effectivenessScore: pattern?.effectivenessScore || 0,\n lastAdaptation: userAdaptations.length > 0 ? userAdaptations[userAdaptations.length - 1].timestamp : null\n };\n }\n\n // Private utility methods for ML analysis\n private analyzeContrastPreferences(interactions: any[]): { optimal: number } {\n // Simulate ML analysis\n const contrastValues = interactions.map(i => i.contrastLevel || 1.0);\n return { optimal: contrastValues.reduce((a, b) => a + b, 0) / contrastValues.length || 1.0 };\n }\n\n private analyzeColorSensitivity(interactions: any[], preferences: Preferences): { sensitivities: string[] } {\n // Simulate color sensitivity analysis\n return { sensitivities: preferences.visual?.colorBlindnessType ? [preferences.visual.colorBlindnessType] : [] };\n }\n\n private analyzeMotionTolerance(interactions: any[]): { tolerance: number } {\n // Simulate motion tolerance analysis\n const motionEvents = interactions.filter(i => i.type === 'motion_response');\n return { tolerance: motionEvents.length > 0 ? motionEvents[0].tolerance || 0.5 : 0.5 };\n }\n\n private analyzeFontPreferences(interactions: any[]): { optimalSize: number } {\n // Simulate font preference analysis\n return { optimalSize: 16 }; // Default optimal size\n }\n\n private analyzeBrightnessAdaptation(interactions: any[]): { adaptation: number } {\n // Simulate brightness adaptation analysis\n return { adaptation: 0.8 }; // Default adaptation level\n }\n\n private predictProcessingSpeed(metrics: CognitiveLoadMetrics, interactions: any[]): number {\n // Simulate processing speed prediction using ML\n return metrics.taskComplexity ? 1 - metrics.taskComplexity : 0.7;\n }\n\n private assessWorkingMemoryCapacity(metrics: CognitiveLoadMetrics, interactions: any[]): number {\n // Simulate working memory assessment\n return metrics.memoryLoad ? 1 - metrics.memoryLoad : 0.7;\n }\n\n private calculateAttentionSpan(interactions: any[]): number {\n // Calculate attention span from interaction patterns\n return 30; // Default 30 seconds\n }\n\n private optimizeInformationDensity(metrics: CognitiveLoadMetrics, interactions: any[]): number {\n // Optimize information density based on cognitive load\n return metrics.cognitiveLoad ? Math.max(0.1, 1 - metrics.cognitiveLoad) : 0.7;\n }\n\n private assessDistractionSensitivity(metrics: CognitiveLoadMetrics, interactions: any[]): number {\n // Assess sensitivity to distractions\n return metrics.distractorImpact || 0.5;\n }\n\n private calculateClickAccuracy(interactions: any[]): number {\n // Calculate click accuracy from motor interactions\n const clicks = interactions.filter(i => i.action === 'click');\n const successfulClicks = clicks.filter(c => c.successful);\n return clicks.length > 0 ? successfulClicks.length / clicks.length : 1.0;\n }\n\n private calculateOptimalHoverDuration(interactions: any[]): number {\n // Calculate optimal hover duration\n const hovers = interactions.filter(i => i.action === 'hover');\n const durations = hovers.map(h => h.duration || 500);\n return durations.reduce((a, b) => a + b, 0) / durations.length || 500;\n }\n\n private calculateKeyboardSpeed(interactions: any[]): number {\n // Calculate keyboard interaction speed\n return 0.8; // Default speed factor\n }\n\n private calculateOptimalTargetSize(interactions: any[]): number {\n // Calculate optimal target size based on accuracy\n return 44; // Default 44px (WCAG recommendation)\n }\n\n private assessGestureComplexity(interactions: any[]): number {\n // Assess comfortable gesture complexity level\n return 0.5; // Default medium complexity\n }\n\n private calculatePatternConfidence(\n visual: VisualPattern,\n cognitive: CognitivePattern,\n motor: MotorPattern,\n sensory: SensoryPattern,\n dataPoints: number\n ): number {\n // Calculate overall confidence based on data quality and consistency\n const dataQualityScore = Math.min(1.0, dataPoints / 100); // More data = higher confidence\n const patternConsistencyScore = 0.8; // Simulate consistency analysis\n \n return (dataQualityScore + patternConsistencyScore) / 2;\n }\n\n private async calculateEffectivenessScore(\n userId: string,\n patterns: { visual: VisualPattern; cognitive: CognitivePattern; motor: MotorPattern; sensory: SensoryPattern }\n ): Promise<number> {\n // Simulate effectiveness score calculation\n return 0.85; // Default high effectiveness\n }\n\n private async simulateModelTraining(model: MLModelConfig, data: any[]): Promise<number> {\n // Simulate ML model training and return accuracy\n await new Promise(resolve => setTimeout(resolve, 100)); // Simulate training time\n return Math.random() * 0.3 + 0.7; // Random accuracy between 0.7-1.0\n }\n\n private async runModelPrediction(\n model: MLModelConfig,\n context: any,\n pattern: AdaptationPattern\n ): Promise<AdaptationEvent> {\n // Simulate ML model prediction\n return {\n type: 'visual_adjustment',\n data: { prediction: 'optimize_contrast' },\n confidence: model.accuracy,\n timestamp: new Date()\n };\n }\n}\n\nexport default AdaptiveEngine; ","/**\n * Neural Adaptation System - Real-time neural network for accessibility adaptation\n * @fileoverview Implements neural networks for continuous learning and optimization of user preferences\n */\n\nimport { EventEmitter } from 'eventemitter3';\n\nexport interface NeuralLayer {\n weights: number[][];\n biases: number[];\n activation: ActivationFunction;\n dropout?: number;\n}\n\nexport type ActivationFunction = 'relu' | 'sigmoid' | 'tanh' | 'leaky_relu' | 'softmax';\n\nexport interface NeuralNetworkConfig {\n layers: number[];\n activations: ActivationFunction[];\n learningRate: number;\n momentum: number;\n regularization: number;\n batchSize: number;\n maxEpochs: number;\n convergenceThreshold: number;\n}\n\nexport interface TrainingData {\n inputs: number[];\n targets: number[];\n userId: string;\n timestamp: Date;\n context: {\n deviceType: string;\n environment: string;\n timeOfDay: number;\n cognitiveState: number;\n };\n}\n\nexport interface PredictionResult {\n adaptations: {\n visual: number[];\n cognitive: number[];\n motor: number[];\n sensory: number[];\n };\n confidence: number;\n reasoning: string[];\n alternatives: Array<{\n adaptations: any;\n confidence: number;\n }>;\n}\n\nexport interface LearningMetrics {\n epoch: number;\n loss: number;\n accuracy: number;\n validationLoss: number;\n validationAccuracy: number;\n learningRate: number;\n convergenceRate: number;\n}\n\n/**\n * Neural Adaptation System for real-time accessibility optimization\n */\nexport class NeuralAdaptationSystem extends EventEmitter {\n private network: NeuralLayer[] = [];\n private trainingHistory: LearningMetrics[] = [];\n private realtimeBuffer: TrainingData[] = [];\n private isTraining: boolean = false;\n private currentEpoch: number = 0;\n \n constructor(\n private config: NeuralNetworkConfig = {\n layers: [24, 64, 32, 16, 8], // Input -> Hidden layers -> Output\n activations: ['relu', 'relu', 'relu', 'relu', 'sigmoid'],\n learningRate: 0.001,\n momentum: 0.9,\n regularization: 0.01,\n batchSize: 32,\n maxEpochs: 1000,\n convergenceThreshold: 0.001\n }\n ) {\n super();\n this.initializeNetwork();\n }\n\n /**\n * Initialize neural network with random weights\n */\n private initializeNetwork(): void {\n this.network = [];\n \n for (let i = 0; i < this.config.layers.length - 1; i++) {\n const inputSize = this.config.layers[i];\n const outputSize = this.config.l