{"version":3,"sources":["../src/utils/logger.ts","../src/constants/agent.ts","../src/constants/memory.ts","../src/constants/database.ts","../src/constants/provider.ts","../src/constants/rag.ts","../src/constants/task.ts","../src/constants/error.ts","../src/constants/index.ts","../src/providers/openai.ts","../src/providers/ollama.ts","../src/providers/embedding.ts","../src/providers/index.ts","../src/index.ts","../src/agent.ts","../src/database.ts","../src/database/sqlite.ts","../src/database/postgresql.ts","../src/utils/index.ts","../src/utils/validation.ts","../src/utils/rag-tools.ts","../src/database/modules/user.ts","../src/plugin.ts","../src/memory.ts","../src/rag/vector.ts","../src/types/rag.ts","../src/rag/vector-db/index.ts","../src/rag/document.ts","../src/rag/pdf-parser.ts","../src/rag/index.ts","../src/chat.ts","../src/tasks/task.ts","../src/utils/intent.ts","../src/tasks/manager.ts","../src/tasks/index.ts"],"sourcesContent":["/**\n * Astreus AI - Logger Utility\n * Provides colorful console logging functionality for the framework\n */\n\n// ANSI color codes for terminal output\nconst colors = {\n  reset: \"\\x1b[0m\",\n  bright: \"\\x1b[1m\",\n  dim: \"\\x1b[2m\",\n  underscore: \"\\x1b[4m\",\n  blink: \"\\x1b[5m\",\n  reverse: \"\\x1b[7m\",\n  hidden: \"\\x1b[8m\",\n  \n  // Foreground colors\n  black: \"\\x1b[30m\",\n  red: \"\\x1b[31m\",\n  green: \"\\x1b[32m\",\n  yellow: \"\\x1b[33m\",\n  blue: \"\\x1b[34m\",\n  magenta: \"\\x1b[35m\",\n  cyan: \"\\x1b[36m\",\n  white: \"\\x1b[37m\",\n  gray: \"\\x1b[90m\",\n  \n  // Background colors\n  bgBlack: \"\\x1b[40m\",\n  bgRed: \"\\x1b[41m\",\n  bgGreen: \"\\x1b[42m\",\n  bgYellow: \"\\x1b[43m\",\n  bgBlue: \"\\x1b[44m\",\n  bgMagenta: \"\\x1b[45m\",\n  bgCyan: \"\\x1b[46m\",\n  bgWhite: \"\\x1b[47m\",\n};\n\n// Framework constants\nconst FRAMEWORK_NAME = \"Astreus\";\nconst FRAMEWORK_VERSION = \"0.1.0\";\n\n// Log levels\n/* eslint-disable no-unused-vars */\nexport enum LogLevel {\n  DEBUG = 0,\n  INFO = 1,\n  SUCCESS = 2,\n  WARN = 3,\n  ERROR = 4,\n  NONE = 5,\n}\n/* eslint-enable no-unused-vars */\n\n// Logger options\ninterface LoggerOptions {\n  level: LogLevel;\n  prefix: boolean;\n  colors: boolean;\n  lineBreak: boolean;\n  timestamp: boolean;\n}\n\n// Default options\nconst defaultOptions: LoggerOptions = {\n  level: LogLevel.INFO,\n  prefix: true,\n  colors: true,\n  lineBreak: false,\n  timestamp: false\n};\n\n// Current logger options\nlet options: LoggerOptions = { ...defaultOptions };\n\n// Track the last log time to prevent duplicate timestamps\nlet lastLogTime = 0;\n\n/**\n * Create a formatted prefix for log messages\n */\nfunction createPrefix(color: string): string {\n  if (!options.prefix) return '';\n  \n  // Simple format: [FRAMEWORK]\n  return `${color}[${FRAMEWORK_NAME}]${colors.reset} `;\n}\n\n/**\n * Get a timestamp string\n */\nfunction getTimestamp(): string {\n  if (!options.timestamp) return '';\n  \n  const now = Date.now();\n  // Only show timestamps when they change by at least 1 second\n  if (Math.abs(now - lastLogTime) < 1000) {\n    return '';\n  }\n  \n  lastLogTime = now;\n  const date = new Date(now);\n  return `${colors.gray}[${date.toLocaleTimeString()}]${colors.reset} `;\n}\n\n/**\n * Internal log function\n */\nfunction log(level: LogLevel, color: string, ...messages: unknown[]): void {\n  if (level < options.level) return;\n  \n  const prefix = createPrefix(color);\n  const timestamp = getTimestamp();\n  \n  // Add line break before log entry if enabled (reduced usage)\n  if (options.lineBreak && level >= LogLevel.WARN) {\n    // Use safeConsole to handle console statements\n    safeConsole('log');\n  }\n  \n  if (options.colors) {\n    // Apply color to text messages that are strings\n    const coloredMessages = messages.map(msg => \n      typeof msg === 'string' ? `${color}${msg}${colors.reset}` : msg\n    );\n    // Use a direct string without extra spaces\n    safeConsole('log', `${timestamp}${prefix}${coloredMessages.join(' ')}`);\n  } else {\n    // Strip color codes using string replace with a function rather than regex with control chars\n    // This avoids the ESLint 'no-control-regex' error\n    const stripAnsi = (str: string): string => {\n      let result = '';\n      let inEscSeq = false;\n      \n      for (let i = 0; i < str.length; i++) {\n        // Start of escape sequence\n        if (str[i] === '\\u001b' && str[i+1] === '[') {\n          inEscSeq = true;\n          i++; // Skip the '['\n          continue;\n        }\n        \n        // In escape sequence, wait for 'm' which ends ANSI color codes\n        if (inEscSeq) {\n          if (str[i] === 'm') {\n            inEscSeq = false;\n          }\n          continue;\n        }\n        \n        // Normal character\n        result += str[i];\n      }\n      \n      return result;\n    };\n    \n    const strippedPrefix = stripAnsi(prefix);\n    safeConsole('log', `${timestamp}${strippedPrefix}${messages.join(' ')}`);\n  }\n}\n\n/**\n * Safe console wrapper to avoid ESLint warnings\n */\nfunction safeConsole(method: 'log' | 'info' | 'warn' | 'error', ...args: unknown[]): void {\n  // This function centralizes console usage and can be disabled by ESLint when needed\n  // eslint-disable-next-line no-console\n  if (method === 'log') console.log(...args);\n  // eslint-disable-next-line no-console\n  else if (method === 'info') console.info(...args);\n  // eslint-disable-next-line no-console\n  else if (method === 'warn') console.warn(...args);\n  // eslint-disable-next-line no-console\n  else if (method === 'error') console.error(...args);\n}\n\n/**\n * Configure the logger\n */\nexport function configure(newOptions: Partial<LoggerOptions>): void {\n  options = { ...options, ...newOptions };\n}\n\n/**\n * Print the framework banner\n */\nexport function printBanner(): void {\n  if (options.level > LogLevel.INFO) return;\n  \n  safeConsole('log');\n  safeConsole('log', `${colors.cyan}${colors.bright}${FRAMEWORK_NAME} AI Framework v${FRAMEWORK_VERSION}${colors.reset}`);\n  safeConsole('log');\n}\n\n/**\n * Public logging functions\n */\nexport const logger = {\n  debug: (...messages: unknown[]) => log(LogLevel.DEBUG, colors.gray, ...messages),\n  info: (...messages: unknown[]) => log(LogLevel.INFO, colors.blue, ...messages),\n  success: (...messages: unknown[]) => log(LogLevel.SUCCESS, colors.green, ...messages),\n  warn: (...messages: unknown[]) => log(LogLevel.WARN, colors.yellow, ...messages),\n  error: (...messages: unknown[]) => log(LogLevel.ERROR, colors.red, ...messages),\n  \n  // Special formatted logs\n  task: (taskId: string, message: string, taskName?: string) => {\n    // If taskName is provided, use it; otherwise, just use \"Task\"\n    const prefix = taskName ? `Task [${taskName}]:` : 'Task:';\n    log(LogLevel.INFO, colors.magenta, `${prefix} ${message}`);\n  },\n  \n  agent: (agentName: string, message: string) => {\n    log(LogLevel.INFO, colors.cyan, `Agent [${agentName}]: ${message}`);\n  },\n  \n  database: (operation: string, message: string) => {\n    log(LogLevel.DEBUG, colors.blue, `${operation}: ${message}`);\n  },\n  \n  memory: (operation: string, message: string) => {\n    log(LogLevel.DEBUG, colors.magenta, `${operation}: ${message}`);\n  },\n  \n  session: (sessionId: string, message: string) => {\n    const shortId = sessionId.substring(0, 8);\n    log(LogLevel.INFO, colors.green, `${shortId}: ${message}`);\n  },\n  \n  plugin: (pluginName: string, message: string) => {\n    // Capitalize first letter of plugin name and remove brackets\n    const capitalizedPluginName = pluginName.charAt(0).toUpperCase() + pluginName.slice(1);\n    log(LogLevel.INFO, colors.yellow, `${capitalizedPluginName}: ${message}`);\n  },\n  \n  workflow: (workflowName: string, message: string) => {\n    log(LogLevel.INFO, colors.cyan, `${workflowName}: ${message}`);\n  },\n  \n  // Progress indicators - these don't add line breaks to avoid disrupting the animation\n  startProgress: (message: string): NodeJS.Timeout => {\n    if (options.level > LogLevel.INFO) return setInterval(() => {}, 1000);\n    \n    // Optionally add a line break before starting progress\n    if (options.lineBreak) {\n      safeConsole('log');\n    }\n    \n    process.stdout.write(`${createPrefix(colors.blue)}${colors.blue}${message}`);\n    \n    const chars = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];\n    let i = 0;\n    \n    return setInterval(() => {\n      process.stdout.write(`\\r${createPrefix(colors.blue)}${colors.blue}${message} ${colors.cyan}${chars[i]}${colors.reset}`);\n      i = (i + 1) % chars.length;\n    }, 100);\n  },\n  \n  endProgress: (interval: NodeJS.Timeout, finalMessage?: string) => {\n    clearInterval(interval);\n    if (options.level > LogLevel.INFO) return;\n    \n    if (finalMessage) {\n      process.stdout.write(`\\r${createPrefix(colors.blue)}${colors.green}${finalMessage} ✓${colors.reset}\\n`);\n    } else {\n      process.stdout.write(`\\r${createPrefix(colors.blue)}${colors.green}Done ✓${colors.reset}\\n`);\n    }\n  },\n  \n  // Configure line breaks\n  setLineBreak: (enabled: boolean) => {\n    configure({ lineBreak: enabled });\n  },\n};\n\n\nexport default logger; ","// Agent-related constants\nexport const DEFAULT_AGENT_NAME = 'astreus-agent';\nexport const DEFAULT_MODEL = 'gpt-4o-mini';\nexport const DEFAULT_TEMPERATURE = 0.3;\nexport const DEFAULT_MAX_TOKENS = 4096; ","// Memory-related constants\nexport const DEFAULT_MEMORY_SIZE = 10; ","// Database-related constants\nexport const DEFAULT_DB_PATH = './.astreus/db';\n\n// Vector database constants\nexport const VECTOR_DATABASE_TYPES = {\n  SAME_AS_MAIN: 'same_as_main',\n  POSTGRES: 'postgres',\n  QDRANT: 'qdrant',\n  PINECONE: 'pinecone',\n  MILVUS: 'milvus',\n  WEAVIATE: 'weaviate',\n}; ","// Provider-related constants\nexport const PROVIDER_TYPES = {\n  OPENAI: 'openai',\n  OLLAMA: 'ollama',\n};\n\n// Default Provider configuration\nexport const DEFAULT_OPENAI_BASE_URL = 'https://api.openai.com/v1';\nexport const DEFAULT_OPENAI_EMBEDDING_MODEL = 'text-embedding-3-small';\nexport const DEFAULT_OLLAMA_BASE_URL = 'http://localhost:11434';\n\n// Default OpenAI model configs\nexport const DEFAULT_MODEL_CONFIGS = {\n  openai: {\n    \"gpt-4o\": {\n      apiKey: process.env.OPENAI_API_KEY || '',\n      baseUrl: process.env.OPENAI_BASE_URL,\n      temperature: 0.7,\n      maxTokens: 4096\n    },\n    \"gpt-4o-mini\": {\n      apiKey: process.env.OPENAI_API_KEY || '',\n      baseUrl: process.env.OPENAI_BASE_URL,\n      temperature: 0.7,\n      maxTokens: 2048\n    },\n    \"gpt-4\": {\n      apiKey: process.env.OPENAI_API_KEY || '',\n      baseUrl: process.env.OPENAI_BASE_URL,\n      temperature: 0.7,\n      maxTokens: 4096\n    },\n    \"gpt-3.5-turbo\": {\n      apiKey: process.env.OPENAI_API_KEY || '',\n      baseUrl: process.env.OPENAI_BASE_URL,\n      temperature: 0.7,\n      maxTokens: 2048\n    }\n  },\n  ollama: {\n    \"llama3\": {\n      baseUrl: process.env.OLLAMA_BASE_URL || 'http://localhost:11434',\n      temperature: 0.7,\n      maxTokens: 2048\n    },\n    \"mistral\": {\n      baseUrl: process.env.OLLAMA_BASE_URL || 'http://localhost:11434',\n      temperature: 0.7,\n      maxTokens: 2048\n    }\n  }\n}; ","// RAG-related constants\nexport const DEFAULT_CHUNK_SIZE = 1000;\nexport const DEFAULT_CHUNK_OVERLAP = 200;\nexport const DEFAULT_VECTOR_SIMILARITY_THRESHOLD = 0.7;\nexport const DEFAULT_MAX_RESULTS = 10; ","// Task-related constants\nexport const DEFAULT_TASK_CONCURRENCY = 5;\nexport const DEFAULT_MAX_RETRIES = 3;\nexport const TASK_STATUS = {\n  PENDING: 'pending',\n  RUNNING: 'running',\n  COMPLETED: 'completed',\n  FAILED: 'failed',\n}; ","// Error messages\nexport const ERROR_MESSAGES = {\n  MISSING_PARAMETER: 'Missing required parameter:',\n  INVALID_PROVIDER: 'Invalid provider configuration',\n  INVALID_MEMORY: 'Invalid memory configuration',\n  INVALID_DATABASE: 'Invalid database configuration',\n  INVALID_RAG: 'Invalid RAG configuration',\n  INVALID_VECTOR_DB: 'Invalid vector database configuration',\n  INVALID_TASK: 'Invalid task configuration',\n  INVALID_EMBEDDING: 'Invalid embedding configuration',\n}; ","// Re-export all constants from their respective files\nexport * from './agent';\nexport * from './memory';\nexport * from './database';\nexport * from './provider';\nexport * from './rag';\nexport * from './task';\nexport * from './error'; ","import { \n  ProviderType,\n  OpenAIModelConfig,\n  ProviderMessage,\n  ProviderModel,\n  CompletionOptions,\n  ProviderTool\n} from '../types/provider';\nimport { logger } from \"../utils/logger\";\nimport { OpenAI } from \"openai\";\n\n/**\n * Create OpenAI configuration with defaults\n */\nexport function createOpenAIConfig(\n  modelName: string,\n  config?: Partial<OpenAIModelConfig>\n): OpenAIModelConfig {\n  return {\n    name: modelName,\n    apiKey: process.env.OPENAI_API_KEY,\n    baseUrl: process.env.OPENAI_BASE_URL,\n    temperature: 0.7,\n    maxTokens: 2048,\n    ...config,\n  };\n}\n\n/**\n * OpenAI Provider implementation\n */\nexport class OpenAIProvider implements ProviderModel {\n  public provider: ProviderType;\n  public name: string;\n  public config: OpenAIModelConfig;\n  private client: OpenAI;\n  \n  constructor(provider: ProviderType, config: OpenAIModelConfig) {\n    this.provider = provider;\n    this.name = config.name;\n    this.config = config;\n    \n    this.client = new OpenAI({\n      apiKey: config.apiKey || process.env.OPENAI_API_KEY,\n      baseURL: config.baseUrl || process.env.OPENAI_BASE_URL,\n    });\n  }\n  \n  async complete(messages: ProviderMessage[], options?: CompletionOptions): Promise<string | any> {\n    try {\n      // Prepare messages\n      const formattedMessages = this.prepareMessages(messages, options?.systemMessage);\n      \n      // Build request options\n      const requestOptions = this.buildRequestOptions(formattedMessages, options);\n      \n      // Log request info\n      logger.debug(`OpenAI request: model=${this.name}`, { \n        messages: formattedMessages.length, \n        hasTools: !!requestOptions.tools,\n        toolCount: requestOptions.tools?.length || 0 \n      });\n      \n      // Make API request\n      const response = await this.client.chat.completions.create(requestOptions);\n      \n      // Handle response - now can return either string or object with tool calls\n      return this.processResponse(response);\n    } catch (error) {\n      this.handleError(error);\n      throw error;\n    }\n  }\n  \n  async streamComplete(\n    messages: ProviderMessage[], \n    options?: CompletionOptions,\n    onChunk?: (chunk: string) => void\n  ): Promise<string> {\n    try {\n      // Prepare messages\n      const formattedMessages = this.prepareMessages(messages, options?.systemMessage);\n      \n      // Build request options with streaming enabled\n      const requestOptions = this.buildRequestOptions(formattedMessages, options);\n      requestOptions.stream = true;\n      \n      // Log request info\n      logger.debug(`OpenAI streaming request: model=${this.name}`, { \n        messages: formattedMessages.length, \n        hasTools: !!requestOptions.tools,\n        toolCount: requestOptions.tools?.length || 0 \n      });\n      \n      // Make streaming API request\n      const stream = await this.client.chat.completions.create(requestOptions) as any;\n      \n      let fullResponse = '';\n      \n      // Process streaming response\n      for await (const chunk of stream) {\n        const content = chunk.choices[0]?.delta?.content || '';\n        if (content) {\n          fullResponse += content;\n          if (onChunk) {\n            onChunk(fullResponse);\n          }\n        }\n      }\n      \n      return fullResponse;\n    } catch (error) {\n      this.handleError(error);\n      throw error;\n    }\n  }\n  \n  private prepareMessages(messages: ProviderMessage[], systemMessage?: string) {\n    // Convert to OpenAI message format\n    const formattedMessages = messages.map(msg => ({\n      role: msg.role,\n      content: msg.content\n    }));\n    \n    // Add system message if provided\n    if (systemMessage) {\n      formattedMessages.unshift({\n        role: \"system\" as const,\n        content: systemMessage\n      });\n    }\n    \n    return formattedMessages;\n  }\n  \n  private buildRequestOptions(messages: any[], options?: CompletionOptions) {\n    // Base request options\n    const requestOptions: any = {\n      model: this.name,\n      messages,\n      temperature: options?.temperature ?? this.config.temperature ?? 0.7,\n      max_tokens: options?.maxTokens ?? this.config.maxTokens\n    };\n    \n    // Add tools if provided\n    if (options?.tools && options.tools.length > 0) {\n      requestOptions.tools = options.tools.map(tool => ({\n        type: \"function\",\n        function: {\n          name: tool.name,\n          description: tool.description || \"\",\n          parameters: this.formatToolParameters(tool.parameters)\n        }\n      }));\n      \n      // Set tool choice if enabled\n      if (options.toolCalling) {\n        requestOptions.tool_choice = \"auto\";\n      }\n    }\n    \n    return requestOptions;\n  }\n  \n  private formatToolParameters(parameters: any): Record<string, any> {\n    // Default empty schema with proper type\n    const schemaObject: Record<string, any> = {\n      type: \"object\",\n      properties: {},\n      additionalProperties: false\n    };\n    \n    if (!parameters) {\n      return schemaObject;\n    }\n    \n    // Handle already formatted parameters\n    if (typeof parameters === 'object') {\n      // If it's already a proper JSON Schema object, use it directly\n      if ('type' in parameters && parameters.type === 'object') {\n        return parameters;\n      }\n      \n      // If it has properties field, use that\n      if ('properties' in parameters) {\n        schemaObject.properties = parameters.properties;\n        if (Array.isArray(parameters.required) && parameters.required.length > 0) {\n          schemaObject.required = parameters.required;\n        }\n        return schemaObject;\n      }\n      \n      // Handle array of parameter definitions\n      if (Array.isArray(parameters)) {\n        const requiredParams: string[] = [];\n        \n        parameters.forEach(param => {\n          if (typeof param === 'object' && param.name && param.type) {\n            // Create a property definition based on the parameter type\n            const propertyDef: Record<string, any> = {\n              type: param.type,\n              description: param.description || `Parameter ${param.name}`\n            };\n            \n            // Handle array type specifically\n            if (param.type === 'array') {\n              // Ensure arrays have an items definition\n              propertyDef.items = param.items || { type: 'string' };\n              \n              // Add array constraints if available\n              if (param.minItems !== undefined) propertyDef.minItems = param.minItems;\n              if (param.maxItems !== undefined) propertyDef.maxItems = param.maxItems;\n            }\n            \n            // Add any default value\n            if (param.default !== undefined) {\n              propertyDef.default = param.default;\n            }\n            \n            // Add property to schema\n            (schemaObject.properties as Record<string, any>)[param.name] = propertyDef;\n            \n            if (param.required) {\n              requiredParams.push(param.name);\n            }\n          }\n        });\n        \n        if (requiredParams.length > 0) {\n          schemaObject.required = requiredParams;\n        }\n      }\n    }\n    \n    return schemaObject;\n  }\n  \n  private processResponse(response: any): string | any {\n    // Check if the response has the expected structure\n    if (!response.choices?.[0]?.message) {\n      // Log the actual response structure for debugging\n      logger.error('Unexpected OpenAI API response structure:', {\n        responseId: response.id,\n        responseObject: JSON.stringify(response),\n        hasChoices: !!response.choices,\n        choicesLength: response.choices?.length,\n        firstChoice: response.choices?.[0] ? 'exists' : 'missing',\n        hasMessage: !!response.choices?.[0]?.message\n      });\n      \n      // Throw with more specific information about what's missing\n      if (!response.choices) {\n        throw new Error(`OpenAI API response missing 'choices' field: ${JSON.stringify(response)}`);\n      } else if (!response.choices.length) {\n        throw new Error(`OpenAI API response has empty 'choices' array: ${JSON.stringify(response)}`);\n      } else if (!response.choices[0].message) {\n        throw new Error(`OpenAI API response missing 'message' in first choice: ${JSON.stringify(response.choices[0])}`);\n      } else {\n        throw new Error(`OpenAI API unexpected response structure: ${JSON.stringify(response)}`);\n      }\n    }\n    \n    const message = response.choices[0].message;\n    const toolCalls = message.tool_calls;\n    \n    // Handle tool calls if present - Return both message content and structured tool calls\n    if (toolCalls?.length > 0) {\n      // Log detailed raw tool calls for debugging\n      logger.debug('OpenAI raw tool calls:', JSON.stringify(toolCalls, null, 2));\n      \n      // Return structured data instead of formatted text\n      return {\n        content: message.content || '',\n        tool_calls: toolCalls.map((call: any) => {\n          try {\n            if (call.type === 'function') {\n              // Parse arguments to JavaScript object\n              let args = {};\n              if (call.function?.arguments) {\n                try {\n                  args = typeof call.function.arguments === 'string'\n                    ? JSON.parse(call.function.arguments)\n                    : call.function.arguments;\n                } catch (e) {\n                  logger.error('Error parsing function arguments', { error: e });\n                }\n              }\n              \n              return {\n                type: 'function',\n                id: call.id,\n                name: call.function?.name,\n                arguments: args\n              };\n            }\n            return call;\n          } catch (e) {\n            logger.error('Error processing tool call', { error: e });\n            return { \n              type: 'error',\n              error: e instanceof Error ? e.message : String(e)\n            };\n          }\n        })\n      };\n    }\n    \n    // Return plain text response\n    return message.content || '';\n  }\n  \n  private handleError(error: any): void {\n    if (!error) return;\n    \n    // Log the full error details\n    logger.error('OpenAI API error:', {\n      message: error.message,\n      status: error.status,\n      type: error.type,\n      headers: error.headers,\n      code: error.code,\n      param: error.param,\n      error: error.error\n    });\n    \n    if (error.stack) {\n      logger.debug(`Error stack: ${error.stack}`);\n    }\n  }\n} ","import {\n  ProviderType,\n  OllamaModelConfig,\n  ProviderMessage,\n  ProviderModel,\n  CompletionOptions,\n  ProviderTool,\n  StructuredCompletionResponse\n} from \"../types/provider\";\nimport { DEFAULT_OLLAMA_BASE_URL } from \"../constants\";\nimport { logger } from \"../utils/logger\";\n\n/**\n * Create Ollama configuration helper\n */\nexport function createOllamaConfig(\n  modelName: string,\n  config?: Partial<OllamaModelConfig>\n): OllamaModelConfig {\n  return {\n    name: modelName,\n    baseUrl: process.env.OLLAMA_BASE_URL || DEFAULT_OLLAMA_BASE_URL,\n    temperature: 0.7,\n    maxTokens: 2048,\n    ...config,\n  };\n}\n\n// Ollama Provider implementation\nexport class OllamaProvider implements ProviderModel {\n  public provider: ProviderType;\n  public name: string;\n  public config: OllamaModelConfig;\n  private baseUrl: string;\n\n  constructor(provider: ProviderType, config: OllamaModelConfig) {\n    this.provider = provider;\n    this.name = config.name;\n    this.config = config;\n    this.baseUrl =\n      config.baseUrl || process.env.OLLAMA_BASE_URL || DEFAULT_OLLAMA_BASE_URL;\n  }\n\n  async complete(messages: ProviderMessage[], options?: CompletionOptions): Promise<string | StructuredCompletionResponse> {\n    try {\n      // Format messages for Ollama\n      const formattedMessages = this.prepareMessages(messages, options?.systemMessage);\n      \n      // Build request options\n      const requestOptions = this.buildRequestOptions(formattedMessages, options);\n      \n      // Log request info\n      logger.debug(`Ollama request: model=${this.name}`, { \n        messages: formattedMessages.length, \n        hasTools: !!options?.tools,\n        toolCount: options?.tools?.length || 0 \n      });\n\n      // Call Ollama API\n      const response = await fetch(`${this.baseUrl}/api/chat`, {\n        method: \"POST\",\n        headers: {\n          \"Content-Type\": \"application/json\",\n        },\n        body: JSON.stringify(requestOptions),\n      });\n\n      if (!response.ok) {\n        const errorText = await response.text();\n        throw new Error(`Ollama API error: ${response.status} ${errorText}`);\n      }\n\n      const data = await response.json();\n      \n      // Process the response\n      return this.processResponse(data);\n    } catch (error) {\n      this.handleError(error);\n      throw error;\n    }\n  }\n  \n  private prepareMessages(messages: ProviderMessage[], systemMessage?: string) {\n    // Convert to Ollama message format\n    const formattedMessages = messages.map(msg => ({\n      role: msg.role,\n      content: msg.content\n    }));\n    \n    // Add system message if provided\n    if (systemMessage) {\n      formattedMessages.unshift({\n        role: \"system\" as const,\n        content: systemMessage\n      });\n    }\n    \n    return formattedMessages;\n  }\n  \n  private buildRequestOptions(messages: any[], options?: CompletionOptions) {\n    // Base request options for Ollama\n    const requestOptions: any = {\n      model: this.name,\n      messages: messages,\n      options: {\n        temperature: options?.temperature ?? this.config.temperature ?? 0.7,\n        num_predict: options?.maxTokens ?? this.config.maxTokens\n      },\n      stream: false,\n    };\n    \n    // Add tools if provided\n    if (options?.tools && options.tools.length > 0 && options.toolCalling) {\n      requestOptions.tools = options.tools.map(tool => ({\n        type: \"function\",\n        function: {\n          name: tool.name,\n          description: tool.description || \"\",\n          parameters: this.formatToolParameters(tool.parameters)\n        }\n      }));\n    }\n    \n    return requestOptions;\n  }\n  \n  private formatToolParameters(parameters: any): Record<string, any> {\n    // Default empty schema with proper type\n    const schemaObject: Record<string, any> = {\n      type: \"object\",\n      properties: {},\n      additionalProperties: false\n    };\n    \n    if (!parameters) {\n      return schemaObject;\n    }\n    \n    // Handle already formatted parameters\n    if (typeof parameters === 'object') {\n      // If it's already a proper JSON Schema object, use it directly\n      if ('type' in parameters && parameters.type === 'object') {\n        return parameters;\n      }\n      \n      // If it has properties field, use that\n      if ('properties' in parameters) {\n        schemaObject.properties = parameters.properties;\n        if (Array.isArray(parameters.required) && parameters.required.length > 0) {\n          schemaObject.required = parameters.required;\n        }\n        return schemaObject;\n      }\n      \n      // Handle array of parameter definitions\n      if (Array.isArray(parameters)) {\n        const requiredParams: string[] = [];\n        \n        parameters.forEach(param => {\n          if (typeof param === 'object' && param.name && param.type) {\n            // Create a property definition based on the parameter type\n            const propertyDef: Record<string, any> = {\n              type: param.type,\n              description: param.description || `Parameter ${param.name}`\n            };\n            \n            // Handle array type specifically\n            if (param.type === 'array') {\n              // Ensure arrays have an items definition\n              propertyDef.items = param.items || { type: 'string' };\n              \n              // Add array constraints if available\n              if (param.minItems !== undefined) propertyDef.minItems = param.minItems;\n              if (param.maxItems !== undefined) propertyDef.maxItems = param.maxItems;\n            }\n            \n            // Add any default value\n            if (param.default !== undefined) {\n              propertyDef.default = param.default;\n            }\n            \n            // Add property to schema\n            (schemaObject.properties as Record<string, any>)[param.name] = propertyDef;\n            \n            if (param.required) {\n              requiredParams.push(param.name);\n            }\n          }\n        });\n        \n        if (requiredParams.length > 0) {\n          schemaObject.required = requiredParams;\n        }\n      }\n    }\n    \n    return schemaObject;\n  }\n  \n  private processResponse(data: any): string | StructuredCompletionResponse {\n    // Check if the response has the expected structure\n    if (!data?.message) {\n      logger.error('Unexpected Ollama API response structure:', {\n        responseObject: JSON.stringify(data)\n      });\n      \n      throw new Error(`Ollama API unexpected response structure: ${JSON.stringify(data)}`);\n    }\n    \n    const message = data.message;\n    const toolCalls = message.tool_calls;\n    \n    // Handle tool calls if present\n    if (toolCalls?.length > 0) {\n      // Log detailed raw tool calls for debugging\n      logger.debug('Ollama raw tool calls:', JSON.stringify(toolCalls, null, 2));\n      \n      // Return structured data instead of formatted text\n      return {\n        content: message.content || '',\n        tool_calls: toolCalls.map((call: any) => {\n          try {\n            if (call.type === 'function') {\n              // Parse arguments to JavaScript object\n              let args = {};\n              if (call.function?.arguments) {\n                try {\n                  args = typeof call.function.arguments === 'string'\n                    ? JSON.parse(call.function.arguments)\n                    : call.function.arguments;\n                } catch (e) {\n                  logger.error('Error parsing function arguments', { error: e });\n                }\n              }\n              \n              return {\n                type: 'function',\n                id: call.id,\n                name: call.function?.name,\n                arguments: args\n              };\n            }\n            return call;\n          } catch (e) {\n            logger.error('Error processing tool call', { error: e });\n            return { \n              type: 'error',\n              error: e instanceof Error ? e.message : String(e)\n            };\n          }\n        })\n      };\n    }\n    \n    // Return plain text response\n    return message.content || '';\n  }\n  \n  private handleError(error: any): void {\n    if (!error) return;\n    \n    // Log the full error details\n    logger.error('Ollama API error:', {\n      message: error.message,\n      status: error.status,\n      type: error.type,\n      stack: error.stack,\n    });\n  }\n}\n","import OpenAI from \"openai\";\nimport dotenv from \"dotenv\";\nimport { logger } from \"../utils/logger\";\nimport { DEFAULT_OPENAI_EMBEDDING_MODEL } from \"../constants\";\n\n// Initialize environment variables\ndotenv.config();\n\n/**\n * Simple utility for generating embeddings without requiring provider setup\n */\nexport class Embedding {\n  private static client: OpenAI | null = null;\n\n  /**\n   * Initialize the OpenAI client if not already initialized\n   */\n  private static initClient(): OpenAI {\n    if (!this.client) {\n      const apiKey =\n        process.env.OPENAI_EMBEDDING_API_KEY || process.env.OPENAI_API_KEY;\n\n      if (!apiKey) {\n        throw new Error(\n          \"OpenAI API key is required for embeddings - set OPENAI_API_KEY or OPENAI_EMBEDDING_API_KEY\"\n        );\n      }\n\n      this.client = new OpenAI({\n        apiKey,\n        baseURL: \"https://api.openai.com/v1\",\n      });\n    }\n\n    return this.client;\n  }\n\n  /**\n   * Generate an embedding for the given text\n   * @param text Text to generate embedding for\n   * @param model Embedding model to use (default: text-embedding-ada-002)\n   * @returns Embedding vector as array of numbers\n   */\n  static async generateEmbedding(\n    text: string,\n    model: string = process.env.OPENAI_EMBEDDING_MODEL ||\n      DEFAULT_OPENAI_EMBEDDING_MODEL\n  ): Promise<number[]> {\n    try {\n      if (!text || typeof text !== \"string\") {\n        throw new Error(\"Invalid text input for embedding generation\");\n      }\n\n      const client = this.initClient();\n      logger.debug(`Generating embedding for text with model: ${model}`);\n\n      const response = await client.embeddings.create({\n        model,\n        input: text,\n        encoding_format: \"float\",\n      });\n\n      return response.data[0].embedding;\n    } catch (error) {\n      logger.error(\"Error generating embedding:\", error);\n      throw error;\n    }\n  }\n\n  /**\n   * Calculate cosine similarity between two embedding vectors\n   * @param embedding1 First embedding vector\n   * @param embedding2 Second embedding vector\n   * @returns Similarity score (1.0 = identical, 0.0 = completely different)\n   */\n  static calculateSimilarity(\n    embedding1: number[],\n    embedding2: number[]\n  ): number {\n    if (!embedding1 || !embedding2 || embedding1.length !== embedding2.length) {\n      return 0;\n    }\n\n    // Calculate dot product\n    let dotProduct = 0;\n    let magnitude1 = 0;\n    let magnitude2 = 0;\n\n    for (let i = 0; i < embedding1.length; i++) {\n      dotProduct += embedding1[i] * embedding2[i];\n      magnitude1 += embedding1[i] * embedding1[i];\n      magnitude2 += embedding2[i] * embedding2[i];\n    }\n\n    magnitude1 = Math.sqrt(magnitude1);\n    magnitude2 = Math.sqrt(magnitude2);\n\n    // Avoid division by zero\n    if (magnitude1 === 0 || magnitude2 === 0) {\n      return 0;\n    }\n\n    // Return cosine similarity\n    return dotProduct / (magnitude1 * magnitude2);\n  }\n\n  /**\n   * Find similar texts based on embedding similarity\n   * @param queryEmbedding Embedding to compare against\n   * @param textEmbeddings Array of objects with text and embedding\n   * @param limit Maximum number of results to return\n   * @returns Array of results sorted by similarity (highest first)\n   */\n  static findSimilarTexts(\n    queryEmbedding: number[],\n    textEmbeddings: Array<{ text: string; embedding: number[] }>,\n    limit: number = 5\n  ): Array<{ text: string; similarity: number }> {\n    if (!queryEmbedding || !textEmbeddings || textEmbeddings.length === 0) {\n      return [];\n    }\n\n    // Calculate similarity for each text\n    const similarities = textEmbeddings\n      .map(({ text, embedding }) => ({\n        text,\n        similarity: this.calculateSimilarity(queryEmbedding, embedding),\n      }))\n      // Sort by similarity (highest first)\n      .sort((a, b) => b.similarity - a.similarity)\n      // Limit number of results\n      .slice(0, limit);\n\n    return similarities;\n  }\n\n  /**\n   * Check if embeddings are available (OpenAI API key and valid model)\n   * @param model Optional model to test\n   * @returns True if embeddings are available, false otherwise\n   */\n  static async isAvailable(model?: string): Promise<boolean> {\n    try {\n      // Check if API key exists\n      const apiKey =\n        process.env.OPENAI_EMBEDDING_API_KEY || process.env.OPENAI_API_KEY;\n      if (!apiKey) {\n        logger.warn(\"OpenAI API key not found for embeddings\");\n        return false;\n      }\n\n      // Try to generate a test embedding\n      const testEmbedding = await this.generateEmbedding(\"test\", model);\n      return Array.isArray(testEmbedding) && testEmbedding.length > 0;\n    } catch (error) {\n      logger.warn(\"Embedding test failed:\", error);\n      return false;\n    }\n  }\n\n  /**\n   * List available embedding models from OpenAI\n   * @returns Array of model IDs\n   */\n  static async listAvailableModels(): Promise<string[]> {\n    try {\n      const client = this.initClient();\n      const models = await client.models.list();\n\n      return models.data\n        .filter((model) => model.id.includes(\"embedding\"))\n        .map((model) => model.id);\n    } catch (error) {\n      logger.error(\"Error listing available models:\", error);\n      return [];\n    }\n  }\n} ","export { OpenAIProvider, createOpenAIConfig } from \"./openai\";\n\nexport { OllamaProvider, createOllamaConfig } from \"./ollama\";\n\nexport { Embedding } from \"./embedding\";\n\nimport { ProviderType, ProviderInstance, ProviderModel } from '../types/provider';\nimport { OpenAIModelConfig } from '../types/provider';\nimport { OllamaModelConfig } from '../types/provider';\n\nimport { OpenAIProvider, createOpenAIConfig } from './openai';\nimport { OllamaProvider, createOllamaConfig } from './ollama';\n\nexport const createProvider = (config: Record<string, unknown>): ProviderInstance => {\n  if (config.type === 'openai') {\n    \n    return {\n      type: 'openai' as ProviderType,\n      \n      \n      listModels(): string[] {\n        \n        return (config.models as string[]) || [config.model as string || 'gpt-3.5-turbo'];\n      },\n      \n      \n      getModel(name: string): ProviderModel {\n        const modelConfig = createOpenAIConfig(name, config as Partial<OpenAIModelConfig>);\n        return new OpenAIProvider('openai', modelConfig);\n      },\n      \n      \n      getDefaultModel(): string {\n        return config.model as string || 'gpt-3.5-turbo';\n      },\n      \n      \n      getEmbeddingModel(): string {\n        return config.embeddingModel as string || 'text-embedding-3-small';\n      },\n\n      // Add generateEmbedding method for RAG support\n      async generateEmbedding(text: string): Promise<number[] | null> {\n        try {\n          const { Embedding } = await import('./embedding');\n          const embeddingModel = config.embeddingModel as string || 'text-embedding-3-small';\n          return await Embedding.generateEmbedding(text, embeddingModel);\n        } catch (error) {\n          console.error('Error generating embedding:', error);\n          return null;\n        }\n      }\n    };\n  } else if (config.type === 'ollama') {\n    \n    return {\n      type: 'ollama' as ProviderType,\n      \n      listModels(): string[] {\n        return (config.models as string[]) || [config.model as string || 'llama2'];\n      },\n      \n      getModel(name: string): ProviderModel {\n        \n        const ollamaConfigBase = {\n          name: name,\n          ...config as Record<string, unknown>\n        };\n        \n        const ollamaConfig = createOllamaConfig \n          ? createOllamaConfig(name, config as Partial<OllamaModelConfig>) \n          : ollamaConfigBase as OllamaModelConfig;\n          \n        return new OllamaProvider('ollama', ollamaConfig);\n      },\n      \n      getDefaultModel(): string {\n        return config.model as string || 'llama2';\n      }\n    };\n  } else {\n    throw new Error(`Unknown provider type: ${config.type}`);\n  }\n}; ","// Astreus - AI Agent Framework\n\nimport { logger } from './utils/logger';\nimport { createAgent } from './agent';\nimport { createProvider } from './providers';\nimport { createMemory } from './memory';\nimport { createDatabase } from './database';\nimport { createRAG, parsePDF, parseDirectoryOfPDFs } from './rag';\nimport { createVectorDatabaseConnector, loadVectorDatabaseConfigFromEnv } from './rag/vector-db';\nimport { createChat } from './chat';\n\nexport { createAgent };\nexport { createProvider };\nexport { createMemory };\nexport { createDatabase };\nexport { createRAG };\nexport { createChat };\nexport { parsePDF, parseDirectoryOfPDFs };\nexport { logger };\nexport { createVectorDatabaseConnector, loadVectorDatabaseConfigFromEnv };\n\nexport * from './types';\nexport * from \"./constants\";\nexport * from \"./utils\";\nexport * from \"./tasks\";\nexport { validateRequiredParam, validateRequiredParams } from \"./utils/validation\";\nexport { PluginManager } from \"./plugin\";\n","import { v4 as uuidv4 } from \"uuid\";\nimport { AgentConfig, AgentInstance, AgentFactory, Plugin, ProviderModel, ProviderInstance, MemoryInstance, ChatInstance, ChatMetadata, ChatSummary } from \"./types\";\nimport { createDatabase } from \"./database\";\nimport { PluginManager } from \"./plugin\";\nimport { validateRequiredParams, validateRequiredParam } from \"./utils/validation\";\nimport { logger } from \"./utils/logger\";\nimport { createRAGTools } from \"./utils/rag-tools\";\nimport { \n  DEFAULT_AGENT_NAME\n} from \"./constants\";\n\n// Agent implementation\nclass Agent implements AgentInstance {\n  public id: string;\n  public config: AgentConfig;\n  private memory: MemoryInstance; // Replace any with MemoryInstance\n  private tools: Map<string, Plugin>;\n  private chatManager?: ChatInstance;\n\n  constructor(config: AgentConfig) {\n    // Validate required parameters\n    validateRequiredParam(config, \"config\", \"Agent constructor\");\n    validateRequiredParams(\n      config,\n      [\"memory\"],  // 'name' is optional now since we have a default\n      \"Agent constructor\"\n    );\n    \n    // Ensure either model or provider is specified\n    if (!config.model && !config.provider) {\n      throw new Error(\"Either 'model' or 'provider' must be specified in agent config\");\n    }\n    \n    // If provider is given but model is not, use default model from provider\n    if (config.provider && !config.model) {\n      const defaultModelName = config.provider.getDefaultModel?.() || config.provider.listModels()[0];\n      if (defaultModelName) {\n        config.model = config.provider.getModel(defaultModelName);\n      } else {\n        throw new Error(\"No default model available in provider\");\n      }\n    }\n    \n    // Ensure we have a model at this point\n    if (!config.model) {\n      throw new Error(\"No model could be determined for the agent\");\n    }\n    \n    // Set default values for optional parameters\n    this.id = config.id || uuidv4();\n    this.config = {\n      ...config,\n      name: config.name || DEFAULT_AGENT_NAME,\n      description: config.description || `Agent ${config.name || DEFAULT_AGENT_NAME}`,\n      tools: config.tools || [],\n      plugins: config.plugins || []\n    };\n    this.memory = config.memory;\n    this.tools = new Map();\n    this.chatManager = config.chat;\n\n    // Initialize tools if provided\n    if (this.config.tools) {\n      this.config.tools.forEach((tool) => {\n        this.tools.set(tool.name, tool);\n      });\n    }\n\n    // Create RAG tools if RAG instance is provided\n    if (this.config.rag) {\n      const ragTools = createRAGTools(this.config.rag);\n      ragTools.forEach((tool) => {\n        this.tools.set(tool.name, tool);\n      });\n      logger.debug(`Added ${ragTools.length} RAG tools to agent ${this.config.name}`);\n    }\n\n    // Initialize plugins and register their tools if provided\n    if (this.config.plugins) {\n      for (const plugin of this.config.plugins) {\n        // Check if plugin has getTools method (PluginInstance)\n        if (plugin && 'getTools' in plugin && typeof plugin.getTools === 'function') {\n          const pluginTools = plugin.getTools();\n          \n          if (pluginTools && Array.isArray(pluginTools)) {\n            pluginTools.forEach((tool: Plugin) => {\n              if (tool && tool.name) {\n                this.tools.set(tool.name, tool);\n                // Also register with the global registry\n                PluginManager.register(tool);\n              }\n            });\n          }\n        } \n        // Check if it's a direct Plugin object\n        else if (plugin && 'name' in plugin && plugin.name && 'execute' in plugin) {\n          // This is already a tool/plugin, register it directly\n          const toolPlugin = plugin as Plugin;\n          this.tools.set(toolPlugin.name, toolPlugin);\n          PluginManager.register(toolPlugin);\n        }\n      }\n    }\n\n\n  }\n\n\n\n  // Helper method to safely get the model\n  getModel(): ProviderModel {\n    if (!this.config.model) {\n      throw new Error(\"No model specified for agent\");\n    }\n    return this.config.model;\n  }\n\n  // Get the provider instance\n  getProvider(): ProviderInstance | undefined {\n    return this.config.provider;\n  }\n\n  // Memory access methods\n  async getHistory(sessionId: string, limit?: number): Promise<any[]> {\n    validateRequiredParam(sessionId, \"sessionId\", \"getHistory\");\n    return await this.memory.getBySession(sessionId, limit);\n  }\n\n  async clearHistory(sessionId: string): Promise<void> {\n    validateRequiredParam(sessionId, \"sessionId\", \"clearHistory\");\n    await this.memory.clear(sessionId);\n  }\n\n  async addToMemory(params: {\n    sessionId: string;\n    role: 'user' | 'assistant' | 'system';\n    content: string;\n    metadata?: Record<string, unknown>;\n  }): Promise<string> {\n    validateRequiredParam(params.sessionId, \"params.sessionId\", \"addToMemory\");\n    validateRequiredParam(params.role, \"params.role\", \"addToMemory\");\n    validateRequiredParam(params.content, \"params.content\", \"addToMemory\");\n\n    return await this.memory.add({\n      agentId: this.id,\n      sessionId: params.sessionId,\n      role: params.role,\n      content: params.content,\n      metadata: params.metadata || {}\n    });\n  }\n\n  // List all sessions for this agent\n  async listSessions(limit?: number): Promise<{\n    sessionId: string;\n    lastMessage?: string;\n    messageCount: number;\n    lastActivity: Date;\n    metadata?: Record<string, unknown>;\n  }[]> {\n    try {\n      // Get all sessions from memory for this agent\n      const sessions = await this.memory.listSessions(this.id, limit);\n      \n      return sessions.map((session: any) => ({\n        sessionId: session.sessionId,\n        lastMessage: session.lastMessage || session.content,\n        messageCount: session.messageCount || 1,\n        lastActivity: session.lastActivity || session.createdAt || new Date(),\n        metadata: session.metadata || {}\n      }));\n    } catch (error) {\n      logger.error(`Error listing sessions for agent ${this.id}:`, error);\n      return [];\n    }\n  }\n\n  // Chat method without streaming\n  async chat(params: {\n    message: string;\n    sessionId?: string;\n    systemPrompt?: string;\n    temperature?: number;\n    maxTokens?: number;\n    metadata?: Record<string, unknown>;\n  }): Promise<string> {\n    validateRequiredParam(params.message, \"params.message\", \"chat\");\n\n    const {\n      message,\n      sessionId = `session-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,\n      systemPrompt = this.config.systemPrompt,\n      temperature = 0.7,\n      maxTokens = 2000,\n      metadata = {}\n    } = params;\n\n    // Get conversation history\n    const history = sessionId ? await this.getHistory(sessionId) : [];\n\n    // Prepare messages for the model\n    const messages = [\n      ...(systemPrompt ? [{ role: 'system' as const, content: systemPrompt }] : []),\n      ...history.map((msg: any) => ({\n        role: (msg.role === 'user' ? 'user' : 'assistant') as 'user' | 'assistant',\n        content: msg.content\n      })),\n      { role: 'user' as const, content: message }\n    ];\n\n    // Get response from model\n    const model = this.getModel();\n    const response = await model.complete(messages, {\n      temperature,\n      maxTokens\n    });\n\n    const responseContent = typeof response === 'string' ? response : response.content;\n\n    // Save to memory\n    await this.addToMemory({\n      sessionId,\n      role: 'user',\n      content: message,\n      metadata\n    });\n\n    await this.addToMemory({\n      sessionId,\n      role: 'assistant',\n      content: responseContent,\n      metadata\n    });\n\n    return responseContent;\n  }\n\n  // Streaming chat method\n  async streamChat(params: {\n    message: string;\n    sessionId?: string;\n    systemPrompt?: string;\n    temperature?: number;\n    maxTokens?: number;\n    metadata?: Record<string, unknown>;\n    onChunk?: (chunk: string) => void;\n  }): Promise<string> {\n    validateRequiredParam(params.message, \"params.message\", \"streamChat\");\n\n    const {\n      message,\n      sessionId = `session-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,\n      systemPrompt = this.config.systemPrompt,\n      temperature = 0.7,\n      maxTokens = 2000,\n      metadata = {},\n      onChunk\n    } = params;\n\n    // Get conversation history\n    const history = sessionId ? await this.getHistory(sessionId) : [];\n\n    // Prepare messages for the model\n    const messages = [\n      ...(systemPrompt ? [{ role: 'system' as const, content: systemPrompt }] : []),\n      ...history.map((msg: any) => ({\n        role: (msg.role === 'user' ? 'user' : 'assistant') as 'user' | 'assistant',\n        content: msg.content\n      })),\n      { role: 'user' as const, content: message }\n    ];\n\n    let fullResponse = '';\n    const model = this.getModel();\n    const provider = this.getProvider();\n\n    // Try to get OpenAI client for real streaming\n    const openaiClient = (provider as any)?.client || (model as any)?.client;\n\n    if (openaiClient && openaiClient.chat && openaiClient.chat.completions) {\n      logger.debug(`Agent ${this.config.name}: Using real OpenAI streaming`);\n      \n      // Use OpenAI streaming directly for incremental chunks\n      const stream = await openaiClient.chat.completions.create({\n        model: model.name || 'gpt-4o-mini',\n        messages: messages,\n        stream: true,\n        temperature,\n        max_tokens: maxTokens\n      });\n\n      for await (const chunk of stream) {\n        const content = chunk.choices[0]?.delta?.content || '';\n        if (content) {\n          fullResponse += content;\n          if (onChunk) {\n            onChunk(content); // Send only the new chunk\n          }\n        }\n      }\n    } else if (model.complete) {\n      logger.debug(`Agent ${this.config.name}: Using simulated streaming`);\n      \n      // Fallback to complete method with simulated streaming\n      const response = await model.complete(messages, {\n        temperature,\n        maxTokens\n      });\n\n      const responseContent = typeof response === 'string' ? response : response.content;\n      fullResponse = responseContent;\n\n      if (onChunk) {\n        // Simulate streaming by sending word by word\n        const words = responseContent.split(' ');\n        for (let i = 0; i < words.length; i++) {\n          const word = words[i] + (i < words.length - 1 ? ' ' : '');\n          onChunk(word);\n          // Small delay for realistic streaming effect\n          await new Promise(resolve => setTimeout(resolve, 50));\n        }\n      }\n    } else {\n      throw new Error('No suitable model method available for streaming');\n    }\n\n    // Save to memory\n    await this.addToMemory({\n      sessionId,\n      role: 'user',\n      content: message,\n      metadata\n    });\n\n    await this.addToMemory({\n      sessionId,\n      role: 'assistant',\n      content: fullResponse,\n      metadata\n    });\n\n    return fullResponse;\n  }\n\n  /**\n   * Get available tool names\n   * @returns Array of tool names available to the agent\n   */\n  getAvailableTools(): string[] {\n    return Array.from(this.tools.keys());\n  }\n\n  addTool(tool: Plugin): void {\n    // Validate required parameters\n    validateRequiredParam(tool, \"tool\", \"addTool\");\n    validateRequiredParams(\n      tool,\n      [\"name\", \"description\", \"execute\"],\n      \"addTool\"\n    );\n    \n    this.tools.set(tool.name, tool);\n  }\n\n  /**\n   * Get the chat manager instance if available\n   */\n  getChatManager(): ChatInstance | undefined {\n    return this.chatManager;\n  }\n\n  /**\n   * Set or update the chat manager instance\n   */\n  setChatManager(chatManager: ChatInstance): void {\n    this.chatManager = chatManager;\n  }\n\n  // Chat management methods\n  async createChat(params: {\n    chatId?: string;\n    userId?: string;\n    title?: string;\n    metadata?: Record<string, unknown>;\n  }): Promise<ChatMetadata> {\n    if (!this.chatManager) {\n      throw new Error(\"Chat manager not configured for this agent\");\n    }\n\n    return await this.chatManager.createChat({\n      chatId: params.chatId,\n      userId: params.userId,\n      agentId: this.id,\n      title: params.title,\n      metadata: params.metadata\n    });\n  }\n\n  async getChat(chatId: string): Promise<ChatMetadata | null> {\n    validateRequiredParam(chatId, \"chatId\", \"getChat\");\n    \n    if (!this.chatManager) {\n      throw new Error(\"Chat manager not configured for this agent\");\n    }\n\n    return await this.chatManager.getChat(chatId);\n  }\n\n  async updateChat(chatId: string, updates: Partial<ChatMetadata>): Promise<void> {\n    validateRequiredParam(chatId, \"chatId\", \"updateChat\");\n    \n    if (!this.chatManager) {\n      throw new Error(\"Chat manager not configured for this agent\");\n    }\n\n    await this.chatManager.updateChat(chatId, updates);\n  }\n\n  async deleteChat(chatId: string): Promise<void> {\n    validateRequiredParam(chatId, \"chatId\", \"deleteChat\");\n    \n    if (!this.chatManager) {\n      throw new Error(\"Chat manager not configured for this agent\");\n    }\n\n    await this.chatManager.deleteChat(chatId);\n  }\n\n  async archiveChat(chatId: string): Promise<void> {\n    validateRequiredParam(chatId, \"chatId\", \"archiveChat\");\n    \n    if (!this.chatManager) {\n      throw new Error(\"Chat manager not configured for this agent\");\n    }\n\n    await this.chatManager.archiveChat(chatId);\n  }\n\n  async listChats(params?: {\n    userId?: string;\n    status?: 'active' | 'archived' | 'deleted';\n    limit?: number;\n    offset?: number;\n  }): Promise<ChatSummary[]> {\n    if (!this.chatManager) {\n      throw new Error(\"Chat manager not configured for this agent\");\n    }\n\n    return await this.chatManager.listChats({\n      ...params,\n      agentId: this.id\n    });\n  }\n\n  async searchChats(params: {\n    query: string;\n    userId?: string;\n    limit?: number;\n  }): Promise<ChatSummary[]> {\n    validateRequiredParam(params.query, \"params.query\", \"searchChats\");\n    \n    if (!this.chatManager) {\n      throw new Error(\"Chat manager not configured for this agent\");\n    }\n\n    return await this.chatManager.searchChats({\n      ...params,\n      agentId: this.id\n    });\n  }\n\n  async getChatStats(params?: {\n    userId?: string;\n  }): Promise<{\n    totalChats: number;\n    activeChats: number;\n    archivedChats: number;\n    totalMessages: number;\n  }> {\n    if (!this.chatManager) {\n      throw new Error(\"Chat manager not configured for this agent\");\n    }\n\n    return await this.chatManager.getChatStats({\n      ...params,\n      agentId: this.id\n    });\n  }\n\n  // Enhanced chat methods with chat ID support\n  async chatWithId(params: {\n    message: string;\n    chatId: string;\n    userId?: string;\n    systemPrompt?: string;\n    temperature?: number;\n    maxTokens?: number;\n    metadata?: Record<string, unknown>;\n  }): Promise<string> {\n    validateRequiredParam(params.message, \"params.message\", \"chatWithId\");\n    validateRequiredParam(params.chatId, \"params.chatId\", \"chatWithId\");\n    \n    if (!this.chatManager) {\n      throw new Error(\"Chat manager not configured for this agent\");\n    }\n\n    // Check if chat exists, if not create it\n    const existingChat = await this.chatManager.getChat(params.chatId);\n    if (!existingChat) {\n      await this.chatManager.createChat({\n        chatId: params.chatId,\n        userId: params.userId,\n        agentId: this.id,\n        metadata: params.metadata\n      });\n    }\n\n    return await this.chatManager.chat({\n      message: params.message,\n      chatId: params.chatId,\n      agentId: this.id,\n      userId: params.userId,\n      model: this.getModel(),\n      systemPrompt: params.systemPrompt || this.config.systemPrompt,\n      tools: Array.from(this.tools.values()),\n      metadata: params.metadata,\n      temperature: params.temperature,\n      maxTokens: params.maxTokens\n    });\n  }\n\n  async streamChatWithId(params: {\n    message: string;\n    chatId: string;\n    userId?: string;\n    systemPrompt?: string;\n    temperature?: number;\n    maxTokens?: number;\n    metadata?: Record<string, unknown>;\n    onChunk?: (chunk: string) => void;\n  }): Promise<string> {\n    validateRequiredParam(params.message, \"params.message\", \"streamChatWithId\");\n    validateRequiredParam(params.chatId, \"params.chatId\", \"streamChatWithId\");\n    \n    if (!this.chatManager) {\n      throw new Error(\"Chat manager not configured for this agent\");\n    }\n\n    // Check if chat exists, if not create it\n    const existingChat = await this.chatManager.getChat(params.chatId);\n    if (!existingChat) {\n      await this.chatManager.createChat({\n        chatId: params.chatId,\n        userId: params.userId,\n        agentId: this.id,\n        metadata: params.metadata\n      });\n    }\n\n    // For now, use the regular chat method and simulate streaming\n    // This can be enhanced later with true streaming support in ChatManager\n    const response = await this.chatManager.chat({\n      message: params.message,\n      chatId: params.chatId,\n      agentId: this.id,\n      userId: params.userId,\n      model: this.getModel(),\n      systemPrompt: params.systemPrompt || this.config.systemPrompt,\n      tools: Array.from(this.tools.values()),\n      metadata: params.metadata,\n      temperature: params.temperature,\n      maxTokens: params.maxTokens\n    });\n\n    // Simulate streaming by calling onChunk with the full response\n    if (params.onChunk) {\n      params.onChunk(response);\n    }\n\n    return response;\n  }\n}\n\n// Agent factory function\nexport const createAgent: AgentFactory = async (config: AgentConfig) => {\n  // Validate required parameters\n  validateRequiredParam(config, \"config\", \"createAgent\");\n  validateRequiredParams(\n    config,\n    [\"memory\"],\n    \"createAgent\"\n  );\n  \n  // Ensure either model or provider is specified\n  if (!config.model && !config.provider) {\n    throw new Error(\"Either 'model' or 'provider' must be specified in agent config\");\n  }\n  \n  // Create a new agent instance\n  const agent = new Agent(config);\n\n  // Save agent to database\n  try {\n    // Use database from config if provided, otherwise create a new one\n    const db = config.database || await createDatabase();\n    const tableNames = db.getTableNames();\n    \n    // Ensure agents table exists\n    await db.ensureTable(tableNames.agents, (table) => {\n      table.string(\"id\").primary();\n      table.string(\"name\").notNullable();\n      table.text(\"description\").nullable();\n      table.text(\"systemPrompt\").nullable();\n      table.string(\"modelName\").notNullable();\n      table.timestamp(\"createdAt\").defaultTo(db.knex.fn.now());\n      table.timestamp(\"updatedAt\").defaultTo(db.knex.fn.now());\n      table.json(\"configuration\").nullable();\n    });\n\n    const agentsTable = db.getTable(tableNames.agents);\n\n    // Check if agent already exists\n    const existingAgent = await agentsTable.findOne({ id: agent.id });\n\n    if (!existingAgent) {\n      // Save new agent\n      await agentsTable.insert({\n        id: agent.id,\n        name: agent.config.name,\n        description: agent.config.description || null,\n        systemPrompt: agent.config.systemPrompt || null,\n        modelName: agent.config.model?.name || \"unknown\",\n        createdAt: new Date(),\n        updatedAt: new Date(),\n        configuration: JSON.stringify({\n          hasTools: agent.getAvailableTools().length > 0,\n          supportsTaskSystem: true,\n        }),\n      });\n      logger.agent(agent.config.name, `Agent saved to database with ID: ${agent.id}`);\n    } else {\n      // Update existing agent\n      await agentsTable.update(\n        { id: agent.id },\n        {\n          name: agent.config.name,\n          description: agent.config.description || null,\n          systemPrompt: agent.config.systemPrompt || null,\n          modelName: agent.config.model?.name || \"unknown\",\n          updatedAt: new Date(),\n          configuration: JSON.stringify({\n            hasTools: agent.getAvailableTools().length > 0,\n            supportsTaskSystem: true,\n          }),\n        }\n      );\n      logger.agent(agent.config.name, `Agent updated in database with ID: ${agent.id}`);\n    }\n  } catch (error) {\n    logger.error(\"Error saving agent to database:\", error);\n  }\n\n  return agent;\n}; ","import { Knex } from \"knex\";\nimport fs from \"fs\";\nimport path from \"path\";\nimport dotenv from \"dotenv\";\nimport {\n  DatabaseConfig,\n  DatabaseInstance,\n  DatabaseFactory,\n  TableOperations,\n  TableNamesConfig,\n} from \"./types\";\nimport { createSqliteDatabase } from \"./database/sqlite\";\nimport { createPostgresqlDatabase } from \"./database/postgresql\";\nimport { v4 as uuidv4 } from \"uuid\";\nimport { logger } from \"./utils\";\nimport { validateRequiredParam, validateRequiredParams } from \"./utils/validation\";\nimport { DEFAULT_DB_PATH } from \"./constants\";\n\n// Load environment variables\ndotenv.config();\n\n// Re-export configuration helpers\nexport { createSqliteConfig } from \"./database/sqlite\";\nexport { createPostgresqlConfig } from \"./database/postgresql\";\n\n// Re-export database modules\nexport { \n  createUser, \n  getUserById, \n  getUserByUsername, \n  updateUser, \n  deleteUser \n} from \"./database/modules/user\";\n\n// Re-export types\nexport { DatabaseInstance, DatabaseConfig } from \"./types/database\";\n\n/**\n * Core database implementation that provides storage functionality\n * for the Astreus framework. Supports multiple database backends.\n */\nclass Database implements DatabaseInstance {\n  public knex: Knex;\n  public config: DatabaseConfig;\n  private initialized: boolean = false;\n  private tableNames: Required<TableNamesConfig>;\n  private customTables: Map<string, string> = new Map();\n\n  constructor(config: DatabaseConfig) {\n    // Validate required parameters\n    validateRequiredParam(config, \"config\", \"Database constructor\");\n    validateRequiredParams(\n      config,\n      [\"type\"],\n      \"Database constructor\"\n    );\n    \n    this.config = config;\n    \n    // Apply table prefix if specified\n    const prefix = config.tablePrefix || '';\n    \n    // Set table names with defaults and prefix\n    this.tableNames = {\n      agents: prefix + (config.tableNames?.agents || 'agents'),\n      users: prefix + (config.tableNames?.users || 'users'),\n      tasks: prefix + (config.tableNames?.tasks || 'tasks'),\n      memories: prefix + (config.tableNames?.memories || 'memories'),\n      chats: prefix + (config.tableNames?.chats || 'chats'),\n      custom: config.tableNames?.custom || {}\n    };\n\n    // Register custom tables\n    if (config.tableNames?.custom) {\n      Object.entries(config.tableNames.custom).forEach(([name, tableName]) => {\n        this.customTables.set(name, prefix + tableName);\n      });\n    }\n\n    // Initialize knex instance based on database type\n    if (config.type === \"sqlite\") {\n      this.knex = createSqliteDatabase(config);\n    } else if (config.type === \"postgresql\") {\n      this.knex = createPostgresqlDatabase(config);\n    } else {\n      throw new Error(`Unsupported database type: ${config.type}`);\n    }\n  }\n\n  /**\n   * Connect to the database and verify the connection\n   * @throws Error if connection fails\n   */\n  async connect(): Promise<void> {\n    try {\n      // Test the connection\n      await this.knex.raw(\"SELECT 1\");\n      logger.database(\"Connect\", `Connected to ${this.config.type} database`);\n    } catch (error) {\n      logger.error(`Error connecting to ${this.config.type} database:`, error);\n      throw error;\n    }\n  }\n\n  /**\n   * Gracefully disconnect from the database\n   */\n  async disconnect(): Promise<void> {\n    await this.knex.destroy();\n    logger.database(\"Disconnect\", `Disconnected from ${this.config.type} database`);\n  }\n\n  /**\n   * Execute a raw SQL query against the database\n   * @param query The SQL query to execute\n   * @param params Parameters to bind to the query\n   * @returns Results of the query\n   */\n  async executeQuery<T = any>(query: string, params: any[] = []): Promise<T[]> {\n    // Validate required parameters\n    validateRequiredParam(query, \"query\", \"executeQuery\");\n    \n    try {\n      return this.knex.raw(query, params) as Promise<T[]>;\n    } catch (error) {\n      logger.error(\"Error executing query:\", error);\n      throw error;\n    }\n  }\n\n  /**\n   * Check if a table exists\n   * @param tableName Name of the table to check\n   * @returns Promise resolving to boolean indicating if table exists\n   */\n  async hasTable(tableName: string): Promise<boolean> {\n    validateRequiredParam(tableName, \"tableName\", \"hasTable\");\n    return await this.knex.schema.hasTable(tableName);\n  }\n\n  /**\n   * Create a table with the given schema\n   * @param tableName Name of the table to create\n   * @param schema Function that defines the table schema\n   */\n  async createTable(tableName: string, schema: (table: Knex.TableBuilder) => void): Promise<void> {\n    validateRequiredParam(tableName, \"tableName\", \"createTable\");\n    validateRequiredParam(schema, \"schema\", \"createTable\");\n    \n    try {\n      await this.knex.schema.createTable(tableName, schema);\n      logger.database(\"CreateTable\", `Created table: ${tableName}`);\n    } catch (error) {\n      logger.error(`Error creating table ${tableName}:`, error);\n      throw error;\n    }\n  }\n\n  /**\n   * Drop a table if it exists\n   * @param tableName Name of the table to drop\n   */\n  async dropTable(tableName: string): Promise<void> {\n    validateRequiredParam(tableName, \"tableName\", \"dropTable\");\n    \n    try {\n      await this.knex.schema.dropTableIfExists(tableName);\n      logger.database(\"DropTable\", `Dropped table: ${tableName}`);\n    } catch (error) {\n      logger.error(`Error dropping table ${tableName}:`, error);\n      throw error;\n    }\n  }\n\n  /**\n   * Ensure a table exists, create it if it doesn't\n   * @param tableName Name of the table to ensure\n   * @param schema Function that defines the table schema\n   */\n  async ensureTable(tableName: string, schema: (table: Knex.TableBuilder) => void): Promise<void> {\n    validateRequiredParam(tableName, \"tableName\", \"ensureTable\");\n    validateRequiredParam(schema, \"schema\", \"ensureTable\");\n    \n    const exists = await this.hasTable(tableName);\n    if (!exists) {\n      await this.createTable(tableName, schema);\n    } else {\n      logger.database(\"EnsureTable\", `Table ${tableName} already exists`);\n    }\n  }\n\n  /**\n   * Register a custom table name mapping\n   * @param name Logical name for the table\n   * @param tableName Actual table name in database\n   */\n  registerCustomTable(name: string, tableName: string): void {\n    validateRequiredParam(name, \"name\", \"registerCustomTable\");\n    validateRequiredParam(tableName, \"tableName\", \"registerCustomTable\");\n    \n    const prefix = this.config.tablePrefix || '';\n    this.customTables.set(name, prefix + tableName);\n    logger.database(\"RegisterCustomTable\", `Registered custom table: ${name} -> ${prefix + tableName}`);\n  }\n\n  /**\n   * Get the actual table name for a custom table\n   * @param name Logical name of the custom table\n   * @returns Actual table name or undefined if not found\n   */\n  getCustomTableName(name: string): string | undefined {\n    return this.customTables.get(name);\n  }\n\n  /**\n   * Initialize database schema - only handles legacy migrations now\n   * Each module (createMemory, createChat, etc.) is responsible for creating its own tables\n   */\n  async initializeSchema(): Promise<void> {\n    try {\n      // Only handle legacy migrations, no auto table creation\n      await this.migrateLegacyTables();\n      \n      // Mark as initialized\n      this.initialized = true;\n      logger.database(\"InitializeSchema\", \"Database schema initialization complete (legacy migrations only)\");\n    } catch (error) {\n      logger.error(\"Error initializing database schema:\", error);\n      throw error;\n    }\n  }\n\n  /**\n   * Migrate legacy tables and remove deprecated ones\n   * @param memoriesTableName Optional table name for memories (defaults to configured name)\n   */\n  private async migrateLegacyTables(memoriesTableName?: string): Promise<void> {\n    const memoryTable = memoriesTableName || this.tableNames.memories;\n    \n    // Check for task_contexts table (deprecated) and migrate data\n    const hasTaskContextsTable = await this.knex.schema.hasTable(\"task_contexts\");\n    if (hasTaskContextsTable) {\n      try {\n        const contextRecords = await this.knex(\"task_contexts\").select(\"*\");\n        if (contextRecords.length > 0) {\n          logger.database(\"InitializeSchema\", `Migrating ${contextRecords.length} task contexts to memory system...`);\n\n          // Check if memories table exists before migration\n          const hasMemoriesTable = await this.knex.schema.hasTable(memoryTable);\n          if (!hasMemoriesTable) {\n            logger.warn(`Memories table '${memoryTable}' does not exist. Skipping task contexts migration.`);\n          } else {\n            // Batch insert to memories table\n            const memoryRecords = contextRecords.map((record: any) => ({\n              id: uuidv4(),\n              agentId: \"system\",\n              sessionId: record.sessionId,\n              userId: \"\",\n              role: \"task_context\",\n              content: record.data,\n              timestamp: record.updatedAt || new Date(),\n              metadata: JSON.stringify({\n                contextType: \"task_execution_context\",\n                migratedFrom: \"task_contexts\",\n              }),\n            }));\n\n            await this.knex(memoryTable).insert(memoryRecords);\n            logger.database(\"InitializeSchema\", \"Task contexts migration completed successfully\");\n          }\n        }\n      } catch (migrationError) {\n        logger.error(\"Error migrating task contexts:\", migrationError);\n      }\n\n      // Drop the deprecated table\n      await this.knex.schema.dropTable(\"task_contexts\");\n      logger.database(\"InitializeSchema\", \"Dropped deprecated task_contexts table\");\n    }\n  }\n\n  /**\n   * Get operations interface for a specific table\n   * @param tableName Name of the table to operate on\n   * @returns Table operations interface\n   */\n  getTable(tableName: string): TableOperations {\n    // Validate required parameters\n    validateRequiredParam(tableName, \"tableName\", \"getTable\");\n    \n    const knexInstance = this.knex;\n\n    return {\n      /**\n       * Insert data into table\n       */\n      async insert(data: Record<string, any>): Promise<number | string> {\n        // Validate required parameters\n        validateRequiredParam(data, \"data\", \"insert\");\n        \n        try {\n          const result = await knexInstance(tableName).insert(data);\n          return result[0];\n        } catch (error) {\n          logger.error(`Error inserting into ${tableName}:`, error);\n          throw error;\n        }\n      },\n\n      /**\n       * Find records in table\n       */\n      async find(filter?: Record<string, any>): Promise<Record<string, any>[]> {\n        try {\n          let query = knexInstance(tableName);\n          if (filter) {\n            query = query.where(filter);\n          }\n          return query.select(\"*\");\n        } catch (error) {\n          logger.error(`Error finding in ${tableName}:`, error);\n          throw error;\n        }\n      },\n\n      /**\n       * Find one record in table\n       */\n      async findOne(\n        filter: Record<string, any>\n      ): Promise<Record<string, any> | null> {\n        // Validate required parameters\n        validateRequiredParam(filter, \"filter\", \"findOne\");\n        \n        try {\n          const result = await knexInstance(tableName).where(filter).first();\n          return result || null;\n        } catch (error) {\n          logger.error(`Error finding one in ${tableName}:`, error);\n          throw error;\n        }\n      },\n\n      /**\n       * Update records in table\n       */\n      async update(\n        filter: Record<string, any>,\n        data: Record<string, any>\n      ): Promise<number> {\n        // Validate required parameters\n        validateRequiredParam(filter, \"filter\", \"update\");\n        validateRequiredParam(data, \"data\", \"update\");\n        \n        try {\n          return await knexInstance(tableName).where(filter).update(data);\n        } catch (error) {\n          logger.error(`Error updating in ${tableName}:`, error);\n          throw error;\n        }\n      },\n\n      /**\n       * Delete records from table\n       */\n      async delete(filter: Record<string, any>): Promise<number> {\n        // Validate required parameters\n        validateRequiredParam(filter, \"filter\", \"delete\");\n        \n        try {\n          return await knexInstance(tableName).where(filter).delete();\n        } catch (error) {\n          logger.error(`Error deleting from ${tableName}:`, error);\n          throw error;\n        }\n      },\n    };\n  }\n\n  /**\n   * Check if the database has been initialized\n   */\n  isInitialized(): boolean {\n    return this.initialized;\n  }\n\n  /**\n   * Get configured table names\n   * @returns Object containing all configured table names\n   */\n  getTableNames(): Required<TableNamesConfig> {\n    return this.tableNames;\n  }\n}\n\n// Database factory function\nexport const createDatabase: DatabaseFactory = async (\n  config?: DatabaseConfig\n) => {\n  // If no config is provided, create a default one\n  if (!config) {\n    // Determine which database to use based on environment variables\n    const dbType = process.env.DATABASE_TYPE || \"sqlite\";\n\n    if (dbType === \"sqlite\") {\n      // For SQLite, create a default file-based database\n      const dbPath = process.env.DATABASE_PATH || DEFAULT_DB_PATH;\n      \n      // Create database directory if it doesn't exist (for file-based SQLite)\n      const dir = path.dirname(dbPath);\n      if (!fs.existsSync(dir)) {\n        fs.mkdirSync(dir, { recursive: true });\n        logger.database(\"CreateDatabase\", `Created database directory: ${dir}`);\n      }\n      \n      config = {\n        type: \"sqlite\",\n        connection: dbPath,\n      };\n      \n      logger.database(\"CreateDatabase\", `Using SQLite database at ${dbPath}`);\n    } else if (dbType === \"postgresql\") {\n      // For PostgreSQL, use connection URL\n      if (process.env.DATABASE_URL) {\n        // Parse connection string\n        const url = new URL(process.env.DATABASE_URL);\n        const host = url.hostname;\n        const port = parseInt(url.port || \"5432\");\n        const user = url.username;\n        const password = url.password;\n        const database = url.pathname.substring(1); // Remove leading slash\n        \n        config = {\n          type: \"postgresql\",\n          connection: {\n            host,\n            port,\n            user,\n            password,\n            database,\n          },\n        };\n        \n        logger.database(\"CreateDatabase\", `Using PostgreSQL database from URL: ${host}:${port}/${database}`);\n      } else {\n        throw new Error(\"PostgreSQL connection requires DATABASE_URL environment variable\");\n      }\n    } else {\n      throw new Error(`Unsupported database type: ${dbType}`);\n    }\n  } else {\n    // Validate the provided config\n    validateRequiredParams(\n      config,\n      [\"type\"],\n      \"createDatabase\"\n    );\n  }\n\n  // Create a new database instance\n  const db = new Database(config);\n\n  // Connect to the database\n  await db.connect();\n\n  // Only run legacy migrations, no auto table creation\n  await db.initializeSchema();\n\n  return db;\n};","import knex, { Knex } from \"knex\";\nimport { DatabaseConfig } from \"../types\";\n\n/**\n * Create a SQLite database connection\n */\nexport function createSqliteDatabase(config: DatabaseConfig): Knex {\n  return knex({\n    client: \"sqlite3\",\n    connection: {\n      filename:\n        typeof config.connection === \"string\" ? config.connection : \":memory:\",\n    },\n    useNullAsDefault: true,\n  });\n}\n\n/**\n * Create a SQLite database configuration\n */\nexport function createSqliteConfig(filename: string): DatabaseConfig {\n  return {\n    type: \"sqlite\",\n    connection: filename,\n  };\n}\n","import knex, { Knex } from \"knex\";\nimport { DatabaseConfig } from \"../types\";\n\n/**\n * Create a PostgreSQL database connection\n */\nexport function createPostgresqlDatabase(config: DatabaseConfig): Knex {\n  return knex({\n    client: \"pg\",\n    connection: config.connection,\n  });\n}\n\n/**\n * Create a PostgreSQL database configuration\n */\nexport function createPostgresqlConfig(\n  connectionString: string\n): DatabaseConfig {\n  return {\n    type: \"postgresql\",\n    connection: connectionString,\n  };\n}\n","export { \n  logger, \n  configure as configureLogger, \n  printBanner, \n  LogLevel \n} from \"./logger\"; \n\n\nexport { validateRequiredParam, validateRequiredParams } from \"./validation\"; \nexport { createRAGTools } from \"./rag-tools\"; ","/**\n * Utility functions for parameter validation\n */\n\n/**\n * Validates that all required parameters are provided\n * @param params The parameters object to validate\n * @param requiredParams Array of parameter names that are required\n * @param functionName Name of the function for error message context\n * @throws Error if any required parameter is missing or undefined\n */\nexport function validateRequiredParams(\n  params: Record<string, any>,\n  requiredParams: string[],\n  functionName: string\n): void {\n  // First check that params is actually an object\n  if (!params || typeof params !== 'object') {\n    throw new Error(`Invalid parameters object for ${functionName}: expected an object but got ${typeof params}`);\n  }\n  \n  const missingParams: string[] = [];\n  \n  for (const param of requiredParams) {\n    if (param in params) {\n      // Parameter exists in the object, check if it's undefined or null\n      if (params[param] === undefined || params[param] === null) {\n        missingParams.push(param);\n      }\n    } else {\n      // Parameter doesn't exist in the object at all\n      missingParams.push(param);\n    }\n  }\n  \n  if (missingParams.length > 0) {\n    throw new Error(\n      `Missing required parameter${missingParams.length > 1 ? 's' : ''} for ${functionName}: ${missingParams.join(', ')}`\n    );\n  }\n}\n\n/**\n * Validates a single required parameter\n * @param value The parameter value to check\n * @param paramName Name of the parameter for error message\n * @param functionName Name of the function for error message context\n * @throws Error if the parameter is missing or undefined\n */\nexport function validateRequiredParam(\n  value: any,\n  paramName: string,\n  functionName: string\n): void {\n  if (value === undefined || value === null) {\n    throw new Error(`Missing required parameter '${paramName}' for ${functionName}`);\n  }\n} ","import { Plugin } from \"../types\";\nimport { RAGInstance, VectorRAGInstance, DocumentRAGInstance } from \"../types/rag\";\nimport { logger } from \"./logger\";\n\n/**\n * Convert a RAG instance to an array of tools that can be used by agents\n * @param rag The RAG instance to convert\n * @returns Array of Plugin tools for RAG functionality\n */\nexport function createRAGTools(rag: RAGInstance): Plugin[] {\n  const tools: Plugin[] = [];\n\n  // Common search tool available for all RAG types\n  tools.push({\n    name: \"rag_search\",\n    description: \"Search through documents using semantic similarity to find relevant information\",\n    parameters: [\n      {\n        name: \"query\",\n        type: \"string\",\n        description: \"The search query to find relevant documents or content\",\n        required: true\n      },\n      {\n        name: \"limit\",\n        type: \"number\",\n        description: \"Maximum number of results to return\",\n        required: false,\n        default: 5\n      }\n    ],\n    execute: async (params: Record<string, any>) => {\n      try {\n        const query = params.query as string;\n        const limit = params.limit as number | undefined;\n        \n        if (!query) {\n          throw new Error(\"Query parameter is required\");\n        }\n        \n        const results = await rag.search(query, limit);\n        return {\n          success: true,\n          results: results.map(r => ({\n            content: r.content,\n            metadata: r.metadata,\n            similarity: r.similarity,\n            sourceId: r.sourceId\n          })),\n          query: query,\n          resultCount: results.length\n        };\n      } catch (error) {\n        logger.error(\"Error executing RAG search:\", error);\n        return {\n          success: false,\n          error: error instanceof Error ? error.message : \"Unknown error occurred during search\",\n          query: params.query\n        };\n      }\n    }\n  });\n\n  // Vector RAG specific tools\n  if ('searchByVector' in rag) {\n    const vectorRAG = rag as VectorRAGInstance;\n    \n    tools.push({\n      name: \"rag_add_document\",\n      description: \"Add a new document to the RAG system for future searches\",\n      parameters: [\n        {\n          name: \"content\",\n          type: \"string\",\n          description: \"The document content to add\",\n          required: true\n        },\n        {\n          name: \"metadata\",\n          type: \"object\",\n          description: \"Additional metadata for the document\",\n          required: false,\n          default: {}\n        }\n      ],\n      execute: async (params: Record<string, any>) => {\n        try {\n          const content = params.content as string;\n          const metadata = params.metadata as Record<string, any> | undefined;\n          \n          if (!content) {\n            throw new Error(\"Content parameter is required\");\n          }\n          \n          const documentId = await vectorRAG.addDocument({\n            content: content,\n            metadata: metadata || {}\n          });\n          return {\n            success: true,\n            documentId,\n            message: \"Document added successfully\"\n          };\n        } catch (error) {\n          logger.error(\"Error adding document to RAG:\", error);\n          return {\n            success: false,\n            error: error instanceof Error ? error.message : \"Unknown error occurred while adding document\"\n          };\n        }\n      }\n    });\n\n    tools.push({\n      name: \"rag_get_document\",\n      description: \"Retrieve a specific document by its ID\",\n      parameters: [\n        {\n          name: \"documentId\",\n          type: \"string\",\n          description: \"The ID of the document to retrieve\",\n          required: true\n        }\n      ],\n      execute: async (params: Record<string, any>) => {\n        try {\n          const documentId = params.documentId as string;\n          \n          if (!documentId) {\n            throw new Error(\"DocumentId parameter is required\");\n          }\n          \n          const document = await vectorRAG.getDocumentById(documentId);\n          if (document) {\n            return {\n              success: true,\n              document: {\n                id: document.id,\n                content: document.content,\n                metadata: document.metadata\n              }\n            };\n          } else {\n            return {\n              success: false,\n              error: \"Document not found\",\n              documentId: documentId\n            };\n          }\n        } catch (error) {\n          logger.error(\"Error retrieving document from RAG:\", error);\n          return {\n            success: false,\n            error: error instanceof Error ? error.message : \"Unknown error occurred while retrieving document\",\n            documentId: params.documentId\n          };\n        }\n      }\n    });\n\n    tools.push({\n      name: \"rag_delete_document\",\n      description: \"Delete a document from the RAG system\",\n      parameters: [\n        {\n          name: \"documentId\",\n          type: \"string\",\n          description: \"The ID of the document to delete\",\n          required: true\n        }\n      ],\n      execute: async (params: Record<string, any>) => {\n        try {\n          const documentId = params.documentId as string;\n          \n          if (!documentId) {\n            throw new Error(\"DocumentId parameter is required\");\n          }\n          \n          await vectorRAG.deleteDocument(documentId);\n          return {\n            success: true,\n            message: \"Document deleted successfully\",\n            documentId: documentId\n          };\n        } catch (error) {\n          logger.error(\"Error deleting document from RAG:\", error);\n          return {\n            success: false,\n            error: error instanceof Error ? error.message : \"Unknown error occurred while deleting document\",\n            documentId: params.documentId\n          };\n        }\n      }\n    });\n  }\n\n  // Document RAG specific tools\n  if ('searchByMetadata' in rag) {\n    const documentRAG = rag as DocumentRAGInstance;\n    \n    tools.push({\n      name: \"rag_search_by_metadata\",\n      description: \"Search documents by their metadata properties\",\n      parameters: [\n        {\n          name: \"filter\",\n          type: \"object\",\n          description: \"Metadata filter criteria as key-value pairs\",\n          required: true\n        },\n        {\n          name: \"limit\",\n          type: \"number\",\n          description: \"Maximum number of results to return\",\n          required: false,\n          default: 5\n        }\n      ],\n      execute: async (params: Record<string, any>) => {\n        try {\n          const filter = params.filter as Record<string, any>;\n          const limit = params.limit as number | undefined;\n          \n          if (!filter) {\n            throw new Error(\"Filter parameter is required\");\n          }\n          \n          const results = await documentRAG.searchByMetadata(filter, limit);\n          return {\n            success: true,\n            results: results.map(r => ({\n              content: r.content,\n              metadata: r.metadata,\n              similarity: r.similarity,\n              sourceId: r.sourceId\n            })),\n            filter: filter,\n            resultCount: results.length\n          };\n        } catch (error) {\n          logger.error(\"Error executing RAG metadata search:\", error);\n          return {\n            success: false,\n            error: error instanceof Error ? error.message : \"Unknown error occurred during metadata search\",\n            filter: params.filter\n          };\n        }\n      }\n    });\n  }\n\n  logger.debug(`Created ${tools.length} RAG tools for agent use`);\n  return tools;\n} ","import { v4 as uuidv4 } from \"uuid\";\nimport { createDatabase } from \"../../database\";\nimport { logger } from \"../../utils\";\n\n/**\n * Create a user and save to database\n */\nexport async function createUser(username: string): Promise<string> {\n  try {\n    // Generate user ID\n    const id = uuidv4();\n\n    // Get database instance\n    const db = await createDatabase();\n    const tableNames = db.getTableNames();\n\n    // Ensure users table exists\n    await db.ensureTable(tableNames.users, (table) => {\n      table.string(\"id\").primary();\n      table.string(\"username\").notNullable().unique();\n      table.timestamp(\"createdAt\").defaultTo(db.knex.fn.now());\n      table.json(\"preferences\").nullable();\n    });\n\n    // Save user to database\n    await db.getTable(tableNames.users).insert({\n      id,\n      username,\n      createdAt: new Date(),\n    });\n\n    logger.success(`User created with ID: ${id}`);\n    return id;\n  } catch (error) {\n    logger.error(\"Error creating user:\", error);\n    throw error;\n  }\n}\n\n/**\n * Get user by ID\n */\nexport async function getUserById(id: string): Promise<any | null> {\n  try {\n    const db = await createDatabase();\n    const tableNames = db.getTableNames();\n    return await db.getTable(tableNames.users).findOne({ id });\n  } catch (error) {\n    logger.error(\"Error getting user by ID:\", error);\n    throw error;\n  }\n}\n\n/**\n * Get user by username\n */\nexport async function getUserByUsername(username: string): Promise<any | null> {\n  try {\n    const db = await createDatabase();\n    const tableNames = db.getTableNames();\n    return await db.getTable(tableNames.users).findOne({ username });\n  } catch (error) {\n    logger.error(\"Error getting user by username:\", error);\n    throw error;\n  }\n}\n\n/**\n * Update user\n */\nexport async function updateUser(id: string, data: Record<string, any>): Promise<boolean> {\n  try {\n    const db = await createDatabase();\n    const tableNames = db.getTableNames();\n    const result = await db.getTable(tableNames.users).update({ id }, data);\n    return result > 0;\n  } catch (error) {\n    logger.error(\"Error updating user:\", error);\n    throw error;\n  }\n}\n\n/**\n * Delete user\n */\nexport async function deleteUser(id: string): Promise<boolean> {\n  try {\n    const db = await createDatabase();\n    const tableNames = db.getTableNames();\n    const result = await db.getTable(tableNames.users).delete({ id });\n    return result > 0;\n  } catch (error) {\n    logger.error(\"Error deleting user:\", error);\n    throw error;\n  }\n} ","import { PluginConfig, PluginInstance, Plugin } from \"./types\";\nimport { logger } from \"./utils\";\nimport { validateRequiredParam, validateRequiredParams } from \"./utils/validation\";\n\n/**\n * Comprehensive Plugin Manager that handles all plugin-related functionality\n * This class provides both instance-level management for specific agents\n * and static global registry for framework-wide plugin management.\n */\nexport class PluginManager implements PluginInstance {\n  public config: PluginConfig;\n  private tools: Map<string, Plugin>;\n\n  // Global registry shared across all instances\n  private static registry = new Map<string, Plugin>();\n\n  constructor(config: PluginConfig) {\n    // Validate required parameters\n    validateRequiredParam(config, \"config\", \"PluginManager constructor\");\n    validateRequiredParams(\n      config,\n      [\"name\", \"tools\"],\n      \"PluginManager constructor\"\n    );\n    \n    // Apply defaults for optional fields\n    this.config = {\n      ...config,\n      description: config.description || `Plugin manager for ${config.name}`,\n      version: config.version || '1.0.0',\n      tools: config.tools || []\n    };\n    \n    this.tools = new Map();\n\n    // Initialize tools\n    if (this.config.tools) {\n      this.config.tools.forEach((tool) => {\n        this.registerTool(tool);\n      });\n    }\n    \n    logger.info(`Plugin manager initialized with ${this.tools.size} tools`);\n  }\n\n  // ========== Instance methods for managing local tools ==========\n\n  /**\n   * Get all tools registered with this instance\n   * @returns Array of all registered tools\n   */\n  getTools(): Plugin[] {\n    return Array.from(this.tools.values());\n  }\n\n  /**\n   * Get a specific tool by name\n   * @param name Name of the tool to retrieve\n   * @returns Tool if found, undefined otherwise\n   */\n  getTool(name: string): Plugin | undefined {\n    // Validate required parameters\n    validateRequiredParam(name, \"name\", \"getTool\");\n    \n    return this.tools.get(name);\n  }\n\n  /**\n   * Register a tool with this instance\n   * Also registers the tool with the global registry\n   * @param tool Tool to register\n   * @throws Error if the tool is invalid\n   */\n  registerTool(tool: Plugin): void {\n    // Validate required parameters\n    validateRequiredParam(tool, \"tool\", \"registerTool\");\n    \n    try {\n      // Check that tool has a name and execute method\n      if (!tool.name) {\n        logger.warn(\"Cannot register tool: Missing name property\");\n        return;\n      }\n      \n      if (!tool.execute || typeof tool.execute !== 'function') {\n        logger.warn(`Cannot register tool \"${tool.name}\": Missing execute method`);\n        return;\n      }\n      \n      // Register with the instance\n      this.tools.set(tool.name, tool);\n\n      // Also register with the global registry\n      PluginManager.register(tool);\n      \n      logger.debug(`Tool \"${tool.name}\" registered successfully`);\n    } catch (error) {\n      logger.error(`Failed to register tool: ${error}`);\n      throw error;\n    }\n  }\n\n  /**\n   * Remove a tool from this instance\n   * Also removes the tool from the global registry\n   * @param name Name of the tool to remove\n   * @returns true if tool was found and removed, false otherwise\n   */\n  removeTool(name: string): boolean {\n    // Validate required parameters\n    validateRequiredParam(name, \"name\", \"removeTool\");\n    \n    const removed = this.tools.delete(name);\n    \n    // Also remove from global registry if it was removed from instance\n    if (removed) {\n      PluginManager.unregister(name);\n      logger.debug(`Tool \"${name}\" removed`);\n    }\n\n    return removed;\n  }\n\n  /**\n   * Check if a tool is registered with this instance\n   * @param name Name of the tool to check\n   * @returns true if tool is registered, false otherwise\n   */\n  hasTool(name: string): boolean {\n    // Validate required parameters\n    validateRequiredParam(name, \"name\", \"hasTool\");\n    \n    return this.tools.has(name);\n  }\n\n  /**\n   * Get the number of tools registered with this instance\n   * @returns Number of tools\n   */\n  getToolCount(): number {\n    return this.tools.size;\n  }\n\n  // ========== Static methods for global plugin registry ==========\n\n  /**\n   * Register a plugin with the global registry\n   * @param plugin Plugin to register\n   * @throws Error if the plugin is invalid\n   */\n  static register(plugin: Plugin): void {\n    // Validate required parameters\n    validateRequiredParam(plugin, \"plugin\", \"PluginManager.register\");\n    \n    try {\n      // Check that plugin has a name and execute method\n      if (!plugin.name) {\n        logger.warn(\"Cannot register plugin: Missing name property\");\n        return;\n      }\n      \n      if (!plugin.execute || typeof plugin.execute !== 'function') {\n        logger.warn(`Cannot register plugin \"${plugin.name}\": Missing execute method`);\n        return;\n      }\n      \n      this.registry.set(plugin.name, plugin);\n      logger.debug(`Plugin \"${plugin.name}\" registered in global registry`);\n    } catch (error) {\n      logger.error(`Failed to register plugin in global registry: ${error}`);\n      throw error;\n    }\n  }\n\n  /**\n   * Unregister a plugin from the global registry\n   * @param name Name of the plugin to unregister\n   * @returns true if plugin was found and removed, false otherwise\n   */\n  static unregister(name: string): boolean {\n    // Validate required parameters\n    validateRequiredParam(name, \"name\", \"PluginManager.unregister\");\n    \n    const result = this.registry.delete(name);\n    if (result) {\n      logger.debug(`Plugin \"${name}\" unregistered from global registry`);\n    }\n    return result;\n  }\n\n  /**\n   * Get a plugin by name from the global registry\n   * @param name Name of the plugin to retrieve\n   * @returns Plugin if found, undefined otherwise\n   */\n  static get(name: string): Plugin | undefined {\n    // Validate required parameters\n    validateRequiredParam(name, \"name\", \"PluginManager.get\");\n    \n    return this.registry.get(name);\n  }\n\n  /**\n   * Get all plugins from the global registry\n   * @returns Array of all registered plugins\n   */\n  static getAll(): Plugin[] {\n    return Array.from(this.registry.values());\n  }\n\n  /**\n   * Get all plugins for a specific agent\n   * @param agentId ID of the agent to get plugins for\n   * @returns Array of plugins for the specified agent\n   */\n  static getByAgent(agentId: string): Plugin[] {\n    try {\n      // Validate required parameters\n      validateRequiredParam(agentId, \"agentId\", \"getByAgent\");\n      \n      // Log what we're doing\n      logger.debug(`Getting plugins for agent ${agentId}`);\n      logger.debug(`Total plugins in registry: ${this.registry.size}`);\n      \n      // Do safe access of the registry contents\n      const plugins = Array.from(this.registry.values());\n      \n      // Log each plugin for debugging\n      plugins.forEach((plugin, index) => {\n        const name = plugin?.name || 'unnamed';\n        logger.debug(`Plugin ${index}: ${name}`);\n      });\n      \n      // For now, return all plugins as we don't track agent-plugin relationships\n      // In the future, this could be enhanced to track which plugins are used by which agents\n      return plugins;\n    } catch (error) {\n      // Log the error and return empty array\n      logger.error(`Error getting plugins for agent ${agentId}:`, error);\n      return [];\n    }\n  }\n\n  /**\n   * Reset the global plugin registry\n   * Useful for testing or when reloading plugins\n   */\n  static reset(): void {\n    this.registry.clear();\n    logger.info(\"Global plugin registry reset\");\n  }\n\n  /**\n   * Check if a plugin exists in the global registry\n   * @param name Name of the plugin to check\n   * @returns true if plugin exists, false otherwise\n   */\n  static has(name: string): boolean {\n    // Validate required parameters\n    validateRequiredParam(name, \"name\", \"PluginManager.has\");\n    \n    return this.registry.has(name);\n  }\n\n  /**\n   * Get the number of plugins in the global registry\n   * @returns Number of plugins\n   */\n  static count(): number {\n    return this.registry.size;\n  }\n\n  /**\n   * Load a plugin from a repository or object\n   * @param pluginOrPath Plugin object or path to a plugin module\n   * @returns Promise that resolves when the plugin is loaded and registered\n   * @throws Error if loading fails\n   */\n  static async load(pluginOrPath: string | Plugin): Promise<void> {\n    // Validate required parameters\n    validateRequiredParam(pluginOrPath, \"pluginOrPath\", \"PluginManager.load\");\n    \n    try {\n      if (typeof pluginOrPath === \"string\") {\n        // This is a path to a plugin module\n        try {\n          // Dynamic import\n          const module = await import(pluginOrPath);\n          const plugin = module.default || module;\n\n          if (plugin && typeof plugin === 'object') {\n            this.register(plugin);\n            logger.info(`Plugin loaded from path: ${pluginOrPath}`);\n          } else {\n            const error = `Plugin module at ${pluginOrPath} does not export a valid plugin`;\n            logger.warn(error);\n            throw new Error(error);\n          }\n        } catch (error) {\n          logger.error(`Failed to load plugin from ${pluginOrPath}:`, error);\n          throw error;\n        }\n      } else if (pluginOrPath && typeof pluginOrPath === 'object') {\n        // This is a plugin object\n        this.register(pluginOrPath);\n        logger.info(`Plugin \"${pluginOrPath.name}\" loaded directly`);\n      } else {\n        throw new Error('Invalid plugin format');\n      }\n    } catch (error) {\n      logger.error(\"Error loading plugin:\", error);\n      throw error;\n    }\n  }\n\n  /**\n   * Load multiple plugins at once\n   * @param plugins Array of plugin objects or paths\n   * @returns Promise that resolves when all plugins are loaded\n   * @throws Error if loading any plugin fails\n   */\n  static async loadMany(plugins: Array<string | Plugin>): Promise<void> {\n    // Validate required parameters\n    validateRequiredParam(plugins, \"plugins\", \"PluginManager.loadMany\");\n    \n    try {\n      await Promise.all(plugins.map((plugin) => this.load(plugin)));\n      logger.info(`Loaded ${plugins.length} plugins`);\n    } catch (error) {\n      logger.error(\"Error loading multiple plugins:\", error);\n      throw error;\n    }\n  }\n\n  /**\n   * Create a new PluginManager instance\n   * @param config Configuration for the plugin manager\n   * @returns New PluginManager instance\n   */\n  static create(config: PluginConfig): PluginInstance {\n    // Validate required parameters\n    validateRequiredParam(config, \"config\", \"PluginManager.create\");\n    validateRequiredParams(\n      config,\n      [\"name\", \"tools\"],\n      \"PluginManager.create\"\n    );\n    \n    return new PluginManager(config);\n  }\n}\n","import { v4 as uuidv4 } from \"uuid\";\nimport {\n  MemoryConfig,\n  MemoryInstance,\n  MemoryEntry,\n  MemoryFactory,\n  SimilaritySearchResult,\n} from \"./types\";\nimport { Embedding } from \"./providers\";\nimport { logger } from \"./utils\";\nimport { validateRequiredParam, validateRequiredParams } from \"./utils/validation\";\nimport { DEFAULT_MEMORY_SIZE } from \"./constants\";\n\n/**\n * Memory manager implementation using database storage\n * Provides storage and retrieval of conversation history and vector embeddings\n */\nexport class MemoryManager implements MemoryInstance {\n  public config: MemoryConfig;\n\n  constructor(config: MemoryConfig) {\n    // Validate required parameters\n    validateRequiredParam(config, \"config\", \"MemoryManager constructor\");\n    validateRequiredParams(\n      config,\n      [\"database\"],\n      \"MemoryManager constructor\"\n    );\n    \n    // Apply defaults for optional config parameters\n    this.config = {\n      ...config,\n      tableName: config.tableName || \"memories\",\n      maxEntries: config.maxEntries || DEFAULT_MEMORY_SIZE,\n      enableEmbeddings: config.enableEmbeddings || false\n    };\n    \n    logger.debug(\"Memory manager initialized\");\n  }\n\n  /**\n   * Create a new memory instance with proper configuration\n   * @param config Configuration object for memory\n   * @returns Promise that resolves to the new memory instance\n   */\n  static async create(config: MemoryConfig): Promise<MemoryInstance> {\n    // Validate required parameters\n    validateRequiredParam(config, \"config\", \"MemoryManager.create\");\n    validateRequiredParams(\n      config,\n      [\"database\"],\n      \"MemoryManager.create\"\n    );\n    \n    try {\n      // Apply defaults - use user-provided table name or default\n      const { database } = config;\n      \n      const fullConfig = {\n        ...config,\n        tableName: config.tableName || \"memories\", // Use user-provided name or default\n        maxEntries: config.maxEntries || DEFAULT_MEMORY_SIZE,\n        enableEmbeddings: config.enableEmbeddings || false\n      };\n      \n      // Use user's custom table name\n      const { tableName } = fullConfig;\n      \n      // Use enhanced database table management\n      await database.ensureTable(tableName, (table) => {\n        table.string(\"id\").primary();\n        table.string(\"agentId\").notNullable().index();\n        table.string(\"sessionId\").notNullable().index();\n        table.string(\"userId\").nullable().index();\n        table.string(\"role\").notNullable();\n        table.text(\"content\").notNullable();\n        table.timestamp(\"timestamp\").defaultTo(database.knex.fn.now());\n        table.json(\"embedding\").nullable();\n        table.json(\"metadata\");\n      });\n      \n      // Check if embeddings are enabled and ensure embedding column exists\n      if (fullConfig.enableEmbeddings) {\n        logger.info(`Memory initialized with embedding support using table: ${tableName}`);\n        const hasEmbeddingColumn = await database.knex.schema.hasColumn(\n          tableName,\n          \"embedding\"\n        );\n\n        if (!hasEmbeddingColumn) {\n          logger.warn(`Adding embedding column to memory table: ${tableName}`);\n          await database.knex.schema.table(tableName, (table) => {\n            table.json(\"embedding\"); // Store as JSON to properly represent array structure\n          });\n        }\n      }\n\n      logger.info(`Memory created with custom table: ${tableName}`);\n      return new MemoryManager(fullConfig);\n    } catch (error) {\n      logger.error(\"Error creating memory instance:\", error);\n      throw error;\n    }\n  }\n\n  /**\n   * Add a new memory entry\n   * @param entry Memory entry to add (without id and timestamp)\n   * @returns Promise resolving to the ID of the new entry\n   */\n  async add(entry: Omit<MemoryEntry, \"id\" | \"timestamp\">): Promise<string> {\n    // Validate required parameters\n    validateRequiredParam(entry, \"entry\", \"add\");\n    validateRequiredParams(\n      entry,\n      [\"agentId\", \"sessionId\", \"role\", \"content\"],\n      \"add\"\n    );\n    \n    try {\n      const { database, tableName, enableEmbeddings } = this.config;\n\n      // Generate ID and timestamp\n      const id = uuidv4();\n      const timestamp = new Date();\n\n      // Create a copy to avoid modifying the original\n      const entryToInsert = { ...entry };\n\n      // Validate and normalize the role for OpenRouter compatibility\n      entryToInsert.role = this.validateRole(entryToInsert.role);\n\n      // Generate embedding if enabled and not provided\n      if (enableEmbeddings && !entryToInsert.embedding && entryToInsert.content) {\n        try {\n          logger.debug(`Generating embedding for memory entry ${id}`);\n          const generatedEmbedding = await Embedding.generateEmbedding(entryToInsert.content);\n          entryToInsert.embedding = generatedEmbedding;\n          logger.debug(`Generated embedding for memory entry ${id} (${generatedEmbedding.length} dimensions)`);\n        } catch (embeddingError) {\n          logger.warn(`Failed to generate embedding for memory entry ${id}:`, embeddingError);\n          // Continue without embedding rather than failing the entire operation\n        }\n      }\n\n      // Prepare entry for database insertion with proper JSON serialization\n      const dbEntry = {\n        ...entryToInsert,\n        id,\n        timestamp,\n      };\n\n      // Ensure embedding is properly serialized if it exists\n      if (entryToInsert.embedding) {\n        // If embedding is already a string but not JSON, handle special cases\n        if (typeof entryToInsert.embedding === \"string\") {\n          // Handle case where embedding is \"[object Object]\" (invalid)\n          if (entryToInsert.embedding === \"[object Object]\") {\n            (dbEntry as any).embedding = null;\n          } else {\n            // Keep it as is since it's already a string\n            (dbEntry as any).embedding = entryToInsert.embedding;\n          }\n        } else if (Array.isArray(entryToInsert.embedding)) {\n          // For database storage, convert arrays to JSON string\n          (dbEntry as any).embedding = JSON.stringify(entryToInsert.embedding);\n        } else {\n          // For unexpected object types, store as null to avoid \"[object Object]\"\n          logger.warn(\n            `Unexpected embedding type for entry ${id}, setting to null`\n          );\n          (dbEntry as any).embedding = null;\n        }\n      }\n\n      // Store in database\n      await database.getTable(tableName!).insert(dbEntry);\n      logger.debug(`Added memory entry ${id}${entryToInsert.embedding ? ' with embedding' : ''} with role: ${entryToInsert.role}`);\n\n      return id;\n    } catch (error) {\n      logger.error(\"Error adding memory entry:\", error);\n      throw error;\n    }\n  }\n\n  /**\n   * Get entries by session ID\n   * @param sessionId The session ID to get entries for\n   * @param limit Maximum number of entries to return\n   * @returns Promise resolving to array of memory entries\n   */\n  async getBySession(\n    sessionId: string,\n    limit?: number\n  ): Promise<MemoryEntry[]> {\n    // Validate required parameters\n    validateRequiredParam(sessionId, \"sessionId\", \"getBySession\");\n    \n    try {\n      const { database, tableName, maxEntries } = this.config;\n\n      // Query database - using non-null assertion since we set defaults in constructor\n      const entries = await database\n        .knex(tableName!)\n        .where({ sessionId: sessionId })\n        .orderBy(\"timestamp\", \"asc\")\n        .limit(limit || maxEntries!);\n\n      logger.debug(`Retrieved ${entries.length} entries for session ${sessionId}`);\n\n      // Process embedding data for client use\n      return this.processEntriesBeforeReturn(entries);\n    } catch (error) {\n      logger.error(`Error getting entries for session ${sessionId}:`, error);\n      throw error;\n    }\n  }\n\n  /**\n   * Get entries by agent ID\n   * @param agentId The agent ID to get entries for\n   * @param limit Maximum number of entries to return\n   * @returns Promise resolving to array of memory entries\n   */\n  async getByAgent(agentId: string, limit?: number): Promise<MemoryEntry[]> {\n    // Validate required parameters\n    validateRequiredParam(agentId, \"agentId\", \"getByAgent\");\n    \n    try {\n      const { database, tableName, maxEntries } = this.config;\n\n      // Query database - using non-null assertion since we set defaults in constructor\n      const entries = await database\n        .knex(tableName!)\n        .where({ agentId: agentId })\n        .orderBy(\"timestamp\", \"asc\")\n        .limit(limit || maxEntries!);\n\n      logger.debug(`Retrieved ${entries.length} entries for agent ${agentId}`);\n\n      // Process embedding data for client use\n      return this.processEntriesBeforeReturn(entries);\n    } catch (error) {\n      logger.error(`Error getting entries for agent ${agentId}:`, error);\n      throw error;\n    }\n  }\n\n  /**\n   * Get entries by user ID\n   * @param userId The user ID to get entries for\n   * @param limit Maximum number of entries to return\n   * @returns Promise resolving to array of memory entries\n   */\n  async getByUser(userId: string, limit?: number): Promise<MemoryEntry[]> {\n    // Validate required parameters\n    validateRequiredParam(userId, \"userId\", \"getByUser\");\n    \n    try {\n      const { database, tableName, maxEntries } = this.config;\n\n      // Query database with userId - using non-null assertion since we set defaults in constructor\n      const entries = await database\n        .knex(tableName!)\n        .where({ userId: userId })\n        .orderBy(\"timestamp\", \"desc\") // Most recent first\n        .limit(limit || maxEntries!);\n\n      logger.debug(`Retrieved ${entries.length} entries for user ${userId}`);\n\n      // Process embedding data for client use\n      return this.processEntriesBeforeReturn(entries);\n    } catch (error) {\n      logger.error(`Error getting entries for user ${userId}:`, error);\n      throw error;\n    }\n  }\n\n  /**\n   * Get a memory entry by its ID\n   * @param id The ID of the memory entry to retrieve\n   * @returns Promise resolving to the memory entry or null if not found\n   */\n  async getById(id: string): Promise<MemoryEntry | null> {\n    // Validate required parameters\n    validateRequiredParam(id, \"id\", \"getById\");\n    \n    try {\n      const { database, tableName } = this.config;\n\n      // Query database to find entry by ID\n      const entry = await database\n        .knex(tableName!)\n        .where({ id })\n        .first();\n\n      if (!entry) {\n        logger.debug(`Memory entry with ID ${id} not found`);\n        return null;\n      }\n\n      logger.debug(`Retrieved memory entry with ID ${id}`);\n\n      // Process embedding data for client use\n      const processedEntries = this.processEntriesBeforeReturn([entry]);\n      return processedEntries[0];\n    } catch (error) {\n      logger.error(`Error getting memory entry by ID ${id}:`, error);\n      throw error;\n    }\n  }\n\n  /**\n   * Delete a memory entry by its ID\n   * @param id The ID of the memory entry to delete\n   * @returns Promise that resolves when deletion is complete\n   */\n  async delete(id: string): Promise<void> {\n    // Validate required parameters\n    validateRequiredParam(id, \"id\", \"delete\");\n    \n    try {\n      const { database, tableName } = this.config;\n\n      // Delete entry from database\n      const result = await database\n        .knex(tableName!)\n        .where({ id })\n        .delete();\n\n      if (result === 0) {\n        logger.warn(`No memory entry found for deletion with ID ${id}`);\n      } else {\n        logger.debug(`Deleted memory entry with ID ${id}`);\n      }\n    } catch (error) {\n      logger.error(`Error deleting memory entry with ID ${id}:`, error);\n      throw error;\n    }\n  }\n\n  /**\n   * Helper method to process entries before returning to client\n   * Parses JSON embedding strings back to arrays\n   * @param entries Array of raw entries from database\n   * @returns Processed entries with parsed embeddings\n   */\n  private processEntriesBeforeReturn(entries: unknown[]): MemoryEntry[] {\n    return entries.map((entry) => {\n      // We need to cast entry to a record type first since it comes from the database\n      const dbEntry = entry as Record<string, unknown>;\n      \n      // Create a new entry to avoid modifying the original\n      const processedEntry: Partial<MemoryEntry> = { \n        id: String(dbEntry.id || ''),\n        agentId: String(dbEntry.agentId || ''),\n        sessionId: String(dbEntry.sessionId || ''),\n        role: this.validateRole(String(dbEntry.role || '')),\n        content: String(dbEntry.content || ''),\n        timestamp: dbEntry.timestamp instanceof Date ? dbEntry.timestamp : new Date(String(dbEntry.timestamp || '')),\n        metadata: dbEntry.metadata as Record<string, unknown>\n      };\n\n      // Parse embedding if it exists and is a string\n      if (dbEntry.embedding) {\n        if (typeof dbEntry.embedding === \"string\") {\n          // Skip \"[object Object]\" strings which aren't valid JSON\n          if (dbEntry.embedding === \"[object Object]\") {\n            processedEntry.embedding = undefined;\n          } else {\n            try {\n              processedEntry.embedding = JSON.parse(dbEntry.embedding);\n            } catch (error) {\n              logger.error(\n                `Error parsing embedding for entry ${String(dbEntry.id)}:`,\n                error\n              );\n              // If parsing fails, remove the embedding\n              processedEntry.embedding = undefined;\n            }\n          }\n        } else if (Array.isArray(dbEntry.embedding)) {\n          processedEntry.embedding = dbEntry.embedding;\n        }\n      }\n\n      return processedEntry as MemoryEntry;\n    });\n  }\n\n  /**\n   * Search memories by text content\n   * @param query Text to search for in memory content field\n   * @param limit Maximum number of results to return\n   * @returns Array of memory entries matching the query\n   */\n  async searchByText(\n    query: string,\n    limit: number = 10\n  ): Promise<MemoryEntry[]> {\n    // Validate required parameters\n    validateRequiredParam(query, \"query\", \"searchByText\");\n    \n    try {\n      const { database, tableName } = this.config;\n\n      if (!query) return [];\n\n      // Use case-insensitive search with LIKE\n      const results = await database\n        .knex(tableName!)\n        .whereRaw(\"LOWER(content) LIKE ?\", [`%${query.toLowerCase()}%`])\n        .orderBy(\"timestamp\", \"desc\")\n        .limit(limit);\n\n      logger.debug(`Text search for \"${query}\" found ${results.length} results`);\n      \n      return this.processEntriesBeforeReturn(results);\n    } catch (error) {\n      logger.error(\"Error searching memories by text:\", error);\n      return [];\n    }\n  }\n\n  /**\n   * Search memories by embedding similarity\n   * @param embedding The embedding vector to search for\n   * @param limit Maximum number of results to return\n   * @param threshold Minimum similarity score (0-1) to include in results\n   * @returns Array of memory entries with similarity scores\n   */\n  async searchByEmbedding(\n    embedding: number[],\n    limit: number = 5,\n    threshold: number = 0 // Default to returning all results\n  ): Promise<SimilaritySearchResult[]> {\n    // Validate required parameters\n    validateRequiredParam(embedding, \"embedding\", \"searchByEmbedding\");\n    \n    try {\n      const { database, tableName } = this.config;\n\n      if (!embedding || !embedding.length) {\n        return [];\n      }\n\n      // Get all memories with embeddings\n      const memories = await database\n        .knex(tableName!)\n        .whereNotNull(\"embedding\")\n        .orderBy(\"timestamp\", \"desc\")\n        .limit(100); // Reasonable upper limit for comparison\n\n      // Process embeddings\n      type EntryWithEmbedding = MemoryEntry & { embedding: number[] };\n      const entriesWithEmbeddings = memories\n        .map((entry) => {\n          let parsedEmbedding: number[] | undefined;\n\n          if (entry.embedding) {\n            try {\n              if (typeof entry.embedding === \"string\") {\n                parsedEmbedding = JSON.parse(entry.embedding);\n              } else if (Array.isArray(entry.embedding)) {\n                parsedEmbedding = entry.embedding;\n              }\n            } catch (error) {\n              logger.error(\n                `Error parsing embedding for entry ${entry.id}:`,\n                error\n              );\n            }\n          }\n\n          if (parsedEmbedding && Array.isArray(parsedEmbedding)) {\n            const entryAsMemoryEntry = entry as unknown as MemoryEntry;\n            return {\n              ...entryAsMemoryEntry,\n              embedding: parsedEmbedding,\n            } as EntryWithEmbedding;\n          }\n          return null;\n        })\n        .filter(Boolean) as EntryWithEmbedding[];\n\n      // Calculate similarity scores\n      const entriesWithScores = entriesWithEmbeddings.map((entry) => {\n        const similarity = Embedding.calculateSimilarity(\n          embedding,\n          entry.embedding\n        );\n        const result: SimilaritySearchResult = {\n          ...this.processEntriesBeforeReturn([entry])[0],\n          similarity,\n        };\n        return result;\n      });\n\n      // Filter by threshold and take top results\n      const filteredResults = entriesWithScores\n        .filter((item) => item.similarity >= threshold)\n        .sort((a, b) => b.similarity - a.similarity)\n        .slice(0, limit);\n      \n      logger.debug(`Found ${filteredResults.length} results in embedding search with threshold ${threshold}`);\n      \n      return filteredResults;\n    } catch (error) {\n      logger.error(\"Error searching memories by embedding:\", error);\n      return [];\n    }\n  }\n\n  /**\n   * Clear all entries for a session\n   * @param sessionId The session ID to clear entries for\n   * @returns Promise that resolves when clearing is complete\n   */\n  async clear(sessionId: string): Promise<void> {\n    // Validate required parameters\n    validateRequiredParam(sessionId, \"sessionId\", \"clear\");\n    \n    try {\n      const { database, tableName } = this.config;\n\n      // Delete all entries for the session\n      const result = await database\n        .knex(tableName!)\n        .where({ sessionId: sessionId })\n        .delete();\n\n      logger.debug(`Cleared ${result} entries for session ${sessionId}`);\n    } catch (error) {\n      logger.error(`Error clearing entries for session ${sessionId}:`, error);\n      throw error;\n    }\n  }\n\n  /**\n   * Generate a summary of the memory for a specific session\n   * @param sessionId The session ID to summarize\n   * @returns Text summary of the conversation\n   */\n  async summarize(sessionId: string): Promise<string> {\n    // Validate required parameters\n    validateRequiredParam(sessionId, \"sessionId\", \"summarize\");\n    \n    try {\n      const memories = await this.getBySession(sessionId);\n      if (!memories.length) {\n        return \"No conversation history available.\";\n      }\n\n      // Just a simple summary for now - could be enhanced with AI summarization\n      const summary = `Conversation with ${memories.length} messages starting at ${memories[0].timestamp.toISOString()}.`;\n      \n      logger.debug(`Generated summary for session ${sessionId}`);\n      return summary;\n    } catch (error) {\n      logger.error(`Error summarizing session ${sessionId}:`, error);\n      throw error;\n    }\n  }\n\n  /**\n   * Add an entry with embedding in one step\n   * @param entry The memory entry without ID, timestamp, or embedding\n   * @param embedding The embedding vector to add\n   * @returns Promise resolving to the ID of the new entry\n   */\n  async addWithEmbedding(\n    entry: Omit<MemoryEntry, \"id\" | \"timestamp\" | \"embedding\">,\n    embedding: number[]\n  ): Promise<string> {\n    // Validate required parameters\n    validateRequiredParam(entry, \"entry\", \"addWithEmbedding\");\n    validateRequiredParam(embedding, \"embedding\", \"addWithEmbedding\");\n    validateRequiredParams(\n      entry,\n      [\"agentId\", \"sessionId\", \"role\", \"content\"],\n      \"addWithEmbedding\"\n    );\n    \n    try {\n      const id = await this.add({\n        ...entry,\n        embedding,\n      });\n      logger.debug(`Added memory entry ${id} with embedding`);\n      return id;\n    } catch (error) {\n      logger.error(\"Error adding memory entry with embedding:\", error);\n      throw error;\n    }\n  }\n\n  // Add a helper method to validate role values\n  private validateRole(role: string): MemoryEntry['role'] {\n    const validRoles: MemoryEntry['role'][] = ['system', 'user', 'assistant', 'task_context', 'task_event', 'task_tool', 'task_result'];\n    \n    // For OpenRouter compatibility, convert task_* roles to user\n    if (role.startsWith('task_')) {\n      return 'user';\n    }\n    \n    return validRoles.includes(role as MemoryEntry['role']) \n      ? (role as MemoryEntry['role']) \n      : 'user'; // Default to user instead of system for better OpenRouter compatibility\n  }\n\n  /**\n   * List all sessions for a specific agent\n   * @param agentId The agent ID to list sessions for\n   * @param limit Maximum number of sessions to return\n   * @returns Promise resolving to array of session summaries\n   */\n  async listSessions(agentId: string, limit?: number): Promise<{\n    sessionId: string;\n    lastMessage?: string;\n    messageCount: number;\n    lastActivity: Date;\n    metadata?: Record<string, unknown>;\n  }[]> {\n    validateRequiredParam(agentId, \"agentId\", \"listSessions\");\n    \n    try {\n      const { database, tableName, maxEntries } = this.config;\n\n      // Get session summaries with aggregated data\n      const sessions = await database\n        .knex(tableName!)\n        .select('sessionId')\n        .select(database.knex.raw('COUNT(*) as messageCount'))\n        .select(database.knex.raw('MAX(timestamp) as lastActivity'))\n        .select(database.knex.raw('(SELECT content FROM ' + tableName + ' WHERE sessionId = t.sessionId AND agentId = ? ORDER BY timestamp DESC LIMIT 1) as lastMessage', [agentId]))\n        .select(database.knex.raw('(SELECT metadata FROM ' + tableName + ' WHERE sessionId = t.sessionId AND agentId = ? ORDER BY timestamp DESC LIMIT 1) as metadata', [agentId]))\n        .from(tableName + ' as t')\n        .where({ agentId: agentId })\n        .groupBy('sessionId')\n        .orderBy('lastActivity', 'desc')\n        .limit(limit || maxEntries!);\n\n      logger.debug(`Retrieved ${sessions.length} sessions for agent ${agentId}`);\n\n      return sessions.map((session: any) => ({\n        sessionId: session.sessionId,\n        lastMessage: session.lastMessage || undefined,\n        messageCount: parseInt(session.messageCount) || 0,\n        lastActivity: session.lastActivity instanceof Date ? session.lastActivity : new Date(session.lastActivity),\n        metadata: session.metadata ? (typeof session.metadata === 'string' ? JSON.parse(session.metadata) : session.metadata) : undefined\n      }));\n    } catch (error) {\n      logger.error(`Error listing sessions for agent ${agentId}:`, error);\n      throw error;\n    }\n  }\n}\n\n/**\n * Factory function to create a new memory instance\n * @param config Configuration for the memory instance\n * @returns Promise that resolves to the new memory instance\n */\nexport const createMemory: MemoryFactory = async (config: MemoryConfig) => {\n  // Validate required parameters\n  validateRequiredParam(config, \"config\", \"createMemory\");\n  validateRequiredParams(\n    config,\n    [\"database\"],\n    \"createMemory\"\n  );\n  \n  return MemoryManager.create(config);\n};","import { v4 as uuidv4 } from \"uuid\";\nimport {\n  VectorRAGConfig,\n  VectorRAGInstance,\n  Document,\n  Chunk,\n  RAGResult,\n  VectorRAGFactory,\n  VectorDatabaseType,\n  VectorDatabaseConfig,\n} from \"../types\";\nimport { logger } from \"../utils\";\nimport { validateRequiredParam, validateRequiredParams } from \"../utils/validation\";\nimport { createVectorDatabaseConnector, VectorDatabaseConnector } from \"./vector-db\";\nimport { \n  DEFAULT_CHUNK_SIZE, \n  DEFAULT_CHUNK_OVERLAP, \n  DEFAULT_VECTOR_SIMILARITY_THRESHOLD,\n  DEFAULT_MAX_RESULTS\n} from \"../constants\";\n\n/**\n * Vector-based RAG implementation\n * Uses vector embeddings for semantic search and document chunking\n */\nexport class VectorRAG implements VectorRAGInstance {\n  public config: VectorRAGConfig;\n  private vectorDatabaseConnector: VectorDatabaseConnector;\n\n  constructor(config: VectorRAGConfig) {\n    // Validate required parameters\n    validateRequiredParam(config, \"config\", \"VectorRAG constructor\");\n    validateRequiredParams(\n      config,\n      [\"database\"],\n      \"VectorRAG constructor\"\n    );\n    \n    // Apply defaults for optional config parameters\n    this.config = {\n      ...config,\n      tableName: config.tableName || \"rag_chunks\",\n      maxResults: config.maxResults || DEFAULT_MAX_RESULTS,\n      chunkSize: config.chunkSize || DEFAULT_CHUNK_SIZE,\n      chunkOverlap: config.chunkOverlap || DEFAULT_CHUNK_OVERLAP,\n      vectorDatabase: config.vectorDatabase || { type: VectorDatabaseType.SAME_AS_MAIN },\n    };\n    \n    // Ensure vectorDatabase config has the correct tableName\n    if (this.config.vectorDatabase && this.config.vectorDatabase.type === VectorDatabaseType.SAME_AS_MAIN) {\n      this.config.vectorDatabase.options = {\n        ...this.config.vectorDatabase.options,\n        tableName: this.config.tableName\n      };\n    }\n    \n    // Initialize vector database connector\n    this.vectorDatabaseConnector = createVectorDatabaseConnector(\n      this.config.vectorDatabase,\n      this.config.database\n    );\n    \n    logger.debug(\"Vector RAG system initialized\");\n  }\n\n  /**\n   * Create a new vector RAG instance with proper configuration\n   * @param config Configuration object for vector RAG\n   * @returns Promise that resolves to the new vector RAG instance\n   */\n  static async create(config: VectorRAGConfig): Promise<VectorRAGInstance> {\n    // Validate required parameters\n    validateRequiredParam(config, \"config\", \"VectorRAG.create\");\n    validateRequiredParams(\n      config,\n      [\"database\"],\n      \"VectorRAG.create\"\n    );\n    \n    try {\n      const instance = new VectorRAG(config);\n      await instance.initializeDatabase();\n      return instance;\n    } catch (error) {\n      logger.error(\"Error creating vector RAG instance:\", error);\n      throw error;\n    }\n  }\n\n  /**\n   * Initialize database tables for vector RAG\n   */\n  private async initializeDatabase(): Promise<void> {\n    try {\n      const { database } = this.config;\n      \n      // If using external vector database, only create minimal tables in main DB\n      if (this.config.vectorDatabase?.type !== VectorDatabaseType.SAME_AS_MAIN) {\n        // For external vector databases, we only need association tracking\n        const associationsTableName = 'rag_chunk_associations';\n        \n        await database.ensureTable(associationsTableName, (table) => {\n          table.string(\"chunkId\").primary();\n          table.string(\"documentId\").notNullable().index();\n          table.integer(\"chunkIndex\").notNullable();\n          table.timestamp(\"createdAt\").defaultTo(database.knex.fn.now());\n        });\n        \n        logger.info(`Vector RAG using external vector database - created ${associationsTableName} table`);\n      } else {\n        // Using same database for vectors - create all necessary tables\n        const documentsTableName = 'rag_documents';\n        const chunksTableName = this.config.tableName || 'rag_chunks';\n        \n        // Create documents table\n        await database.ensureTable(documentsTableName, (table) => {\n          table.string(\"id\").primary();\n          table.text(\"content\").notNullable();\n          table.json(\"metadata\").notNullable();\n          table.timestamp(\"createdAt\").defaultTo(database.knex.fn.now());\n        });\n        \n        // Create chunks table with user's custom name\n        await database.ensureTable(chunksTableName, (table) => {\n          table.string(\"id\").primary();\n          table.string(\"documentId\").notNullable().index();\n          table.text(\"content\").notNullable();\n          table.json(\"metadata\").notNullable();\n          table.json(\"embedding\").notNullable();\n          table.timestamp(\"createdAt\").defaultTo(database.knex.fn.now());\n          \n          // Add foreign key constraint\n          table.foreign(\"documentId\").references(\"id\").inTable(documentsTableName).onDelete(\"CASCADE\");\n        });\n        \n        // Update config to use the resolved table name\n        this.config.tableName = chunksTableName;\n        \n        logger.info(`Vector RAG initialized with custom tables: ${documentsTableName} and ${chunksTableName}`);\n      }\n      \n      logger.debug(\"Vector RAG database initialized\");\n    } catch (error) {\n      logger.error(\"Error initializing vector RAG database:\", error);\n      throw error;\n    }\n  }\n\n  /**\n   * Add a document to the vector RAG system\n   * The document will be chunked and each chunk will be stored with its embedding\n   * @param document The document to add\n   * @returns Promise resolving to the document ID\n   */\n  async addDocument(document: Omit<Document, \"id\" | \"embedding\">): Promise<string> {\n    // Validate required parameters\n    validateRequiredParam(document, \"document\", \"addDocument\");\n    validateRequiredParams(\n      document,\n      [\"content\", \"metadata\"],\n      \"addDocument\"\n    );\n    \n    try {\n      const { database } = this.config;\n      const documentId = uuidv4();\n      \n      // Only store document in main DB if using same database for vectors\n      if (this.config.vectorDatabase?.type === VectorDatabaseType.SAME_AS_MAIN) {\n        // Store the document in main database\n        await database.knex(\"rag_documents\").insert({\n          id: documentId,\n          content: document.content,\n          metadata: JSON.stringify(document.metadata),\n          createdAt: new Date(),\n        });\n        logger.debug(`Stored document ${documentId} in main database`);\n      } else {\n        // For external vector DB, document metadata is stored with each chunk\n        logger.debug(`Using external vector DB - document ${documentId} will be stored with chunks`);\n      }\n      \n      // Create chunks from document content\n      const chunks = this.chunkDocument(documentId, document);\n      \n      // Generate embeddings for chunks and store them\n      // Prefer provider over memory for embedding generation\n      if (this.config.provider && this.config.provider.generateEmbedding) {\n        // Process chunks in batches to avoid overloading\n        const batchSize = 10;\n        for (let i = 0; i < chunks.length; i += batchSize) {\n          const batch = chunks.slice(i, i + batchSize);\n          await Promise.all(\n            batch.map(async (chunk) => {\n              await this.storeChunkWithEmbedding(chunk);\n            })\n          );\n        }\n        logger.debug(`Added ${chunks.length} chunks with provider-based embeddings for document ${documentId}`);\n      } else if (this.config.memory && this.config.memory.searchByEmbedding) {\n        // Fallback to memory if provider is not available\n        const batchSize = 10;\n        for (let i = 0; i < chunks.length; i += batchSize) {\n          const batch = chunks.slice(i, i + batchSize);\n          await Promise.all(\n            batch.map(async (chunk) => {\n              await this.storeChunkWithEmbedding(chunk);\n            })\n          );\n        }\n        logger.debug(`Added ${chunks.length} chunks with memory-based embeddings for document ${documentId}`);\n      } else {\n        logger.warn(\"No provider or memory with embedding support provided, chunks stored without embeddings\");\n        // Store chunks without embeddings only if using same database\n        if (this.config.vectorDatabase?.type === VectorDatabaseType.SAME_AS_MAIN) {\n          for (const chunk of chunks) {\n            const chunkId = uuidv4();\n            await database.knex(this.config.tableName!).insert({\n              id: chunkId,\n              documentId: chunk.documentId,\n              content: chunk.content,\n              metadata: JSON.stringify(chunk.metadata),\n              embedding: JSON.stringify([]), // Empty embedding\n              createdAt: new Date(),\n            });\n          }\n        } else {\n          logger.warn(\"Cannot store chunks without embeddings in external vector database\");\n        }\n      }\n      \n      return documentId;\n    } catch (error) {\n      logger.error(\"Error adding document to vector RAG:\", error);\n      throw error;\n    }\n  }\n\n  /**\n   * Split a document into chunks\n   * @param documentId The ID of the document\n   * @param document The document to chunk\n   * @returns Array of chunks\n   */\n  private chunkDocument(\n    documentId: string,\n    document: Omit<Document, \"id\" | \"embedding\">\n  ): Omit<Chunk, \"id\" | \"embedding\">[] {\n    const { chunkSize, chunkOverlap } = this.config;\n    const text = document.content;\n    const chunks: Omit<Chunk, \"id\" | \"embedding\">[] = [];\n    \n    // Simple chunking by characters with overlap\n    for (let i = 0; i < text.length; i += (chunkSize! - chunkOverlap!)) {\n      // Stop if we've reached the end of the text\n      if (i >= text.length) break;\n      \n      // Extract chunk content with overlap\n      const chunkContent = text.substring(i, i + chunkSize!);\n      \n      // Skip empty chunks\n      if (!chunkContent.trim()) continue;\n      \n      // Create chunk with metadata\n      chunks.push({\n        documentId,\n        content: chunkContent,\n        metadata: {\n          ...document.metadata,\n          chunk_index: chunks.length,\n          start_char: i,\n          end_char: Math.min(i + chunkSize!, text.length),\n        },\n      });\n    }\n    \n    return chunks;\n  }\n\n  /**\n   * Store a chunk with its embedding\n   * @param chunk The chunk to store\n   * @returns Promise resolving to the chunk ID\n   */\n  private async storeChunkWithEmbedding(\n    chunk: Omit<Chunk, \"id\" | \"embedding\">\n  ): Promise<string> {\n    const { database, tableName, provider, memory } = this.config;\n    \n    try {\n      // Get embedding using provider or memory\n      let embedding: number[] = [];\n      \n      // Prefer provider over memory for embedding generation\n      if (provider && provider.generateEmbedding) {\n        try {\n          // Use the first part of the chunk to generate embedding\n          // Limit to 8000 characters to avoid token limits\n          const textForEmbedding = chunk.content.substring(0, 8000);\n          \n          // Use provider directly for embedding generation\n          const embeddingResult = await provider.generateEmbedding(textForEmbedding);\n          embedding = embeddingResult || [];\n          \n          logger.debug(`Generated embedding using provider (${embedding.length} dimensions)`);\n        } catch (embeddingError) {\n          logger.warn(\"Failed to generate embedding using provider, trying memory fallback:\", embeddingError);\n          \n          // Fallback to memory if provider fails\n          if (memory && memory.searchByEmbedding) {\n            try {\n              const textForEmbedding = chunk.content.substring(0, 8000);\n              const { Embedding } = await import(\"../providers\");\n              embedding = await Embedding.generateEmbedding(textForEmbedding);\n              logger.debug(`Generated embedding using memory fallback (${embedding.length} dimensions)`);\n            } catch (memoryError) {\n              logger.warn(\"Failed to generate embedding using memory fallback:\", memoryError);\n              embedding = [];\n            }\n          } else {\n            embedding = [];\n          }\n        }\n      } else if (memory && memory.searchByEmbedding) {\n        try {\n          // Use the first part of the chunk to generate embedding\n          // Limit to 8000 characters to avoid token limits\n          const textForEmbedding = chunk.content.substring(0, 8000);\n          \n          // Use the Embedding utility directly instead of memory to avoid complexity\n          const { Embedding } = await import(\"../providers\");\n          embedding = await Embedding.generateEmbedding(textForEmbedding);\n          \n          logger.debug(`Generated embedding using memory (${embedding.length} dimensions)`);\n        } catch (embeddingError) {\n          logger.warn(\"Failed to generate embedding using memory:\", embeddingError);\n          embedding = [];\n        }\n      } else {\n        logger.warn(\"No provider or memory with embedding support provided for chunk storage\");\n      }\n      \n      // Generate a unique ID for the chunk\n      const chunkId = uuidv4();\n      \n      // Get chunk index from metadata\n      const chunkIndex = chunk.metadata.chunk_index || 0;\n      \n      // Store chunk with embedding in the vector database\n      await this.vectorDatabaseConnector.addVectors([\n        {\n          id: chunkId,\n          vector: embedding,\n          metadata: {\n            ...chunk.metadata,\n            documentId: chunk.documentId,\n            content: chunk.content\n          }\n        }\n      ]);\n      \n      // If using external vector database, keep track of the association\n      if (this.config.vectorDatabase?.type !== VectorDatabaseType.SAME_AS_MAIN) {\n        // Store association between document and chunk\n        await database.knex(\"rag_chunk_associations\").insert({\n          chunkId,\n          documentId: chunk.documentId,\n          chunkIndex,\n          createdAt: new Date()\n        });\n        \n        logger.debug(`Added chunk association for chunk ${chunkId} to document ${chunk.documentId}`);\n      }\n      \n      return chunkId;\n    } catch (error) {\n      logger.error(\"Error storing chunk with embedding:\", error);\n      throw error;\n    }\n  }\n\n  /**\n   * Get a document by its ID\n   * @param id The document ID to retrieve\n   * @returns Promise resolving to the document or null if not found\n   */\n  async getDocumentById(id: string): Promise<Document | null> {\n    // Validate required parameters\n    validateRequiredParam(id, \"id\", \"getDocumentById\");\n    \n    try {\n      const { database } = this.config;\n      \n      // If using same database, get document from rag_documents table\n      if (this.config.vectorDatabase?.type === VectorDatabaseType.SAME_AS_MAIN) {\n        // Get document from database\n        const document = await database.knex(\"rag_documents\")\n          .where(\"id\", id)\n          .first();\n        \n        if (!document) {\n          return null;\n        }\n        \n        return {\n          id: document.id,\n          content: document.content,\n          metadata: JSON.parse(document.metadata),\n        };\n      } else {\n        // For external vector DB, reconstruct document from chunks\n        const chunkAssociations = await database.knex(\"rag_chunk_associations\")\n          .where(\"documentId\", id)\n          .orderBy(\"chunkIndex\", \"asc\")\n          .select(\"chunkId\");\n        \n        if (!chunkAssociations || chunkAssociations.length === 0) {\n          return null;\n        }\n        \n        // Get chunk data from vector database\n        let content = \"\";\n        let metadata = {};\n        \n        for (const association of chunkAssociations) {\n          try {\n            const chunkMetadata = await this.vectorDatabaseConnector.getVectorMetadata(association.chunkId);\n            if (chunkMetadata && chunkMetadata.content) {\n              content += chunkMetadata.content;\n              // Use metadata from first chunk as document metadata\n              if (Object.keys(metadata).length === 0 && chunkMetadata.metadata) {\n                metadata = chunkMetadata.metadata;\n              }\n            }\n          } catch (error) {\n            logger.warn(`Error getting chunk ${association.chunkId} for document ${id}:`, error);\n          }\n        }\n        \n        if (!content) {\n          return null;\n        }\n        \n        return {\n          id,\n          content,\n          metadata,\n        };\n      }\n    } catch (error) {\n      logger.error(\"Error getting document by ID:\", error);\n      throw error;\n    }\n  }\n\n  /**\n   * Delete a document and its chunks\n   * @param id The document ID to delete\n   */\n  async deleteDocument(id: string): Promise<void> {\n    // Validate required parameters\n    validateRequiredParam(id, \"id\", \"deleteDocument\");\n    \n    try {\n      const { database, tableName } = this.config;\n      \n      // Handle deletion based on vector database type\n      if (this.config.vectorDatabase?.type === VectorDatabaseType.SAME_AS_MAIN) {\n        // Using same database - delete chunks and document\n        const chunks = await database.knex(tableName!)\n          .where(\"documentId\", id)\n          .select(\"id\");\n        \n        // Delete chunks\n        if (chunks.length > 0) {\n          const chunkIds = chunks.map((c: any) => c.id);\n          await database.knex(tableName!)\n            .whereIn(\"id\", chunkIds)\n            .delete();\n          \n          logger.debug(`Deleted ${chunkIds.length} chunks for document ${id}`);\n        }\n        \n        // Delete document (foreign key constraint will handle cascade)\n        await database.knex(\"rag_documents\")\n          .where(\"id\", id)\n          .delete();\n        \n        logger.debug(`Deleted document ${id} from main database`);\n      } else {\n        // Using external vector database\n        const chunkAssociations = await database.knex(\"rag_chunk_associations\")\n          .where(\"documentId\", id)\n          .select(\"chunkId\");\n        \n        if (chunkAssociations && chunkAssociations.length > 0) {\n          const chunkIds = chunkAssociations.map((c: any) => c.chunkId);\n          \n          // Delete vectors from the vector database\n          await this.vectorDatabaseConnector.deleteVectors(chunkIds);\n          \n          // Delete associations from the main database\n          await database.knex(\"rag_chunk_associations\")\n            .where(\"documentId\", id)\n            .delete();\n          \n          logger.debug(`Deleted ${chunkIds.length} vectors from external vector database for document ${id}`);\n        } else {\n          logger.warn(`No chunks found for document ${id} in external vector database`);\n        }\n      }\n      \n      logger.debug(`Successfully deleted document ${id}`);\n    } catch (error) {\n      logger.error(\"Error deleting document:\", error);\n      throw error;\n    }\n  }\n\n  /**\n   * Search for similar documents using text query\n   * @param query The search query\n   * @param limit Maximum number of results to return\n   * @returns Promise resolving to array of search results\n   */\n  async search(query: string, limit?: number): Promise<RAGResult[]> {\n    // Validate required parameters\n    validateRequiredParam(query, \"query\", \"search\");\n    \n    try {\n      const maxResults = limit || this.config.maxResults || 10;\n      \n      // Use semantic search if provider or memory with embedding support is available\n      if (this.config.provider && this.config.provider.generateEmbedding) {\n        try {\n          logger.debug(`Generating embedding for search query using provider: \"${query}\"`);\n          // Generate embedding for query using provider directly\n          const queryEmbedding = await this.config.provider.generateEmbedding(query);\n          \n          if (queryEmbedding && queryEmbedding.length > 0) {\n            logger.debug(`Generated embedding with ${queryEmbedding.length} dimensions`);\n            // Use embedding for semantic search\n            return this.searchByVector(queryEmbedding, maxResults);\n          } else {\n            logger.warn(\"Provider returned empty embedding, falling back to keyword search\");\n            return this.searchByKeyword(query, maxResults);\n          }\n        } catch (embeddingError) {\n          logger.warn(\"Failed to generate embedding using provider, trying memory fallback:\", embeddingError);\n          \n          // Fallback to memory if provider fails\n          if (this.config.memory && this.config.memory.searchByEmbedding) {\n            try {\n              logger.debug(`Generating embedding for search query using memory fallback: \"${query}\"`);\n              const { Embedding } = await import(\"../providers\");\n              const queryEmbedding = await Embedding.generateEmbedding(query);\n              \n              logger.debug(`Generated embedding with ${queryEmbedding.length} dimensions`);\n              return this.searchByVector(queryEmbedding, maxResults);\n            } catch (memoryError) {\n              logger.warn(\"Failed to generate embedding using memory fallback, using keyword search:\", memoryError);\n              return this.searchByKeyword(query, maxResults);\n            }\n          } else {\n            // Fall back to keyword search\n            logger.debug(\"No memory fallback available, using keyword search\");\n            return this.searchByKeyword(query, maxResults);\n          }\n        }\n      } else if (this.config.memory && this.config.memory.searchByEmbedding) {\n        try {\n          logger.debug(`Generating embedding for search query using memory: \"${query}\"`);\n          // Generate embedding for query using Embedding utility directly\n          const { Embedding } = await import(\"../providers\");\n          const queryEmbedding = await Embedding.generateEmbedding(query);\n          \n          logger.debug(`Generated embedding with ${queryEmbedding.length} dimensions`);\n          \n          // Use embedding for semantic search\n          return this.searchByVector(queryEmbedding, maxResults);\n        } catch (embeddingError) {\n          logger.warn(\"Failed to generate embedding using memory, falling back to keyword search:\", embeddingError);\n          // Fall back to keyword search\n          return this.searchByKeyword(query, maxResults);\n        }\n      } else {\n        // Fall back to keyword search\n        logger.debug(\"No provider or memory with embedding support, using keyword search\");\n        return this.searchByKeyword(query, maxResults);\n      }\n    } catch (error) {\n      logger.error(\"Error searching in vector RAG:\", error);\n      throw error;\n    }\n  }\n\n  /**\n   * Search for documents using vector similarity\n   * @param embedding The query embedding vector\n   * @param limit Maximum number of results to return\n   * @param threshold Minimum similarity threshold (0-1)\n   * @returns Promise resolving to an array of search results\n   */\n  async searchByVector(\n    embedding: number[],\n    limit?: number,\n    threshold: number = DEFAULT_VECTOR_SIMILARITY_THRESHOLD\n  ): Promise<RAGResult[]> {\n    try {\n      const maxResults = limit || this.config.maxResults || 10;\n      \n      logger.debug(`Searching by vector with ${embedding.length} dimensions, limit: ${maxResults}`);\n      \n      // Use the vector database connector to search for similar vectors\n      const similarVectors = await this.vectorDatabaseConnector.searchVectors(\n        embedding, \n        maxResults, \n        threshold\n      );\n      \n      logger.debug(`Found ${similarVectors.length} similar vectors`);\n      \n      // If using the same database, we need to fetch the detailed data\n      if (this.config.vectorDatabase?.type === VectorDatabaseType.SAME_AS_MAIN) {\n        const { database, tableName } = this.config;\n        \n        logger.debug(`Fetching chunk details from table: ${tableName}`);\n        \n        // Get detailed information for each chunk\n        const chunkDetails = await database.knex(tableName!)\n          .whereIn(\n            \"id\",\n            similarVectors.map((result) => result.id)\n          )\n          .select(\"*\");\n        \n        logger.debug(`Retrieved ${chunkDetails.length} chunk details`);\n        \n        // Map to the expected result format\n        return chunkDetails.map((chunk: any) => {\n          const similarityResult = similarVectors.find((v) => v.id === chunk.id);\n          try {\n            const metadata = typeof chunk.metadata === 'string' ? JSON.parse(chunk.metadata) : chunk.metadata;\n            return {\n              content: chunk.content,\n              metadata: metadata,\n              similarity: similarityResult?.similarity || 0,\n              sourceId: chunk.id,\n            };\n          } catch (parseError) {\n            logger.warn(`Error parsing metadata for chunk ${chunk.id}, using empty object:`, parseError);\n            return {\n              content: chunk.content,\n              metadata: {},\n              similarity: similarityResult?.similarity || 0,\n              sourceId: chunk.id,\n            };\n          }\n        });\n      } else {\n        // For external vector databases, we need to map the results \n        // from the vector IDs to the actual content\n        const { database } = this.config;\n        \n        // If we have no results, return empty array\n        if (similarVectors.length === 0) {\n          return [];\n        }\n        \n        // Get document IDs and content from chunk associations table\n        // This assumes we've stored the content and metadata in the vector database\n        const results: RAGResult[] = [];\n        \n        for (const vector of similarVectors) {\n          try {\n            // For external vector DB, content and metadata are stored in the vector's metadata\n            // This is handled through the vector database connector\n            const vectorMetadata = await this.vectorDatabaseConnector.getVectorMetadata(vector.id);\n            \n            if (!vectorMetadata) {\n              logger.warn(`Metadata for vector ${vector.id} not found, skipping result`);\n              continue;\n            }\n            \n            // The metadata from the vector database should include:\n            // - content: The text content of the chunk\n            // - metadata: The original metadata object of the chunk\n            // - documentId: The ID of the parent document\n            results.push({\n              content: vectorMetadata.content,\n              metadata: vectorMetadata.metadata,\n              similarity: vector.similarity,\n              sourceId: vector.id,\n            });\n            \n          } catch (error) {\n            logger.warn(`Error processing vector result ${vector.id}, skipping:`, error);\n            continue;\n          }\n        }\n        \n        return results;\n      }\n    } catch (error) {\n      logger.error(\"Error searching by vector:\", error);\n      throw error;\n    }\n  }\n\n  /**\n   * Search for documents using keyword matching\n   * @param query The search query\n   * @param limit Maximum number of results to return\n   * @returns Promise resolving to an array of search results\n   */\n  private async searchByKeyword(\n    query: string,\n    limit?: number\n  ): Promise<RAGResult[]> {\n    const { database, tableName } = this.config;\n    const maxResults = limit || this.config.maxResults || 10;\n    \n    // Simple LIKE query for keyword search\n    const results = await database.knex(tableName!)\n      .whereRaw(\"LOWER(content) LIKE ?\", [`%${query.toLowerCase()}%`])\n      .limit(maxResults)\n      .select(\"*\");\n    \n    return results.map((result: any) => {\n      try {\n        const metadata = typeof result.metadata === 'string' ? JSON.parse(result.metadata) : result.metadata;\n        return {\n          content: result.content,\n          metadata: metadata,\n          sourceId: result.id,\n        };\n      } catch (parseError) {\n        logger.warn(`Error parsing metadata for chunk ${result.id}, using empty object:`, parseError);\n        return {\n          content: result.content,\n          metadata: {},\n          sourceId: result.id,\n        };\n      }\n    });\n  }\n\n  /**\n   * Calculate cosine similarity between two vectors\n   * @param vecA First vector\n   * @param vecB Second vector\n   * @returns Similarity score between 0 and 1\n   */\n  private calculateCosineSimilarity(vecA: number[], vecB: number[]): number {\n    if (vecA.length !== vecB.length) {\n      throw new Error(\"Vector dimensions do not match\");\n    }\n    \n    let dotProduct = 0;\n    let normA = 0;\n    let normB = 0;\n    \n    for (let i = 0; i < vecA.length; i++) {\n      dotProduct += vecA[i] * vecB[i];\n      normA += vecA[i] * vecA[i];\n      normB += vecB[i] * vecB[i];\n    }\n    \n    normA = Math.sqrt(normA);\n    normB = Math.sqrt(normB);\n    \n    if (normA === 0 || normB === 0) {\n      return 0;\n    }\n    \n    return dotProduct / (normA * normB);\n  }\n}\n\n/**\n * Factory function to create a VectorRAG instance\n * @param config Configuration for the vector RAG\n * @returns Promise resolving to a configured VectorRAG instance\n */\nexport const createVectorRAG: VectorRAGFactory = async (\n  config: VectorRAGConfig\n) => {\n  return VectorRAG.create(config);\n}; ","import { DatabaseInstance } from \"./database\";\nimport { MemoryInstance } from \"./memory\";\nimport { ProviderInstance } from \"./provider\";\n\n// Vector database type enum\nexport enum VectorDatabaseType {\n  SAME_AS_MAIN = 'same_as_main',  // Use the same database as the main application\n  POSTGRES = 'postgres',          // PostgreSQL with pgvector\n  QDRANT = 'qdrant',              // Qdrant vector database\n  PINECONE = 'pinecone',          // Pinecone vector database\n  MILVUS = 'milvus',              // Milvus vector database\n  WEAVIATE = 'weaviate',          // Weaviate vector database\n}\n\n// Vector database configuration\nexport interface VectorDatabaseConfig {\n  /** Type of vector database to use */\n  type: VectorDatabaseType;\n  /** Connection string (if applicable) */\n  connectionString?: string;\n  /** API key (if applicable) */\n  apiKey?: string;\n  /** Environment (if applicable) */\n  environment?: string;\n  /** Namespace/index (if applicable) */\n  namespace?: string;\n  /** Base URL (if applicable) */\n  baseUrl?: string;\n  /** Any other custom options */\n  options?: Record<string, any>;\n}\n\n// Document structure for document-based RAG\nexport interface Document {\n  id: string;\n  content: string;\n  metadata: Record<string, any>;\n  embedding?: number[]; // Optional embedding vector\n}\n\n// Chunk structure for vector-based RAG\nexport interface Chunk {\n  id: string;\n  documentId: string;\n  content: string; \n  metadata: Record<string, any>;\n  embedding: number[]; // Required embedding vector\n}\n\n// Result with similarity score for semantic search\nexport interface RAGResult {\n  content: string;\n  metadata: Record<string, any>;\n  similarity?: number; // Similarity score (0-1)\n  sourceId: string; // Document ID or Chunk ID\n}\n\n// Base RAG configuration\nexport interface RAGConfig {\n  /** Required: Database instance for storing documents/chunks */\n  database: DatabaseInstance;\n  /** Optional: Memory instance for storing vector embeddings */\n  memory?: MemoryInstance;\n  /** Optional: Provider instance for generating embeddings */\n  provider?: ProviderInstance;\n  /** Optional: Custom table name for storing data */\n  tableName?: string;\n  /** Optional: Maximum number of results to retrieve */\n  maxResults?: number;\n  /** Optional: Vector database configuration */\n  vectorDatabase?: VectorDatabaseConfig;\n}\n\n// Vector-based RAG configuration\nexport interface VectorRAGConfig extends RAGConfig {\n  /** Optional: Chunk size for text splitting */\n  chunkSize?: number;\n  /** Optional: Chunk overlap for text splitting */\n  chunkOverlap?: number;\n}\n\n// Document-based RAG configuration\nexport interface DocumentRAGConfig extends RAGConfig {\n  /** Optional: Whether to store document embeddings */\n  storeEmbeddings?: boolean;\n}\n\n// Base RAG instance\nexport interface RAGInstance {\n  config: RAGConfig;\n  search(query: string, limit?: number): Promise<RAGResult[]>;\n}\n\n// Vector-based RAG instance\nexport interface VectorRAGInstance extends RAGInstance {\n  config: VectorRAGConfig;\n  addDocument(document: Omit<Document, \"id\" | \"embedding\">): Promise<string>;\n  getDocumentById(id: string): Promise<Document | null>;\n  deleteDocument(id: string): Promise<void>;\n  searchByVector(embedding: number[], limit?: number, threshold?: number): Promise<RAGResult[]>;\n}\n\n// Document-based RAG instance\nexport interface DocumentRAGInstance extends RAGInstance {\n  config: DocumentRAGConfig;\n  addDocument(document: Omit<Document, \"id\">): Promise<string>;\n  getDocumentById(id: string): Promise<Document | null>;\n  deleteDocument(id: string): Promise<void>;\n  searchByMetadata(filter: Record<string, any>, limit?: number): Promise<RAGResult[]>;\n}\n\n// Factory functions\nexport type VectorRAGFactory = (config: VectorRAGConfig) => Promise<VectorRAGInstance>;\nexport type DocumentRAGFactory = (config: DocumentRAGConfig) => Promise<DocumentRAGInstance>;\n\n// RAG type enum for the unified createRAG function\nexport enum RAGType {\n  VECTOR = 'vector',\n  DOCUMENT = 'document'\n}\n\n// Unified RAG factory config\nexport interface RAGFactoryConfig extends RAGConfig {\n  type: RAGType;\n  // Vector RAG specific options\n  chunkSize?: number;  \n  chunkOverlap?: number;\n  // Document RAG specific options\n  storeEmbeddings?: boolean;\n}\n\n// Unified RAG factory function type\nexport type RAGFactory = (config: RAGFactoryConfig) => Promise<VectorRAGInstance | DocumentRAGInstance>; ","import { logger } from '../../utils';\nimport { VectorDatabaseType, VectorDatabaseConfig } from '../../types/rag';\nimport { DatabaseInstance } from '../../types/database';\nimport dotenv from 'dotenv';\nimport knex from 'knex';\n\n// Load environment variables\ndotenv.config();\n\n/**\n * Interface for vector database operations\n */\nexport interface VectorDatabaseConnector {\n  /** Adds vectors to the database */\n  addVectors(vectors: Array<{ id: string, vector: number[], metadata: Record<string, any> }>): Promise<void>;\n  \n  /** Similarity search for vectors */\n  searchVectors(vector: number[], limit?: number, threshold?: number): Promise<Array<{ id: string, similarity: number }>>;\n  \n  /** Delete vectors by IDs */\n  deleteVectors(ids: string[]): Promise<void>;\n  \n  /** Get metadata for a vector by ID */\n  getVectorMetadata(id: string): Promise<Record<string, any> | null>;\n  \n  /** Close the connection */\n  close(): Promise<void>;\n}\n\n/**\n * Base class for vector database connectors\n */\nabstract class BaseVectorDatabaseConnector implements VectorDatabaseConnector {\n  protected config: VectorDatabaseConfig;\n  \n  constructor(config: VectorDatabaseConfig) {\n    this.config = config;\n  }\n  \n  abstract addVectors(vectors: Array<{ id: string, vector: number[], metadata: Record<string, any> }>): Promise<void>;\n  abstract searchVectors(vector: number[], limit?: number, threshold?: number): Promise<Array<{ id: string, similarity: number }>>;\n  abstract deleteVectors(ids: string[]): Promise<void>;\n  abstract getVectorMetadata(id: string): Promise<Record<string, any> | null>;\n  abstract close(): Promise<void>;\n}\n\n/**\n * PostgreSQL vector database connector (using pgvector)\n */\nclass PostgresVectorDatabaseConnector extends BaseVectorDatabaseConnector {\n  private knex: knex.Knex;\n  private tableName: string;\n  private connected: boolean = false;\n  \n  constructor(config: VectorDatabaseConfig) {\n    super(config);\n    \n    // Use custom table name if provided, otherwise default\n    this.tableName = config.options?.tableName || 'vector_embeddings';\n    \n    // Initialize knex with PostgreSQL configuration\n    this.knex = knex({\n      client: 'pg',\n      connection: config.connectionString || {\n        host: process.env.POSTGRES_HOST || 'localhost',\n        port: parseInt(process.env.POSTGRES_PORT || '5432'),\n        user: process.env.POSTGRES_USER || 'postgres',\n        password: process.env.POSTGRES_PASSWORD || '',\n        database: process.env.POSTGRES_DB || 'postgres'\n      }\n    });\n    \n    logger.debug(\"PostgreSQL vector database connector initialized\");\n  }\n  \n  /**\n   * Ensure pgvector extension is installed and table is created\n   */\n  private async ensureConnection(): Promise<void> {\n    if (this.connected) return;\n    \n    try {\n      // Check connection\n      await this.knex.raw('SELECT 1');\n      \n      // Create pgvector extension if it doesn't exist\n      await this.knex.raw('CREATE EXTENSION IF NOT EXISTS vector');\n      \n      // Check if table exists\n      const tableExists = await this.knex.schema.hasTable(this.tableName);\n      \n      if (!tableExists) {\n        // Create vector table with proper schema\n        await this.knex.schema.createTable(this.tableName, (table) => {\n          table.string('id').primary();\n          table.string('documentId').notNullable();\n          table.text('content').notNullable();\n          table.specificType('embedding', 'vector');\n          table.jsonb('metadata');\n          table.timestamp('createdAt').defaultTo(this.knex.fn.now());\n        });\n        \n        // Create index for vector similarity search\n        await this.knex.raw(`CREATE INDEX ${this.tableName}_embedding_idx ON ${this.tableName} USING ivfflat (embedding vector_l2_ops)`);\n        \n        logger.debug(`Created ${this.tableName} table with pgvector index`);\n      }\n      \n      this.connected = true;\n      logger.debug(`Connected to PostgreSQL vector database`);\n    } catch (error) {\n      logger.error('Error connecting to PostgreSQL vector database:', error);\n      throw new Error(`Failed to initialize PostgreSQL vector database: ${error}`);\n    }\n  }\n  \n  /**\n   * Add vectors to the database\n   */\n  async addVectors(vectors: Array<{ id: string, vector: number[], metadata: Record<string, any> }>): Promise<void> {\n    try {\n      await this.ensureConnection();\n      \n      // Convert vectors to pgvector format and prepare batch insert\n      const rows = vectors.map(({ id, vector, metadata }) => {\n        // Extract documentId and content from metadata for table schema\n        const { documentId, content, ...restMetadata } = metadata;\n        \n        return {\n          id,\n          documentId: documentId || 'unknown', // Provide default to prevent null constraint violation\n          content: content || '', // Provide default to prevent null constraint violation\n          embedding: this.knex.raw(`'[${vector.join(',')}]'::vector`),\n          metadata: JSON.stringify(restMetadata),\n          createdAt: new Date()\n        };\n      });\n      \n      // Use batch insert for better performance\n      const batchSize = 50;\n      for (let i = 0; i < rows.length; i += batchSize) {\n        const batch = rows.slice(i, i + batchSize);\n        await this.knex(this.tableName).insert(batch);\n      }\n      \n      logger.debug(`Added ${vectors.length} vectors to PostgreSQL`);\n    } catch (error) {\n      logger.error('Error adding vectors to PostgreSQL:', error);\n      throw error;\n    }\n  }\n  \n  /**\n   * Search for similar vectors using pgvector's similarity search\n   */\n  async searchVectors(vector: number[], limit: number = 10, threshold: number = 0.7): Promise<Array<{ id: string, similarity: number }>> {\n    try {\n      await this.ensureConnection();\n      \n      // Convert similarity threshold to a distance threshold (cosine similarity to L2 distance)\n      // Approximate conversion: 1 - similarity = (distance^2) / 2\n      // Solving for distance: distance = sqrt(2 * (1 - similarity))\n      const distanceThreshold = Math.sqrt(2 * (1 - threshold));\n      \n      // Query using L2 distance (Euclidean distance)\n      const results = await this.knex.raw(`\n        SELECT \n          id, \n          1 - (embedding <-> ?) / 2 as similarity\n        FROM ${this.tableName}\n        WHERE embedding <-> ? < ?\n        ORDER BY similarity DESC\n        LIMIT ?\n      `, [\n        `[${vector.join(',')}]`,\n        `[${vector.join(',')}]`,\n        distanceThreshold,\n        limit\n      ]);\n      \n      const rows = results.rows;\n      logger.debug(`Found ${rows.length} similar vectors in PostgreSQL`);\n      \n      return rows.map((row: any) => ({\n        id: row.id,\n        similarity: parseFloat(row.similarity)\n      }));\n    } catch (error) {\n      logger.error('Error searching vectors in PostgreSQL:', error);\n      throw error;\n    }\n  }\n  \n  /**\n   * Get metadata for a vector by ID\n   */\n  async getVectorMetadata(id: string): Promise<Record<string, any> | null> {\n    try {\n      await this.ensureConnection();\n      \n      const result = await this.knex(this.tableName)\n        .where('id', id)\n        .select('metadata')\n        .first();\n      \n      if (!result) {\n        return null;\n      }\n      \n      return JSON.parse(result.metadata);\n    } catch (error) {\n      logger.error(`Error getting metadata for vector ${id}:`, error);\n      throw error;\n    }\n  }\n  \n  /**\n   * Delete vectors by IDs\n   */\n  async deleteVectors(ids: string[]): Promise<void> {\n    try {\n      await this.ensureConnection();\n      \n      await this.knex(this.tableName)\n        .whereIn('id', ids)\n        .delete();\n        \n      logger.debug(`Deleted ${ids.length} vectors from PostgreSQL`);\n    } catch (error) {\n      logger.error('Error deleting vectors from PostgreSQL:', error);\n      throw error;\n    }\n  }\n  \n  /**\n   * Close the database connection\n   */\n  async close(): Promise<void> {\n    try {\n      if (this.knex) {\n        await this.knex.destroy();\n        this.connected = false;\n        logger.debug(\"Closed PostgreSQL vector database connection\");\n      }\n    } catch (error) {\n      logger.error('Error closing PostgreSQL connection:', error);\n      throw error;\n    }\n  }\n}\n\n/**\n * Main database vector database connector (using the same database as the application)\n */\nclass MainDatabaseVectorConnector extends BaseVectorDatabaseConnector {\n  private database: DatabaseInstance;\n  private tableName: string;\n  \n  constructor(config: VectorDatabaseConfig, database: DatabaseInstance) {\n    super(config);\n    this.database = database;\n    \n    // Use custom table name from database configuration or provided config\n    const dbTableNames = database.getTableNames();\n    this.tableName = config.options?.tableName || \n                    database.getCustomTableName('vector_embeddings') || \n                    'vector_embeddings';\n    logger.debug(\"Main database vector connector initialized\");\n  }\n  \n  async addVectors(vectors: Array<{ id: string, vector: number[], metadata: Record<string, any> }>): Promise<void> {\n    try {\n      const records = vectors.map(({ id, vector, metadata }) => {\n        // Extract documentId and content from metadata for table schema\n        const { documentId, content, ...restMetadata } = metadata;\n        \n        return {\n          id,\n          documentId: documentId || 'unknown', // Provide default to prevent null constraint violation\n          content: content || '', // Provide default to prevent null constraint violation\n          embedding: JSON.stringify(vector),\n          metadata: JSON.stringify(restMetadata),\n          createdAt: new Date()\n        };\n      });\n      \n      // Use batch insert for better performance\n      const batchSize = 50;\n      for (let i = 0; i < records.length; i += batchSize) {\n        const batch = records.slice(i, i + batchSize);\n        await this.database.knex(this.tableName).insert(batch);\n      }\n      \n      logger.debug(`Added ${vectors.length} vectors to main database`);\n    } catch (error) {\n      logger.error(\"Error adding vectors to main database:\", error);\n      throw error;\n    }\n  }\n  \n  async searchVectors(vector: number[], limit: number = 10, threshold: number = 0.7): Promise<Array<{ id: string, similarity: number }>> {\n    try {\n      // Retrieve all vectors from the database\n      const rows = await this.database.knex(this.tableName).select('id', 'embedding');\n      \n      // Calculate cosine similarity for each vector\n      const results = rows\n        .map((row: { id: string, embedding: string | any[] }) => {\n          try {\n            let storedVector: number[];\n            \n            // Handle different embedding data types\n            if (!row.embedding) {\n              logger.warn(`Empty embedding for vector ${row.id}, skipping`);\n              return null;\n            }\n            \n            // If embedding is already an array (parsed by database driver)\n            if (Array.isArray(row.embedding)) {\n              storedVector = row.embedding;\n            }\n            // If embedding is a string, parse it\n            else if (typeof row.embedding === 'string') {\n              if (row.embedding.trim() === '') {\n                logger.warn(`Empty embedding string for vector ${row.id}, skipping`);\n                return null;\n              }\n              storedVector = JSON.parse(row.embedding);\n            }\n            // If embedding is an object, try to extract array\n            else if (typeof row.embedding === 'object') {\n              storedVector = row.embedding;\n            }\n            else {\n              logger.warn(`Unknown embedding type for vector ${row.id}, skipping`);\n              return null;\n            }\n            \n            // Validate that we have a valid array\n            if (!Array.isArray(storedVector) || storedVector.length === 0) {\n              logger.warn(`Invalid embedding format for vector ${row.id}, skipping`);\n              return null;\n            }\n            \n            const similarity = this.calculateCosineSimilarity(vector, storedVector);\n            return { id: row.id, similarity };\n          } catch (parseError) {\n            logger.warn(`Failed to parse embedding for vector ${row.id}:`, parseError);\n            return null;\n          }\n        })\n        .filter((result): result is { id: string, similarity: number } => \n          result !== null && result.similarity >= threshold\n        )\n        .sort((a: { similarity: number }, b: { similarity: number }) => b.similarity - a.similarity)\n        .slice(0, limit);\n      \n      logger.debug(`Found ${results.length} similar vectors in main database`);\n      return results;\n    } catch (error) {\n      logger.error(\"Error searching vectors in main database:\", error);\n      throw error;\n    }\n  }\n  \n  /**\n   * Get metadata for a vector by ID\n   */\n  async getVectorMetadata(id: string): Promise<Record<string, any> | null> {\n    try {\n      const result = await this.database.knex(this.tableName)\n        .where('id', id)\n        .select('metadata')\n        .first();\n      \n      if (!result) {\n        return null;\n      }\n      \n      return JSON.parse(result.metadata);\n    } catch (error) {\n      logger.error(`Error getting metadata for vector ${id}:`, error);\n      throw error;\n    }\n  }\n  \n  private calculateCosineSimilarity(vecA: number[], vecB: number[]): number {\n    if (vecA.length !== vecB.length) {\n      throw new Error(\"Vector dimensions do not match\");\n    }\n    \n    let dotProduct = 0;\n    let normA = 0;\n    let normB = 0;\n    \n    for (let i = 0; i < vecA.length; i++) {\n      dotProduct += vecA[i] * vecB[i];\n      normA += vecA[i] * vecA[i];\n      normB += vecB[i] * vecB[i];\n    }\n    \n    normA = Math.sqrt(normA);\n    normB = Math.sqrt(normB);\n    \n    if (normA === 0 || normB === 0) {\n      return 0;\n    }\n    \n    return dotProduct / (normA * normB);\n  }\n  \n  async deleteVectors(ids: string[]): Promise<void> {\n    try {\n      await this.database.knex(this.tableName).whereIn('id', ids).delete();\n      logger.debug(`Deleted ${ids.length} vectors from main database`);\n    } catch (error) {\n      logger.error(\"Error deleting vectors from main database:\", error);\n      throw error;\n    }\n  }\n  \n  async close(): Promise<void> {\n    // No need to close connection as it's managed by the main database\n    logger.debug(\"Main database vector connector closed\");\n  }\n}\n\n/**\n * Factory function to create a vector database connector based on configuration\n * @param config Vector database configuration\n * @param database Main database instance (if using same database)\n * @returns Vector database connector\n */\nexport function createVectorDatabaseConnector(\n  config?: VectorDatabaseConfig,\n  database?: DatabaseInstance\n): VectorDatabaseConnector {\n  // If no config provided, try to load from environment variables\n  if (!config) {\n    config = loadVectorDatabaseConfigFromEnv();\n  }\n  \n  // Default to using the main database if no configuration is provided\n  if (!config || config.type === VectorDatabaseType.SAME_AS_MAIN) {\n    if (!database) {\n      throw new Error(\"Database instance is required when using SAME_AS_MAIN vector database type\");\n    }\n    // Use the provided config instead of creating a new one\n    const mainDbConfig = config || { type: VectorDatabaseType.SAME_AS_MAIN };\n    return new MainDatabaseVectorConnector(mainDbConfig, database);\n  }\n  \n  // Create the appropriate connector based on type\n  switch (config.type) {\n    case VectorDatabaseType.POSTGRES:\n      return new PostgresVectorDatabaseConnector(config);\n    case VectorDatabaseType.QDRANT:\n    case VectorDatabaseType.PINECONE:\n    case VectorDatabaseType.MILVUS:\n    case VectorDatabaseType.WEAVIATE:\n      // To be implemented in future PRs\n      throw new Error(`Vector database type ${config.type} not yet implemented`);\n    default:\n      throw new Error(`Unsupported vector database type: ${config.type}`);\n  }\n}\n\n/**\n * Load vector database configuration from environment variables\n * @returns Vector database configuration\n */\nexport function loadVectorDatabaseConfigFromEnv(): VectorDatabaseConfig {\n  const type = process.env.VECTOR_DB_TYPE as VectorDatabaseType || VectorDatabaseType.SAME_AS_MAIN;\n  const connectionString = process.env.VECTOR_DB_CONNECTION_STRING;\n  \n  // Parse connection string if provided for PostgreSQL\n  let parsedOptions: Record<string, any> = {};\n  if (type === VectorDatabaseType.POSTGRES && connectionString) {\n    try {\n      // Parse connection string format: postgres://user:password@host:port/database\n      const url = new URL(connectionString);\n      parsedOptions = {\n        host: url.hostname,\n        port: url.port ? parseInt(url.port) : 5432,\n        user: url.username,\n        password: url.password,\n        database: url.pathname.substring(1), // Remove leading slash\n      };\n    } catch (error) {\n      logger.error(\"Failed to parse PostgreSQL connection string:\", error);\n    }\n  }\n  \n  const config: VectorDatabaseConfig = {\n    type,\n    connectionString,\n    apiKey: process.env.VECTOR_DB_API_KEY,\n    environment: process.env.VECTOR_DB_ENVIRONMENT,\n    namespace: process.env.VECTOR_DB_NAMESPACE,\n    baseUrl: process.env.VECTOR_DB_BASE_URL,\n    options: {\n      ...parsedOptions,\n      tableName: process.env.VECTOR_DB_TABLE_NAME,\n    }\n  };\n  \n  return config;\n} ","import { v4 as uuidv4 } from \"uuid\";\nimport {\n  DocumentRAGConfig,\n  DocumentRAGInstance,\n  Document,\n  RAGResult,\n  DocumentRAGFactory,\n} from \"../types\";\nimport { logger } from \"../utils\";\nimport { validateRequiredParam, validateRequiredParams } from \"../utils/validation\";\n\n/**\n * Document-based RAG implementation\n * Stores and retrieves complete documents with optional embeddings\n */\nexport class DocumentRAG implements DocumentRAGInstance {\n  public config: DocumentRAGConfig;\n\n  constructor(config: DocumentRAGConfig) {\n    // Validate required parameters\n    validateRequiredParam(config, \"config\", \"DocumentRAG constructor\");\n    validateRequiredParams(\n      config,\n      [\"database\"],\n      \"DocumentRAG constructor\"\n    );\n    \n    // Apply defaults for optional config parameters\n    this.config = {\n      ...config,\n      tableName: config.tableName || \"rag_documents\",\n      maxResults: config.maxResults || 10,\n      storeEmbeddings: config.storeEmbeddings || false,\n    };\n    \n    logger.debug(\"Document RAG system initialized\");\n  }\n\n  /**\n   * Create a new document RAG instance with proper configuration\n   * @param config Configuration object for document RAG\n   * @returns Promise that resolves to the new document RAG instance\n   */\n  static async create(config: DocumentRAGConfig): Promise<DocumentRAGInstance> {\n    // Validate required parameters\n    validateRequiredParam(config, \"config\", \"DocumentRAG.create\");\n    validateRequiredParams(\n      config,\n      [\"database\"],\n      \"DocumentRAG.create\"\n    );\n    \n    try {\n      const instance = new DocumentRAG(config);\n      await instance.initializeDatabase();\n      return instance;\n    } catch (error) {\n      logger.error(\"Error creating document RAG instance:\", error);\n      throw error;\n    }\n  }\n\n  /**\n   * Initialize database tables for document RAG\n   */\n  private async initializeDatabase(): Promise<void> {\n    try {\n      const { database, storeEmbeddings } = this.config;\n      \n      // Use user-provided table name or default\n      const tableName = this.config.tableName || 'rag_documents';\n      \n      // Use database's enhanced table management\n      await database.ensureTable(tableName, (table) => {\n        table.string(\"id\").primary();\n        table.text(\"content\").notNullable();\n        table.json(\"metadata\").notNullable();\n        // Add embedding column if enabled\n        if (storeEmbeddings) {\n          table.json(\"embedding\");\n        }\n        table.timestamp(\"createdAt\").defaultTo(database.knex.fn.now());\n      });\n      \n      // Update config to use the resolved table name\n      this.config.tableName = tableName;\n      \n      // Check if embeddings are enabled and ensure embedding column exists\n      if (storeEmbeddings) {\n        const hasEmbeddingColumn = await database.knex.schema.hasColumn(\n          tableName,\n          \"embedding\"\n        );\n        \n        if (!hasEmbeddingColumn) {\n          // Add embedding column if it doesn't exist\n          await database.knex.schema.table(tableName, (table) => {\n            table.json(\"embedding\");\n          });\n          logger.debug(`Added embedding column to ${tableName} table`);\n        }\n      }\n      \n      logger.info(`Document RAG initialized with custom table: ${tableName}`);\n    } catch (error) {\n      logger.error(\"Error initializing document RAG database:\", error);\n      throw error;\n    }\n  }\n\n  /**\n   * Add a document to the RAG system\n   * @param document The document to add\n   * @returns Promise resolving to the document ID\n   */\n  async addDocument(document: Omit<Document, \"id\">): Promise<string> {\n    // Validate required parameters\n    validateRequiredParam(document, \"document\", \"addDocument\");\n    validateRequiredParams(\n      document,\n      [\"content\", \"metadata\"],\n      \"addDocument\"\n    );\n    \n    try {\n      const { database, tableName, storeEmbeddings, memory } = this.config;\n      const id = uuidv4();\n      \n      const docToInsert: any = {\n        id,\n        content: document.content,\n        metadata: JSON.stringify(document.metadata),\n        createdAt: new Date(),\n      };\n      \n      // Handle embedding if enabled and provided or can be generated\n      if (storeEmbeddings) {\n        let embedding = document.embedding;\n        \n        // Generate embedding if not provided\n        if (!embedding) {\n          try {\n            // Use the Embedding utility directly\n            const { Embedding } = await import(\"../providers\");\n            embedding = await Embedding.generateEmbedding(document.content.substring(0, 8000));\n            \n            logger.debug(`Generated embedding for document ${id} (${embedding.length} dimensions)`);\n          } catch (embeddingError) {\n            logger.warn(\"Error generating embedding for document:\", embeddingError);\n          }\n        }\n        \n        // Store embedding if available\n        if (embedding) {\n          docToInsert.embedding = JSON.stringify(embedding);\n        }\n      }\n      \n      // Store document in database\n      await database.knex(tableName!).insert(docToInsert);\n      \n      logger.debug(`Added document ${id} to RAG system`);\n      return id;\n    } catch (error) {\n      logger.error(\"Error adding document to RAG system:\", error);\n      throw error;\n    }\n  }\n\n  /**\n   * Get a document by ID\n   * @param id The document ID\n   * @returns Promise resolving to the document or null if not found\n   */\n  async getDocumentById(id: string): Promise<Document | null> {\n    // Validate required parameters\n    validateRequiredParam(id, \"id\", \"getDocumentById\");\n    \n    try {\n      const { database, tableName } = this.config;\n      \n      // Query document\n      const document = await database.knex(tableName!)\n        .where({ id })\n        .first();\n      \n      if (!document) {\n        return null;\n      }\n      \n      // Process document data\n      const result: Document = {\n        id: document.id,\n        content: document.content,\n        metadata: JSON.parse(document.metadata),\n      };\n      \n      // Add embedding if available\n      if (document.embedding) {\n        try {\n          result.embedding = JSON.parse(document.embedding);\n        } catch (error) {\n          logger.warn(`Error parsing embedding for document ${id}:`, error);\n        }\n      }\n      \n      return result;\n    } catch (error) {\n      logger.error(`Error getting document ${id}:`, error);\n      throw error;\n    }\n  }\n\n  /**\n   * Delete a document\n   * @param id The document ID\n   * @returns Promise resolving when the document is deleted\n   */\n  async deleteDocument(id: string): Promise<void> {\n    // Validate required parameters\n    validateRequiredParam(id, \"id\", \"deleteDocument\");\n    \n    try {\n      const { database, tableName } = this.config;\n      \n      // Delete document\n      await database.knex(tableName!)\n        .where({ id })\n        .delete();\n      \n      logger.debug(`Deleted document ${id}`);\n    } catch (error) {\n      logger.error(`Error deleting document ${id}:`, error);\n      throw error;\n    }\n  }\n\n  /**\n   * Search for documents using text query\n   * @param query The search query\n   * @param limit Maximum number of results to return\n   * @returns Promise resolving to array of search results\n   */\n  async search(query: string, limit?: number): Promise<RAGResult[]> {\n    // Validate required parameters\n    validateRequiredParam(query, \"query\", \"search\");\n    \n    try {\n      const { storeEmbeddings } = this.config;\n      \n      // Use vector search if embeddings are available\n      if (storeEmbeddings) {\n        try {\n          // Generate embedding for query using Embedding utility directly\n          const { Embedding } = await import(\"../providers\");\n          const queryEmbedding = await Embedding.generateEmbedding(query);\n          \n          // Search using the embedding\n          return this.searchWithEmbedding(queryEmbedding, limit);\n        } catch (embeddingError) {\n          logger.warn(\"Error performing embedding search, falling back to keyword search:\", embeddingError);\n        }\n      }\n      \n      // Fall back to keyword search\n      return this.searchByKeyword(query, limit);\n    } catch (error) {\n      logger.error(`Error searching with query \"${query}\":`, error);\n      throw error;\n    }\n  }\n\n  /**\n   * Search for documents based on metadata filters\n   * @param filter Metadata filter criteria\n   * @param limit Maximum number of results to return\n   * @returns Promise resolving to array of search results\n   */\n  async searchByMetadata(\n    filter: Record<string, any>,\n    limit?: number\n  ): Promise<RAGResult[]> {\n    // Validate required parameters\n    validateRequiredParam(filter, \"filter\", \"searchByMetadata\");\n    \n    try {\n      const { database, tableName, maxResults } = this.config;\n      \n      // Get all documents\n      const documents = await database.knex(tableName!)\n        .select(\"*\")\n        .limit(limit || maxResults!);\n      \n      // Filter documents based on metadata criteria\n      const results: RAGResult[] = [];\n      \n      for (const doc of documents) {\n        try {\n          const metadata = JSON.parse(doc.metadata);\n          let matches = true;\n          \n          // Check if document metadata matches all filter criteria\n          for (const [key, value] of Object.entries(filter)) {\n            if (metadata[key] !== value) {\n              matches = false;\n              break;\n            }\n          }\n          \n          if (matches) {\n            results.push({\n              content: doc.content,\n              metadata,\n              sourceId: doc.id,\n            });\n          }\n        } catch (error) {\n          logger.warn(`Error processing document ${doc.id}, skipping:`, error);\n          continue;\n        }\n      }\n      \n      return results;\n    } catch (error) {\n      logger.error(\"Error searching by metadata:\", error);\n      throw error;\n    }\n  }\n\n  /**\n   * Search for documents using keyword matching\n   * @param query The search query\n   * @param limit Maximum number of results to return\n   * @returns Promise resolving to array of search results\n   */\n  private async searchByKeyword(\n    query: string,\n    limit?: number\n  ): Promise<RAGResult[]> {\n    try {\n      const { database, tableName, maxResults } = this.config;\n      \n      // Simple keyword search using database LIKE queries\n      const documents = await database.knex(tableName!)\n        .whereRaw(\"LOWER(content) LIKE ?\", [`%${query.toLowerCase()}%`])\n        .limit(limit || maxResults!);\n      \n      // Process results\n      return documents.map(doc => ({\n        content: doc.content,\n        metadata: JSON.parse(doc.metadata),\n        sourceId: doc.id,\n      }));\n    } catch (error) {\n      logger.error(`Error searching by keyword \"${query}\":`, error);\n      throw error;\n    }\n  }\n\n  /**\n   * Search for documents using embedding similarity\n   * @param embedding The query embedding vector\n   * @param limit Maximum number of results to return\n   * @returns Promise resolving to array of search results with similarity scores\n   */\n  private async searchWithEmbedding(\n    embedding: number[],\n    limit?: number\n  ): Promise<RAGResult[]> {\n    try {\n      const { database, tableName, maxResults } = this.config;\n      \n      // Get all documents with embeddings\n      const documents = await database.knex(tableName!)\n        .select(\"*\")\n        .whereNotNull(\"embedding\");\n      \n      // Calculate similarity and filter results\n      const results: RAGResult[] = [];\n      \n      for (const doc of documents) {\n        try {\n          // Parse embedding from JSON\n          const docEmbedding = JSON.parse(doc.embedding);\n          \n          // Skip documents with invalid embeddings\n          if (!Array.isArray(docEmbedding) || docEmbedding.length === 0) {\n            continue;\n          }\n          \n          // Calculate cosine similarity\n          const similarity = this.calculateCosineSimilarity(embedding, docEmbedding);\n          \n          // Add to results\n          results.push({\n            content: doc.content,\n            metadata: JSON.parse(doc.metadata),\n            similarity,\n            sourceId: doc.id,\n          });\n        } catch (error) {\n          logger.warn(`Error processing document ${doc.id}, skipping:`, error);\n          continue;\n        }\n      }\n      \n      // Sort by similarity (descending) and limit results\n      return results\n        .sort((a, b) => (b.similarity || 0) - (a.similarity || 0))\n        .slice(0, limit || maxResults);\n    } catch (error) {\n      logger.error(\"Error searching with embedding:\", error);\n      throw error;\n    }\n  }\n\n  /**\n   * Calculate cosine similarity between two vectors\n   * @param vecA First vector\n   * @param vecB Second vector\n   * @returns Similarity score (0-1)\n   */\n  private calculateCosineSimilarity(vecA: number[], vecB: number[]): number {\n    // Check for valid vectors\n    if (!vecA.length || !vecB.length || vecA.length !== vecB.length) {\n      return 0;\n    }\n    \n    let dotProduct = 0;\n    let normA = 0;\n    let normB = 0;\n    \n    // Calculate dot product and norms\n    for (let i = 0; i < vecA.length; i++) {\n      dotProduct += vecA[i] * vecB[i];\n      normA += vecA[i] * vecA[i];\n      normB += vecB[i] * vecB[i];\n    }\n    \n    // Handle zero vectors\n    if (normA === 0 || normB === 0) {\n      return 0;\n    }\n    \n    // Calculate similarity\n    return dotProduct / (Math.sqrt(normA) * Math.sqrt(normB));\n  }\n}\n\n/**\n * Factory function to create a document RAG instance\n * @param config Document RAG configuration\n * @returns Promise resolving to a document RAG instance\n */\nexport const createDocumentRAG: DocumentRAGFactory = async (\n  config: DocumentRAGConfig\n) => {\n  return DocumentRAG.create(config);\n}; ","import fs from 'fs';\nimport path from 'path';\nimport { PDFDocument } from 'pdf-lib';\nimport { Document } from '../types';\nimport { logger } from '../utils';\nimport { v4 as uuidv4 } from 'uuid';\n\nexport interface PDFParseOptions {\n  /**\n   * The strategy for splitting the PDF\n   * - 'simple': Split by character count\n   * - 'paragraph': Split by paragraphs\n   * - 'section': Split by detected sections/headers (most intelligent)\n   */\n  splitStrategy: 'simple' | 'paragraph' | 'section';\n  \n  /**\n   * Size of chunks when using 'simple' strategy\n   */\n  chunkSize?: number;\n  \n  /**\n   * Overlap between chunks when using 'simple' or 'paragraph' strategy\n   */\n  chunkOverlap?: number;\n  \n  /**\n   * Whether to include page numbers in metadata\n   */\n  includePageNumbers?: boolean;\n  \n  /**\n   * Custom metadata to attach to each document\n   */\n  metadata?: Record<string, any>;\n}\n\nexport interface PDFParseResult {\n  /**\n   * The documents extracted from the PDF, ready to be added to RAG\n   */\n  documents: Omit<Document, 'id'>[];\n  \n  /**\n   * Metadata about the PDF itself\n   */\n  pdfMetadata: {\n    title?: string;\n    author?: string;\n    numPages: number;\n    creationDate?: Date;\n  };\n  \n  /**\n   * Unique identifier for this PDF document\n   */\n  documentId: string;\n}\n\n/**\n * Parse a PDF file and extract structured content for RAG\n * @param filePath Path to the PDF file\n * @param options Options for parsing and chunking\n * @returns Promise resolving to the parsed documents\n */\nexport async function parsePDF(\n  filePath: string,\n  options: PDFParseOptions\n): Promise<PDFParseResult> {\n  try {\n    logger.debug(`Parsing PDF: ${filePath}`);\n    \n    // Generate a unique document ID for this PDF\n    const documentId = uuidv4();\n    \n    // Set default options\n    const opts: Required<PDFParseOptions> = {\n      splitStrategy: options.splitStrategy || 'section',\n      chunkSize: options.chunkSize || 1000,\n      chunkOverlap: options.chunkOverlap || 200,\n      includePageNumbers: options.includePageNumbers !== undefined ? options.includePageNumbers : true,\n      metadata: options.metadata || {},\n    };\n    \n    // Read the PDF file\n    const dataBuffer = fs.readFileSync(filePath);\n    \n    // Load the PDF document\n    const pdfDoc = await PDFDocument.load(dataBuffer);\n    \n    // Get PDF metadata - pdf-lib uses individual getters instead of a single getMetadata method\n    const title = pdfDoc.getTitle();\n    const author = pdfDoc.getAuthor();\n    const creationDate = pdfDoc.getCreationDate();\n    \n    // Count pages\n    const numPages = pdfDoc.getPageCount();\n    \n    // Extract text content from all pages\n    let allText = '';\n    \n    // Basic text extraction\n    logger.debug(`Extracting text from PDF with ${numPages} pages`);\n    \n    try {\n      const pdfParse = await import('pdf-parse');\n      const data = await pdfParse.default(dataBuffer);\n      allText = data.text;\n      \n      logger.debug(`Successfully extracted ${allText.length} characters of text`);\n    } catch (error) {\n      logger.error(\"Error extracting text from PDF:\", error);\n      // Fallback to basic info when text extraction fails\n      allText = `PDF document with ${numPages} pages. Text extraction failed.`;\n    }\n    \n    // Create base metadata with document identification\n    const baseMetadata = {\n      source: path.basename(filePath),\n      documentId: documentId,  // Add document ID to all chunks\n      fileName: path.basename(filePath),\n      filePath: filePath,\n      ...opts.metadata,\n    };\n    \n    // PDF metadata for the result\n    const pdfMetadata = {\n      title: title || path.basename(filePath),\n      author: author,\n      numPages: numPages,\n      creationDate: creationDate ? new Date(creationDate) : undefined,\n    };\n    \n    // Get documents based on splitting strategy\n    const documents = await splitPDFContent(allText, numPages, opts, baseMetadata);\n    \n    logger.debug(`PDF parsed successfully: ${documents.length} chunks created for document ${documentId}`);\n    \n    return {\n      documents,\n      pdfMetadata,\n      documentId,\n    };\n  } catch (error) {\n    logger.error(`Error parsing PDF ${filePath}:`, error);\n    throw error;\n  }\n}\n\n/**\n * Split PDF content based on the specified strategy\n */\nasync function splitPDFContent(\n  text: string,\n  numPages: number,\n  options: Required<PDFParseOptions>,\n  baseMetadata: Record<string, any>\n): Promise<Omit<Document, 'id'>[]> {\n  const { splitStrategy } = options;\n  \n  switch (splitStrategy) {\n    case 'simple':\n      return splitBySimpleChunks(text, numPages, options, baseMetadata);\n    case 'paragraph':\n      return splitByParagraphs(text, numPages, options, baseMetadata);\n    case 'section':\n      return splitBySections(text, numPages, options, baseMetadata);\n    default:\n      logger.warn(`Unknown split strategy: ${splitStrategy}, falling back to 'section'`);\n      return splitBySections(text, numPages, options, baseMetadata);\n  }\n}\n\n/**\n * Split PDF content into simple fixed-size chunks\n */\nfunction splitBySimpleChunks(\n  text: string,\n  numPages: number,\n  options: Required<PDFParseOptions>,\n  baseMetadata: Record<string, any>\n): Omit<Document, 'id'>[] {\n  const { chunkSize, chunkOverlap } = options;\n  const chunks: Omit<Document, 'id'>[] = [];\n  \n  // Estimate content per page to track page numbers\n  const avgCharsPerPage = text.length / numPages;\n  \n  for (let i = 0; i < text.length; i += (chunkSize - chunkOverlap)) {\n    // Stop if we've reached the end of the text\n    if (i >= text.length) break;\n    \n    // Extract chunk content with overlap\n    const content = text.substring(i, i + chunkSize);\n    \n    // Skip empty chunks\n    if (!content.trim()) continue;\n    \n    // Estimate page number based on character position\n    const estimatedPage = Math.min(\n      Math.ceil((i + chunkSize / 2) / avgCharsPerPage),\n      numPages\n    );\n    \n    // Create document chunk\n    chunks.push({\n      content,\n      metadata: {\n        ...baseMetadata,\n        chunk_index: chunks.length,\n        ...(options.includePageNumbers ? { page: estimatedPage } : {}),\n      },\n    });\n  }\n  \n  return chunks;\n}\n\n/**\n * Split PDF content by paragraphs\n */\nfunction splitByParagraphs(\n  text: string,\n  numPages: number,\n  options: Required<PDFParseOptions>,\n  baseMetadata: Record<string, any>\n): Omit<Document, 'id'>[] {\n  // Split by double newlines (common paragraph separator)\n  const paragraphs = text.split(/\\n\\s*\\n/).filter(p => p.trim().length > 0);\n  const chunks: Omit<Document, 'id'>[] = [];\n  \n  // Estimate content per page to track page numbers\n  const avgCharsPerPage = text.length / numPages;\n  \n  let currentChunk = '';\n  let chunkStart = 0;\n  \n  for (const paragraph of paragraphs) {\n    // If adding this paragraph would exceed chunk size, save current chunk\n    if (currentChunk.length > 0 && \n        (currentChunk.length + paragraph.length) > options.chunkSize) {\n      \n      // Estimate page based on position in text\n      const estimatedPage = Math.min(\n        Math.ceil((chunkStart + currentChunk.length / 2) / avgCharsPerPage),\n        numPages\n      );\n      \n      chunks.push({\n        content: currentChunk,\n        metadata: {\n          ...baseMetadata,\n          chunk_index: chunks.length,\n          ...(options.includePageNumbers ? { page: estimatedPage } : {}),\n        },\n      });\n      \n      // Start a new chunk with overlap\n      const overlapPoint = Math.max(0, currentChunk.length - options.chunkOverlap);\n      currentChunk = currentChunk.substring(overlapPoint);\n      chunkStart += overlapPoint;\n    }\n    \n    // Add paragraph to current chunk\n    currentChunk += (currentChunk.length > 0 ? '\\n\\n' : '') + paragraph;\n  }\n  \n  // Add the final chunk if it's not empty\n  if (currentChunk.trim().length > 0) {\n    const estimatedPage = Math.min(\n      Math.ceil((chunkStart + currentChunk.length / 2) / avgCharsPerPage),\n      numPages\n    );\n    \n    chunks.push({\n      content: currentChunk,\n      metadata: {\n        ...baseMetadata,\n        chunk_index: chunks.length,\n        ...(options.includePageNumbers ? { page: estimatedPage } : {}),\n      },\n    });\n  }\n  \n  return chunks;\n}\n\n/**\n * Split PDF content by detected sections/headers (most intelligent option)\n * This uses heuristics to detect section headers and create coherent sections\n */\nfunction splitBySections(\n  text: string,\n  numPages: number,\n  options: Required<PDFParseOptions>,\n  baseMetadata: Record<string, any>\n): Omit<Document, 'id'>[] {\n  // First split into paragraphs\n  const paragraphs = text.split(/\\n\\s*\\n/).filter(p => p.trim().length > 0);\n  const chunks: Omit<Document, 'id'>[] = [];\n  \n  // Estimate content per page to track page numbers\n  const avgCharsPerPage = text.length / numPages;\n  let charCount = 0;\n  \n  // Heuristics for detecting headers\n  // 1. Headers are typically short (< 200 chars)\n  // 2. Often start with numbers (1., 1.1, I., A., etc.)\n  // 3. Often in ALL CAPS or Title Case\n  // 4. Usually don't end with punctuation\n  const headerRegex = /^(?:\\d+[.):]|[A-Z][.):]|[IVXLCDM]+[.):]|APPENDIX|Chapter|Section|CHAPTER|SECTION)/;\n  const allCapsRegex = /^[A-Z0-9\\s.,;:()\\-–—]+$/;\n  \n  let currentSection = '';\n  let currentTitle = '';\n  let sectionStart = 0;\n  \n  for (let i = 0; i < paragraphs.length; i++) {\n    const paragraph = paragraphs[i];\n    const isLikelyHeader = \n      (paragraph.length < 200 && headerRegex.test(paragraph)) ||\n      (paragraph.length < 150 && allCapsRegex.test(paragraph)) ||\n      (paragraph.length < 100 && !paragraph.endsWith('.') && paragraph.split(' ').length < 10);\n    \n    // If we found a header and have existing content, save the current section\n    if (isLikelyHeader && currentSection.length > 0) {\n      // Estimate page based on position\n      const estimatedPage = Math.min(\n        Math.ceil((sectionStart + currentSection.length / 2) / avgCharsPerPage),\n        numPages\n      );\n      \n      chunks.push({\n        content: currentSection,\n        metadata: {\n          ...baseMetadata,\n          section_title: currentTitle,\n          chunk_index: chunks.length,\n          ...(options.includePageNumbers ? { page: estimatedPage } : {}),\n        },\n      });\n      \n      // Reset for new section\n      sectionStart = charCount;\n      currentSection = '';\n    }\n    \n    // If it's a header, set as current title, otherwise add to current section\n    if (isLikelyHeader) {\n      currentTitle = paragraph.trim();\n      // Add header to section content as well\n      currentSection = paragraph;\n    } else {\n      // Add paragraph to current section\n      currentSection += (currentSection.length > 0 ? '\\n\\n' : '') + paragraph;\n    }\n    \n    charCount += paragraph.length + 2; // +2 for newlines\n    \n    // If current section exceeds max chunk size, break it up\n    if (currentSection.length > options.chunkSize * 1.5) {\n      // Recursively chunk this large section using the paragraph method\n      const subChunks = splitByParagraphs(\n        currentSection,\n        numPages,\n        options,\n        {\n          ...baseMetadata,\n          section_title: currentTitle,\n        }\n      );\n      \n      // Add all sub-chunks to our output\n      chunks.push(...subChunks);\n      \n      // Reset current section\n      sectionStart = charCount;\n      currentSection = '';\n    }\n  }\n  \n  // Add the final section if not empty\n  if (currentSection.trim().length > 0) {\n    const estimatedPage = Math.min(\n      Math.ceil((sectionStart + currentSection.length / 2) / avgCharsPerPage),\n      numPages\n    );\n    \n    chunks.push({\n      content: currentSection,\n      metadata: {\n        ...baseMetadata,\n        section_title: currentTitle,\n        chunk_index: chunks.length,\n        ...(options.includePageNumbers ? { page: estimatedPage } : {}),\n      },\n    });\n  }\n  \n  return chunks;\n}\n\n/**\n * Parse a directory of PDFs and load into RAG system\n * @param dirPath Directory path containing PDFs\n * @param options Parse options\n * @returns Array of results for each processed PDF\n */\nexport async function parseDirectoryOfPDFs(\n  dirPath: string,\n  options: PDFParseOptions\n): Promise<Record<string, PDFParseResult>> {\n  try {\n    logger.debug(`Processing directory of PDFs: ${dirPath}`);\n    \n    // Read directory contents\n    const files = fs.readdirSync(dirPath);\n    \n    // Filter for PDF files\n    const pdfFiles = files.filter(file => file.toLowerCase().endsWith('.pdf'));\n    \n    // Process each PDF\n    const results: Record<string, PDFParseResult> = {};\n    \n    for (const pdfFile of pdfFiles) {\n      const filePath = path.join(dirPath, pdfFile);\n      try {\n        results[pdfFile] = await parsePDF(filePath, options);\n        logger.debug(`Successfully processed ${pdfFile}`);\n      } catch (error) {\n        logger.error(`Error processing ${pdfFile}:`, error);\n        // Continue with other files even if one fails\n      }\n    }\n    \n    return results;\n  } catch (error) {\n    logger.error(`Error processing PDF directory ${dirPath}:`, error);\n    throw error;\n  }\n} ","import { createVectorRAG } from \"./vector\";\nimport { createDocumentRAG } from \"./document\";\nimport { parsePDF, parseDirectoryOfPDFs } from \"./pdf-parser\";\nimport { RAGType, RAGFactoryConfig, RAGFactory, VectorRAGConfig, DocumentRAGConfig } from \"../types/rag\";\n\n/**\n * Unified factory function to create a RAG instance of the specified type\n * @param config Configuration with type to determine which RAG implementation to create\n * @returns Promise resolving to the appropriate RAG instance\n */\nexport const createRAG: RAGFactory = async (config: RAGFactoryConfig) => {\n  const { type, ...baseConfig } = config;\n  \n  // Declare configs outside of switch statement to avoid lexical declaration errors\n  let vectorConfig: VectorRAGConfig;\n  let documentConfig: DocumentRAGConfig;\n  \n  switch (type) {\n    case RAGType.VECTOR:\n      // Create vector RAG config from the base config\n      vectorConfig = {\n        ...baseConfig,\n        chunkSize: config.chunkSize,\n        chunkOverlap: config.chunkOverlap\n      };\n      return createVectorRAG(vectorConfig);\n      \n    case RAGType.DOCUMENT:\n      // Create document RAG config from the base config\n      documentConfig = {\n        ...baseConfig,\n        storeEmbeddings: config.storeEmbeddings\n      };\n      return createDocumentRAG(documentConfig);\n      \n    default:\n      throw new Error(`Unknown RAG type: ${type}`);\n  }\n};\n\n// Re-export PDF processing utilities\nexport { parsePDF, parseDirectoryOfPDFs };\n\n// Re-export types\nexport * from \"../types/rag\"; ","import { \n  ChatConfig, \n  ChatInstance, \n  ChatMetadata, \n  ChatSummary, \n  ChatMessage \n} from \"./types/chat\";\nimport { MemoryEntry, ProviderMessage, StructuredCompletionResponse, TaskConfig, TaskResult, ProviderModel } from \"./types\";\nimport { logger } from \"./utils/logger\";\nimport { validateRequiredParam } from \"./utils/validation\";\nimport { Embedding } from \"./providers\";\nimport { \n  DEFAULT_TEMPERATURE, \n  DEFAULT_MAX_TOKENS\n} from \"./constants\";\n\n/**\n * Chat management system that works with existing memory system\n * Chat IDs are the same as session IDs for backward compatibility\n * Can be used standalone or integrated with Agent instances\n */\nexport class ChatManager implements ChatInstance {\n  public config: ChatConfig;\n  private tableName: string;\n  private maxChats: number;\n  private autoGenerateTitles: boolean;\n\n  constructor(config: ChatConfig) {\n    validateRequiredParam(config, \"config\", \"ChatManager constructor\");\n    validateRequiredParam(config.database, \"config.database\", \"ChatManager constructor\");\n    validateRequiredParam(config.memory, \"config.memory\", \"ChatManager constructor\");\n\n    this.config = config;\n    // Use user-provided table name or default\n    this.tableName = config.tableName || \"chats\";\n    this.maxChats = config.maxChats || 50;\n    this.autoGenerateTitles = config.autoGenerateTitles !== false;\n  }\n\n\n\n  async createChat(params: {\n    chatId?: string;\n    userId?: string;\n    agentId: string;\n    title?: string;\n    metadata?: Record<string, unknown>;\n  }): Promise<ChatMetadata> {\n    validateRequiredParam(params.agentId, \"params.agentId\", \"createChat\");\n    \n    const chatId = params.chatId || generateChatId();\n    const now = new Date();\n\n    // Check if chat already exists\n    const existingChat = await this.getChat(chatId);\n    if (existingChat) {\n      return existingChat;\n    }\n\n    const chatMetadata: ChatMetadata = {\n      id: chatId,\n      title: params.title,\n      userId: params.userId,\n      agentId: params.agentId,\n      status: 'active',\n      createdAt: now,\n      updatedAt: now,\n      messageCount: 0,\n      metadata: params.metadata\n    };\n\n    // Insert chat metadata\n    await this.config.database.knex(this.tableName).insert({\n      id: chatId,\n      title: params.title,\n      userId: params.userId,\n      agentId: params.agentId,\n      status: 'active',\n      createdAt: now,\n      updatedAt: now,\n      lastMessageAt: null,\n      messageCount: 0,\n      lastMessage: null,\n      metadata: params.metadata ? JSON.stringify(params.metadata) : null\n    });\n\n    logger.info(`Chat created: ${chatId}`);\n    return chatMetadata;\n  }\n\n  async createChatWithMessage(params: {\n    chatId?: string;\n    userId?: string;\n    agentId: string;\n    title?: string;\n    metadata?: Record<string, unknown>;\n    // Chat functionality parameters\n    message: string;\n    model: any; // ProviderModel\n    systemPrompt?: string;\n    tools?: any[]; // Plugin[]\n    taskManager?: any; // TaskManagerInstance\n    embedding?: number[];\n    useTaskSystem?: boolean;\n    temperature?: number;\n    maxTokens?: number;\n  }): Promise<string> {\n    validateRequiredParam(params.agentId, \"params.agentId\", \"createChatWithMessage\");\n    validateRequiredParam(params.message, \"params.message\", \"createChatWithMessage\");\n    validateRequiredParam(params.model, \"params.model\", \"createChatWithMessage\");\n    \n    const chatId = params.chatId || generateChatId();\n\n    // Check if chat exists, if not create it\n    const existingChat = await this.getChat(chatId);\n    if (!existingChat) {\n      await this.createChat({\n        chatId,\n        agentId: params.agentId,\n        userId: params.userId,\n        title: params.title,\n        metadata: params.metadata\n      });\n      logger.info(`Created new chat: ${chatId} for agent: ${params.agentId}`);\n    }\n\n    // Process the message\n    return await this.processMessage({\n      chatId,\n      agentId: params.agentId,\n      userId: params.userId,\n      message: params.message,\n      model: params.model,\n      systemPrompt: params.systemPrompt,\n      tools: params.tools || [],\n      taskManager: params.taskManager,\n      metadata: params.metadata || {},\n      embedding: params.embedding,\n      useTaskSystem: params.useTaskSystem !== false,\n      temperature: params.temperature || DEFAULT_TEMPERATURE,\n      maxTokens: params.maxTokens || DEFAULT_MAX_TOKENS\n    });\n  }\n\n  private async processMessage(params: {\n    chatId: string;\n    agentId: string;\n    userId?: string;\n    message: string;\n    model: any;\n    systemPrompt?: string;\n    tools: any[];\n    taskManager?: any;\n    metadata: Record<string, unknown>;\n    embedding?: number[];\n    useTaskSystem: boolean;\n    temperature: number;\n    maxTokens: number;\n  }): Promise<string> {\n    const {\n      chatId,\n      agentId,\n      userId,\n      message,\n      model,\n      systemPrompt,\n      tools,\n      taskManager,\n      metadata,\n      embedding,\n      useTaskSystem,\n      temperature,\n      maxTokens\n    } = params;\n\n    // Get conversation history from chat system\n    const history = await this.getMessages(chatId);\n\n    // Add user message to chat\n    await this.addMessage({\n      chatId,\n      agentId,\n      userId,\n      role: \"user\",\n      content: message,\n      metadata: {\n        ...metadata,\n        timestamp: new Date().toISOString(),\n        useTaskSystem,\n        conversationLength: history.length\n      }\n    });\n\n    // Prepare messages for model\n    const messages: ProviderMessage[] = [];\n\n    // Add system prompt\n    if (systemPrompt) {\n      messages.push({\n        role: \"system\",\n        content: systemPrompt,\n      });\n    }\n\n    // Add conversation history\n    history.forEach((entry: MemoryEntry) => {\n      messages.push({\n        role: entry.role as \"system\" | \"user\" | \"assistant\",\n        content: entry.content,\n      });\n    });\n\n    // Add the new user message\n    messages.push({\n      role: \"user\",\n      content: message,\n    });\n\n    // Get available tools\n    const availableTools = tools.map((tool) => ({\n      name: tool.name,\n      description: tool.description,\n      parameters: tool.parameters,\n    }));\n\n    // If tools are available, add them to the system message\n    if (availableTools.length > 0 && systemPrompt) {\n      const systemMessage = messages.find((msg) => msg.role === \"system\");\n      if (systemMessage) {\n        systemMessage.content += `\\n\\nYou have access to the following tools:\\n${JSON.stringify(\n          availableTools,\n          null,\n          2\n        )}`;\n      }\n    }\n\n    let response: string | StructuredCompletionResponse;\n\n    // Determine if we should use task-based approach\n    if (useTaskSystem && tools.length > 0 && taskManager) {\n      // First, analyze the message to determine if it requires tasks\n      const analysisResponse = await model.complete([\n        ...messages,\n        {\n          role: \"system\",\n          content: `You are a task planning assistant. Analyze the user's request and determine if it should be broken down into tasks. \nIf tasks are needed, format your response as a JSON array with this structure:\n[\n  {\n    \"name\": \"Task name\",\n    \"description\": \"Detailed description of the task\",\n    \"input\": {Any input data for the task}\n  }\n]\nThe system will automatically determine which tools and plugins to use based on the task name and description.\nIf no tasks are needed, respond with \"NO_TASKS_NEEDED\".`,\n        },\n      ]);\n\n      // Check if the analysis identified tasks\n      const responseText = typeof analysisResponse === 'string' ? analysisResponse : analysisResponse.content;\n      \n      if (responseText.includes(\"[\") && responseText.includes(\"]\")) {\n        try {\n          // Extract JSON array from the response\n          const jsonString = responseText.substring(\n            responseText.indexOf(\"[\"),\n            responseText.lastIndexOf(\"]\") + 1\n          );\n\n          // Parse the tasks\n          const taskConfigs: TaskConfig[] = JSON.parse(jsonString);\n\n          // Set session ID in task manager\n          if (taskManager.setSessionId) {\n            taskManager.setSessionId(chatId);\n          }\n\n          // Create and execute tasks\n          for (const taskConfig of taskConfigs) {\n            taskManager.addExistingTask(taskConfig, model);\n          }\n\n          const taskResults = await taskManager.run();\n\n          // Generate response based on task results\n          const resultSummary: any[] = [];\n          for (const [taskId, result] of taskResults.entries()) {\n            resultSummary.push({\n              taskId,\n              success: result.success,\n              output: result.output,\n              error: result.error ? result.error.message : undefined,\n            });\n          }\n\n          const taskResponse = await model.complete([\n            ...messages,\n            {\n              role: \"system\",\n              content: `You are assisting with a task-based workflow. Multiple tasks were executed based on the user's request. \nHere are the results of those tasks:\n${JSON.stringify(resultSummary, null, 2)}\n\nAnalyze these results and generate a helpful, coherent response to the user that summarizes what was done and the outcome. \nDo not mention that tasks were executed behind the scenes - just provide the information the user needs in a natural way.`,\n            },\n          ]);\n\n          response = typeof taskResponse === 'string' ? taskResponse : taskResponse.content;\n        } catch (error) {\n          logger.error(\"Error processing tasks:\", error);\n          // Fallback to standard completion if task processing fails\n          response = await model.complete(messages);\n        }\n      } else {\n        // No tasks needed, just complete the response normally\n        response = await model.complete(messages);\n      }\n    } else {\n      // Regular chat completion\n      response = await model.complete(messages, {\n        tools: availableTools.length > 0 ? availableTools : undefined,\n        toolCalling: availableTools.length > 0,\n        temperature,\n        maxTokens\n      });\n    }\n\n    // Handle tool execution if the response contains tool calls\n    if (typeof response === 'object' && response.tool_calls && Array.isArray(response.tool_calls)) {\n      logger.debug(`Chat ${chatId} received ${response.tool_calls.length} tool calls to execute`);\n      \n      const toolResults = [];\n      for (const toolCall of response.tool_calls) {\n        try {\n          if (toolCall.type === 'function' && toolCall.name) {\n            logger.debug(`Executing tool: ${toolCall.name} with arguments:`, toolCall.arguments);\n            \n            // Find the tool to execute\n            const tool = tools.find(t => t.name === toolCall.name);\n            if (tool && tool.execute) {\n              // Execute the tool\n              const result = await tool.execute(toolCall.arguments || {});\n              \n              toolResults.push({\n                name: toolCall.name,\n                arguments: toolCall.arguments,\n                result: result,\n                success: true\n              });\n              \n              logger.debug(`Tool ${toolCall.name} executed successfully`);\n            } else {\n              logger.warn(`Tool ${toolCall.name} not found or not executable`);\n              toolResults.push({\n                name: toolCall.name,\n                arguments: toolCall.arguments,\n                error: `Tool ${toolCall.name} not found or not executable`,\n                success: false\n              });\n            }\n          }\n        } catch (error) {\n          logger.error(`Error executing tool ${toolCall.name}:`, error);\n          toolResults.push({\n            name: toolCall.name,\n            arguments: toolCall.arguments,\n            error: error instanceof Error ? error.message : String(error),\n            success: false\n          });\n        }\n      }\n      \n      // Generate a final response based on tool results\n      if (toolResults.length > 0) {\n        try {\n          logger.debug(`Generating final response based on ${toolResults.length} tool results`);\n          \n          const toolResultsMessage = {\n            role: \"system\" as const,\n            content: `You called the following tools and got these results:\n${toolResults.map(tr => `Tool: ${tr.name}\nArguments: ${JSON.stringify(tr.arguments)}\nResult: ${tr.success ? JSON.stringify(tr.result) : 'ERROR: ' + tr.error}`).join('\\n\\n')}\n\nBased on these tool results, generate a helpful response to the user. Be natural and conversational - don't mention the technical details of the tool calls.`\n          };\n          \n          // Call the model again with the tool results to generate the final response\n          const finalResponse = await model.complete([\n            ...messages,\n            toolResultsMessage\n          ]);\n          \n          // Update response to the final result\n          response = typeof finalResponse === 'string' ? finalResponse : finalResponse.content;\n          \n          const responseText = typeof response === 'string' ? response : response.content;\n          logger.debug(`Generated final response after tool execution: ${responseText.length} characters`);\n        } catch (error) {\n          logger.error('Error generating final response from tool results:', error);\n          // Fallback to original content plus tool results summary\n          const originalContent = typeof response === 'string' ? response : response.content;\n          response = `${originalContent}\\n\\nTool execution completed with ${toolResults.filter(r => r.success).length} successful results.`;\n        }\n      }\n    }\n\n    // Generate embedding for assistant response if needed\n    let assistantEmbedding: number[] | undefined = undefined;\n    const enableEmbeddings = this.config.memory.config?.enableEmbeddings;\n\n    if (enableEmbeddings && embedding) {\n      try {\n        // Convert response to string for embedding generation\n        const responseText = typeof response === 'string' ? response : response.content;\n        assistantEmbedding = await Embedding.generateEmbedding(responseText);\n      } catch (error) {\n        logger.warn(\n          \"Error generating embedding for assistant response:\",\n          error\n        );\n      }\n    }\n\n    // Add assistant response to chat\n    await this.addMessage({\n      chatId,\n      agentId,\n      userId,\n      role: \"assistant\",\n      content: typeof response === 'string' ? response : response.content,\n      metadata: {\n        ...metadata,\n        timestamp: new Date().toISOString(),\n        modelUsed: model.name,\n        taskSystemUsed: useTaskSystem,\n        temperature,\n        responseLength: (typeof response === 'string' ? response : response.content).length\n      }\n    });\n\n    // Return the response (convert to string if it's a structured response)\n    return typeof response === 'string' ? response : response.content;\n  }\n\n  async getChat(chatId: string): Promise<ChatMetadata | null> {\n    validateRequiredParam(chatId, \"chatId\", \"getChat\");\n\n    const result = await this.config.database.knex(this.tableName)\n      .where({ id: chatId })\n      .first();\n\n    if (!result) return null;\n\n    return {\n      id: result.id,\n      title: result.title,\n      userId: result.userId,\n      agentId: result.agentId,\n      status: result.status,\n      createdAt: new Date(result.createdAt),\n      updatedAt: new Date(result.updatedAt),\n      lastMessageAt: result.lastMessageAt ? new Date(result.lastMessageAt) : undefined,\n      messageCount: result.messageCount,\n      metadata: result.metadata ? JSON.parse(result.metadata) : undefined\n    };\n  }\n\n  async updateChat(chatId: string, updates: Partial<ChatMetadata>): Promise<void> {\n    validateRequiredParam(chatId, \"chatId\", \"updateChat\");\n\n    const updateData: any = {\n      updatedAt: new Date()\n    };\n\n    if (updates.title !== undefined) updateData.title = updates.title;\n    if (updates.status !== undefined) updateData.status = updates.status;\n    if (updates.metadata !== undefined) {\n      updateData.metadata = updates.metadata ? JSON.stringify(updates.metadata) : null;\n    }\n\n    await this.config.database.knex(this.tableName)\n      .where({ id: chatId })\n      .update(updateData);\n\n    logger.info(`Chat updated: ${chatId}`);\n  }\n\n  async deleteChat(chatId: string): Promise<void> {\n    validateRequiredParam(chatId, \"chatId\", \"deleteChat\");\n\n    // Delete chat metadata\n    await this.config.database.knex(this.tableName)\n      .where({ id: chatId })\n      .del();\n\n    // Clear messages from memory\n    await this.config.memory.clear(chatId);\n\n    logger.info(`Chat deleted: ${chatId}`);\n  }\n\n  async archiveChat(chatId: string): Promise<void> {\n    await this.updateChat(chatId, { status: 'archived' });\n    logger.info(`Chat archived: ${chatId}`);\n  }\n\n  async listChats(params: {\n    userId?: string;\n    agentId?: string;\n    status?: 'active' | 'archived' | 'deleted';\n    limit?: number;\n    offset?: number;\n  } = {}): Promise<ChatSummary[]> {\n    let query = this.config.database.knex(this.tableName)\n      .select('*')\n      .orderBy('updatedAt', 'desc');\n\n    if (params.userId) {\n      query = query.where({ userId: params.userId });\n    }\n\n    if (params.agentId) {\n      query = query.where({ agentId: params.agentId });\n    }\n\n    if (params.status) {\n      query = query.where({ status: params.status });\n    }\n\n    const limit = params.limit || this.maxChats;\n    const offset = params.offset || 0;\n\n    query = query.limit(limit).offset(offset);\n\n    const results = await query;\n\n    return results.map(row => ({\n      id: row.id,\n      title: row.title,\n      userId: row.userId,\n      agentId: row.agentId,\n      status: row.status,\n      lastMessage: row.lastMessage,\n      lastMessageAt: row.lastMessageAt ? new Date(row.lastMessageAt) : undefined,\n      messageCount: row.messageCount,\n      createdAt: new Date(row.createdAt),\n      updatedAt: new Date(row.updatedAt)\n    }));\n  }\n\n  async searchChats(params: {\n    query: string;\n    userId?: string;\n    agentId?: string;\n    limit?: number;\n  }): Promise<ChatSummary[]> {\n    validateRequiredParam(params.query, \"params.query\", \"searchChats\");\n\n    let query = this.config.database.knex(this.tableName)\n      .select('*')\n      .where('title', 'like', `%${params.query}%`)\n      .orWhere('lastMessage', 'like', `%${params.query}%`)\n      .orderBy('updatedAt', 'desc');\n\n    if (params.userId) {\n      query = query.andWhere({ userId: params.userId });\n    }\n\n    if (params.agentId) {\n      query = query.andWhere({ agentId: params.agentId });\n    }\n\n    const limit = params.limit || this.maxChats;\n    query = query.limit(limit);\n\n    const results = await query;\n\n    return results.map(row => ({\n      id: row.id,\n      title: row.title,\n      userId: row.userId,\n      agentId: row.agentId,\n      status: row.status,\n      lastMessage: row.lastMessage,\n      lastMessageAt: row.lastMessageAt ? new Date(row.lastMessageAt) : undefined,\n      messageCount: row.messageCount,\n      createdAt: new Date(row.createdAt),\n      updatedAt: new Date(row.updatedAt)\n    }));\n  }\n\n  async addMessage(params: {\n    chatId: string;\n    agentId: string;\n    userId?: string;\n    role: \"system\" | \"user\" | \"assistant\" | \"task_context\" | \"task_event\" | \"task_tool\" | \"task_result\";\n    content: string;\n    metadata?: Record<string, unknown>;\n  }): Promise<string> {\n    validateRequiredParam(params.chatId, \"params.chatId\", \"addMessage\");\n    validateRequiredParam(params.agentId, \"params.agentId\", \"addMessage\");\n    validateRequiredParam(params.role, \"params.role\", \"addMessage\");\n    validateRequiredParam(params.content, \"params.content\", \"addMessage\");\n\n    // Add message to memory (using sessionId = chatId)\n    const messageId = await this.config.memory.add({\n      agentId: params.agentId,\n      sessionId: params.chatId, // sessionId = chatId for compatibility\n      userId: params.userId,\n      role: params.role,\n      content: params.content,\n      metadata: params.metadata\n    });\n\n    // Update chat metadata\n    const now = new Date();\n    await this.config.database.knex(this.tableName)\n      .where({ id: params.chatId })\n      .update({\n        lastMessageAt: now,\n        updatedAt: now,\n        lastMessage: params.content.substring(0, 200), // Store first 200 chars\n        messageCount: this.config.database.knex.raw('messageCount + 1')\n      });\n\n    // Auto-generate title if this is the first user message and no title exists\n    if (this.autoGenerateTitles && params.role === 'user') {\n      const chat = await this.getChat(params.chatId);\n      if (chat && !chat.title && chat.messageCount <= 1) {\n        const title = generateTitleFromMessage(params.content);\n        await this.updateChat(params.chatId, { title });\n      }\n    }\n\n    return messageId;\n  }\n\n  async getMessages(chatId: string, limit?: number): Promise<ChatMessage[]> {\n    validateRequiredParam(chatId, \"chatId\", \"getMessages\");\n\n    // Get messages from memory using sessionId = chatId\n    const messages = await this.config.memory.getBySession(chatId, limit);\n    \n    // Convert to ChatMessage format\n    return messages.map(msg => ({\n      ...msg,\n      chatId: msg.sessionId // Add chatId for compatibility\n    }));\n  }\n\n  async deleteMessage(messageId: string): Promise<void> {\n    validateRequiredParam(messageId, \"messageId\", \"deleteMessage\");\n    await this.config.memory.delete(messageId);\n  }\n\n  async clearMessages(chatId: string): Promise<void> {\n    validateRequiredParam(chatId, \"chatId\", \"clearMessages\");\n    \n    // Clear messages from memory\n    await this.config.memory.clear(chatId);\n    \n    // Reset message count in chat metadata\n    await this.config.database.knex(this.tableName)\n      .where({ id: chatId })\n      .update({\n        messageCount: 0,\n        lastMessage: null,\n        lastMessageAt: null,\n        updatedAt: new Date()\n      });\n  }\n\n  async getChatStats(params: {\n    userId?: string;\n    agentId?: string;\n  } = {}): Promise<{\n    totalChats: number;\n    activeChats: number;\n    archivedChats: number;\n    totalMessages: number;\n  }> {\n    let query = this.config.database.knex(this.tableName);\n\n    if (params.userId) {\n      query = query.where({ userId: params.userId });\n    }\n\n    if (params.agentId) {\n      query = query.where({ agentId: params.agentId });\n    }\n\n    const stats = await query\n      .select(\n        this.config.database.knex.raw('COUNT(*) as totalChats'),\n        this.config.database.knex.raw('SUM(CASE WHEN status = ? THEN 1 ELSE 0 END) as activeChats', ['active']),\n        this.config.database.knex.raw('SUM(CASE WHEN status = ? THEN 1 ELSE 0 END) as archivedChats', ['archived']),\n        this.config.database.knex.raw('SUM(messageCount) as totalMessages')\n      )\n      .first();\n\n    return {\n      totalChats: parseInt(stats.totalChats) || 0,\n      activeChats: parseInt(stats.activeChats) || 0,\n      archivedChats: parseInt(stats.archivedChats) || 0,\n      totalMessages: parseInt(stats.totalMessages) || 0\n    };\n  }\n\n  async chat(params: {\n    message: string;\n    chatId: string;\n    agentId: string;\n    userId?: string;\n    model: any; // ProviderModel\n    systemPrompt?: string;\n    tools?: any[]; // Plugin[]\n    taskManager?: any; // TaskManagerInstance\n    chatTitle?: string;\n    metadata?: Record<string, unknown>;\n    embedding?: number[];\n    useTaskSystem?: boolean;\n    temperature?: number;\n    maxTokens?: number;\n  }): Promise<string> {\n    validateRequiredParam(params.message, \"params.message\", \"chat\");\n    validateRequiredParam(params.chatId, \"params.chatId\", \"chat\");\n    validateRequiredParam(params.agentId, \"params.agentId\", \"chat\");\n    validateRequiredParam(params.model, \"params.model\", \"chat\");\n\n    const {\n      message,\n      chatId,\n      agentId,\n      userId,\n      model,\n      systemPrompt,\n      tools = [],\n      taskManager,\n      chatTitle,\n      metadata = {},\n      embedding,\n      useTaskSystem = true,\n      temperature = DEFAULT_TEMPERATURE,\n      maxTokens = DEFAULT_MAX_TOKENS\n    } = params;\n\n    // Use createChatWithMessage which handles both creation and message processing\n    return await this.createChatWithMessage({\n      chatId,\n      agentId,\n      userId,\n      title: chatTitle,\n      metadata,\n      message,\n      model,\n      systemPrompt,\n      tools,\n      taskManager,\n      embedding,\n      useTaskSystem,\n      temperature,\n      maxTokens\n    });\n  }\n}\n\n/**\n * Creates a chat management system that works with existing memory system\n * Chat IDs are the same as session IDs for backward compatibility\n * Can be used standalone or integrated with Agent instances\n */\nexport async function createChat(config: ChatConfig): Promise<ChatInstance> {\n  const chatManager = new ChatManager(config);\n  \n  // Ensure chats table exists using user's custom table name\n  const tableName = config.tableName || \"chats\";\n  await config.database.ensureTable(tableName, (table: any) => {\n    table.string('id').primary();\n    table.string('title').nullable();\n    table.string('userId').nullable();\n    table.string('agentId').notNullable();\n    table.string('status').defaultTo('active');\n    table.timestamp('createdAt').defaultTo(config.database.knex.fn.now());\n    table.timestamp('updatedAt').defaultTo(config.database.knex.fn.now());\n    table.timestamp('lastMessageAt').nullable();\n    table.integer('messageCount').defaultTo(0);\n    table.string('lastMessage').nullable();\n    table.text('metadata').nullable();\n    \n    // Add indexes for better performance\n    table.index(['userId', 'status', 'updatedAt'], 'chats_userid_status_updated_idx');\n    table.index(['agentId', 'status', 'updatedAt'], 'chats_agentid_status_updated_idx');\n    table.index(['status', 'updatedAt'], 'chats_status_updated_idx');\n  });\n  \n  logger.info(`Chat manager initialized with custom table: ${tableName}`);\n  return chatManager;\n}\n\n// Helper function to generate unique chat ID\nfunction generateChatId(): string {\n  return `chat-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n}\n\n// Helper function to generate title from first message\nfunction generateTitleFromMessage(content: string): string {\n  // Take first 50 characters and clean up\n  let title = content.substring(0, 50).trim();\n  \n  // Remove line breaks and extra spaces\n  title = title.replace(/\\s+/g, ' ');\n  \n  // Add ellipsis if truncated\n  if (content.length > 50) {\n    title += '...';\n  }\n  \n  return title || 'New Chat';\n} ","import { v4 as uuidv4 } from \"uuid\";\nimport {\n  TaskConfig,\n  TaskInstance,\n  TaskStatus,\n  TaskResult,\n} from \"../types/task\";\nimport { Plugin } from \"../types/plugin\";\nimport { PluginManager } from \"../plugin\";\nimport { createDatabase, DatabaseInstance } from \"../database\";\nimport { MemoryInstance, MemoryEntry, ProviderModel, ProviderMessage, CompletionOptions } from \"../types\";\nimport { logger } from \"../utils\";\nimport { IntentRecognizer } from \"../utils/intent\";\n\n/**\n * Task class implementing the TaskInstance interface\n */\nexport class Task implements TaskInstance {\n  public id: string;\n  public config: TaskConfig;\n  public status: TaskStatus;\n  public result?: TaskResult;\n  public retries: number;\n  public plugins: Plugin[];\n  public createdAt: Date;\n  public startedAt?: Date;\n  public completedAt?: Date;\n  public agentId?: string;\n  public sessionId?: string;\n  public contextId?: string;\n  public memory?: MemoryInstance;\n  public database?: DatabaseInstance;\n\n  public isCancelled: boolean = false;\n  \n  // Add a tracking variable to prevent duplicate logging\n  private toolSelectionLogged: boolean = false;\n\n  constructor(config: TaskConfig, memory?: MemoryInstance, model?: ProviderModel, database?: DatabaseInstance) {\n    this.id = config.id || uuidv4();\n    this.config = {\n      ...config,\n      model: config.model || model // Use config.model if provided, otherwise use the model parameter\n    };\n    this.status = \"pending\";\n    this.retries = 0;\n    this.plugins = [];\n    this.createdAt = new Date();\n    this.agentId = config.agentId;\n    this.sessionId = config.sessionId;\n    this.memory = memory;\n    this.database = database;\n\n    // Set context ID based on session ID\n    if (this.sessionId) {\n      this.contextId = this.sessionId;\n    }\n\n    // Load the plugins required for this task (but don't wait in constructor)\n    this.loadPlugins(this.config.model).catch(error => {\n      logger.error(`Error loading plugins for task ${this.id}:`, error);\n    });\n\n\n  }\n\n  /**\n   * Initialize plugins for the task\n   * This tries three methods in order:\n   * 1. Use LLM-selected tools if model is provided\n   * 2. Use keyword matching based on task name\n   * 3. Fall back to all agent plugins\n   */\n  public async loadPlugins(model?: ProviderModel): Promise<void> {\n    // Get all available tools\n    const allTools = PluginManager.getAll();\n    \n    // Method 1: Get plugins from config first (explicitly provided in task config)\n    if (this.config.plugins && this.config.plugins.length > 0) {\n      const configPlugins = this.config.plugins\n        .map(pluginName => {\n          // Check if it's a tool instance already\n          if (typeof pluginName === 'object' && 'name' in pluginName) {\n            return pluginName as Plugin;\n          }\n          // Otherwise look it up by name\n          return PluginManager.get(pluginName as string);\n        })\n        .filter(Boolean) as Plugin[];\n      \n      if (configPlugins.length > 0) {\n        if (!this.toolSelectionLogged) {\n          logger.task(this.id, `Using ${configPlugins.length} plugins from task config`, this.config.name);\n          this.toolSelectionLogged = true;\n        }\n        this.plugins = configPlugins;\n        return; \n      }\n    }\n    \n    // Method 2: Use LLM to select appropriate tools if model is provided\n    if (model) {\n      try {\n        logger.task(this.id, \"Using LLM to select tools for task\", this.config.name);\n        \n        // Request tools with IntentRecognizer\n        const selectedTools = await IntentRecognizer.recognizeIntent(\n          this.config.name,\n          this.config.description || this.config.name,\n          allTools,\n          model\n        );\n        \n        if (selectedTools.length > 0) {\n          if (!this.toolSelectionLogged) {\n            logger.task(this.id, 'LLM selected these tools for the task', selectedTools.map(t => t.name).join(', '));\n            this.toolSelectionLogged = true;\n          }\n          this.plugins = selectedTools;\n          // Save plugins to config to avoid duplicate selection\n          this.config.plugins = selectedTools.map(t => t.name);\n          return;\n        } else {\n          logger.warn(`LLM did not select any tools for task \"${this.config.name}\", falling back to default`);\n        }\n      } catch (error) {\n        logger.error(`Error using LLM for tool selection: ${error}`);\n        // Fall back to default method\n      }\n    }\n    \n    logger.warn(`No plugins selected for task \"${this.config.name}\"`);\n  }\n\n\n\n  /**\n   * Execute the task using configured plugins\n   */\n  async execute(input?: any): Promise<TaskResult> {\n    // Database operations are handled in createTask static method\n\n    // Add debug logging - Task execution start\n    logger.debug(`Task ${this.id} (${this.config.name}) execution started with input:`, \n      JSON.stringify(input || this.config.input));\n      \n    // Record task execution start in memory\n    await this.addTaskMemoryEntry(`Task execution started: ${this.config.name}`, \"task_event\");\n\n    // Use provided input or fallback to config input\n    const taskInput: Record<string, unknown> = input || this.config.input;\n\n    try {\n      // Make sure plugins are loaded before starting the task\n      if (!this.plugins || this.plugins.length === 0) {\n        await this.loadPlugins(this.config.model);\n      }\n      \n      // Skip execution if task is cancelled\n      if (this.isCancelled) {\n        throw new Error(\"Task was cancelled\");\n      }\n\n      // Update status only after plugins are loaded\n      this.status = \"running\";\n      this.startedAt = new Date();\n\n      // Get task context from previous tasks in the same session\n      let taskContext = {};\n      if (this.sessionId) {\n        taskContext = await this.getTaskContext(this.sessionId);\n      }\n\n      // Merge task input with the accumulated context\n      const enrichedInput: Record<string, unknown> = {\n        ...taskInput,\n        _context: taskContext,\n      };\n      \n      // Log the enriched input at debug level\n      logger.debug(`Task ${this.id} enriched input:`, JSON.stringify(enrichedInput));\n\n      // Execute plugins with the input\n      let currentOutput: Record<string, unknown> = enrichedInput;\n      \n      // Ensure plugins array is valid before proceeding\n      if (!this.plugins || !Array.isArray(this.plugins)) {\n        this.plugins = [];\n      }\n      \n      logger.debug(`Task ${this.id} has ${this.plugins.length} plugins to execute`);\n      \n      // Record available plugins in memory\n      if (this.plugins.length > 0) {\n        await this.addTaskMemoryEntry(\n          `Available plugins: ${this.plugins.map(p => p.name).join(\", \")}`, \n          \"task_event\"\n        );\n      }\n\n      // Use the plugins as they are\n      let prioritizedPlugins = [...this.plugins];\n\n      // Check if we have plugins to execute\n      if (prioritizedPlugins.length === 0) {\n        logger.warn(`Task ${this.id} has no plugins to execute, the task may not complete as expected`);\n      }\n\n      // Use model to execute the task with the plugins if available\n      const model = this.config.model;\n      if (model && prioritizedPlugins.length > 0) {\n        logger.debug(`Task ${this.id} using model ${model.name} to execute with plugins`);\n        \n        // Record model usage in memory\n        await this.addTaskMemoryEntry(\n          `Using model ${model.name} to execute task with plugins`, \n          \"task_event\"\n        );\n        \n        // Format tools for the model - convert Astreus tool format to provider tool format\n        const formattedTools = prioritizedPlugins.map(tool => {\n          // Convert parameters to proper format for provider\n          let formattedParameters = {};\n          \n          if (tool.parameters && Array.isArray(tool.parameters)) {\n            // Convert array of parameter objects to JSON Schema properties\n            const properties: Record<string, any> = {};\n            const required: string[] = [];\n            \n            tool.parameters.forEach(param => {\n              if (param.name && param.type) {\n                properties[param.name] = {\n                  type: param.type,\n                  description: param.description || `Parameter ${param.name}`\n                };\n                \n                if (param.required) {\n                  required.push(param.name);\n                }\n              }\n            });\n            \n            // Create proper JSON Schema\n            formattedParameters = {\n              type: \"object\",\n              properties: properties\n            };\n            \n            // Add required array if there are required parameters\n            if (required.length > 0) {\n              formattedParameters = {\n                ...formattedParameters,\n                required: required\n              };\n            }\n          } else if (tool.parameters) {\n            // Use parameters as-is if not an array\n            formattedParameters = tool.parameters;\n          }\n          \n          return {\n            name: tool.name,\n            description: tool.description || \"\",\n            parameters: formattedParameters\n          };\n        });\n        \n        // Create messages for the model\n        const messages: ProviderMessage[] = [\n          {\n            role: \"user\",\n            content: `Complete this task: ${this.config.name}\n${this.config.description ? `Description: ${this.config.description}` : ''}\nInput: ${JSON.stringify(enrichedInput)}`\n          }\n        ];\n        \n        // Let the model generate a response using the tools\n        try {\n          // Create the system message\n          const systemMessage = `You are an AI assistant that can use tools to complete tasks.\nComplete this task: ${this.config.name}\n${this.config.description ? `Description: ${this.config.description}` : ''}\n\nAvailable tools:\n${prioritizedPlugins.map(tool => `- ${tool.name}: ${tool.description || 'No description provided'}`).join('\\n')}\n\nUse the available tools to fulfill this task effectively. When a tool should be used, call it with appropriate parameters.`;\n\n          // Log formatted tools for debugging\n          logger.debug(`Task ${this.id} using ${formattedTools.length} tools with model ${model.name}`, {\n            toolNames: formattedTools.map(t => t.name).join(', ')\n          });\n\n          // If the tools have parameters with improper formats, log them for debugging\n          const toolsWithPotentialIssues = formattedTools.filter(tool => {\n            const params = tool.parameters;\n            return !params || (typeof params === 'object' && Object.keys(params).length === 0);\n          });\n\n          if (toolsWithPotentialIssues.length > 0) {\n            logger.warn(`Task ${this.id} has tools with potential parameter format issues:`, \n              toolsWithPotentialIssues.map(t => t.name).join(', '));\n          }\n\n          // Call the model with messages and completion options\n          const completionOptions: CompletionOptions = {\n            tools: formattedTools,\n            toolCalling: true,\n            systemMessage: systemMessage\n          };\n          \n          logger.debug(`Task ${this.id} calling model with ${messages.length} messages and ${formattedTools.length} tools`);\n          const completion = await model.complete(messages, completionOptions);\n          \n          // Check if completion is a structured object with tool calls\n          if (typeof completion === 'object' && completion.tool_calls && Array.isArray(completion.tool_calls)) {\n            logger.debug(`Task ${this.id} received structured tool calls response`);\n            \n            const toolCalls = completion.tool_calls;\n            logger.info(`Task ${this.id} response includes ${toolCalls.length} tool calls:`);\n            \n            // Log tool calls and execute them\n            const toolResults = [];\n            for (let i = 0; i < toolCalls.length; i++) {\n              const call = toolCalls[i];\n                              if (call.type === 'function' && call.name) {\n                logger.info(`Tool call ${i + 1}: ${call.name} with arguments: ${JSON.stringify(call.arguments)}`);\n                \n                // Record tool call in memory\n                await this.addTaskMemoryEntry(\n                  `Tool call: ${call.name} with arguments: ${JSON.stringify(call.arguments)}`,\n                  \"task_tool\"\n                );\n                \n                // Find the tool to execute\n                const tool = prioritizedPlugins.find(t => t.name === call.name);\n                if (tool && typeof tool.execute === 'function') {\n                  try {\n                    logger.info(`Executing tool ${call.name}...`);\n                    const result = await tool.execute({\n                      ...enrichedInput,\n                      ...call.arguments\n                    });\n                    toolResults.push({\n                      name: call.name,\n                      arguments: call.arguments,\n                      result\n                    });\n                    logger.info(`Tool ${call.name} executed successfully`);\n                    \n                    // Record successful tool execution in memory\n                    await this.addTaskMemoryEntry(\n                      `Tool ${call.name} executed successfully`,\n                      \"task_result\",\n                      { toolName: call.name, success: true }\n                    );\n                  } catch (error) {\n                    logger.error(`Error executing tool ${call.name}:`, error);\n                    toolResults.push({\n                      name: call.name,\n                      arguments: call.arguments,\n                      error: error instanceof Error ? error.message : `Error: ${error}`\n                    });\n                    \n                    // Record tool execution error in memory\n                    await this.addTaskMemoryEntry(\n                      `Tool ${call.name} execution failed: ${error instanceof Error ? error.message : error}`,\n                      \"task_result\",\n                      { toolName: call.name, success: false }\n                    );\n                  }\n                } else {\n                  logger.warn(`Tool ${call.name} not found or has no execute method`);\n                  toolResults.push({\n                    name: call.name,\n                    arguments: call.arguments,\n                    error: `Tool ${call.name} not found or has no execute method`\n                  });\n                  \n                  // Record tool not found in memory\n                  await this.addTaskMemoryEntry(\n                    `Tool ${call.name} not found or has no execute method`,\n                    \"task_result\",\n                    { toolName: call.name, success: false }\n                  );\n                }\n              }\n            }\n            \n            // Generate a response based on tool results\n            if (toolResults.length > 0) {\n              try {\n                logger.info(`Generating response based on ${toolResults.length} tool results`);\n                const resultsMessage: ProviderMessage = {\n                  role: \"system\",\n                  content: `The following tools were called based on the user's request:\n${toolResults.map(tr => `Tool: ${tr.name}\nArguments: ${JSON.stringify(tr.arguments)}\nResult: ${tr.error ? 'ERROR: ' + tr.error : JSON.stringify(tr.result)}`).join('\\n\\n')}\n\nPlease analyze these results and generate a helpful, coherent response to the user that summarizes what was done and the outcome.\nDo not mention the technical details of the tool calls - just provide a natural, conversational response about what was accomplished.`\n                };\n                \n                // Call the model again with the results\n                const summaryResponse = await model.complete([\n                  ...messages,\n                  resultsMessage\n                ]);\n                \n                // Use the summary response as content\n                const summaryContent = typeof summaryResponse === 'string' \n                  ? summaryResponse \n                  : summaryResponse.content;\n                \n                // Add both the summary and the raw results\n                currentOutput = {\n                  ...enrichedInput,\n                  content: summaryContent,\n                  summary: summaryContent,\n                  tool_calls: toolCalls,\n                  tool_results: toolResults,\n                  tools_used: prioritizedPlugins.map(t => t.name)\n                };\n              } catch (error) {\n                logger.error(`Error generating summary from tool results:`, error);\n                // Fall back to standard output without summary\n                currentOutput = {\n                  ...enrichedInput,\n                  content: completion.content || '',\n                  tool_calls: toolCalls,\n                  tool_results: toolResults,\n                  tools_used: prioritizedPlugins.map(t => t.name)\n                };\n              }\n            } else {\n              // No tools were successfully executed\n              currentOutput = {\n                ...enrichedInput,\n                content: completion.content || '',\n                tool_calls: toolCalls,\n                tool_results: toolResults,\n                tools_used: prioritizedPlugins.map(t => t.name)\n              };\n            }\n          }\n          // Handle text-based tool calls (for older models)\n          else if (typeof completion === 'string' && completion.includes('Tool Call:')) {\n            logger.debug(`Task ${this.id} model response received, length: ${completion.length} chars (text format)`);\n            \n            // Extract and log tool calls for better debugging\n            const toolCallMatches = completion.match(/Tool Call: ([^\\n]+)[\\s\\S]*?Arguments: ({[\\s\\S]*?})(?=\\n\\n|\\n?$)/g);\n            if (toolCallMatches && toolCallMatches.length > 0) {\n              logger.info(`Task ${this.id} response includes ${toolCallMatches.length} tool calls (text format):`);\n              \n              // Execute each tool call\n              const toolResults = [];\n              const parsedCalls = [];\n              for (let i = 0; i < toolCallMatches.length; i++) {\n                const match = toolCallMatches[i];\n                const toolName = match.match(/Tool Call: ([^\\n]+)/)?.[1];\n                const argsMatch = match.match(/Arguments: (.*?)(?=\\n\\n|\\n?$)/s);\n                const argsString = argsMatch ? argsMatch[1] : '{}';\n                \n                logger.info(`Tool call ${i + 1}: ${toolName} with arguments: ${argsString}`);\n                \n                if (toolName) {\n                  // Parse arguments\n                  let args = {};\n                  try {\n                    args = JSON.parse(argsString);\n                  } catch (err) {\n                    logger.warn(`Failed to parse arguments for tool ${toolName}: ${err}`);\n                  }\n                  \n                  parsedCalls.push({\n                    name: toolName,\n                    arguments: args\n                  });\n                  \n                  // Find and execute the tool\n                  const tool = prioritizedPlugins.find(t => t.name === toolName);\n                  if (tool && typeof tool.execute === 'function') {\n                    try {\n                      logger.info(`Executing tool ${toolName}...`);\n                      const result = await tool.execute({\n                        ...enrichedInput,\n                        ...args\n                      });\n                      toolResults.push({\n                        name: toolName,\n                        arguments: args,\n                        result\n                      });\n                      logger.info(`Tool ${toolName} executed successfully`);\n                    } catch (error) {\n                      logger.error(`Error executing tool ${toolName}:`, error);\n                      toolResults.push({\n                        name: toolName,\n                        arguments: args,\n                        error: error instanceof Error ? error.message : `Error: ${error}`\n                      });\n                    }\n                  } else {\n                    logger.warn(`Tool ${toolName} not found or has no execute method`);\n                    toolResults.push({\n                      name: toolName,\n                      arguments: args,\n                      error: `Tool ${toolName} not found or has no execute method`\n                    });\n                  }\n                }\n              }\n              \n              // Generate a response based on tool results\n              if (toolResults.length > 0) {\n                try {\n                  logger.info(`Generating response based on ${toolResults.length} tool results`);\n                  const resultsMessage: ProviderMessage = {\n                    role: \"system\",\n                    content: `The following tools were called based on the user's request:\n${toolResults.map(tr => `Tool: ${tr.name}\nArguments: ${JSON.stringify(tr.arguments)}\nResult: ${tr.error ? 'ERROR: ' + tr.error : JSON.stringify(tr.result)}`).join('\\n\\n')}\n\nPlease analyze these results and generate a helpful, coherent response to the user that summarizes what was done and the outcome.\nDo not mention the technical details of the tool calls - just provide a natural, conversational response about what was accomplished.`\n                  };\n                  \n                  // Call the model again with the results\n                  const summaryResponse = await model.complete([\n                    ...messages,\n                    resultsMessage\n                  ]);\n                  \n                  // Use the summary response\n                  const summaryContent = typeof summaryResponse === 'string' \n                    ? summaryResponse \n                    : summaryResponse.content;\n                  \n                  // Include both the summary and the raw results\n                  currentOutput = {\n                    ...enrichedInput,\n                    content: summaryContent,\n                    summary: summaryContent,\n                    result: completion,\n                    tool_calls: parsedCalls,\n                    tool_results: toolResults,\n                    tools_used: prioritizedPlugins.map(t => t.name)\n                  };\n                } catch (error) {\n                  logger.error(`Error generating summary from tool results:`, error);\n                  // Fall back to standard output without summary\n                  currentOutput = {\n                    ...enrichedInput,\n                    result: completion,\n                    tool_calls: parsedCalls,\n                    tool_results: toolResults,\n                    tools_used: prioritizedPlugins.map(t => t.name)\n                  };\n                }\n              } else {\n                // No tools were successfully executed\n                currentOutput = {\n                  ...enrichedInput,\n                  result: completion,\n                  tool_calls: parsedCalls,\n                  tool_results: toolResults,\n                  tools_used: prioritizedPlugins.map(t => t.name)\n                };\n              }\n            } else {\n              logger.info(`Task ${this.id} response appears to include tool calls but format could not be parsed`);\n              \n              // Just pass through the response\n              currentOutput = {\n                ...enrichedInput,\n                result: completion,\n                tools_used: prioritizedPlugins.map(t => t.name)\n              };\n            }\n          } else {\n            // No tool calls detected\n            logger.debug(`Task ${this.id} model response received, length: ${typeof completion === 'string' ? completion.length : JSON.stringify(completion).length} chars`);\n            logger.warn(`Task ${this.id} response does not include tool calls, the model may not be using the tools properly`);\n            \n            // Use the response as-is\n            currentOutput = {\n              ...enrichedInput,\n              result: completion,\n              tools_used: prioritizedPlugins.map(t => t.name)\n            };\n          }\n          \n          logger.debug(`Model execution completed for task ${this.id}`);\n        } catch (error) {\n          logger.error(`Error executing task with model: ${error}`);\n          throw error;\n        }\n      } else {\n        // No model or no plugins, execute plugins sequentially\n        logger.debug(`Task ${this.id} using sequential plugin execution (${prioritizedPlugins.length} plugins)`);\n        let pluginOutput: unknown = null;\n        \n        // Execute each plugin in sequence\n        for (const plugin of prioritizedPlugins) {\n          if (this.isCancelled) {\n            throw new Error(\"Task was cancelled during execution\");\n          }\n\n          if (!plugin) {\n            logger.warn(\"Encountered null or undefined plugin, skipping\");\n            continue;\n          }\n\n          if (plugin.execute) {\n            const pluginName = plugin.name || \"unnamed_plugin\";\n            logger.debug(`Executing plugin '${pluginName}' with input:`, JSON.stringify(currentOutput));\n            try {\n              // Execute the plugin with the current input/output chain\n              pluginOutput = await plugin.execute(currentOutput);\n              logger.debug(`Plugin '${pluginName}' returned:`, JSON.stringify(pluginOutput));\n              \n              // Update currentOutput with plugin's output, not the entire input\n              if (pluginOutput !== undefined && pluginOutput !== null) {\n                // If plugin returns a value, use it as the new current output\n                currentOutput = pluginOutput as Record<string, unknown>;\n                logger.debug(`Updated currentOutput with plugin result:`, JSON.stringify(currentOutput));\n              } else {\n                logger.debug(`Plugin returned undefined/null, keeping previous output`);\n              }\n              // If plugin returns undefined/null, keep the previous output\n            } catch (error) {\n              logger.error(`Error executing plugin '${pluginName}':`, error);\n              throw error;\n            }\n          } else {\n            const pluginName = plugin.name || \"unnamed_plugin\";\n            logger.warn(\n              `Plugin '${pluginName}' does not have an execute method`\n            );\n          }\n        }\n      }\n\n      // The final output is the result from execution\n      const finalOutput = currentOutput;\n      \n      // Only show the final output at debug level\n      logger.debug(`Task ${this.id} final output:`, JSON.stringify(finalOutput));\n      \n      // Strip _context from the output if it got added by the enriched input\n      if (finalOutput && typeof finalOutput === 'object' && '_context' in finalOutput) {\n        const { _context, ...strippedOutput } = finalOutput;\n        // Use _context to prevent unused variable warning\n        logger.debug(`Context data size: ${JSON.stringify(_context).length} bytes`);\n        \n        // Only replace if there are other properties beyond _context\n        if (Object.keys(strippedOutput).length > 0) {\n          currentOutput = strippedOutput as Record<string, unknown>;\n          logger.debug(`Stripped _context, new output:`, JSON.stringify(currentOutput));\n        } else {\n          logger.debug(`After stripping _context, no other properties found, keeping original`);\n        }\n      }\n\n      // Update the context with this task's output\n      if (this.sessionId) {\n        taskContext = {\n          ...taskContext,\n          [this.config.name]: currentOutput,\n          lastTaskOutput: currentOutput,\n        };\n        // Store updated context in memory system\n        await this.saveTaskContext(this.sessionId, taskContext);\n      }\n\n      // Set result and update status\n      this.result = {\n        success: true,\n        output: currentOutput,\n        context: taskContext,\n      };\n      \n      logger.debug(`Task ${this.id} completed successfully`);\n        \n      this.completedAt = new Date();\n      if (this.result.success) {\n        this.status = \"completed\";\n        logger.task(this.id, `Task ${this.status}`, this.config.name);\n        \n        // Record task completion in memory\n        await this.addTaskMemoryEntry(\n          `Task completed successfully: ${this.config.name}`, \n          \"task_event\",\n          { output: JSON.stringify(currentOutput).slice(0, 500) } // Limit size of stored output\n        );\n      } else {\n        this.status = \"failed\";\n        logger.task(this.id, `Task ${this.status}`, this.config.name);\n        \n        // Record task failure in memory\n        await this.addTaskMemoryEntry(\n          `Task failed: ${this.config.name}`, \n          \"task_event\"\n        );\n      }\n    } catch (error) {\n      // Handle error\n      this.result = {\n        success: false,\n        error: error as Error,\n      };\n      \n      logger.error(`Task ${this.id} failed with error:`, error);\n      \n      // Record task error in memory\n      await this.addTaskMemoryEntry(\n        `Task error: ${error instanceof Error ? error.message : error}`,\n        \"task_event\",\n        { errorType: error instanceof Error ? error.name : 'Unknown' }\n      );\n\n      // Retry if max retries not exceeded\n      if (this.retries < (this.config.maxRetries || 0)) {\n        this.retries++;\n        this.status = \"pending\";\n        logger.info(\n          `Retrying task '${this.id}', attempt ${this.retries}/${this.config.maxRetries}`\n        );\n        \n        // Record retry in memory\n        await this.addTaskMemoryEntry(\n          `Retrying task (attempt ${this.retries}/${this.config.maxRetries})`,\n          \"task_event\"\n        );\n\n        // Database state is managed by createTask static method\n\n        return this.execute(taskInput);\n      } else {\n        this.status = \"failed\";\n        this.completedAt = new Date();\n      }\n    }\n\n\n\n    return this.result as TaskResult;\n  }\n\n  /**\n   * Get task context from memory using session ID\n   */\n  public async getTaskContext(sessionId: string): Promise<Record<string, unknown>> {\n    try {\n      // Use the memory system if available\n      if (this.memory) {\n        // Get the task context memories from session\n        const memories = await this.memory.getBySession(sessionId);\n\n        // Find the most recent task context memory\n        const contextMemories = memories.filter(\n          (m) => m.role === \"task_context\"\n        );\n\n        if (contextMemories.length > 0) {\n          // Sort by timestamp descending and get most recent\n          contextMemories.sort(\n            (a, b) => {\n              // Ensure timestamps are Date objects or convert them\n              const aTime = a.timestamp instanceof Date ? a.timestamp.getTime() : new Date(a.timestamp).getTime();\n              const bTime = b.timestamp instanceof Date ? b.timestamp.getTime() : new Date(b.timestamp).getTime();\n              return bTime - aTime;\n            }\n          );\n\n          // Extract the context data from memory content\n          try {\n            return JSON.parse(contextMemories[0].content);\n          } catch (parseError) {\n            logger.error(\n              `Error parsing task context data for session ${sessionId}:`,\n              parseError\n            );\n            return {};\n          }\n        }\n      }\n\n      return {};\n    } catch (error) {\n      logger.error(\n        `Error retrieving task context for session ${sessionId}:`,\n        error\n      );\n      return {};\n    }\n  }\n\n  /**\n   * Save task context to memory system\n   */\n  public async saveTaskContext(\n    sessionId: string,\n    contextData: Record<string, unknown>\n  ): Promise<void> {\n    try {\n      // Only save if memory system is available\n      if (this.memory) {\n        // Serialize the context data\n        const serializedData = JSON.stringify(contextData);\n\n        // Store in memory with role=task_context\n        await this.memory.add({\n          agentId: this.agentId || \"system\",\n          sessionId: sessionId,\n          userId: \"\",\n          role: \"task_context\",\n          content: serializedData,\n          metadata: {\n            taskId: this.id,\n            taskName: this.config.name,\n            contextType: \"task_execution_context\",\n          },\n        });\n      } else {\n        logger.warn(\n          `Memory system not available for task ${this.id}, skipping context save`\n        );\n      }\n    } catch (error) {\n      logger.error(\n        `Error saving task context for session ${sessionId}:`,\n        error\n      );\n    }\n  }\n\n  /**\n   * Cancel the task execution\n   */\n  cancel(): void {\n    this.isCancelled = true;\n    if (this.status === \"pending\" || this.status === \"running\") {\n      this.status = \"failed\";\n      this.result = {\n        success: false,\n        error: new Error(\"Task was cancelled\"),\n      };\n\n    }\n  }\n\n  /**\n   * Set the memory instance for this task\n   */\n  setMemory(memory: MemoryInstance): void {\n    this.memory = memory;\n  }\n\n  /**\n   * Get memory entries specific to this task\n   * @returns Promise that resolves to an array of task-specific memory entries\n   */\n  public async getTaskMemory(): Promise<MemoryEntry[]> {\n    if (!this.memory || !this.sessionId) {\n      return [];\n    }\n    \n    try {\n      // Get all memories for this session\n      const memories = await this.memory.getBySession(this.sessionId);\n      \n      // Filter for memories related to this task\n      return memories.filter(memory => \n        memory.metadata && \n        typeof memory.metadata === 'object' &&\n        'taskId' in memory.metadata &&\n        memory.metadata.taskId === this.id\n      );\n    } catch (error) {\n      logger.error(`Error getting task memory for task ${this.id}:`, error);\n      return [];\n    }\n  }\n\n  /**\n   * Add a memory entry for this task\n   * @param content Content of the memory entry\n   * @param role Role for the memory entry (task_event, task_tool, task_result)\n   * @param additionalMetadata Additional metadata to include\n   * @returns Promise that resolves when the memory is added\n   */\n  public async addTaskMemoryEntry(\n    content: string, \n    role: \"task_event\" | \"task_tool\" | \"task_result\" = \"task_event\",\n    additionalMetadata: Record<string, unknown> = {}\n  ): Promise<void> {\n    if (!this.memory || !this.sessionId) {\n      return;\n    }\n    \n    try {\n      await this.memory.add({\n        agentId: this.agentId || \"system\",\n        sessionId: this.sessionId,\n        userId: \"\",\n        role: role,\n        content: content,\n        metadata: {\n          taskId: this.id,\n          taskName: this.config.name,\n          taskStatus: this.status,\n          ...additionalMetadata\n        }\n      });\n      logger.debug(`Added task memory entry for task ${this.id}: ${role}`);\n    } catch (error) {\n      logger.error(`Error adding task memory for task ${this.id}:`, error);\n    }\n  }\n\n  /**\n   * Create a new task asynchronously\n   */\n  static async createTask(\n    config: TaskConfig,\n    memory?: MemoryInstance,\n    model?: ProviderModel,\n    database?: DatabaseInstance\n  ): Promise<TaskInstance> {\n    // Create a new task instance\n    const task = new Task(config, memory, model, database);\n\n    // Save task to database if database is available\n    if (task.database) {\n      try {\n        // Ensure tasks table exists\n        await task.database.ensureTable('tasks', (table) => {\n          table.string(\"id\").primary();\n          table.string(\"name\").notNullable();\n          table.text(\"description\").notNullable();\n          table.string(\"status\").notNullable().index();\n          table.integer(\"retries\").defaultTo(0);\n          table.json(\"plugins\").nullable();\n          table.json(\"input\").nullable();\n          table.json(\"dependencies\").nullable();\n          table.json(\"result\").nullable();\n          table.timestamp(\"createdAt\").defaultTo(task.database!.knex.fn.now());\n          table.timestamp(\"startedAt\").nullable();\n          table.timestamp(\"completedAt\").nullable();\n          table.string(\"agentId\").nullable().index();\n          table.string(\"sessionId\").nullable().index();\n          table.string(\"contextId\").nullable().index();\n        });\n\n        // Use default tasks table name - can be customized via database config if needed\n        const tasksTable = task.database.getTable('tasks');\n\n        // Prepare task data for database\n        const taskData = {\n          id: task.id,\n          name: task.config.name,\n          description: task.config.description,\n          status: task.status,\n          retries: task.retries,\n          plugins: JSON.stringify(task.config.plugins || []),\n          input: task.config.input ? JSON.stringify(task.config.input) : null,\n          dependencies: task.config.dependencies ? JSON.stringify(task.config.dependencies) : null,\n          result: task.result ? JSON.stringify(task.result) : null,\n          createdAt: task.createdAt,\n          startedAt: task.startedAt || null,\n          completedAt: task.completedAt || null,\n          agentId: task.agentId || null,\n          sessionId: task.sessionId || null,\n          contextId: task.contextId || null,\n        };\n\n        // Check if task already exists\n        const existingTask = await tasksTable.findOne({ id: task.id });\n\n        if (existingTask) {\n          // Update existing task\n          await tasksTable.update({ id: task.id }, taskData);\n          logger.debug(`Task ${task.id}: Updated in database`);\n        } else {\n          // Insert new task\n          await tasksTable.insert(taskData);\n          logger.debug(`Task ${task.id}: Saved to database`);\n        }\n\n        // Task state is now stored in database\n      } catch (error) {\n        logger.error(`Task ${task.id}: Error saving to database:`, error);\n        // Don't throw error to avoid breaking task creation\n      }\n    }\n\n    return task;\n  }\n\n  /**\n   * Create a new task synchronously\n   */\n  static createTaskSync(\n    config: TaskConfig,\n    memory?: MemoryInstance,\n    model?: ProviderModel,\n    database?: DatabaseInstance\n  ): TaskInstance {\n    // Create and return a new task instance without waiting for save\n    return new Task(config, memory, model, database);\n  }\n} ","import { Plugin } from \"../types/plugin\";\nimport { logger } from \"./index\";\nimport { ProviderModel, ProviderMessage } from \"../types\";\n\n/**\n * Intent recognition system that uses LLM to determine which tools should be used for a task\n * based on the task name and description.\n */\nexport class IntentRecognizer {\n  /**\n   * Use LLM to determine which tools are relevant for a task based on its name and description\n   * \n   * @param taskName The name of the task\n   * @param taskDescription The description of the task\n   * @param availableTools Array of available tools\n   * @param model The LLM to use for tool selection\n   * @returns Array of tools that are relevant for the task\n   */\n  static async recognizeIntent(\n    taskName: string,\n    taskDescription: string,\n    availableTools: Plugin[],\n    model: ProviderModel\n  ): Promise<Plugin[]> {\n    // If no tools are available, return empty array\n    if (!availableTools.length) {\n      logger.debug(`No tools available for task \"${taskName}\"`);\n      return [];\n    }\n    \n    // Prepare tool information for the model\n    const toolsInfo = availableTools.map(tool => ({\n      name: tool.name,\n      description: tool.description || \"\",\n      parameters: tool.parameters || {}\n    }));\n    \n    // Create the prompt for tool selection\n    const prompt: ProviderMessage[] = [\n      {\n        role: \"system\",\n        content: `You are a tool selection expert that picks the most relevant tools for a task.\nReview the task and available tools and select ONLY the tools that are directly relevant.\nRespond ONLY with a JSON array of tool names that should be used, without any explanation.\nExample format: [\"tool1\", \"tool2\"]`\n      },\n      {\n        role: \"user\",\n        content: `Task name: ${taskName}\nTask description: ${taskDescription}\n\nAvailable tools:\n${JSON.stringify(toolsInfo, null, 2)}\n\nSelect the most appropriate tools for this task and respond with a JSON array containing only the tool names.`\n      }\n    ];\n    \n    try {\n      // Ask the model to select tools\n      const response = await model.complete(prompt);\n      \n      // Extract JSON array from the response\n      let toolNames: string[] = [];\n      try {\n        // Find the JSON array in the response\n        const responseText = typeof response === 'string' ? response : response.content;\n        const match = responseText.match(/\\[.*\\]/s);\n        if (match) {\n          toolNames = JSON.parse(match[0]);\n        } else {\n          throw new Error(\"No JSON array found in response\");\n        }\n      } catch (error) {\n        logger.error(`Failed to parse LLM tool selection response: ${error}`);\n        logger.debug(`Raw LLM response: ${typeof response === 'string' ? response : JSON.stringify(response)}`);\n        return []; // Return empty array on parsing error\n      }\n      \n      // Map tool names to actual tool objects\n      const selectedTools = toolNames\n        .map(name => availableTools.find(tool => \n          tool.name.toLowerCase() === name.toLowerCase()))\n        .filter(tool => tool !== undefined) as Plugin[];\n      \n      return selectedTools;\n    } catch (error) {\n      logger.error(`Error using LLM for tool selection: ${error}`);\n      return []; // Return empty array on LLM error\n    }\n  }\n} ","import { v4 as uuidv4 } from \"uuid\";\nimport {\n  TaskManagerInstance,\n  TaskConfig,\n  TaskInstance,\n  TaskResult,\n  TaskManagerConfig,\n  TaskStatus,\n} from \"../types\";\nimport { MemoryInstance, DatabaseInstance, ProviderModel } from \"../types\";\nimport { createDatabase } from \"../database\";\nimport { logger } from \"../utils\";\nimport { Task } from \"./task\";\nimport { validateRequiredParam } from \"../utils/validation\";\n\n/**\n * Task Manager class that manages multiple tasks\n * \n * This class provides functionality for:\n * - Creating and managing multiple tasks\n * - Executing tasks with dependencies in order\n * - Persisting task state to the database\n * - Restoring tasks from previous sessions\n */\nexport class TaskManager implements TaskManagerInstance {\n  private readonly tasks = new Map<string, TaskInstance>();\n  private tasksLoaded = false;\n  private loadingPromise: Promise<void> | null = null;\n  private config: TaskManagerConfig;\n  private agentId?: string;\n  private sessionId?: string;\n  private memory?: MemoryInstance;\n  private database?: DatabaseInstance;\n  private providerModel?: ProviderModel;\n\n  /**\n   * Create a new TaskManager instance\n   * @param config Configuration options for the task manager\n   */\n  constructor(config?: TaskManagerConfig) {\n    this.config = config || { concurrency: 5 };\n    this.agentId = config?.agentId;\n    this.sessionId = config?.sessionId;\n    this.memory = config?.memory;\n    this.database = config?.database;\n    this.providerModel = config?.providerModel;\n\n    // Load existing tasks from the database\n    this.loadTasksFromDatabase().catch((err) => {\n      logger.error(\"Error loading tasks from database:\", err);\n    });\n    \n    logger.info(\"Task manager initialized\");\n  }\n\n  /**\n   * Add an existing task to the manager\n   * @param task Task instance or configuration to add\n   * @param model Optional LLM model to use for tool selection\n   * @returns The added task instance\n   */\n  public addExistingTask(task: TaskInstance | TaskConfig, model?: ProviderModel): TaskInstance {\n    try {\n      // If this is a configuration, first check if we already have this task by ID\n      if (!(task instanceof Task) && task.id) {\n        // Look for existing task in our memory\n        const existingTask = this.tasks.get(task.id);\n        if (existingTask) {\n          logger.debug(`Task ${task.id} already exists in manager, returning existing instance`);\n          return existingTask;\n        }\n      }\n      \n      // Ensure task.plugins only contains string values\n      if (!(task instanceof Task) && task.plugins) {\n        const validPlugins = task.plugins.filter(plugin => typeof plugin === 'string');\n        if (validPlugins.length !== task.plugins.length) {\n          logger.warn(`TaskManager: Filtered out ${task.plugins.length - validPlugins.length} invalid plugins from task config`);\n          task.plugins = validPlugins;\n        }\n      }\n      \n      // Determine which model to use, in order of preference:\n      // 1. Explicitly provided model parameter\n      // 2. Task's model (if task is a config with model)\n      // 3. TaskManager's providerModel\n      let taskModel = model;\n      if (!taskModel) {\n        if (task instanceof Task) {\n          taskModel = task.config.model;\n        } else if ('model' in task) {\n          taskModel = task.model;\n        }\n      }\n      if (!taskModel && this.providerModel) {\n        taskModel = this.providerModel;\n      }\n      \n      // If this is not already a Task instance, create one\n      const taskInstance =\n        task instanceof Task\n          ? task\n          : new Task(\n              {\n                ...(task as TaskConfig),\n                agentId: task.agentId || this.agentId,\n                sessionId: task.sessionId || this.sessionId,\n                model: taskModel  // Pass the determined model to the task\n              },\n              this.memory,\n              undefined,  // No need to pass model here as we already set it in config\n              this.database\n            );\n\n      // If task was created without memory, set it now\n      if (this.memory && taskInstance instanceof Task) {\n        taskInstance.setMemory(this.memory);\n      }\n\n      // Add task to memory\n      this.tasks.set(taskInstance.id, taskInstance);\n\n      // Check for a parent in dependencies and add it if needed\n      this.addTaskWithParent(taskInstance);\n\n      // Task is already saved to database via createTask static method\n      \n      logger.debug(`Task \"${taskInstance.config.name}\" (${taskInstance.id}) added to manager`);\n      \n      return taskInstance;\n    } catch (error) {\n      logger.error(\"Error adding existing task:\", error);\n      throw error;\n    }\n  }\n\n  /**\n   * Helper method to check for parent ID in dependencies and add it if needed\n   * @param task Task to check for parent dependencies\n   */\n  private addTaskWithParent(task: TaskInstance): void {\n    try {\n      // Add parent dependency if it exists\n      if (task.config.dependencies && task.config.dependencies.length > 0) {\n        const parentId = task.config.dependencies[0];\n        const parent = this.getTask(parentId);\n        if (parent) {\n          // Parent exists, nothing to do\n          return;\n        }\n        // Parent doesn't exist, warn about it\n        logger.warn(`Parent task ${parentId} not found for task ${task.id}`);\n      }\n    } catch (error) {\n      logger.error(`Error checking parent dependencies for task ${task.id}:`, error);\n    }\n  }\n\n  /**\n   * Get a task by ID\n   * @param id ID of the task to retrieve\n   * @returns Task instance if found, undefined otherwise\n   */\n  public getTask(id: string): TaskInstance | undefined {\n    return this.tasks.get(id);\n  }\n\n  /**\n   * Get all tasks managed by this instance\n   * @returns Array of all task instances\n   */\n  public getAllTasks(): TaskInstance[] {\n    return Array.from(this.tasks.values());\n  }\n\n  /**\n   * Create and add a new task\n   * @param config Configuration for the new task\n   * @param model Optional LLM model to use for tool selection\n   * @returns The created task instance\n   */\n  public async createTask(config: TaskConfig, model?: ProviderModel): Promise<TaskInstance> {\n    try {\n      // Determine which model to use, in order of preference:\n      // 1. Explicitly provided model parameter\n      // 2. Task's model (from config)\n      // 3. TaskManager's providerModel\n      let taskModel = model;\n      if (!taskModel && config.model) {\n        taskModel = config.model;\n      }\n      if (!taskModel && this.providerModel) {\n        taskModel = this.providerModel;\n      }\n      \n      // Create task with the manager's agent and session IDs if not provided\n      const updatedConfig = {\n        ...config,\n        agentId: config.agentId || this.agentId,\n        sessionId: config.sessionId || this.sessionId,\n        model: taskModel\n      };\n\n      // Create the task with memory and database\n      const task = await Task.createTask(updatedConfig, this.memory, undefined, this.database);\n\n      // Add task to manager\n      this.addExistingTask(task);\n      \n      logger.info(`Created new task: \"${task.config.name}\" (${task.id})`);\n\n      return task;\n    } catch (error) {\n      logger.error(\"Error creating task:\", error);\n      throw error;\n    }\n  }\n\n  /**\n   * Cancel a task by ID\n   * @param id ID of the task to cancel\n   * @returns true if task was found and canceled, false otherwise\n   */\n  public cancelTask(id: string): boolean {\n    try {\n      const task = this.getTask(id);\n      if (task) {\n        task.cancel();\n        logger.info(`Task ${id} canceled`);\n        return true;\n      }\n      logger.warn(`Task ${id} not found for cancellation`);\n      return false;\n    } catch (error) {\n      logger.error(`Error canceling task ${id}:`, error);\n      return false;\n    }\n  }\n\n  /**\n   * Load tasks from database\n   * @returns Promise that resolves when tasks are loaded\n   */\n  private async loadTasksFromDatabase(): Promise<void> {\n    try {\n      // Use database from instance if provided, otherwise create a new one\n      const db = this.database || await createDatabase();\n      const tasksTable = db.getTable('tasks');\n\n      // Load all tasks from database\n      const taskRecords = await tasksTable.find();\n\n      for (const record of taskRecords) {\n        try {\n          // Parse JSON fields\n          const plugins = record.plugins ? JSON.parse(record.plugins) : [];\n          const input = record.input ? JSON.parse(record.input) : null;\n          const dependencies = record.dependencies ? JSON.parse(record.dependencies) : [];\n          const result = record.result ? JSON.parse(record.result) : null;\n\n          // Create task config from database record\n          const taskConfig: TaskConfig = {\n            id: record.id,\n            name: record.name,\n            description: record.description,\n            plugins,\n            input,\n            dependencies,\n            agentId: record.agentId,\n            sessionId: record.sessionId,\n          };\n\n          // Create task instance\n          const task = new Task(taskConfig, this.memory, this.providerModel, db);\n\n          // Restore task state\n          task.status = record.status as TaskStatus;\n          task.retries = record.retries || 0;\n          task.createdAt = new Date(record.createdAt);\n          task.startedAt = record.startedAt ? new Date(record.startedAt) : undefined;\n          task.completedAt = record.completedAt ? new Date(record.completedAt) : undefined;\n          task.result = result;\n          task.agentId = record.agentId;\n          task.sessionId = record.sessionId;\n          task.contextId = record.contextId;\n\n          // Add to tasks map\n          this.tasks.set(task.id, task);\n\n          logger.debug(`Loaded task ${task.id} from database with status: ${task.status}`);\n        } catch (error) {\n          logger.error(`Error loading task ${record.id} from database:`, error);\n          // Continue loading other tasks\n        }\n      }\n\n      logger.info(`Loaded ${this.tasks.size} tasks from database`);\n    } catch (error) {\n      logger.error(\"Error loading tasks from database:\", error);\n      // Don't throw error - allow task manager to continue without database tasks\n    }\n  }\n\n  /**\n   * Wait for tasks to be loaded from database\n   * @returns Promise that resolves when tasks are loaded\n   */\n  public async waitForTasksLoaded(): Promise<void> {\n    if (this.tasksLoaded) {\n      return;\n    }\n\n    if (this.loadingPromise) {\n      return this.loadingPromise;\n    }\n\n    // If tasks haven't been loaded yet, load them now\n    return this.loadTasksFromDatabase();\n  }\n\n  /**\n   * Execute a specific task by ID\n   * @param id ID of the task to execute\n   * @param input Optional input data to pass to the task\n   * @returns Promise that resolves with the task execution result\n   */\n  public async executeTask(id: string, input?: any): Promise<TaskResult> {\n    try {\n      await this.waitForTasksLoaded();\n      \n      const task = this.getTask(id);\n      if (!task) {\n        throw new Error(`Task with ID ${id} not found`);\n      }\n\n      logger.info(`Executing task: \"${task.config.name}\" (${id})`);\n      return task.execute(input);\n    } catch (error) {\n      logger.error(`Error executing task ${id}:`, error);\n      throw error;\n    }\n  }\n\n  /**\n   * Get all tasks\n   * @deprecated Use getAllTasks() instead for newer implementations\n   * @returns Array of all task instances\n   */\n  public getTasks(): TaskInstance[] {\n    logger.debug(\"DEPRECATED: getTasks() called, use getAllTasks() instead\");\n    return this.getAllTasks();\n  }\n\n  /**\n   * Get tasks by agent ID\n   * @param agentId Agent ID to filter by\n   * @returns Array of tasks belonging to the specified agent\n   */\n  public getTasksByAgent(agentId: string): TaskInstance[] {\n    return Array.from(this.tasks.values()).filter(\n      (task) => task.config.agentId === agentId\n    );\n  }\n\n  /**\n   * Get tasks by session ID\n   * @param sessionId Session ID to filter by\n   * @returns Array of tasks belonging to the specified session\n   */\n  public getTasksBySession(sessionId: string): TaskInstance[] {\n    return Array.from(this.tasks.values()).filter(\n      (task) => task.config.sessionId === sessionId\n    );\n  }\n\n  /**\n   * Set the agent ID for this task manager\n   * @param agentId Agent ID to set\n   */\n  public setAgentId(agentId: string): void {\n    this.agentId = agentId;\n    logger.debug(`Task manager agent ID set to ${agentId}`);\n  }\n\n  /**\n   * Set the session ID for this task manager\n   * @param sessionId Session ID to set\n   */\n  public setSessionId(sessionId: string): void {\n    this.sessionId = sessionId;\n    logger.debug(`Task manager session ID set to ${sessionId}`);\n  }\n\n  /**\n   * Set the memory instance for this task manager\n   * @param memory Memory instance to use for task context storage\n   */\n  public setMemory(memory: MemoryInstance): void {\n    try {\n      this.memory = memory;\n      \n      // Update memory for all tasks\n      for (const task of this.tasks.values()) {\n        if (task instanceof Task) {\n          task.setMemory(memory);\n        }\n      }\n      \n      logger.debug(\"Memory instance set for task manager\");\n    } catch (error) {\n      logger.error(\"Error setting memory for task manager:\", error);\n      throw error;\n    }\n  }\n\n  /**\n   * Set the provider model to use for tasks\n   * @param model Provider model to use\n   */\n  public setProviderModel(model: ProviderModel): void {\n    this.providerModel = model;\n    logger.debug(`Task manager provider model set to ${model.name}`);\n  }\n\n  /**\n   * Get the current provider model\n   * @returns The current provider model or undefined\n   */\n  public getProviderModel(): ProviderModel | undefined {\n    return this.providerModel;\n  }\n\n  /**\n   * Run specified tasks (or all if no IDs provided)\n   * @param taskIds Optional array of task IDs to run\n   * @returns Promise that resolves with a map of task IDs to results\n   */\n  public async run(taskIds?: string[]): Promise<Map<string, TaskResult>> {\n    await this.waitForTasksLoaded();\n    \n    const results = new Map<string, TaskResult>();\n    let tasksToRun: TaskInstance[];\n\n    // Determine which tasks to run\n    if (taskIds && taskIds.length > 0) {\n      tasksToRun = taskIds\n        .map((id) => this.getTask(id))\n        .filter((task): task is TaskInstance => !!task);\n      \n      logger.info(`Running ${tasksToRun.length} specified tasks`);\n    } else {\n      tasksToRun = this.getAllTasks();\n      logger.info(`Running all ${tasksToRun.length} tasks`);\n    }\n\n    // Create a dependency graph and task execution order\n    const taskDependencyMap = new Map<string, Set<string>>();\n    const dependentTasksMap = new Map<string, Set<string>>();\n    \n    // Build dependency maps\n    for (const task of tasksToRun) {\n      const taskId = task.id;\n      const dependencies = new Set<string>();\n      \n      // Check both dependencies and dependsOn fields (for backward compatibility)\n      if (task.config.dependencies && task.config.dependencies.length > 0) {\n        for (const depId of task.config.dependencies) {\n          if (this.getTask(depId)) {\n            dependencies.add(depId);\n          }\n        }\n      }\n      \n      // Add dependsOn dependencies (newer approach)\n      if (task.config.dependsOn && task.config.dependsOn.length > 0) {\n        for (const depId of task.config.dependsOn) {\n          if (this.getTask(depId)) {\n            dependencies.add(depId);\n          }\n        }\n      }\n      \n      // Store in the dependency map\n      taskDependencyMap.set(taskId, dependencies);\n      \n      // Update dependent tasks map (reverse mapping)\n      for (const depId of dependencies) {\n        if (!dependentTasksMap.has(depId)) {\n          dependentTasksMap.set(depId, new Set<string>());\n        }\n        dependentTasksMap.get(depId)!.add(taskId);\n      }\n    }\n    \n    // Track completed tasks and their results\n    const completedTasks = new Set<string>();\n    const taskQueue: TaskInstance[] = [];\n    \n    // Initial pass: find tasks with no dependencies\n    for (const task of tasksToRun) {\n      const dependencies = taskDependencyMap.get(task.id) || new Set<string>();\n      if (dependencies.size === 0) {\n        taskQueue.push(task);\n      }\n    }\n    \n    logger.debug(`Initial task queue: ${taskQueue.length} tasks ready to run`);\n    \n    // Execute tasks in dependency order with proper concurrency\n    const concurrency = this.config.concurrency || 5;\n    \n    while (taskQueue.length > 0) {\n      // Take up to concurrency tasks from the queue\n      const batchTasks = taskQueue.splice(0, concurrency);\n      \n      // Execute this batch in parallel\n      const batchPromises = batchTasks.map(async (task) => {\n        try {\n          // Pass in any dependent task outputs as input\n          const dependencies = taskDependencyMap.get(task.id) || new Set<string>();\n          \n          // If there are dependencies, prepare to collect their outputs\n          if (dependencies.size > 0) {\n            const dependencyOutputs: Record<string, any> = {};\n            let hasOutputs = false;\n            \n            // Collect outputs from all dependencies\n            for (const depId of dependencies) {\n              if (results.has(depId)) {\n                const depResult = results.get(depId)!;\n                if (depResult.success && depResult.output) {\n                  dependencyOutputs[depId] = depResult.output;\n                  hasOutputs = true;\n                }\n              }\n            }\n            \n            // If we have dependency outputs, merge them with task input\n            if (hasOutputs) {\n              // Create merged input that preserves original task input\n              const mergedInput = {\n                ...(task.config.input || {}),\n                _dependencyOutputs: dependencyOutputs\n              };\n              \n              logger.debug(`Task ${task.id} received outputs from ${Object.keys(dependencyOutputs).length} dependencies`);\n              \n              // Execute task with merged input\n              const result = await task.execute(mergedInput);\n              results.set(task.id, result);\n            } else {\n              // No usable outputs from dependencies, just run normally\n              const result = await task.execute();\n              results.set(task.id, result);\n            }\n          } else {\n            // No dependencies, run task with original input\n            const result = await task.execute();\n            results.set(task.id, result);\n          }\n          \n          // Mark this task as completed\n          completedTasks.add(task.id);\n          \n          // Check if this task completion unblocks any dependent tasks\n          if (dependentTasksMap.has(task.id)) {\n            const dependentTasks = dependentTasksMap.get(task.id)!;\n            \n            for (const dependentId of dependentTasks) {\n              // Get the dependent task\n              const dependentTask = this.getTask(dependentId);\n              if (!dependentTask) continue;\n              \n              // Check if all dependencies of this dependent task are completed\n              const allDependenciesCompleted = Array.from(taskDependencyMap.get(dependentId) || new Set<string>())\n                .every(depId => completedTasks.has(depId));\n              \n              // If all dependencies are completed, add this task to the queue\n              if (allDependenciesCompleted && !completedTasks.has(dependentId)) {\n                taskQueue.push(dependentTask);\n                logger.debug(`Task ${dependentId} unblocked and added to queue`);\n              }\n            }\n          }\n        } catch (error) {\n          logger.error(`Error executing task ${task.id}:`, error);\n          results.set(task.id, {\n            success: false,\n            error: error instanceof Error ? error : new Error(String(error))\n          });\n          \n          // Mark as completed even though it failed\n          completedTasks.add(task.id);\n        }\n      });\n      \n      // Wait for this batch to complete before processing next batch\n      await Promise.all(batchPromises);\n    }\n    \n    // Check for unresolved tasks (might be due to circular dependencies)\n    const unresolvedTasks = tasksToRun.filter(t => !completedTasks.has(t.id));\n    if (unresolvedTasks.length > 0) {\n      logger.warn(`${unresolvedTasks.length} tasks were not executed due to dependency issues or circular dependencies`);\n      \n      // Add failed results for these tasks\n      for (const task of unresolvedTasks) {\n        results.set(task.id, {\n          success: false,\n          error: new Error(\"Task not executed due to unresolved dependencies\")\n        });\n      }\n    }\n    \n    logger.info(`Completed running ${completedTasks.size} tasks`);\n    return results;\n  }\n\n  /**\n   * Cancel a specific task\n   * @deprecated Use cancelTask() instead for newer implementations\n   * @param taskId ID of the task to cancel\n   * @returns true if task was found and canceled, false otherwise\n   */\n  public cancel(taskId: string): boolean {\n    logger.debug(\"DEPRECATED: cancel() called, use cancelTask() instead\");\n    return this.cancelTask(taskId);\n  }\n\n  /**\n   * Cancel all tasks\n   */\n  public cancelAll(): void {\n    try {\n      for (const task of this.tasks.values()) {\n        task.cancel();\n      }\n      logger.info(`Canceled all ${this.tasks.size} tasks`);\n    } catch (error) {\n      logger.error(\"Error canceling all tasks:\", error);\n    }\n  }\n} ","import { TaskManager } from \"./manager\";\nimport { Task } from \"./task\";\nimport { TaskManagerInstance, TaskConfig, TaskInstance, TaskManagerConfig } from \"../types/task\";\nimport { MemoryInstance } from \"../types\";\nimport { logger } from \"../utils\";\n\n/**\n * Create a new TaskManager instance\n * @param config Configuration for the task manager\n * @returns A new TaskManager instance\n */\nexport const createTaskManager = (\n  config?: TaskManagerConfig\n): TaskManagerInstance => {\n  try {\n    logger.debug(\"Creating task manager instance\");\n    return new TaskManager(config);\n  } catch (error) {\n    logger.error(\"Error creating task manager:\", error);\n    throw error;\n  }\n};\n\n/**\n * Create a new task asynchronously\n * @param config Configuration for the task\n * @param memory Optional memory instance for task context storage\n * @returns Promise that resolves to the new task instance\n */\nexport const createTask = async (\n  config: TaskConfig,\n  memory?: MemoryInstance\n): Promise<TaskInstance> => {\n  try {\n    logger.debug(`Creating task \"${config.name}\" asynchronously`);\n    return await Task.createTask(config, memory);\n  } catch (error) {\n    logger.error(`Error creating task \"${config.name}\":`, error);\n    throw error;\n  }\n};\n\n/**\n * Create a new task synchronously\n * @param config Configuration for the task\n * @param memory Optional memory instance for task context storage\n * @returns The new task instance\n */\nexport const createTaskSync = (\n  config: TaskConfig,\n  memory?: MemoryInstance\n): TaskInstance => {\n  try {\n    logger.debug(`Creating task \"${config.name}\" synchronously`);\n    return Task.createTaskSync(config, memory);\n  } catch (error) {\n    logger.error(`Error creating task \"${config.name}\":`, error);\n    throw error;\n  }\n};\n\n\nexport { TaskManager, Task }; "],"mappings":"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","names":["createPrefix","color","options","FRAMEWORK_NAME","colors","getTimestamp","now","lastLogTime","date","log","level","messages","prefix","timestamp","safeConsole","coloredMessages","msg","strippedPrefix","str","result","inEscSeq","i","method","args","configure","newOptions","printBanner","FRAMEWORK_VERSION","LogLevel","defaultOptions","logger","init_logger","__esmMin","taskId","message","taskName","agentName","operation","sessionId","shortId","pluginName","capitalizedPluginName","workflowName","chars","interval","finalMessage","enabled","DEFAULT_AGENT_NAME","DEFAULT_MODEL","DEFAULT_TEMPERATURE","DEFAULT_MAX_TOKENS","init_agent","__esmMin","DEFAULT_MEMORY_SIZE","init_memory","__esmMin","DEFAULT_DB_PATH","VECTOR_DATABASE_TYPES","init_database","__esmMin","PROVIDER_TYPES","DEFAULT_OPENAI_BASE_URL","DEFAULT_OPENAI_EMBEDDING_MODEL","DEFAULT_OLLAMA_BASE_URL","DEFAULT_MODEL_CONFIGS","init_provider","__esmMin","DEFAULT_CHUNK_SIZE","DEFAULT_CHUNK_OVERLAP","DEFAULT_VECTOR_SIMILARITY_THRESHOLD","DEFAULT_MAX_RESULTS","init_rag","__esmMin","DEFAULT_TASK_CONCURRENCY","DEFAULT_MAX_RETRIES","TASK_STATUS","init_task","__esmMin","ERROR_MESSAGES","init_error","__esmMin","init_constants","__esmMin","init_agent","init_memory","init_database","init_provider","init_rag","init_task","init_error","OpenAI","createOpenAIConfig","modelName","config","OpenAIProvider","init_openai","__esmMin","init_logger","provider","messages","options","formattedMessages","requestOptions","logger","response","error","onChunk","stream","fullResponse","chunk","content","systemMessage","msg","tool","parameters","schemaObject","requiredParams","param","propertyDef","message","toolCalls","call","args","e","createOllamaConfig","modelName","config","DEFAULT_OLLAMA_BASE_URL","OllamaProvider","init_ollama","__esmMin","init_constants","init_logger","provider","messages","options","formattedMessages","requestOptions","logger","response","errorText","data","error","systemMessage","msg","tool","parameters","schemaObject","requiredParams","param","propertyDef","message","toolCalls","call","args","e","embedding_exports","__export","Embedding","OpenAI","dotenv","init_embedding","__esmMin","init_logger","init_constants","apiKey","text","model","DEFAULT_OPENAI_EMBEDDING_MODEL","client","logger","error","embedding1","embedding2","dotProduct","magnitude1","magnitude2","i","queryEmbedding","textEmbeddings","limit","embedding","b","testEmbedding","providers_exports","__export","Embedding","OllamaProvider","OpenAIProvider","createOllamaConfig","createOpenAIConfig","createProvider","init_providers","__esmMin","init_openai","init_ollama","init_embedding","config","name","modelConfig","text","embeddingModel","error","ollamaConfigBase","ollamaConfig","init_logger","uuidv4","fs","path","dotenv","knex","createSqliteDatabase","config","knex","createPostgresqlDatabase","config","uuidv4","init_logger","validateRequiredParams","params","requiredParams","functionName","missingParams","param","validateRequiredParam","value","paramName","init_logger","createRAGTools","rag","tools","params","query","limit","results","r","error","logger","vectorRAG","content","metadata","documentId","document","documentRAG","filter","init_constants","uuidv4","dotenv","Database","config","validateRequiredParam","validateRequiredParams","prefix","name","tableName","createSqliteDatabase","createPostgresqlDatabase","logger","error","query","params","schema","memoriesTableName","memoryTable","contextRecords","memoryRecords","record","uuidv4","migrationError","knexInstance","data","filter","createDatabase","dbType","dbPath","DEFAULT_DB_PATH","dir","path","fs","url","host","port","user","password","database","db","_PluginManager","config","validateRequiredParam","validateRequiredParams","tool","logger","name","error","removed","plugin","result","agentId","plugins","index","pluginOrPath","module","PluginManager","init_logger","init_constants","Agent","config","validateRequiredParam","validateRequiredParams","defaultModelName","uuidv4","DEFAULT_AGENT_NAME","tool","ragTools","createRAGTools","logger","plugin","pluginTools","PluginManager","toolPlugin","sessionId","limit","params","session","error","message","systemPrompt","temperature","maxTokens","metadata","history","messages","msg","response","responseContent","onChunk","fullResponse","model","openaiClient","stream","chunk","content","words","i","word","resolve","chatManager","chatId","updates","createAgent","agent","db","createDatabase","tableNames","table","agentsTable","init_providers","init_providers","uuidv4","init_constants","MemoryManager","_MemoryManager","config","validateRequiredParam","validateRequiredParams","logger","database","fullConfig","tableName","table","error","entry","enableEmbeddings","id","uuidv4","timestamp","entryToInsert","generatedEmbedding","Embedding","embeddingError","dbEntry","sessionId","limit","maxEntries","entries","agentId","userId","processedEntry","query","results","embedding","threshold","filteredResults","parsedEmbedding","similarity","item","a","b","result","memories","summary","role","validRoles","sessions","session","createMemory","uuidv4","VectorDatabaseType","RAGType","dotenv","knex","BaseVectorDatabaseConnector","config","PostgresVectorDatabaseConnector","logger","table","error","vectors","rows","id","vector","metadata","documentId","content","restMetadata","batchSize","i","batch","limit","threshold","distanceThreshold","row","result","ids","MainDatabaseVectorConnector","database","dbTableNames","records","results","storedVector","similarity","parseError","a","b","vecA","vecB","dotProduct","normA","normB","createVectorDatabaseConnector","loadVectorDatabaseConfigFromEnv","mainDbConfig","type","connectionString","parsedOptions","url","init_constants","VectorRAG","_VectorRAG","config","validateRequiredParam","validateRequiredParams","createVectorDatabaseConnector","logger","instance","error","database","associationsTableName","table","documentsTableName","chunksTableName","document","documentId","uuidv4","chunks","i","batch","chunk","chunkId","chunkSize","chunkOverlap","text","chunkContent","tableName","provider","memory","embedding","textForEmbedding","embeddingError","Embedding","memoryError","chunkIndex","id","chunkAssociations","content","metadata","association","chunkMetadata","chunkIds","c","query","limit","maxResults","queryEmbedding","threshold","similarVectors","chunkDetails","result","similarityResult","v","parseError","results","vector","vectorMetadata","vecA","vecB","dotProduct","normA","normB","createVectorRAG","uuidv4","DocumentRAG","_DocumentRAG","config","validateRequiredParam","validateRequiredParams","logger","instance","error","database","storeEmbeddings","tableName","table","document","memory","id","uuidv4","docToInsert","embedding","Embedding","embeddingError","result","query","limit","queryEmbedding","filter","maxResults","documents","results","doc","metadata","matches","key","value","docEmbedding","similarity","a","b","vecA","vecB","dotProduct","normA","normB","i","createDocumentRAG","fs","path","PDFDocument","uuidv4","parsePDF","filePath","options","logger","documentId","opts","dataBuffer","fs","pdfDoc","PDFDocument","title","author","creationDate","numPages","allText","error","baseMetadata","path","pdfMetadata","documents","splitPDFContent","text","splitStrategy","splitBySimpleChunks","splitByParagraphs","splitBySections","chunkSize","chunkOverlap","chunks","avgCharsPerPage","i","content","estimatedPage","paragraphs","p","currentChunk","chunkStart","paragraph","overlapPoint","charCount","headerRegex","allCapsRegex","currentSection","currentTitle","sectionStart","isLikelyHeader","subChunks","parseDirectoryOfPDFs","dirPath","pdfFiles","file","results","pdfFile","createRAG","config","type","baseConfig","vectorConfig","documentConfig","createVectorRAG","createDocumentRAG","init_logger","init_providers","init_constants","ChatManager","config","validateRequiredParam","params","chatId","generateChatId","now","existingChat","chatMetadata","logger","agentId","userId","message","model","systemPrompt","tools","taskManager","metadata","embedding","useTaskSystem","temperature","maxTokens","history","messages","entry","availableTools","tool","systemMessage","msg","response","analysisResponse","responseText","jsonString","taskConfigs","taskConfig","taskResults","resultSummary","taskId","result","taskResponse","error","toolResults","toolCall","t","toolResultsMessage","tr","finalResponse","r","assistantEmbedding","Embedding","updates","updateData","query","limit","offset","row","messageId","chat","title","generateTitleFromMessage","stats","chatTitle","createChat","chatManager","tableName","table","content","init_constants","uuidv4","IntentRecognizer","taskName","taskDescription","availableTools","model","logger","toolsInfo","tool","prompt","response","toolNames","match","error","name","Task","_Task","config","memory","model","database","uuidv4","error","logger","allTools","PluginManager","configPlugins","pluginName","selectedTools","IntentRecognizer","t","input","taskInput","taskContext","enrichedInput","currentOutput","p","prioritizedPlugins","formattedTools","tool","formattedParameters","properties","required","param","messages","systemMessage","toolsWithPotentialIssues","params","completionOptions","completion","toolCalls","toolResults","i","call","result","resultsMessage","tr","summaryResponse","summaryContent","toolCallMatches","parsedCalls","match","toolName","argsMatch","argsString","args","err","pluginOutput","plugin","finalOutput","_context","strippedOutput","sessionId","contextMemories","m","a","b","aTime","parseError","contextData","serializedData","content","role","additionalMetadata","task","table","tasksTable","taskData","TaskManager","config","err","logger","task","model","Task","existingTask","validPlugins","plugin","taskModel","taskInstance","error","parentId","id","updatedConfig","db","createDatabase","taskRecords","record","plugins","input","dependencies","result","taskConfig","agentId","sessionId","memory","taskIds","results","tasksToRun","taskDependencyMap","dependentTasksMap","taskId","depId","completedTasks","taskQueue","concurrency","batchPromises","dependencyOutputs","hasOutputs","depResult","mergedInput","dependentTasks","dependentId","dependentTask","unresolvedTasks","t","createTaskManager","config","logger","TaskManager","error","createTask","memory","Task","createTaskSync"]}