UNPKG

@neuroequality/neuroadapt-ai

Version:

AI-powered accessibility personalization for neurodivergent users

1 lines 65.4 kB
{"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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"}