@neuroequality/neuroadapt-ai
Version:
AI-powered accessibility personalization for neurodivergent users
1 lines • 65.4 kB
Source Map (JSON)
{"version":3,"file":"ollama-provider-gL0I5wVg.cjs","sources":["../src/providers/base-provider.ts","../src/providers/claude-provider.ts","../src/providers/openai-provider.ts","../src/providers/ollama-provider.ts"],"sourcesContent":["import { EventEmitter } from 'eventemitter3';\nimport type { \n AIProviderConfig, \n ModelCapabilities, \n StreamChunk, \n AdaptationSuggestion \n} from '../types/common.js';\n\n/**\n * Events emitted by AI providers\n */\nexport interface AIProviderEvents {\n 'stream-chunk': (chunk: StreamChunk) => void;\n 'stream-complete': (result: string) => void;\n 'stream-error': (error: Error) => void;\n 'rate-limit': (retryAfter: number) => void;\n 'error': (error: Error) => void;\n}\n\n/**\n * Request parameters for AI providers\n */\nexport interface AIRequest {\n prompt: string;\n system?: string;\n context?: Record<string, unknown>;\n maxTokens?: number;\n temperature?: number;\n stream?: boolean;\n functions?: AIFunction[];\n}\n\n/**\n * AI function definition for function calling\n */\nexport interface AIFunction {\n name: string;\n description: string;\n parameters: {\n type: 'object';\n properties: Record<string, {\n type: string;\n description: string;\n enum?: string[];\n }>;\n required?: string[];\n };\n}\n\n/**\n * AI response structure\n */\nexport interface AIResponse {\n content: string;\n usage?: {\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n };\n functionCall?: {\n name: string;\n arguments: Record<string, unknown>;\n };\n finishReason: 'stop' | 'length' | 'function_call' | 'content_filter';\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Provider status information\n */\nexport interface ProviderStatus {\n isAvailable: boolean;\n isConfigured: boolean;\n lastError?: string;\n rateLimitRemaining?: number;\n rateLimitReset?: number;\n}\n\n/**\n * Abstract base class for AI providers\n */\nexport abstract class BaseAIProvider extends EventEmitter<AIProviderEvents> {\n protected config: AIProviderConfig;\n protected capabilities: ModelCapabilities;\n protected status: ProviderStatus;\n\n constructor(config: AIProviderConfig) {\n super();\n this.config = { ...config };\n this.capabilities = this.getCapabilities();\n this.status = {\n isAvailable: false,\n isConfigured: this.isConfigValid(),\n };\n }\n\n /**\n * Get provider capabilities\n */\n abstract getCapabilities(): ModelCapabilities;\n\n /**\n * Get provider name\n */\n abstract getProviderName(): string;\n\n /**\n * Get available models\n */\n abstract getAvailableModels(): string[];\n\n /**\n * Generate text completion\n */\n abstract generate(request: AIRequest): Promise<AIResponse>;\n\n /**\n * Generate streaming text completion\n */\n abstract generateStream(request: AIRequest): AsyncGenerator<StreamChunk, void, unknown>;\n\n /**\n * Analyze content for accessibility adaptations\n */\n abstract analyzeAccessibility(\n content: string,\n currentPreferences: Record<string, unknown>,\n context?: Record<string, unknown>\n ): Promise<AdaptationSuggestion[]>;\n\n /**\n * Simplify content for cognitive accessibility\n */\n abstract simplifyContent(\n content: string,\n targetLevel: 'simple' | 'intermediate' | 'advanced',\n context?: Record<string, unknown>\n ): Promise<string>;\n\n /**\n * Update provider configuration\n */\n updateConfig(newConfig: Partial<AIProviderConfig>): void {\n this.config = { ...this.config, ...newConfig };\n this.status.isConfigured = this.isConfigValid();\n this.checkAvailability();\n }\n\n /**\n * Get current provider status\n */\n getStatus(): ProviderStatus {\n return { ...this.status };\n }\n\n /**\n * Test provider availability\n */\n async testConnection(): Promise<boolean> {\n try {\n const testRequest: AIRequest = {\n prompt: 'Hello',\n maxTokens: 5,\n };\n \n await this.generate(testRequest);\n this.status.isAvailable = true;\n return true;\n } catch (error) {\n this.status.isAvailable = false;\n this.status.lastError = error instanceof Error ? error.message : String(error);\n return false;\n }\n }\n\n /**\n * Get estimated cost for request\n */\n estimateCost(request: AIRequest): number {\n // Base implementation - providers should override with actual pricing\n const estimatedTokens = Math.ceil(request.prompt.length / 4) + (request.maxTokens || 100);\n return estimatedTokens * 0.00001; // $0.00001 per token as base estimate\n }\n\n /**\n * Check if provider supports a specific capability\n */\n supportsCapability(capability: keyof ModelCapabilities): boolean {\n return this.capabilities[capability];\n }\n\n /**\n * Get rate limit information\n */\n getRateLimitInfo(): { remaining?: number; reset?: number } {\n return {\n remaining: this.status.rateLimitRemaining,\n reset: this.status.rateLimitReset,\n };\n }\n\n // Protected methods for subclasses\n\n /**\n * Validate provider configuration\n */\n protected isConfigValid(): boolean {\n return !!(this.config.apiKey || this.config.baseURL);\n }\n\n /**\n * Check provider availability\n */\n protected async checkAvailability(): Promise<void> {\n if (this.status.isConfigured) {\n await this.testConnection();\n }\n }\n\n /**\n * Handle rate limiting\n */\n protected handleRateLimit(retryAfter: number): void {\n this.status.rateLimitReset = Date.now() + (retryAfter * 1000);\n this.status.rateLimitRemaining = 0;\n this.emit('rate-limit', retryAfter);\n }\n\n /**\n * Update rate limit status\n */\n protected updateRateLimit(remaining: number, reset: number): void {\n this.status.rateLimitRemaining = remaining;\n this.status.rateLimitReset = reset;\n }\n\n /**\n * Create standard error response\n */\n protected createErrorResponse(error: Error): never {\n this.status.lastError = error.message;\n this.emit('error', error);\n throw error;\n }\n\n /**\n * Validate request parameters\n */\n protected validateRequest(request: AIRequest): void {\n if (!request.prompt) {\n throw new Error('Prompt is required');\n }\n\n if (request.maxTokens && request.maxTokens <= 0) {\n throw new Error('maxTokens must be positive');\n }\n\n if (request.temperature && (request.temperature < 0 || request.temperature > 2)) {\n throw new Error('temperature must be between 0 and 2');\n }\n\n if (request.stream && !this.capabilities.streaming) {\n throw new Error('Streaming not supported by this provider');\n }\n\n if (request.functions && !this.capabilities.functionCalling) {\n throw new Error('Function calling not supported by this provider');\n }\n }\n\n /**\n * Create accessibility analysis prompt\n */\n protected createAccessibilityPrompt(\n content: string,\n currentPreferences: Record<string, unknown>\n ): string {\n return `Analyze this content for accessibility improvements for neurodivergent users.\n\nCurrent user preferences: ${JSON.stringify(currentPreferences, null, 2)}\n\nContent to analyze:\n${content}\n\nProvide specific suggestions for:\n1. Sensory adaptations (motion, contrast, visual)\n2. Cognitive load reduction (chunking, simplification)\n3. Navigation improvements\n4. Content structure optimizations\n\nFormat your response as actionable recommendations with confidence scores.`;\n }\n\n /**\n * Create content simplification prompt\n */\n protected createSimplificationPrompt(\n content: string,\n targetLevel: string\n ): string {\n return `Simplify this content for a ${targetLevel} reading level while preserving all important information.\n\nGuidelines:\n- Use shorter sentences\n- Replace complex words with simpler alternatives\n- Break up long paragraphs\n- Add clear headings and structure\n- Maintain factual accuracy\n\nOriginal content:\n${content}\n\nSimplified version:`;\n }\n\n /**\n * Parse adaptation suggestions from AI response\n */\n protected parseAdaptationSuggestions(response: string): AdaptationSuggestion[] {\n // Basic parsing - providers can override for better parsing\n const suggestions: AdaptationSuggestion[] = [];\n \n // This is a simplified parser - real implementation would be more sophisticated\n const lines = response.split('\\n').filter(line => line.trim());\n \n for (const line of lines) {\n if (line.includes('motion') || line.includes('animation')) {\n suggestions.push({\n type: 'sensory',\n target: 'motionReduction',\n action: 'enable',\n reasoning: line,\n confidence: 'medium',\n priority: 'medium',\n estimatedImpact: 0.6,\n });\n }\n \n if (line.includes('contrast') || line.includes('color')) {\n suggestions.push({\n type: 'sensory',\n target: 'highContrast',\n action: 'enable',\n reasoning: line,\n confidence: 'medium',\n priority: 'medium',\n estimatedImpact: 0.7,\n });\n }\n \n if (line.includes('chunk') || line.includes('break')) {\n suggestions.push({\n type: 'cognitive',\n target: 'chunkSize',\n action: 'adjust',\n value: 2,\n reasoning: line,\n confidence: 'high',\n priority: 'high',\n estimatedImpact: 0.8,\n });\n }\n }\n \n return suggestions;\n }\n} ","import { BaseAIProvider } from './base-provider.js';\nimport type { \n AIRequest, \n AIResponse, \n ModelCapabilities, \n StreamChunk, \n AdaptationSuggestion,\n AIProviderConfig \n} from '../types/common.js';\n\n/**\n * Anthropic Claude provider configuration\n */\nexport interface ClaudeConfig extends AIProviderConfig {\n model?: 'claude-3-opus-20240229' | 'claude-3-sonnet-20240229' | 'claude-3-haiku-20240307';\n anthropicVersion?: string;\n}\n\n/**\n * Claude API response structure\n */\ninterface ClaudeMessage {\n role: 'user' | 'assistant';\n content: string;\n}\n\ninterface ClaudeResponse {\n content: Array<{ type: 'text'; text: string }>;\n id: string;\n model: string;\n role: 'assistant';\n stop_reason: 'end_turn' | 'max_tokens' | 'stop_sequence';\n stop_sequence?: string;\n type: 'message';\n usage: {\n input_tokens: number;\n output_tokens: number;\n };\n}\n\n/**\n * Claude provider for Anthropic's Claude models\n */\nexport class ClaudeProvider extends BaseAIProvider {\n private anthropic: any; // Will be imported dynamically\n private model: string;\n\n constructor(config: ClaudeConfig) {\n super(config);\n this.model = config.model || 'claude-3-sonnet-20240229';\n this.initializeClient();\n }\n\n getProviderName(): string {\n return 'Claude/Anthropic';\n }\n\n getCapabilities(): ModelCapabilities {\n return {\n textGeneration: true,\n textAnalysis: true,\n codeGeneration: true,\n reasoning: true,\n streaming: true,\n functionCalling: false, // Claude doesn't support function calling yet\n vision: this.model.includes('claude-3'), // Vision available in Claude 3\n };\n }\n\n getAvailableModels(): string[] {\n return [\n 'claude-3-opus-20240229',\n 'claude-3-sonnet-20240229', \n 'claude-3-haiku-20240307',\n ];\n }\n\n async generate(request: AIRequest): Promise<AIResponse> {\n this.validateRequest(request);\n\n if (!this.anthropic) {\n throw new Error('Claude client not initialized. Make sure anthropic package is installed.');\n }\n\n try {\n const messages: ClaudeMessage[] = [\n { role: 'user', content: request.prompt }\n ];\n\n const response = await this.anthropic.messages.create({\n model: this.model,\n max_tokens: request.maxTokens || 1000,\n temperature: request.temperature || 0.7,\n messages,\n ...(request.system && { system: request.system }),\n });\n\n return this.mapResponse(response);\n } catch (error) {\n return this.createErrorResponse(\n error instanceof Error ? error : new Error(String(error))\n );\n }\n }\n\n async* generateStream(request: AIRequest): AsyncGenerator<StreamChunk, void, unknown> {\n this.validateRequest(request);\n\n if (!this.anthropic) {\n throw new Error('Claude client not initialized');\n }\n\n try {\n const messages: ClaudeMessage[] = [\n { role: 'user', content: request.prompt }\n ];\n\n const stream = await this.anthropic.messages.create({\n model: this.model,\n max_tokens: request.maxTokens || 1000,\n temperature: request.temperature || 0.7,\n messages,\n stream: true,\n ...(request.system && { system: request.system }),\n });\n\n let content = '';\n for await (const chunk of stream) {\n if (chunk.type === 'content_block_delta' && chunk.delta?.text) {\n content += chunk.delta.text;\n \n const streamChunk: StreamChunk = {\n id: chunk.index?.toString() || Date.now().toString(),\n type: 'token',\n content: chunk.delta.text,\n timestamp: Date.now(),\n };\n\n yield streamChunk;\n this.emit('stream-chunk', streamChunk);\n } else if (chunk.type === 'message_stop') {\n const doneChunk: StreamChunk = {\n id: 'done',\n type: 'done',\n content: content,\n timestamp: Date.now(),\n };\n \n yield doneChunk;\n this.emit('stream-complete', content);\n }\n }\n } catch (error) {\n const errorChunk: StreamChunk = {\n id: 'error',\n type: 'error',\n content: error instanceof Error ? error.message : String(error),\n timestamp: Date.now(),\n };\n \n yield errorChunk;\n this.emit('stream-error', error instanceof Error ? error : new Error(String(error)));\n }\n }\n\n async analyzeAccessibility(\n content: string,\n currentPreferences: Record<string, unknown>,\n context?: Record<string, unknown>\n ): Promise<AdaptationSuggestion[]> {\n const prompt = `${this.createAccessibilityPrompt(content, currentPreferences)}\n\nAdditional context: ${context ? JSON.stringify(context) : 'None'}\n\nPlease analyze the content and provide specific, actionable accessibility recommendations for neurodivergent users. Focus on:\n\n1. Visual adaptations (motion reduction, contrast, font size)\n2. Cognitive load management (content chunking, simplification)\n3. Navigation and interaction improvements\n4. Content structure optimization\n\nFormat your response as a structured analysis with specific recommendations, confidence levels, and estimated impact.`;\n\n const response = await this.generate({\n prompt,\n system: 'You are an accessibility expert specializing in neurodivergent user needs. Provide practical, specific recommendations.',\n maxTokens: 1500,\n temperature: 0.3,\n });\n\n return this.parseAdaptationSuggestions(response.content);\n }\n\n async simplifyContent(\n content: string,\n targetLevel: 'simple' | 'intermediate' | 'advanced',\n context?: Record<string, unknown>\n ): Promise<string> {\n const prompt = `${this.createSimplificationPrompt(content, targetLevel)}\n\n${context ? `Additional context: ${JSON.stringify(context)}` : ''}\n\nGuidelines for ${targetLevel} level:\n- Simple: 5th-8th grade reading level, short sentences, common words\n- Intermediate: 9th-12th grade reading level, moderate complexity\n- Advanced: College level, but still clear and well-structured\n\nImportant: Preserve all factual information and key concepts while making the language more accessible.`;\n\n const response = await this.generate({\n prompt,\n system: 'You are an expert at making content accessible while preserving information accuracy and completeness.',\n maxTokens: Math.max(2000, Math.ceil(content.length * 1.5)),\n temperature: 0.2,\n });\n\n return response.content;\n }\n\n // Private methods\n\n private async initializeClient(): Promise<void> {\n try {\n // Dynamic import to handle optional dependency\n const { Anthropic } = await import('anthropic');\n \n if (!this.config.apiKey) {\n throw new Error('Claude API key is required');\n }\n\n this.anthropic = new Anthropic({\n apiKey: this.config.apiKey,\n baseURL: this.config.baseURL,\n });\n\n this.status.isAvailable = true;\n } catch (error) {\n console.warn('Claude provider not available:', error);\n this.status.isAvailable = false;\n this.status.lastError = 'anthropic package not installed or API key missing';\n }\n }\n\n private mapResponse(claudeResponse: ClaudeResponse): AIResponse {\n const content = claudeResponse.content\n .filter(block => block.type === 'text')\n .map(block => block.text)\n .join('');\n\n return {\n content,\n usage: {\n promptTokens: claudeResponse.usage.input_tokens,\n completionTokens: claudeResponse.usage.output_tokens,\n totalTokens: claudeResponse.usage.input_tokens + claudeResponse.usage.output_tokens,\n },\n finishReason: this.mapStopReason(claudeResponse.stop_reason),\n metadata: {\n model: claudeResponse.model,\n id: claudeResponse.id,\n },\n };\n }\n\n private mapStopReason(stopReason: string): AIResponse['finishReason'] {\n switch (stopReason) {\n case 'end_turn':\n return 'stop';\n case 'max_tokens':\n return 'length';\n case 'stop_sequence':\n return 'stop';\n default:\n return 'stop';\n }\n }\n\n protected parseAdaptationSuggestions(response: string): AdaptationSuggestion[] {\n const suggestions: AdaptationSuggestion[] = [];\n \n // Enhanced parsing for Claude's structured responses\n const sections = response.split('\\n').filter(line => line.trim());\n \n for (const line of sections) {\n const lowercaseLine = line.toLowerCase();\n \n // Motion and animation suggestions\n if (lowercaseLine.includes('motion') || lowercaseLine.includes('animation') || lowercaseLine.includes('autoplay')) {\n suggestions.push({\n type: 'sensory',\n target: 'motionReduction',\n action: 'enable',\n reasoning: line.trim(),\n confidence: 'high',\n priority: 'high',\n estimatedImpact: 0.8,\n });\n }\n \n // Contrast and color suggestions\n if (lowercaseLine.includes('contrast') || lowercaseLine.includes('color') || lowercaseLine.includes('visibility')) {\n suggestions.push({\n type: 'sensory',\n target: 'highContrast',\n action: 'enable',\n reasoning: line.trim(),\n confidence: 'high',\n priority: 'medium',\n estimatedImpact: 0.7,\n });\n }\n \n // Font size suggestions\n if (lowercaseLine.includes('font') || lowercaseLine.includes('text size') || lowercaseLine.includes('readability')) {\n suggestions.push({\n type: 'sensory',\n target: 'fontSize',\n action: 'adjust',\n value: 1.2,\n reasoning: line.trim(),\n confidence: 'medium',\n priority: 'medium',\n estimatedImpact: 0.6,\n });\n }\n \n // Cognitive load suggestions\n if (lowercaseLine.includes('chunk') || lowercaseLine.includes('break') || lowercaseLine.includes('section')) {\n suggestions.push({\n type: 'cognitive',\n target: 'chunkSize',\n action: 'adjust',\n value: 2,\n reasoning: line.trim(),\n confidence: 'high',\n priority: 'high',\n estimatedImpact: 0.9,\n });\n }\n \n // Content structure suggestions\n if (lowercaseLine.includes('heading') || lowercaseLine.includes('structure') || lowercaseLine.includes('organize')) {\n suggestions.push({\n type: 'content',\n target: 'structure',\n action: 'adjust',\n reasoning: line.trim(),\n confidence: 'high',\n priority: 'medium',\n estimatedImpact: 0.7,\n });\n }\n }\n \n // Remove duplicates based on type and target\n const uniqueSuggestions = suggestions.filter((suggestion, index, array) => \n array.findIndex(s => s.type === suggestion.type && s.target === suggestion.target) === index\n );\n \n return uniqueSuggestions;\n }\n\n estimateCost(request: AIRequest): number {\n // Claude pricing (approximate, as of 2024)\n const inputTokens = Math.ceil(request.prompt.length / 4);\n const outputTokens = request.maxTokens || 1000;\n \n let inputCost, outputCost;\n \n switch (this.model) {\n case 'claude-3-opus-20240229':\n inputCost = inputTokens * 0.000015; // $15 per 1M tokens\n outputCost = outputTokens * 0.000075; // $75 per 1M tokens\n break;\n case 'claude-3-sonnet-20240229':\n inputCost = inputTokens * 0.000003; // $3 per 1M tokens\n outputCost = outputTokens * 0.000015; // $15 per 1M tokens\n break;\n case 'claude-3-haiku-20240307':\n inputCost = inputTokens * 0.00000025; // $0.25 per 1M tokens\n outputCost = outputTokens * 0.00000125; // $1.25 per 1M tokens\n break;\n default:\n return super.estimateCost(request);\n }\n \n return inputCost + outputCost;\n }\n} ","import { BaseAIProvider } from './base-provider.js';\nimport type { \n AIRequest, \n AIResponse, \n ModelCapabilities, \n StreamChunk, \n AdaptationSuggestion,\n AIProviderConfig \n} from './base-provider.js';\n\n/**\n * OpenAI provider configuration\n */\nexport interface OpenAIConfig extends AIProviderConfig {\n model?: string;\n organization?: string;\n}\n\n/**\n * OpenAI API response structure\n */\ninterface OpenAIResponse {\n id: string;\n object: string;\n created: number;\n model: string;\n choices: Array<{\n index: number;\n message: {\n role: 'assistant';\n content: string;\n };\n finish_reason: 'stop' | 'length' | 'function_call' | 'content_filter';\n }>;\n usage: {\n prompt_tokens: number;\n completion_tokens: number;\n total_tokens: number;\n };\n}\n\n/**\n * OpenAI provider for GPT models\n */\nexport class OpenAIProvider extends BaseAIProvider {\n private openai: any; // Will be imported dynamically\n private model: string;\n\n constructor(config: OpenAIConfig) {\n super(config);\n this.model = config.model || 'gpt-4-turbo-preview';\n this.initializeClient();\n }\n\n getProviderName(): string {\n return 'OpenAI';\n }\n\n getCapabilities(): ModelCapabilities {\n return {\n textGeneration: true,\n textAnalysis: true,\n codeGeneration: true,\n reasoning: true,\n streaming: true,\n functionCalling: this.model.includes('gpt-4') || this.model.includes('gpt-3.5-turbo'),\n vision: this.model.includes('vision') || this.model === 'gpt-4-turbo-preview',\n };\n }\n\n getAvailableModels(): string[] {\n return [\n 'gpt-4-turbo-preview',\n 'gpt-4',\n 'gpt-4-vision-preview',\n 'gpt-3.5-turbo',\n 'gpt-3.5-turbo-16k',\n ];\n }\n\n async generate(request: AIRequest): Promise<AIResponse> {\n this.validateRequest(request);\n\n if (!this.openai) {\n throw new Error('OpenAI client not initialized. Make sure openai package is installed.');\n }\n\n try {\n const messages = [\n ...(request.system ? [{ role: 'system' as const, content: request.system }] : []),\n { role: 'user' as const, content: request.prompt },\n ];\n\n const response = await this.openai.chat.completions.create({\n model: this.model,\n messages,\n max_tokens: request.maxTokens || 1000,\n temperature: request.temperature || 0.7,\n ...(request.functions && { functions: request.functions }),\n });\n\n return this.mapResponse(response);\n } catch (error) {\n return this.createErrorResponse(\n error instanceof Error ? error : new Error(String(error))\n );\n }\n }\n\n async* generateStream(request: AIRequest): AsyncGenerator<StreamChunk, void, unknown> {\n this.validateRequest(request);\n\n if (!this.openai) {\n throw new Error('OpenAI client not initialized');\n }\n\n try {\n const messages = [\n ...(request.system ? [{ role: 'system' as const, content: request.system }] : []),\n { role: 'user' as const, content: request.prompt },\n ];\n\n const stream = await this.openai.chat.completions.create({\n model: this.model,\n messages,\n max_tokens: request.maxTokens || 1000,\n temperature: request.temperature || 0.7,\n stream: true,\n ...(request.functions && { functions: request.functions }),\n });\n\n let content = '';\n for await (const chunk of stream) {\n const delta = chunk.choices[0]?.delta;\n \n if (delta?.content) {\n content += delta.content;\n \n const streamChunk: StreamChunk = {\n id: chunk.id,\n type: 'token',\n content: delta.content,\n timestamp: Date.now(),\n };\n\n yield streamChunk;\n this.emit('stream-chunk', streamChunk);\n } else if (chunk.choices[0]?.finish_reason) {\n const doneChunk: StreamChunk = {\n id: chunk.id,\n type: 'done',\n content: content,\n timestamp: Date.now(),\n };\n \n yield doneChunk;\n this.emit('stream-complete', content);\n }\n }\n } catch (error) {\n const errorChunk: StreamChunk = {\n id: 'error',\n type: 'error',\n content: error instanceof Error ? error.message : String(error),\n timestamp: Date.now(),\n };\n \n yield errorChunk;\n this.emit('stream-error', error instanceof Error ? error : new Error(String(error)));\n }\n }\n\n async analyzeAccessibility(\n content: string,\n currentPreferences: Record<string, unknown>,\n context?: Record<string, unknown>\n ): Promise<AdaptationSuggestion[]> {\n const prompt = `${this.createAccessibilityPrompt(content, currentPreferences)}\n\nAdditional context: ${context ? JSON.stringify(context) : 'None'}\n\nAnalyze the content and provide specific accessibility recommendations for neurodivergent users. Focus on practical, implementable suggestions for:\n\n1. Visual adaptations (motion, contrast, font sizing)\n2. Cognitive load management (content structure, complexity)\n3. Navigation improvements\n4. Interactive element accessibility\n\nProvide specific, actionable recommendations with confidence levels and estimated impact scores.`;\n\n const response = await this.generate({\n prompt,\n system: 'You are an expert accessibility consultant specializing in neurodivergent user experience. Provide specific, actionable recommendations.',\n maxTokens: 1500,\n temperature: 0.3,\n });\n\n return this.parseAdaptationSuggestions(response.content);\n }\n\n async simplifyContent(\n content: string,\n targetLevel: 'simple' | 'intermediate' | 'advanced',\n context?: Record<string, unknown>\n ): Promise<string> {\n const prompt = `${this.createSimplificationPrompt(content, targetLevel)}\n\n${context ? `Additional context: ${JSON.stringify(context)}` : ''}\n\nSimplification guidelines for ${targetLevel} level:\n- Simple: Elementary to middle school reading level (grades 3-8)\n- Intermediate: High school reading level (grades 9-12) \n- Advanced: College level but clear and accessible\n\nKey requirements:\n- Preserve all factual information\n- Maintain logical flow and structure\n- Use appropriate vocabulary for target level\n- Keep content engaging and informative`;\n\n const response = await this.generate({\n prompt,\n system: 'You are an expert content editor specializing in making complex information accessible while preserving accuracy and completeness.',\n maxTokens: Math.max(2000, Math.ceil(content.length * 1.5)),\n temperature: 0.2,\n });\n\n return response.content;\n }\n\n // Private methods\n\n private async initializeClient(): Promise<void> {\n try {\n // Dynamic import to handle optional dependency\n const { OpenAI } = await import('openai');\n \n if (!this.config.apiKey) {\n throw new Error('OpenAI API key is required');\n }\n\n this.openai = new OpenAI({\n apiKey: this.config.apiKey,\n baseURL: this.config.baseURL,\n organization: (this.config as OpenAIConfig).organization,\n });\n\n this.status.isAvailable = true;\n } catch (error) {\n console.warn('OpenAI provider not available:', error);\n this.status.isAvailable = false;\n this.status.lastError = 'openai package not installed or API key missing';\n }\n }\n\n private mapResponse(openaiResponse: OpenAIResponse): AIResponse {\n const choice = openaiResponse.choices[0];\n \n return {\n content: choice.message.content,\n usage: {\n promptTokens: openaiResponse.usage.prompt_tokens,\n completionTokens: openaiResponse.usage.completion_tokens,\n totalTokens: openaiResponse.usage.total_tokens,\n },\n finishReason: choice.finish_reason,\n metadata: {\n model: openaiResponse.model,\n id: openaiResponse.id,\n created: openaiResponse.created,\n },\n };\n }\n\n protected parseAdaptationSuggestions(response: string): AdaptationSuggestion[] {\n const suggestions: AdaptationSuggestion[] = [];\n \n // Enhanced parsing for OpenAI's responses\n const lines = response.split('\\n').filter(line => line.trim());\n \n for (const line of lines) {\n const lowercaseLine = line.toLowerCase();\n \n // Motion and animation suggestions\n if (lowercaseLine.includes('motion') || lowercaseLine.includes('animation') || \n lowercaseLine.includes('reduce movement') || lowercaseLine.includes('autoplay')) {\n suggestions.push({\n type: 'sensory',\n target: 'motionReduction',\n action: 'enable',\n reasoning: line.trim(),\n confidence: 'high',\n priority: 'high',\n estimatedImpact: 0.8,\n });\n }\n \n // Contrast and visibility suggestions\n if (lowercaseLine.includes('contrast') || lowercaseLine.includes('visibility') || \n lowercaseLine.includes('color') || lowercaseLine.includes('dark mode')) {\n suggestions.push({\n type: 'sensory',\n target: 'highContrast',\n action: 'enable',\n reasoning: line.trim(),\n confidence: 'high',\n priority: 'medium',\n estimatedImpact: 0.7,\n });\n }\n \n // Font and text size suggestions\n if (lowercaseLine.includes('font') || lowercaseLine.includes('text size') || \n lowercaseLine.includes('readability') || lowercaseLine.includes('larger text')) {\n suggestions.push({\n type: 'sensory',\n target: 'fontSize',\n action: 'adjust',\n value: 1.2,\n reasoning: line.trim(),\n confidence: 'medium',\n priority: 'medium',\n estimatedImpact: 0.6,\n });\n }\n \n // Cognitive load and content structure suggestions\n if (lowercaseLine.includes('chunk') || lowercaseLine.includes('break up') || \n lowercaseLine.includes('section') || lowercaseLine.includes('simplify')) {\n suggestions.push({\n type: 'cognitive',\n target: 'chunkSize',\n action: 'adjust',\n value: 2,\n reasoning: line.trim(),\n confidence: 'high',\n priority: 'high',\n estimatedImpact: 0.9,\n });\n }\n \n // Content structure and organization suggestions\n if (lowercaseLine.includes('heading') || lowercaseLine.includes('structure') || \n lowercaseLine.includes('organize') || lowercaseLine.includes('navigation')) {\n suggestions.push({\n type: 'content',\n target: 'structure',\n action: 'adjust',\n reasoning: line.trim(),\n confidence: 'high',\n priority: 'medium',\n estimatedImpact: 0.7,\n });\n }\n }\n \n // Remove duplicates and return unique suggestions\n const uniqueSuggestions = suggestions.filter((suggestion, index, array) => \n array.findIndex(s => s.type === suggestion.type && s.target === suggestion.target) === index\n );\n \n return uniqueSuggestions;\n }\n\n estimateCost(request: AIRequest): number {\n // OpenAI pricing (approximate, as of 2024)\n const inputTokens = Math.ceil(request.prompt.length / 4);\n const outputTokens = request.maxTokens || 1000;\n \n let inputCost, outputCost;\n \n switch (this.model) {\n case 'gpt-4-turbo-preview':\n case 'gpt-4':\n inputCost = inputTokens * 0.00003; // $30 per 1M tokens\n outputCost = outputTokens * 0.00006; // $60 per 1M tokens\n break;\n case 'gpt-4-vision-preview':\n inputCost = inputTokens * 0.00001; // $10 per 1M tokens\n outputCost = outputTokens * 0.00003; // $30 per 1M tokens\n break;\n case 'gpt-3.5-turbo':\n case 'gpt-3.5-turbo-16k':\n inputCost = inputTokens * 0.0000005; // $0.50 per 1M tokens\n outputCost = outputTokens * 0.0000015; // $1.50 per 1M tokens\n break;\n default:\n return super.estimateCost(request);\n }\n \n return inputCost + outputCost;\n }\n} ","import { BaseAIProvider } from './base-provider.js';\nimport type { \n AIRequest, \n AIResponse, \n ModelCapabilities, \n StreamChunk, \n AdaptationSuggestion,\n AIProviderConfig \n} from './base-provider.js';\n\n/**\n * Ollama provider configuration\n */\nexport interface OllamaConfig extends AIProviderConfig {\n model?: string;\n host?: string;\n keepAlive?: string | number;\n}\n\n/**\n * Ollama API response structure\n */\ninterface OllamaResponse {\n model: string;\n created_at: string;\n response: string;\n done: boolean;\n context?: number[];\n total_duration?: number;\n load_duration?: number;\n prompt_eval_count?: number;\n prompt_eval_duration?: number;\n eval_count?: number;\n eval_duration?: number;\n}\n\n/**\n * Ollama provider for local AI models\n */\nexport class OllamaProvider extends BaseAIProvider {\n private model: string;\n private host: string;\n private keepAlive: string | number;\n\n constructor(config: OllamaConfig) {\n super(config);\n this.model = config.model || 'llama2';\n this.host = config.host || config.baseURL || 'http://localhost:11434';\n this.keepAlive = config.keepAlive || '5m';\n this.checkAvailability();\n }\n\n getProviderName(): string {\n return 'Ollama';\n }\n\n getCapabilities(): ModelCapabilities {\n return {\n textGeneration: true,\n textAnalysis: true,\n codeGeneration: this.model.includes('code') || this.model.includes('wizard'),\n reasoning: true,\n streaming: true,\n functionCalling: false, // Most Ollama models don't support function calling\n vision: this.model.includes('vision') || this.model.includes('llava'),\n };\n }\n\n getAvailableModels(): string[] {\n // Common Ollama models - in real implementation, this would query the API\n return [\n 'llama2',\n 'llama2:13b',\n 'llama2:70b',\n 'mistral',\n 'mixtral',\n 'codellama',\n 'llava',\n 'neural-chat',\n 'starling-lm',\n ];\n }\n\n async generate(request: AIRequest): Promise<AIResponse> {\n this.validateRequest(request);\n\n try {\n const prompt = this.buildPrompt(request);\n \n const response = await fetch(`${this.host}/api/generate`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n model: this.model,\n prompt,\n stream: false,\n options: {\n temperature: request.temperature || 0.7,\n num_predict: request.maxTokens || 1000,\n },\n keep_alive: this.keepAlive,\n }),\n });\n\n if (!response.ok) {\n throw new Error(`Ollama API error: ${response.status} ${response.statusText}`);\n }\n\n const data: OllamaResponse = await response.json();\n return this.mapResponse(data);\n } catch (error) {\n return this.createErrorResponse(\n error instanceof Error ? error : new Error(String(error))\n );\n }\n }\n\n async* generateStream(request: AIRequest): AsyncGenerator<StreamChunk, void, unknown> {\n this.validateRequest(request);\n\n try {\n const prompt = this.buildPrompt(request);\n \n const response = await fetch(`${this.host}/api/generate`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n model: this.model,\n prompt,\n stream: true,\n options: {\n temperature: request.temperature || 0.7,\n num_predict: request.maxTokens || 1000,\n },\n keep_alive: this.keepAlive,\n }),\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 let content = '';\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 \n // Keep the last incomplete line in the buffer\n buffer = lines.pop() || '';\n\n for (const line of lines) {\n if (line.trim() === '') continue;\n\n try {\n const data: OllamaResponse = JSON.parse(line);\n \n if (data.response) {\n content += data.response;\n \n const streamChunk: StreamChunk = {\n id: Date.now().toString(),\n type: 'token',\n content: data.response,\n timestamp: Date.now(),\n metadata: {\n model: data.model,\n eval_count: data.eval_count,\n },\n };\n\n yield streamChunk;\n this.emit('stream-chunk', streamChunk);\n }\n\n if (data.done) {\n const doneChunk: StreamChunk = {\n id: 'done',\n type: 'done',\n content: content,\n timestamp: Date.now(),\n metadata: {\n total_duration: data.total_duration,\n eval_count: data.eval_count,\n eval_duration: data.eval_duration,\n },\n };\n \n yield doneChunk;\n this.emit('stream-complete', content);\n return;\n }\n } catch (parseError) {\n console.warn('Failed to parse Ollama response line:', line);\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n } catch (error) {\n const errorChunk: StreamChunk = {\n id: 'error',\n type: 'error',\n content: error instanceof Error ? error.message : String(error),\n timestamp: Date.now(),\n };\n \n yield errorChunk;\n this.emit('stream-error', error instanceof Error ? error : new Error(String(error)));\n }\n }\n\n async analyzeAccessibility(\n content: string,\n currentPreferences: Record<string, unknown>,\n context?: Record<string, unknown>\n ): Promise<AdaptationSuggestion[]> {\n const prompt = `${this.buildAccessibilityAnalysisPrompt(content, currentPreferences, context)}\n\nPlease provide a detailed analysis with specific recommendations for improving accessibility for neurodivergent users.`;\n\n const response = await this.generate({\n prompt,\n maxTokens: 1500,\n temperature: 0.3,\n });\n\n return this.parseAdaptationSuggestions(response.content);\n }\n\n async simplifyContent(\n content: string,\n targetLevel: 'simple' | 'intermediate' | 'advanced',\n context?: Record<string, unknown>\n ): Promise<string> {\n const prompt = this.buildSimplificationPrompt(content, targetLevel, context);\n\n const response = await this.generate({\n prompt,\n maxTokens: Math.max(2000, Math.ceil(content.length * 1.5)),\n temperature: 0.2,\n });\n\n return response.content;\n }\n\n // Override to check Ollama availability\n async testConnection(): Promise<boolean> {\n try {\n const response = await fetch(`${this.host}/api/tags`, {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n if (response.ok) {\n this.status.isAvailable = true;\n return true;\n } else {\n throw new Error(`HTTP ${response.status}`);\n }\n } catch (error) {\n this.status.isAvailable = false;\n this.status.lastError = error instanceof Error ? error.message : String(error);\n return false;\n }\n }\n\n // Private methods\n\n private buildPrompt(request: AIRequest): string {\n if (request.system) {\n return `System: ${request.system}\\n\\nUser: ${request.prompt}\\n\\nAssistant:`;\n }\n return request.prompt;\n }\n\n private buildAccessibilityAnalysisPrompt(\n content: string,\n preferences: Record<string, unknown>,\n context?: Record<string, unknown>\n ): string {\n return `You are an accessibility expert. Analyze the following content for neurodivergent users and provide specific recommendations.\n\nCurrent User Preferences:\n${JSON.stringify(preferences, null, 2)}\n\n${context ? `Context: ${JSON.stringify(context, null, 2)}` : ''}\n\nContent to Analyze:\n${content}\n\nProvide specific suggestions for:\n1. Visual adaptations (motion reduction, contrast, font size)\n2. Cognitive load management (content chunking, simplification)\n3. Navigation improvements\n4. Content structure optimization\n\nFormat your response with clear recommendations and reasoning.`;\n }\n\n private buildSimplificationPrompt(\n content: string,\n targetLevel: string,\n context?: Record<string, unknown>\n ): string {\n return `You are an expert content editor. Simplify the following content for a ${targetLevel} reading level while preserving all important information.\n\n${context ? `Context: ${JSON.stringify(context, null, 2)}` : ''}\n\nGuidelines:\n- Use shorter, clearer sentences\n- Replace complex words with simpler alternatives\n- Break up long paragraphs\n- Maintain factual accuracy\n- Keep the content engaging\n\nOriginal Content:\n${content}\n\nSimplified Content:`;\n }\n\n private mapResponse(ollamaResponse: OllamaResponse): AIResponse {\n return {\n content: ollamaResponse.response,\n usage: {\n promptTokens: ollamaResponse.prompt_eval_count || 0,\n completionTokens: ollamaResponse.eval_count || 0,\n totalTokens: (ollamaResponse.prompt_eval_count || 0) + (ollamaResponse.eval_count || 0),\n },\n finishReason: ollamaResponse.done ? 'stop' : 'length',\n metadata: {\n model: ollamaResponse.model,\n created_at: ollamaResponse.created_at,\n total_duration: ollamaResponse.total_duration,\n eval_duration: ollamaResponse.eval_duration,\n },\n };\n }\n\n protected parseAdaptationSuggestions(response: string): AdaptationSuggestion[] {\n const suggestions: AdaptationSuggestion[] = [];\n \n // Parse Ollama responses which tend to be more conversational\n const lines = response.split('\\n').filter(line => line.trim());\n \n for (const line of lines) {\n const lowercaseLine = line.toLowerCase();\n \n // Look for motion-related suggestions\n if (lowercaseLine.includes('motion') || lowercaseLine.includes('animation') || \n lowercaseLine.includes('movement') || lowercaseLine.includes('autoplay')) {\n suggestions.push({\n type: 'sensory',\n target: 'motionReduction',\n action: 'enable',\n reasoning: line.trim(),\n confidence: 'medium',\n priority: 'high',\n estimatedImpact: 0.7,\n });\n }\n \n // Look for contrast suggestions\n if (lowercaseLine.includes('contrast') || lowercaseLine.includes('dark') || \n lowercaseLine.includes('light') || lowercaseLine.includes('color')) {\n suggestions.push({\n type: 'sensory',\n target: 'highContrast',\n action: 'enable',\n reasoning: line.trim(),\n confidence: 'medium',\n priority: 'medium',\n estimatedImpact: 0.6,\n });\n }\n \n // Look for text size suggestions\n if (lowercaseLine.includes('font') || lowercaseLine.includes('text') || \n lowercaseLine.includes('size') || lowercaseLine.includes('larger')) {\n suggestions.push({\n type: 'sensory',\n target: 'fontSize',\n action: 'adjust',\n value: 1.15,\n reasoning: line.trim(),\n confidence: 'medium',\n priority: 'medium',\n estimatedImpact: 0.5,\n });\n }\n \n // Look for content structure suggestions\n if (lowercaseLine.includes('chunk') || lowercaseLine.includes('break') || \n lowercaseLine.includes('section') || lowercaseLine.includes('paragraph')) {\n suggestions.push({\n type: 'cognitive',\n target: 'chunkSize',\n action: 'adjust',\n value: 2,\n reasoning: line.trim(),\n confidence: 'high',\n priority: 'high',\n estimatedImpact: 0.8,\n });\n }\n }\n \n // Remove duplicates\n const uniqueSuggestions = suggestions.filter((suggestion, index, array) => \n array.findIndex(s => s.type === suggestion.type && s.target === suggestion.target) === index\n );\n \n return uniqueSuggestions;\n }\n\n estimateCost(request: AIRequest): number {\n // Ollama is free for local usage\n return 0;\n }\n\n protected isConfigValid(): boolean {\n // Ollama doesn't require API key, just host availability\n return !!this.host;\n }\n} "],"names":["BaseAIProvider","EventEmitter","config","newConfig","testRequest","error","request","capability","retryAfter","remaining","reset","content","currentPreferences","targetLevel","response","suggestions","lines","line","ClaudeProvider","messages","stream","chunk","streamChunk","context","prompt","Anthropic","claudeResponse","block","stopReason","sections","lowercaseLine","suggestion","index","array","s","inputTokens","outputTokens","inputCost","outputCost","OpenAIProvider","delta","OpenAI","openaiResponse","choice","OllamaProvider","data","reader","decoder","buffer","done","value","preferences","ollamaResponse"],"mappings":"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"}