{"version":3,"sources":["../src/index.ts","../src/agent/defaults.ts","../src/plugin/defaults.ts","../src/errors/index.ts","../src/plugin/index.ts","../src/task/index.ts","../src/database/index.ts","../src/database/defaults.ts","../src/logger/index.ts","../src/database/knex.ts","../src/database/encryption.ts","../src/database/utils.ts","../src/database/sensitive-fields.ts","../src/llm/providers/openai.ts","../src/llm/types.ts","../src/llm/providers/claude.ts","../src/llm/providers/gemini.ts","../src/llm/providers/ollama.ts","../src/llm/models.ts","../src/llm/defaults.ts","../src/llm/index.ts","../src/memory/defaults.ts","../src/memory/index.ts","../src/task/defaults.ts","../src/mcp/index.ts","../src/knowledge/storage.ts","../src/knowledge/defaults.ts","../src/knowledge/plugin.ts","../src/knowledge/index.ts","../src/vision/tools.ts","../src/vision/index.ts","../src/vision/defaults.ts","../src/sub-agent/coordination.ts","../src/sub-agent/defaults.ts","../src/sub-agent/delegation.ts","../src/sub-agent/index.ts","../src/context/defaults.ts","../src/context/strategies.ts","../src/context/compressor.ts","../src/context/storage.ts","../src/context/manager.ts","../src/agent/index.ts","../src/graph/storage.ts","../src/graph/index.ts","../src/scheduler/parser.ts"],"sourcesContent":["// Main exports\nexport { Agent } from './agent';\nexport type { AgentConfig, AskOptions } from './agent/types';\n\n// Sub-agent exports\nexport { SubAgent } from './sub-agent';\nexport type {\n  SubAgentTask,\n  SubAgentResult,\n  SubAgentCoordinationResult,\n  DelegationStrategy,\n} from './sub-agent/types';\n\n// Common types\nexport type { MetadataObject } from './types';\nexport { Memory } from './memory';\nexport { Task } from './task';\n\n// Database exports\nexport { getDatabase } from './database';\nexport type { DatabaseConfig } from './database/types';\n\n// Memory types\nexport type { Memory as MemoryType, MemorySearchOptions } from './memory/types';\n\n// Task types\nexport type {\n  Task as TaskType,\n  TaskRequest,\n  TaskResponse,\n  TaskSearchOptions,\n  TaskStatus,\n} from './task/types';\n\n// LLM exports\nexport { getLLM, clearLLMInstances } from './llm';\nexport type { LLMProvider, LLMRequestOptions, LLMResponse, LLMUsage } from './llm/types';\n\n// Logger exports\nexport { getLogger, initializeLogger, shutdownLogger, resetLogger } from './logger';\nexport type { Logger, LoggerConfig, LogLevel } from './logger/types';\n\n// Graph exports\nexport { Graph } from './graph';\nexport type {\n  Graph as GraphType,\n  GraphNode,\n  GraphEdge,\n  GraphConfig,\n  GraphExecutionResult,\n  AddAgentNodeOptions,\n  AddTaskNodeOptions,\n} from './graph/types';\n\n// Plugin exports\nexport { getPlugin, Plugin } from './plugin';\nexport type {\n  Plugin as PluginDefinition,\n  ToolDefinition,\n  ToolCall,\n  ToolResult,\n  ToolContext,\n  ToolCallResult,\n  PluginConfig,\n} from './plugin/types';\n\n// MCP exports\nexport { getMCP } from './mcp';\nexport type {\n  MCPServerConfig,\n  MCPTool,\n  MCPToolCall,\n  MCPToolResult,\n  MCPServerDefinition,\n} from './mcp/types';\n\n// Knowledge exports\nexport { Knowledge, knowledgeSearchTool, knowledgeTools } from './knowledge';\nexport type { KnowledgeConfig } from './knowledge';\n\n// Scheduler exports - simplified utilities only\nexport { parseScheduleString } from './scheduler';\nexport type { Schedule, ScheduledItem, SchedulerConfig, ScheduleOptions } from './scheduler/types';\n\n// Context exports\nexport { ContextManager, ContextCompressor, Context } from './context';\nexport type {\n  ContextMessage,\n  ContextWindow,\n  ContextAnalysis,\n  CompressionResult,\n  ContextCompressorOptions,\n  ContextSummary,\n} from './context/types';\n\n// Default export\nexport { default } from './agent';\n","/**\n * Default configuration values for agents\n */\nexport const DEFAULT_AGENT_CONFIG = {\n  model: 'gpt-4o-mini',\n  temperature: 0.7,\n  maxTokens: 2000,\n  useTools: true,\n  memory: false,\n  knowledge: false,\n  vision: false,\n  autoContextCompression: false,\n  debug: false,\n} as const;\n\n/**\n * Get default value for an agent config property\n */\nexport function getDefaultValue<K extends keyof typeof DEFAULT_AGENT_CONFIG>(\n  key: K\n): (typeof DEFAULT_AGENT_CONFIG)[K] {\n  return DEFAULT_AGENT_CONFIG[key];\n}\n","/**\n * Default configuration values for plugin module\n */\nexport const DEFAULT_PLUGIN_CONFIG = {\n  defaultVersion: 'unknown',\n  defaultDescription: 'none',\n  missingName: '[missing]',\n  defaultTimeout: 30000, // 30 seconds\n} as const;\n\n/**\n * Get default value for a plugin config property\n */\nexport function getPluginDefaultValue<K extends keyof typeof DEFAULT_PLUGIN_CONFIG>(\n  key: K\n): (typeof DEFAULT_PLUGIN_CONFIG)[K] {\n  return DEFAULT_PLUGIN_CONFIG[key];\n}\n","/**\n * Custom Error Classes for Astreus\n *\n * These error classes provide structured error handling with:\n * - Error cause chaining (ES2022 Error cause)\n * - Provider/service context\n * - Proper error names for debugging\n *\n * Graceful Degradation Notes:\n * - LLMApiError: Provider failures should trigger retry with exponential backoff\n * - DatabaseError: Non-critical DB operations can use cached data as fallback\n * - MCPConnectionError: MCP server failures allow agent to continue without that tool\n * - SubAgentError: Sub-agent failures return partial results when possible\n */\n\n/**\n * Base error class for all Astreus errors\n * Provides consistent error structure with cause chaining\n */\nexport class AstreusError extends Error {\n  public readonly cause?: Error;\n\n  constructor(message: string, cause?: Error) {\n    super(message);\n    this.cause = cause;\n    this.name = 'AstreusError';\n    // Maintain proper prototype chain for instanceof checks\n    Object.setPrototypeOf(this, new.target.prototype);\n  }\n\n  /**\n   * Get the full error chain as a string for logging\n   */\n  getFullStack(): string {\n    let fullStack = this.stack || this.message;\n    if (this.cause instanceof Error) {\n      fullStack += `\\nCaused by: ${this.cause.stack || this.cause.message}`;\n    }\n    return fullStack;\n  }\n}\n\n/**\n * Error thrown when an LLM API request fails\n * Use this for OpenAI, Claude, Gemini, Ollama provider errors\n *\n * Graceful Degradation:\n * - Retry with exponential backoff (already implemented in providers)\n * - For embedding failures: continue without semantic search\n * - For vision failures: return text-based analysis if available\n */\nexport class LLMApiError extends AstreusError {\n  constructor(\n    message: string,\n    public readonly provider: string,\n    cause?: Error\n  ) {\n    super(message, cause);\n    this.name = 'LLMApiError';\n  }\n}\n\n/**\n * Error thrown for database operations\n * Use this for connection, query, and schema errors\n *\n * Graceful Degradation:\n * - Memory operations: Fall back to in-memory cache\n * - Agent config: Use default configuration\n * - Context storage: Continue without persistence\n */\nexport class DatabaseError extends AstreusError {\n  constructor(message: string, cause?: Error) {\n    super(message, cause);\n    this.name = 'DatabaseError';\n  }\n}\n\n/**\n * Error thrown when MCP server connection or communication fails\n * Use this for MCP process spawn, message, and tool call errors\n *\n * Graceful Degradation:\n * - Tool discovery: Agent continues without MCP tools\n * - Tool call failure: Return error result to LLM for alternative approach\n * - Server crash: Attempt reconnection on next tool call\n */\nexport class MCPConnectionError extends AstreusError {\n  constructor(\n    message: string,\n    public readonly serverName: string,\n    cause?: Error\n  ) {\n    super(message, cause);\n    this.name = 'MCPConnectionError';\n  }\n}\n\n/**\n * Error thrown when sub-agent operations fail\n * Use this for delegation, coordination, and execution errors\n *\n * Graceful Degradation:\n * - Single sub-agent failure: Return results from successful sub-agents\n * - All sub-agents fail: Fall back to main agent processing\n * - Timeout: Return partial results with timeout indication\n */\nexport class SubAgentError extends AstreusError {\n  constructor(\n    message: string,\n    public readonly agentId?: string,\n    cause?: Error\n  ) {\n    super(message, cause);\n    this.name = 'SubAgentError';\n  }\n}\n\n/**\n * Error thrown when context operations fail\n * Use this for context compression, loading, and storage errors\n *\n * Graceful Degradation:\n * - Compression failure: Use uncompressed context (may hit token limits)\n * - Load failure: Start with empty context\n * - Save failure: Log warning and continue (context lost on restart)\n */\nexport class ContextError extends AstreusError {\n  constructor(message: string, cause?: Error) {\n    super(message, cause);\n    this.name = 'ContextError';\n  }\n}\n\n/**\n * Error thrown when knowledge base operations fail\n * Use this for document indexing, search, and retrieval errors\n *\n * Graceful Degradation:\n * - Search failure: Continue without knowledge augmentation\n * - Index failure: Log warning and skip document\n * - Embedding failure: Fall back to keyword search\n */\nexport class KnowledgeError extends AstreusError {\n  constructor(message: string, cause?: Error) {\n    super(message, cause);\n    this.name = 'KnowledgeError';\n  }\n}\n\n/**\n * Error thrown when vision analysis fails\n * Use this for image processing and analysis errors\n *\n * Graceful Degradation:\n * - Analysis failure: Return error message to user\n * - Unsupported format: Suggest alternative formats\n * - Model unavailable: Fall back to text description request\n */\nexport class VisionError extends AstreusError {\n  constructor(\n    message: string,\n    public readonly provider: string,\n    cause?: Error\n  ) {\n    super(message, cause);\n    this.name = 'VisionError';\n  }\n}\n\n/**\n * Error thrown when configuration is invalid\n * This is typically a non-recoverable error requiring user intervention\n */\nexport class ConfigurationError extends AstreusError {\n  constructor(message: string, cause?: Error) {\n    super(message, cause);\n    this.name = 'ConfigurationError';\n  }\n}\n\n/**\n * Error thrown when a Graph node execution fails\n * Provides detailed error chain with node context for debugging\n *\n * Graceful Degradation:\n * - Node failure: Skip dependent nodes, continue with independent ones\n * - Critical node failure: Mark graph as failed, return partial results\n * - Timeout: Return timeout error with node context\n */\nexport class GraphNodeError extends AstreusError {\n  constructor(\n    message: string,\n    public readonly nodeId: string,\n    public readonly nodeName: string,\n    public readonly step: 'initialization' | 'dependency_check' | 'execution' | 'result_processing',\n    public readonly graphId?: string,\n    public readonly parentNodeId?: string,\n    cause?: Error\n  ) {\n    super(message, cause);\n    this.name = 'GraphNodeError';\n  }\n\n  /**\n   * Get error chain information for debugging\n   */\n  getErrorChain(): {\n    nodeId: string;\n    nodeName: string;\n    step: string;\n    graphId?: string;\n    parentNodeId?: string;\n    message: string;\n    cause?: string;\n  } {\n    return {\n      nodeId: this.nodeId,\n      nodeName: this.nodeName,\n      step: this.step,\n      graphId: this.graphId,\n      parentNodeId: this.parentNodeId,\n      message: this.message,\n      cause: this.cause instanceof Error ? this.cause.message : undefined,\n    };\n  }\n}\n\n/**\n * Error thrown when a tool call fails (Plugin or MCP)\n * Provides normalized error structure across all tool types\n *\n * Graceful Degradation:\n * - Tool not found: Return error message to LLM\n * - Validation failure: Return validation error to LLM\n * - Execution failure: Return error with context for LLM to try alternative\n * - Timeout: Return timeout error with retry suggestion\n */\nexport class ToolError extends AstreusError {\n  constructor(\n    message: string,\n    public readonly toolName: string,\n    public readonly toolType: 'plugin' | 'mcp' | 'unknown',\n    public readonly errorType: 'not_found' | 'validation' | 'execution' | 'timeout' | 'unknown',\n    public readonly recoverable: boolean = true,\n    cause?: Error\n  ) {\n    super(message, cause);\n    this.name = 'ToolError';\n  }\n\n  /**\n   * Get normalized error response for LLM\n   */\n  toToolResult(): { success: false; error: string; recoverable: boolean; toolType: string } {\n    return {\n      success: false,\n      error: this.message,\n      recoverable: this.recoverable,\n      toolType: this.toolType,\n    };\n  }\n}\n\n/**\n * Type guard to check if an error is a GraphNodeError\n */\nexport function isGraphNodeError(error: unknown): error is GraphNodeError {\n  return error instanceof GraphNodeError;\n}\n\n/**\n * Type guard to check if an error is a ToolError\n */\nexport function isToolError(error: unknown): error is ToolError {\n  return error instanceof ToolError;\n}\n\n/**\n * Type guard to check if an error is an AstreusError\n */\nexport function isAstreusError(error: unknown): error is AstreusError {\n  return error instanceof AstreusError;\n}\n\n/**\n * Type guard to check if an error is an LLMApiError\n */\nexport function isLLMApiError(error: unknown): error is LLMApiError {\n  return error instanceof LLMApiError;\n}\n\n/**\n * Type guard to check if an error is a DatabaseError\n */\nexport function isDatabaseError(error: unknown): error is DatabaseError {\n  return error instanceof DatabaseError;\n}\n\n/**\n * Type guard to check if an error is an MCPConnectionError\n */\nexport function isMCPConnectionError(error: unknown): error is MCPConnectionError {\n  return error instanceof MCPConnectionError;\n}\n\n/**\n * Type guard to check if an error is a SubAgentError\n */\nexport function isSubAgentError(error: unknown): error is SubAgentError {\n  return error instanceof SubAgentError;\n}\n\n/**\n * Wrap an error with proper cause chaining\n * Helper function for consistent error wrapping\n *\n * Note: The error class constructor signature is (message, ...contextArgs, cause?)\n * So we need to place the cause at the end of the args array\n */\nexport function wrapError<T extends AstreusError>(\n  ErrorClass: new (message: string, ...args: unknown[]) => T,\n  message: string,\n  cause: unknown,\n  ...contextArgs: unknown[]\n): T {\n  const originalError = cause instanceof Error ? cause : new Error(String(cause));\n  // Place cause at the end as per AstreusError subclass constructor signatures\n  // e.g., LLMApiError(message, provider, cause?), MCPConnectionError(message, serverName, cause?)\n  return new ErrorClass(message, ...contextArgs, originalError) as T;\n}\n\n/**\n * Type-safe wrapError for LLMApiError\n */\nexport function wrapLLMApiError(message: string, provider: string, cause: unknown): LLMApiError {\n  const originalError = cause instanceof Error ? cause : new Error(String(cause));\n  return new LLMApiError(message, provider, originalError);\n}\n\n/**\n * Type-safe wrapError for MCPConnectionError\n */\nexport function wrapMCPConnectionError(\n  message: string,\n  serverName: string,\n  cause: unknown\n): MCPConnectionError {\n  const originalError = cause instanceof Error ? cause : new Error(String(cause));\n  return new MCPConnectionError(message, serverName, originalError);\n}\n\n/**\n * Type-safe wrapError for SubAgentError\n */\nexport function wrapSubAgentError(\n  message: string,\n  agentId: string | undefined,\n  cause: unknown\n): SubAgentError {\n  const originalError = cause instanceof Error ? cause : new Error(String(cause));\n  return new SubAgentError(message, agentId, originalError);\n}\n\n/**\n * Type-safe wrapError for VisionError\n */\nexport function wrapVisionError(message: string, provider: string, cause: unknown): VisionError {\n  const originalError = cause instanceof Error ? cause : new Error(String(cause));\n  return new VisionError(message, provider, originalError);\n}\n\n/**\n * Type-safe wrapError for simple errors (no extra context)\n */\nexport function wrapSimpleError<T extends AstreusError>(\n  ErrorClass: new (message: string, cause?: Error) => T,\n  message: string,\n  cause: unknown\n): T {\n  const originalError = cause instanceof Error ? cause : new Error(String(cause));\n  return new ErrorClass(message, originalError);\n}\n","import { IAgentModule, IAgent } from '../agent/types';\nimport {\n  Plugin as IPlugin,\n  PluginConfig,\n  PluginManager as IPluginManager,\n  ToolDefinition,\n  ToolCall,\n  ToolCallResult,\n  ToolContext,\n  ToolParameter,\n  ToolParameterValue,\n} from './types';\nimport { Logger } from '../logger/types';\nimport { DEFAULT_PLUGIN_CONFIG } from './defaults';\nimport { ToolError } from '../errors';\n\n// Type for LLM function calling tool schema property\ninterface LLMToolProperty {\n  type: 'string' | 'number' | 'boolean' | 'object' | 'array';\n  description?: string;\n  enum?: Array<string | number>;\n  items?: { type: string };\n  properties?: Record<\n    string,\n    {\n      type: 'string' | 'number' | 'boolean' | 'object' | 'array';\n      description?: string;\n    }\n  >;\n}\n\n// Type for LLM function calling tool schema\ninterface LLMToolSchema {\n  type: 'object';\n  properties: Record<string, LLMToolProperty>;\n  required?: string[];\n}\n\nexport class Plugin implements IAgentModule, IPluginManager {\n  readonly name = 'plugin';\n  private plugins: Map<string, IPlugin> = new Map();\n  private configs: Map<string, PluginConfig> = new Map();\n  private tools: Map<string, ToolDefinition> = new Map();\n  private logger: Logger;\n  private registrationLock: Set<string> = new Set(); // Lock for preventing race conditions\n\n  constructor(private agent: IAgent) {\n    this.logger = agent.logger;\n\n    // User-facing info log\n    this.logger.info('Plugin manager initialized');\n\n    this.logger.debug('Plugin manager initialized', {\n      agentId: agent.id,\n      agentName: agent.name,\n    });\n  }\n\n  async initialize(): Promise<void> {\n    // User-facing info log\n    this.logger.info('Plugin manager ready');\n\n    this.logger.debug('Plugin manager initialization completed');\n  }\n\n  async registerPlugin(plugin: IPlugin, config?: PluginConfig): Promise<void> {\n    // User-facing info log\n    this.logger.info(`Registering plugin: ${plugin.name}`);\n\n    this.logger.debug('Registering plugin', {\n      name: plugin.name,\n      version: plugin.version,\n      description: plugin.description,\n      toolCount: plugin.tools.length,\n      toolNames: plugin.tools.map((t) => t.name),\n      hasConfig: !!config,\n      hasInitialize: !!plugin.initialize,\n      hasCleanup: !!plugin.cleanup,\n    });\n\n    // Check if plugin already exists\n    if (this.plugins.has(plugin.name)) {\n      this.logger.error(`Plugin already registered: ${plugin.name}`);\n      this.logger.debug('Plugin registration failed - already exists', {\n        pluginName: plugin.name,\n        existingPlugins: Array.from(this.plugins.keys()),\n      });\n      throw new Error(`Plugin '${plugin.name}' is already registered`);\n    }\n\n    // Validate plugin\n    this.logger.debug('Validating plugin structure', { pluginName: plugin.name });\n    this.validatePlugin(plugin);\n\n    // Set default config\n    const pluginConfig: PluginConfig = config || {\n      name: plugin.name,\n      enabled: true,\n    };\n\n    this.logger.debug('Plugin config prepared', {\n      pluginName: plugin.name,\n      enabled: pluginConfig.enabled,\n      hasCustomConfig: !!pluginConfig.config,\n    });\n\n    // Initialize plugin if it has an initialize method\n    if (plugin.initialize) {\n      this.logger.debug('Initializing plugin', { pluginName: plugin.name });\n      await plugin.initialize(pluginConfig.config);\n      this.logger.debug('Plugin initialized successfully', { pluginName: plugin.name });\n    }\n\n    // Register plugin and its tools\n    this.plugins.set(plugin.name, plugin);\n    this.configs.set(plugin.name, pluginConfig);\n\n    // Register tools if plugin is enabled\n    if (pluginConfig.enabled) {\n      this.logger.debug('Registering plugin tools', {\n        pluginName: plugin.name,\n        toolCount: plugin.tools.length,\n      });\n\n      for (const tool of plugin.tools) {\n        // Wait if another registration is in progress for this tool name\n        // Add timeout to prevent infinite busy-wait\n        const maxWaitTime = 5000; // 5 seconds max wait\n        const startWait = Date.now();\n        while (this.registrationLock.has(tool.name)) {\n          if (Date.now() - startWait > maxWaitTime) {\n            this.logger.error(`Tool registration lock timeout: ${tool.name}`);\n            throw new Error(`Tool registration timeout for '${tool.name}': lock held for too long`);\n          }\n          await new Promise((r) => setTimeout(r, 10));\n        }\n\n        // Acquire lock for this tool name\n        this.registrationLock.add(tool.name);\n\n        try {\n          if (this.tools.has(tool.name)) {\n            this.logger.error(`Tool name conflict: ${tool.name}`);\n            this.logger.debug('Tool registration failed - name conflict', {\n              toolName: tool.name,\n              pluginName: plugin.name,\n              existingTools: Array.from(this.tools.keys()),\n            });\n            throw new Error(`Tool '${tool.name}' is already registered by another plugin`);\n          }\n          this.tools.set(tool.name, tool);\n\n          this.logger.debug('Tool registered', {\n            toolName: tool.name,\n            pluginName: plugin.name,\n            description: tool.description,\n          });\n        } finally {\n          // Release lock\n          this.registrationLock.delete(tool.name);\n        }\n      }\n    } else {\n      this.logger.debug('Plugin disabled, tools not registered', {\n        pluginName: plugin.name,\n        toolCount: plugin.tools.length,\n      });\n    }\n\n    // User-facing success message\n    this.logger.info(`Plugin registered: ${plugin.name} (${plugin.tools.length} tools)`);\n\n    this.logger.debug('Plugin registered successfully', {\n      pluginName: plugin.name,\n      version: plugin.version,\n      toolsRegistered: pluginConfig.enabled ? plugin.tools.length : 0,\n      totalPlugins: this.plugins.size,\n      totalTools: this.tools.size,\n    });\n  }\n\n  async unregisterPlugin(name: string): Promise<void> {\n    // User-facing info log\n    this.logger.info(`Unregistering plugin: ${name}`);\n\n    this.logger.debug('Unregistering plugin', {\n      pluginName: name,\n      isRegistered: this.plugins.has(name),\n    });\n\n    const plugin = this.plugins.get(name);\n    if (!plugin) {\n      this.logger.error(`Plugin not found: ${name}`);\n      this.logger.debug('Plugin unregistration failed - not found', {\n        pluginName: name,\n        availablePlugins: Array.from(this.plugins.keys()),\n      });\n      throw new Error(`Plugin '${name}' is not registered`);\n    }\n\n    // Remove tools\n    const removedTools = [];\n    for (const tool of plugin.tools) {\n      if (this.tools.has(tool.name)) {\n        this.tools.delete(tool.name);\n        removedTools.push(tool.name);\n\n        this.logger.debug('Tool unregistered', {\n          toolName: tool.name,\n          pluginName: name,\n        });\n      }\n    }\n\n    this.logger.debug('Plugin tools removed', {\n      pluginName: name,\n      removedTools,\n      removedCount: removedTools.length,\n    });\n\n    // Cleanup plugin if it has a cleanup method\n    if (plugin.cleanup) {\n      this.logger.debug('Running plugin cleanup', { pluginName: name });\n      await plugin.cleanup();\n      this.logger.debug('Plugin cleanup completed', { pluginName: name });\n    }\n\n    // Remove plugin\n    this.plugins.delete(name);\n    this.configs.delete(name);\n\n    // User-facing success message\n    this.logger.info(`Plugin unregistered: ${name}`);\n\n    this.logger.debug('Plugin unregistered successfully', {\n      pluginName: name,\n      removedToolCount: removedTools.length,\n      remainingPlugins: this.plugins.size,\n      remainingTools: this.tools.size,\n    });\n  }\n\n  getPlugin(name: string): IPlugin | undefined {\n    const plugin = this.plugins.get(name);\n\n    this.logger.debug('Plugin lookup', {\n      pluginName: name,\n      found: !!plugin,\n      version: plugin?.version ?? DEFAULT_PLUGIN_CONFIG.defaultVersion,\n    });\n\n    return plugin;\n  }\n\n  getTools(): ToolDefinition[] {\n    const tools = Array.from(this.tools.values());\n\n    this.logger.debug('Retrieved all tools', {\n      toolCount: tools.length,\n      toolNames: tools.map((t) => t.name),\n    });\n\n    return tools;\n  }\n\n  getTool(name: string): ToolDefinition | undefined {\n    const tool = this.tools.get(name);\n\n    this.logger.debug('Tool lookup', {\n      toolName: name,\n      found: !!tool,\n      description: tool?.description ?? DEFAULT_PLUGIN_CONFIG.defaultDescription,\n    });\n\n    return tool;\n  }\n\n  async executeTool(toolCall: ToolCall, context?: ToolContext): Promise<ToolCallResult> {\n    const startTime = Date.now();\n\n    // User-facing info log\n    this.logger.info(`Executing tool: ${toolCall.name}`);\n\n    this.logger.debug('Executing tool', {\n      toolName: toolCall.name,\n      callId: toolCall.id,\n      parameters: Object.keys(toolCall.parameters),\n      parameterCount: Object.keys(toolCall.parameters).length,\n      hasContext: !!context,\n    });\n\n    try {\n      const tool = this.getTool(toolCall.name);\n      if (!tool) {\n        this.logger.error(`Tool not found: ${toolCall.name}`);\n        this.logger.debug('Tool execution failed - tool not found', {\n          toolName: toolCall.name,\n          callId: toolCall.id,\n          availableTools: Array.from(this.tools.keys()),\n        });\n\n        return {\n          id: toolCall.id,\n          name: toolCall.name,\n          result: {\n            success: false,\n            error: `Tool '${toolCall.name}' not found`,\n          },\n          executionTime: Date.now() - startTime,\n        };\n      }\n\n      // Validate parameters\n      this.logger.debug('Validating tool parameters', {\n        toolName: toolCall.name,\n        callId: toolCall.id,\n      });\n\n      const validationError = this.validateToolParameters(tool, toolCall.parameters);\n      if (validationError) {\n        this.logger.error(`Tool parameter validation failed: ${toolCall.name}`);\n        this.logger.debug('Tool parameter validation error', {\n          toolName: toolCall.name,\n          callId: toolCall.id,\n          validationError,\n          parameters: toolCall.parameters,\n        });\n\n        return {\n          id: toolCall.id,\n          name: toolCall.name,\n          result: {\n            success: false,\n            error: validationError,\n          },\n          executionTime: Date.now() - startTime,\n        };\n      }\n\n      // Validate agent is available\n      if (!this.agent || typeof this.agent.id !== 'string') {\n        this.logger.error('Agent not available for tool execution');\n        return {\n          id: toolCall.id,\n          name: toolCall.name,\n          result: {\n            success: false,\n            error: 'Agent not available for tool execution',\n          },\n          executionTime: Date.now() - startTime,\n        };\n      }\n\n      // Create isolated execution context for this tool call\n      // This prevents state sharing between plugins and tool calls\n      const isolatedContext: ToolContext = {\n        // Copy existing context properties if provided\n        ...(context || {}),\n        // Add execution isolation metadata\n        agentId: context?.agentId || this.agent.id,\n        agent: context?.agent || this.agent,\n        // Add unique execution ID for this specific call\n        executionId: `${toolCall.id}-${Date.now()}`,\n        // Isolate any shared state by creating fresh copies\n        toolName: toolCall.name,\n        callTimestamp: new Date(),\n      };\n\n      // Execute tool with timeout\n      this.logger.debug('Calling tool handler with isolated context', {\n        toolName: toolCall.name,\n        callId: toolCall.id,\n        timeout: DEFAULT_PLUGIN_CONFIG.defaultTimeout,\n        executionId: isolatedContext.executionId ?? null,\n      });\n\n      let timeoutId: NodeJS.Timeout;\n      const timeoutPromise = new Promise<never>((_, reject) => {\n        timeoutId = setTimeout(() => {\n          reject(\n            new Error(\n              `Tool '${toolCall.name}' execution timed out after ${DEFAULT_PLUGIN_CONFIG.defaultTimeout}ms`\n            )\n          );\n        }, DEFAULT_PLUGIN_CONFIG.defaultTimeout);\n      });\n\n      let result;\n      try {\n        result = await Promise.race([\n          tool.handler(toolCall.parameters, isolatedContext),\n          timeoutPromise,\n        ]);\n        clearTimeout(timeoutId!);\n      } catch (raceError) {\n        clearTimeout(timeoutId!);\n        throw raceError;\n      }\n      const executionTime = Date.now() - startTime;\n\n      // User-facing success message\n      this.logger.info(`Tool completed: ${toolCall.name} (${executionTime}ms)`);\n\n      this.logger.debug('Tool execution successful', {\n        toolName: toolCall.name,\n        callId: toolCall.id,\n        executionTime,\n        success: result.success,\n        hasData: !!result.data,\n        hasError: !!result.error,\n        executionId: isolatedContext.executionId ?? null,\n      });\n\n      return {\n        id: toolCall.id,\n        name: toolCall.name,\n        result,\n        executionTime,\n      };\n    } catch (error) {\n      const executionTime = Date.now() - startTime;\n      const originalError = error instanceof Error ? error : new Error('Unknown error occurred');\n\n      // Determine error type based on error characteristics\n      let errorType: 'not_found' | 'validation' | 'execution' | 'timeout' | 'unknown' = 'execution';\n      if (\n        originalError.message.includes('timed out') ||\n        originalError.message.includes('timeout')\n      ) {\n        errorType = 'timeout';\n      } else if (\n        originalError.message.includes('not found') ||\n        originalError.message.includes('not available')\n      ) {\n        errorType = 'not_found';\n      } else if (\n        originalError.message.includes('Invalid') ||\n        originalError.message.includes('validation')\n      ) {\n        errorType = 'validation';\n      }\n\n      // Determine if error is recoverable\n      const recoverable = errorType !== 'not_found';\n\n      // Create normalized ToolError for consistent error handling\n      const toolError = new ToolError(\n        `Plugin tool '${toolCall.name}' failed: ${originalError.message}`,\n        toolCall.name,\n        'plugin',\n        errorType,\n        recoverable,\n        originalError\n      );\n\n      this.logger.error(`Tool execution failed: ${toolCall.name}`, toolError);\n      this.logger.debug('Tool execution error', {\n        toolName: toolCall.name,\n        callId: toolCall.id,\n        executionTime,\n        errorType,\n        recoverable,\n        error: originalError.message,\n        hasStack: !!originalError.stack,\n      });\n\n      // Return normalized error result\n      const errorResult = toolError.toToolResult();\n      return {\n        id: toolCall.id,\n        name: toolCall.name,\n        result: {\n          success: false,\n          error: errorResult.error,\n        },\n        executionTime,\n      };\n    }\n  }\n\n  listPlugins(): IPlugin[] {\n    const plugins = Array.from(this.plugins.values());\n\n    this.logger.debug('Listed plugins', {\n      pluginCount: plugins.length,\n      pluginNames: plugins.map((p) => p.name),\n    });\n\n    return plugins;\n  }\n\n  // Get tools formatted for LLM function calling\n  getToolsForLLM(): Array<{\n    type: string;\n    function: { name: string; description: string; parameters: LLMToolSchema };\n  }> {\n    const tools = this.getTools();\n    const llmTools = tools.map((tool) => ({\n      type: 'function',\n      function: {\n        name: tool.name,\n        description: tool.description,\n        parameters: this.convertParametersToJsonSchema(tool.parameters),\n      },\n    }));\n\n    this.logger.debug('Generated LLM tool schemas', {\n      toolCount: llmTools.length,\n      toolNames: llmTools.map((t) => t.function.name),\n    });\n\n    return llmTools;\n  }\n\n  private validatePlugin(plugin: IPlugin): void {\n    this.logger.debug('Validating plugin structure', {\n      pluginName: plugin.name,\n      hasName: !!plugin.name,\n      hasVersion: !!plugin.version,\n      hasTools: Array.isArray(plugin.tools),\n      toolCount: Array.isArray(plugin.tools) ? plugin.tools.length : 0,\n    });\n\n    // Validate plugin name\n    if (!plugin.name || typeof plugin.name !== 'string' || plugin.name.trim().length === 0) {\n      this.logger.debug('Plugin validation failed - invalid name', {\n        pluginName: plugin.name ?? DEFAULT_PLUGIN_CONFIG.missingName,\n        nameType: typeof plugin.name,\n      });\n      throw new Error('Plugin must have a valid non-empty name');\n    }\n\n    // Validate plugin version\n    if (\n      !plugin.version ||\n      typeof plugin.version !== 'string' ||\n      plugin.version.trim().length === 0\n    ) {\n      this.logger.debug('Plugin validation failed - invalid version', {\n        pluginName: plugin.name,\n        version: plugin.version ?? DEFAULT_PLUGIN_CONFIG.defaultVersion,\n        versionType: typeof plugin.version,\n      });\n      throw new Error(`Plugin '${plugin.name}' must have a valid non-empty version`);\n    }\n\n    // Validate plugin name format (alphanumeric with hyphens/underscores)\n    const namePattern = /^[a-zA-Z][a-zA-Z0-9_-]*$/;\n    if (!namePattern.test(plugin.name)) {\n      this.logger.debug('Plugin validation failed - invalid name format', {\n        pluginName: plugin.name,\n      });\n      throw new Error(\n        `Plugin name '${plugin.name}' must start with a letter and contain only alphanumeric characters, hyphens, or underscores`\n      );\n    }\n\n    if (!Array.isArray(plugin.tools)) {\n      this.logger.debug('Plugin validation failed - invalid tools array', {\n        pluginName: plugin.name,\n        toolsType: typeof plugin.tools,\n        isArray: Array.isArray(plugin.tools),\n      });\n      throw new Error(`Plugin '${plugin.name}' must have tools array`);\n    }\n\n    // Check for duplicate tool names within the plugin\n    const toolNames = new Set<string>();\n    for (const tool of plugin.tools) {\n      if (toolNames.has(tool.name)) {\n        this.logger.debug('Plugin validation failed - duplicate tool name', {\n          pluginName: plugin.name,\n          duplicateToolName: tool.name,\n        });\n        throw new Error(`Plugin '${plugin.name}' has duplicate tool name '${tool.name}'`);\n      }\n      toolNames.add(tool.name);\n    }\n\n    // Validate each tool\n    for (const tool of plugin.tools) {\n      this.logger.debug('Validating tool definition', {\n        pluginName: plugin.name,\n        toolName: tool.name,\n        hasName: !!tool.name,\n        hasDescription: !!tool.description,\n        hasHandler: !!tool.handler,\n      });\n\n      if (!tool.name || typeof tool.name !== 'string' || tool.name.trim().length === 0) {\n        this.logger.debug('Tool validation failed - invalid name', {\n          pluginName: plugin.name,\n          toolName: tool.name ?? DEFAULT_PLUGIN_CONFIG.missingName,\n        });\n        throw new Error(`Invalid tool name in plugin '${plugin.name}'`);\n      }\n\n      if (!tool.description || typeof tool.description !== 'string') {\n        this.logger.debug('Tool validation failed - invalid description', {\n          pluginName: plugin.name,\n          toolName: tool.name,\n        });\n        throw new Error(\n          `Tool '${tool.name}' in plugin '${plugin.name}' must have a valid description`\n        );\n      }\n\n      if (!tool.handler || typeof tool.handler !== 'function') {\n        this.logger.debug('Tool validation failed - invalid handler', {\n          pluginName: plugin.name,\n          toolName: tool.name,\n          handlerType: typeof tool.handler,\n        });\n        throw new Error(\n          `Tool '${tool.name}' in plugin '${plugin.name}' must have a valid handler function`\n        );\n      }\n\n      // Validate tool parameters\n      if (tool.parameters && typeof tool.parameters === 'object') {\n        this.validateToolParameterDefinitions(plugin.name, tool.name, tool.parameters);\n      }\n    }\n\n    this.logger.debug('Plugin validation successful', {\n      pluginName: plugin.name,\n      version: plugin.version,\n      toolCount: plugin.tools.length,\n    });\n  }\n\n  private validateToolParameterDefinitions(\n    pluginName: string,\n    toolName: string,\n    parameters: Record<string, ToolParameter>,\n    depth: number = 0\n  ): void {\n    // Prevent stack overflow with depth limit\n    const MAX_DEPTH = 50;\n    if (depth > MAX_DEPTH) {\n      throw new Error(`Parameter nesting too deep in tool '${toolName}' (max depth: ${MAX_DEPTH})`);\n    }\n\n    const validTypes = ['string', 'number', 'boolean', 'object', 'array'];\n\n    for (const [paramName, paramDef] of Object.entries(parameters)) {\n      if (!paramDef.type || !validTypes.includes(paramDef.type)) {\n        this.logger.debug('Parameter validation failed - invalid type', {\n          pluginName,\n          toolName,\n          paramName,\n          paramType: paramDef.type,\n          validTypes,\n        });\n        throw new Error(\n          `Parameter '${paramName}' in tool '${toolName}' has invalid type '${paramDef.type}'`\n        );\n      }\n\n      if (!paramDef.description || typeof paramDef.description !== 'string') {\n        this.logger.debug('Parameter validation failed - missing description', {\n          pluginName,\n          toolName,\n          paramName,\n        });\n        throw new Error(`Parameter '${paramName}' in tool '${toolName}' must have a description`);\n      }\n\n      // Validate nested object properties\n      if (paramDef.type === 'object' && paramDef.properties) {\n        this.validateToolParameterDefinitions(pluginName, toolName, paramDef.properties, depth + 1);\n      }\n\n      // Validate array items\n      if (paramDef.type === 'array' && paramDef.items) {\n        if (!validTypes.includes(paramDef.items.type)) {\n          this.logger.debug('Parameter validation failed - invalid array items type', {\n            pluginName,\n            toolName,\n            paramName,\n            itemsType: paramDef.items.type,\n          });\n          throw new Error(\n            `Array parameter '${paramName}' in tool '${toolName}' has invalid items type`\n          );\n        }\n      }\n    }\n  }\n\n  private validateToolParameters(\n    tool: ToolDefinition,\n    parameters: Record<string, ToolParameterValue>\n  ): string | null {\n    this.logger.debug('Validating tool parameters', {\n      toolName: tool.name,\n      expectedParams: Object.keys(tool.parameters),\n      providedParams: Object.keys(parameters),\n      parameterCount: Object.keys(parameters).length,\n    });\n\n    for (const [paramName, paramDef] of Object.entries(tool.parameters)) {\n      const value = parameters[paramName];\n\n      this.logger.debug('Validating parameter', {\n        toolName: tool.name,\n        paramName,\n        paramType: paramDef.type,\n        required: !!paramDef.required,\n        hasValue: value !== undefined && value !== null,\n        valueType: typeof value,\n      });\n\n      // Check required parameters\n      if (paramDef.required && (value === undefined || value === null)) {\n        this.logger.debug('Required parameter missing', {\n          toolName: tool.name,\n          paramName,\n          paramType: paramDef.type,\n        });\n        return `Required parameter '${paramName}' is missing`;\n      }\n\n      // Type validation\n      if (value !== undefined && value !== null) {\n        if (!this.isToolParameterValue(value) || !this.validateParameterType(value, paramDef)) {\n          this.logger.debug('Parameter type validation failed', {\n            toolName: tool.name,\n            paramName,\n            expectedType: paramDef.type,\n            actualType: typeof value,\n            value: String(value).slice(0, 100), // Truncate long values\n          });\n          return `Parameter '${paramName}' has invalid type. Expected ${paramDef.type}`;\n        }\n      }\n    }\n\n    this.logger.debug('Tool parameter validation successful', {\n      toolName: tool.name,\n      validatedParams: Object.keys(tool.parameters).length,\n    });\n\n    return null;\n  }\n\n  private isToolParameterValue(value: unknown, depth: number = 0): value is ToolParameterValue {\n    // Prevent stack overflow with depth limit\n    const MAX_DEPTH = 50;\n    if (depth > MAX_DEPTH) {\n      this.logger.warn('Maximum nesting depth exceeded for parameter validation', { depth });\n      return false;\n    }\n\n    if (value === null) return true;\n    if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {\n      return true;\n    }\n    if (Array.isArray(value)) {\n      return value.every((item) => this.isToolParameterValue(item, depth + 1));\n    }\n    if (typeof value === 'object') {\n      return Object.values(value as Record<string, unknown>).every((v) =>\n        this.isToolParameterValue(v, depth + 1)\n      );\n    }\n    return false;\n  }\n\n  private validateParameterType(value: ToolParameterValue, paramDef: ToolParameter): boolean {\n    switch (paramDef.type) {\n      case 'string':\n        return typeof value === 'string';\n      case 'number':\n        return typeof value === 'number';\n      case 'boolean':\n        return typeof value === 'boolean';\n      case 'object':\n        return typeof value === 'object' && value !== null && !Array.isArray(value);\n      case 'array':\n        return Array.isArray(value);\n      default:\n        return false;\n    }\n  }\n\n  public convertParametersToJsonSchema(\n    parameters: Record<string, ToolParameter>,\n    depth: number = 0\n  ): LLMToolSchema {\n    // Prevent stack overflow with depth limit\n    const MAX_DEPTH = 50;\n    if (depth > MAX_DEPTH) {\n      this.logger.warn('Maximum nesting depth exceeded for JSON schema conversion', { depth });\n      return { type: 'object', properties: {}, required: [] };\n    }\n\n    const properties: Record<string, LLMToolProperty> = {};\n\n    for (const [name, param] of Object.entries(parameters)) {\n      properties[name] = {\n        type: param.type as 'string' | 'number' | 'boolean' | 'object' | 'array',\n        description: param.description,\n      };\n\n      if (param.enum) {\n        properties[name].enum = param.enum;\n      }\n\n      if (param.properties) {\n        properties[name].properties = this.convertParametersToJsonSchema(\n          param.properties,\n          depth + 1\n        ).properties;\n      }\n\n      if (param.items) {\n        properties[name].items = {\n          type: param.items.type,\n        };\n      }\n    }\n\n    return {\n      type: 'object',\n      properties,\n      required: Object.entries(parameters)\n        .filter(([, param]) => param.required)\n        .map(([name]) => name),\n    };\n  }\n}\n\n// Agent-based plugin instances\nconst pluginInstances = new Map<string, Plugin>();\n\nexport function getPlugin(agent?: IAgent): Plugin {\n  if (!agent) {\n    throw new Error('Agent required for plugin initialization');\n  }\n  const agentId = agent.id;\n  if (!pluginInstances.has(agentId)) {\n    pluginInstances.set(agentId, new Plugin(agent));\n  }\n  return pluginInstances.get(agentId)!;\n}\n\n/**\n * Cleanup plugin instance for a specific agent to prevent memory leaks.\n * Should be called when an agent is destroyed or no longer needed.\n * @param agentId - The agent ID to cleanup plugin for.\n */\nexport async function cleanupPluginForAgent(agentId: string): Promise<void> {\n  const plugin = pluginInstances.get(agentId);\n  if (plugin) {\n    // Unregister all plugins to trigger their cleanup methods\n    const plugins = plugin.listPlugins();\n    for (const p of plugins) {\n      await plugin.unregisterPlugin(p.name);\n    }\n    pluginInstances.delete(agentId);\n  }\n}\n\n/**\n * Cleanup plugin instance for a specific agent to prevent memory leaks.\n * Should be called when the plugin manager is no longer needed.\n * @param agentId - The agent ID to cleanup plugin for. If not provided, cleans up all instances.\n */\nexport async function cleanupPlugin(agentId?: string): Promise<void> {\n  if (agentId) {\n    await cleanupPluginForAgent(agentId);\n  } else {\n    // Cleanup all instances\n    const agentIds = Array.from(pluginInstances.keys());\n    for (const id of agentIds) {\n      await cleanupPluginForAgent(id);\n    }\n  }\n}\n\n/**\n * Reset plugin instances (mainly for testing purposes).\n * Performs cleanup before clearing instances to prevent memory leaks.\n * @param agentId - The agent ID to reset plugin for. If not provided, resets all instances.\n */\nexport async function resetPlugin(agentId?: string): Promise<void> {\n  if (agentId) {\n    // Cleanup before deleting\n    const plugin = pluginInstances.get(agentId);\n    if (plugin) {\n      const plugins = plugin.listPlugins();\n      for (const p of plugins) {\n        try {\n          await plugin.unregisterPlugin(p.name);\n        } catch {\n          // Ignore cleanup errors during reset\n        }\n      }\n    }\n    pluginInstances.delete(agentId);\n  } else {\n    // Cleanup all instances before clearing\n    for (const [, plugin] of pluginInstances) {\n      const plugins = plugin.listPlugins();\n      for (const p of plugins) {\n        try {\n          await plugin.unregisterPlugin(p.name);\n        } catch {\n          // Ignore cleanup errors during reset\n        }\n      }\n    }\n    pluginInstances.clear();\n  }\n}\n\nexport * from './types';\n\n// Export utility function for converting tool parameters to JSON schema\nexport function convertToolParametersToJsonSchema(\n  parameters: Record<string, ToolParameter>,\n  depth: number = 0\n): LLMToolSchema {\n  // Prevent stack overflow with depth limit\n  const MAX_DEPTH = 50;\n  if (depth > MAX_DEPTH) {\n    return { type: 'object', properties: {}, required: [] };\n  }\n\n  const properties: Record<string, LLMToolProperty> = {};\n\n  for (const [name, param] of Object.entries(parameters)) {\n    properties[name] = {\n      type: param.type as 'string' | 'number' | 'boolean' | 'object' | 'array',\n      description: param.description,\n    };\n\n    if (param.enum) {\n      properties[name].enum = param.enum;\n    }\n\n    if (param.properties) {\n      properties[name].properties = convertToolParametersToJsonSchema(\n        param.properties,\n        depth + 1\n      ).properties;\n    }\n\n    if (param.items) {\n      properties[name].items = {\n        type: param.items.type,\n      };\n    }\n  }\n\n  return {\n    type: 'object',\n    properties,\n    required: Object.entries(parameters)\n      .filter(([, param]) => param.required)\n      .map(([name]) => name),\n  };\n}\n","import crypto from 'crypto';\nimport { IAgentModule, IAgent } from '../agent/types';\nimport { SubAgentRunOptions } from '../sub-agent/types';\nimport {\n  Task as TaskType,\n  TaskSearchOptions,\n  TaskStatus,\n  TaskRequest,\n  TaskResponse,\n} from './types';\nimport { getDatabase } from '../database';\nimport {\n  getLLM,\n  LLMResponse,\n  LLMMessage,\n  LLMMessageContent,\n  LLMMessageContentPart,\n  Tool,\n  ToolCall,\n} from '../llm';\nimport { LLMUsage } from '../llm/types';\nimport { Memory } from '../memory';\nimport { Memory as MemoryType } from '../memory/types';\nimport { Knex } from 'knex';\nimport { Logger } from '../logger/types';\nimport { encryptSensitiveFields, decryptSensitiveFields } from '../database/utils';\nimport * as fs from 'fs/promises';\nimport * as path from 'path';\nimport { DEFAULT_AGENT_CONFIG } from '../agent/defaults';\nimport { DEFAULT_TASK_CONFIG } from './defaults';\nimport { convertToolParametersToJsonSchema } from '../plugin';\nimport { MetadataObject } from '../types';\n\n/**\n * Simple async mutex for protecting initialization.\n * Replaces spin-wait anti-pattern with proper promise-based waiting.\n */\nclass AsyncMutex {\n  private locked = false;\n  private queue: Array<() => void> = [];\n\n  async acquire(): Promise<void> {\n    if (!this.locked) {\n      this.locked = true;\n      return;\n    }\n    return new Promise<void>((resolve) => {\n      this.queue.push(resolve);\n    });\n  }\n\n  release(): void {\n    const next = this.queue.shift();\n    if (next) {\n      next();\n    } else {\n      this.locked = false;\n    }\n  }\n}\n\n// Database row interfaces\ninterface TaskDbRow {\n  id: string; // UUID\n  agentId: string; // UUID\n  prompt: string;\n  response: string | null;\n  status: TaskStatus;\n  metadata: string | null;\n  created_at: string;\n  updated_at: string;\n  completedAt: string | null;\n}\n\nexport class Task implements IAgentModule {\n  readonly name = 'task';\n  private knex: Knex | null = null;\n  private logger: Logger;\n  private static initializingDatabase: Promise<void> | null = null;\n  private static readonly MAX_TOOL_CALLS = DEFAULT_TASK_CONFIG.maxToolCalls;\n  // AsyncMutex pattern for race condition prevention (replaces spin-wait)\n  private static initMutex = new AsyncMutex();\n\n  constructor(private agent: IAgent) {\n    this.logger = agent.logger;\n  }\n\n  async initialize(): Promise<void> {\n    await this.ensureDatabase();\n  }\n\n  private async ensureDatabase(): Promise<void> {\n    if (this.knex) {\n      return;\n    }\n\n    // Check if another instance is already initializing\n    if (Task.initializingDatabase) {\n      await Task.initializingDatabase;\n      // After waiting, get the knex instance from the initialized database\n      const db = await getDatabase();\n      this.knex = db.getKnex();\n      return;\n    }\n\n    // Use AsyncMutex instead of spin-wait for proper synchronization\n    await Task.initMutex.acquire();\n    let mutexReleased = false;\n    try {\n      // Double-check after acquiring lock\n      if (this.knex) return;\n\n      // Check again if initialization started while waiting for lock\n      if (Task.initializingDatabase) {\n        // Release mutex early since we'll wait on the promise\n        Task.initMutex.release();\n        mutexReleased = true;\n        await Task.initializingDatabase;\n        const db = await getDatabase();\n        this.knex = db.getKnex();\n        return;\n      }\n\n      // Start initialization\n      Task.initializingDatabase = (async () => {\n        const db = await getDatabase();\n        this.knex = db.getKnex();\n      })();\n\n      try {\n        await Task.initializingDatabase;\n      } finally {\n        Task.initializingDatabase = null;\n      }\n    } finally {\n      // Only release if not already released\n      if (!mutexReleased) {\n        Task.initMutex.release();\n      }\n    }\n  }\n\n  private getKnex(): Knex {\n    if (!this.knex) {\n      throw new Error('Database not initialized. Call ensureDatabase() first.');\n    }\n    return this.knex;\n  }\n\n  async createTask(request: TaskRequest): Promise<TaskType> {\n    // User-facing info log\n    this.logger.info('Creating new task');\n\n    this.logger.debug('Creating task', {\n      promptLength: request.prompt.length,\n      promptPreview: request.prompt.slice(0, 100) + '...',\n      agentId: this.agent.id,\n      hasAttachments: !!request.attachments?.length,\n      hasMcpServers: !!request.mcpServers?.length,\n      hasPlugins: !!request.plugins?.length,\n      useTools: !!request.useTools,\n    });\n\n    await this.ensureDatabase();\n    const tableName = 'tasks';\n\n    const metadata = request.metadata || {};\n    if (request.useTools !== undefined) {\n      metadata.useTools = request.useTools;\n    }\n    if (request.attachments) {\n      metadata.attachments = JSON.stringify(request.attachments);\n    }\n    if (request.mcpServers) {\n      metadata.mcpServers = JSON.stringify(request.mcpServers);\n    }\n    if (request.plugins) {\n      metadata.plugins = JSON.stringify(request.plugins);\n    }\n    if (request.schedule) {\n      metadata.schedule = request.schedule;\n    }\n    // Store sub-agent delegation options\n    if (request.useSubAgents !== undefined) {\n      metadata.useSubAgents = request.useSubAgents;\n    }\n    if (request.subAgentDelegation) {\n      metadata.subAgentDelegation = request.subAgentDelegation;\n    }\n    if (request.subAgentCoordination) {\n      metadata.subAgentCoordination = request.subAgentCoordination;\n    }\n    if (request.taskAssignment) {\n      metadata.taskAssignment = JSON.stringify(request.taskAssignment);\n    }\n\n    // Process attachments and enhance prompt\n    let enhancedPrompt = request.prompt;\n\n    if (request.attachments && request.attachments.length > 0) {\n      const attachmentDescriptions = await Promise.all(\n        request.attachments.map(async (attachment) => {\n          const displayName = attachment.name || attachment.path?.split('/').pop() || 'unknown';\n          let description = `${attachment.type}: ${displayName} (${attachment.path})`;\n\n          if (attachment.language) {\n            description += ` [Language: ${attachment.language}]`;\n          }\n\n          // For text-based files, include a preview\n          if (['text', 'markdown', 'code', 'json'].includes(attachment.type)) {\n            try {\n              const content = await fs.readFile(attachment.path, 'utf-8');\n              const preview = content.length > 200 ? content.slice(0, 200) + '...' : content;\n              description += `\\nPreview: ${preview}`;\n            } catch (error) {\n              description += ` [File not accessible: ${error instanceof Error ? error.message : 'Unknown error'}]`;\n            }\n          }\n\n          return description;\n        })\n      );\n\n      enhancedPrompt = `${request.prompt}\\n\\nAttached files:\\n${attachmentDescriptions.join('\\n\\n')}`;\n\n      // Auto-enable tools if attachments are present and useTools not explicitly set\n      if (request.useTools === undefined) {\n        metadata.useTools = true;\n      }\n    }\n\n    // Prepare data for encryption\n    const insertData = {\n      id: crypto.randomUUID(), // Generate UUID for task\n      agentId: this.agent.id,\n      graphId: request.graphId || null, // Graph relationship\n      graphNodeId: request.graphNodeId || null, // Graph node relationship\n      prompt: enhancedPrompt,\n      response: null,\n      status: 'pending',\n      metadata: Object.keys(metadata).length > 0 ? JSON.stringify(metadata) : null,\n      executionContext: request.executionContext ? JSON.stringify(request.executionContext) : null,\n    };\n\n    // Encrypt sensitive fields using centralized encryption\n    const encryptedData = await encryptSensitiveFields(insertData, 'tasks');\n\n    // Use transaction for atomicity - ensures data consistency\n    const task = await this.getKnex().transaction(async (trx) => {\n      const [inserted] = await trx(tableName).insert(encryptedData).returning('*');\n      return inserted;\n    });\n\n    // Decrypt for response\n    const decryptedTask = await decryptSensitiveFields(\n      task as Record<string, string | number | boolean | null>,\n      'tasks'\n    );\n    const formattedTask = this.formatTask(decryptedTask as unknown as TaskDbRow);\n\n    // User-facing success message\n    this.logger.info(`Task created with ID: ${formattedTask.id}`);\n\n    this.logger.debug('Task created successfully', {\n      taskId: formattedTask.id || 0,\n      status: String(formattedTask.status),\n      hasMetadata: !!formattedTask.metadata,\n    });\n\n    return formattedTask;\n  }\n\n  async executeTask(\n    taskId: string,\n    options?: {\n      model?: string;\n      stream?: boolean;\n      onChunk?: (chunk: string) => void;\n      onToolCall?: (\n        toolName: string,\n        args: Record<string, unknown>,\n        status: 'start' | 'end',\n        result?: string\n      ) => void;\n    }\n  ): Promise<TaskResponse> {\n    const startTime = Date.now();\n\n    // User-facing info log\n    this.logger.info(`Executing task: ${taskId}`);\n\n    this.logger.debug('Starting task execution', {\n      taskId,\n      agentId: this.agent.id,\n      model: options?.model || 'default',\n      stream: !!options?.stream,\n    });\n\n    const task = await this.getTask(taskId);\n    if (!task) {\n      throw new Error(`Task ${taskId} not found`);\n    }\n\n    // Auto-detect scheduled task and log info\n    if (task.metadata?.schedule) {\n      this.logger.info(\n        `Task has schedule: ${task.metadata.schedule} - this will be handled by the graph system when used in graphs`\n      );\n    }\n\n    // Update status to in_progress\n    await this.updateTaskStatus(taskId, 'in_progress');\n\n    try {\n      // Check if tools should be used for this specific task\n      const taskUseTools = task.metadata?.useTools;\n      const agentUseTools = this.agent.config.useTools;\n      const shouldUseTools = taskUseTools !== undefined ? taskUseTools : agentUseTools !== false;\n\n      let llmResponse: LLMResponse;\n\n      // Add memory context if agent has memory enabled\n      const agentHasMemory = this.agent.config.memory || false;\n\n      // Add task-level MCP servers if specified\n      if (\n        task.metadata?.mcpServers &&\n        this.agent &&\n        'addMCPServers' in this.agent &&\n        typeof this.agent.addMCPServers === 'function'\n      ) {\n        await this.agent.addMCPServers(task.metadata.mcpServers);\n      }\n\n      // Add task-level plugins if specified\n      if (\n        task.metadata?.plugins &&\n        typeof task.metadata.plugins === 'string' &&\n        this.agent &&\n        'registerPlugin' in this.agent &&\n        typeof this.agent.registerPlugin === 'function'\n      ) {\n        try {\n          const parsedPlugins = JSON.parse(task.metadata.plugins);\n          if (Array.isArray(parsedPlugins)) {\n            for (const pluginData of parsedPlugins) {\n              await this.agent.registerPlugin(pluginData.plugin, pluginData.config);\n            }\n          }\n        } catch (error) {\n          this.logger.debug('Failed to parse plugins metadata', {\n            error: error instanceof Error ? error.message : String(error),\n          });\n        }\n      }\n\n      // Check for sub-agent delegation options\n      const taskUseSubAgents = task.metadata?.useSubAgents;\n      const hasSubAgents =\n        this.agent &&\n        'config' in this.agent &&\n        this.agent.config.subAgents &&\n        this.agent.config.subAgents.length > 0;\n\n      // If task should use sub-agents and agent has sub-agents, use agent.ask() for delegation\n      if (\n        taskUseSubAgents &&\n        hasSubAgents &&\n        this.agent &&\n        'ask' in this.agent &&\n        typeof this.agent.ask === 'function'\n      ) {\n        // Prepare sub-agent options from task metadata\n        const delegation = task.metadata?.subAgentDelegation;\n        const coordination = task.metadata?.subAgentCoordination;\n\n        const subAgentOptions: SubAgentRunOptions = {\n          useSubAgents: true,\n          delegation:\n            typeof delegation === 'string' && ['auto', 'manual', 'sequential'].includes(delegation)\n              ? (delegation as 'auto' | 'manual' | 'sequential')\n              : 'auto',\n          coordination:\n            typeof coordination === 'string' && ['parallel', 'sequential'].includes(coordination)\n              ? (coordination as 'parallel' | 'sequential')\n              : 'sequential',\n        };\n\n        // Add task assignment if specified\n        if (task.metadata?.taskAssignment && typeof task.metadata.taskAssignment === 'string') {\n          try {\n            subAgentOptions.taskAssignment = JSON.parse(task.metadata.taskAssignment);\n          } catch (error) {\n            this.logger.debug('Failed to parse taskAssignment metadata', {\n              error: error instanceof Error ? error.message : String(error),\n            });\n          }\n        }\n\n        // Add other options\n        if (options?.model) {\n          subAgentOptions.model = options.model;\n        }\n        if (options?.stream) {\n          subAgentOptions.stream = options.stream;\n        }\n        if (typeof shouldUseTools === 'boolean') {\n          subAgentOptions.useTools = shouldUseTools;\n        }\n\n        // Execute task with sub-agent delegation using agent.ask()\n        const response = await this.agent.ask(task.prompt, subAgentOptions);\n\n        llmResponse = {\n          content: response,\n          model: options?.model || this.agent.config.model || DEFAULT_AGENT_CONFIG.model,\n        };\n      } else {\n        // Direct LLM execution with optional tool support\n        const llm = getLLM(this.logger);\n\n        // Prepare messages for LLM (with max context limit)\n        const MAX_CONTEXT_MESSAGES = 100;\n        const llmMessages: LLMMessage[] = [];\n\n        // Add system prompt\n        const systemPrompt = this.agent.config.systemPrompt;\n        if (systemPrompt) {\n          llmMessages.push({ role: 'system', content: systemPrompt });\n        }\n\n        // Add conversation context from agent (with bounds checking)\n        const contextMessages = this.agent.getContext();\n        const maxContextToAdd = Math.max(0, MAX_CONTEXT_MESSAGES - llmMessages.length - 1); // Reserve space for user message\n        const contextToAdd = contextMessages.slice(-maxContextToAdd); // Keep most recent context\n\n        if (contextMessages.length > maxContextToAdd) {\n          this.logger.debug('Context messages truncated due to limit', {\n            original: contextMessages.length,\n            kept: maxContextToAdd,\n          });\n        }\n\n        for (const contextMsg of contextToAdd) {\n          llmMessages.push({\n            role: contextMsg.role,\n            content: contextMsg.content,\n          });\n        }\n\n        // Build the prompt with context and memory if needed\n        // Skip manual memory loading if task is part of a graph - graph handles context via loadGraphContext\n        let contextualPrompt = task.prompt;\n\n        if (agentHasMemory && !task.graphId) {\n          const memory = new Memory(this.agent);\n          const recentMemories = await memory.listMemories({\n            limit: 20,\n            orderBy: 'createdAt',\n            order: 'asc',\n          });\n\n          if (recentMemories.length > 0) {\n            const memoryContext = recentMemories\n              .map((mem: MemoryType) => {\n                if (mem.metadata?.type === 'user_message') {\n                  return `Human: ${mem.content}`;\n                } else if (mem.metadata?.type === 'assistant_response') {\n                  return `Assistant: ${mem.content}`;\n                }\n                return null;\n              })\n              .filter(Boolean)\n              .join('\\n');\n\n            contextualPrompt = `Previous conversation:\\n${memoryContext}\\n\\nCurrent request: ${task.prompt}`;\n          }\n        }\n\n        // Prepare tools if enabled\n        const tools: Tool[] = [];\n\n        if (shouldUseTools && this.agent.canUseTools()) {\n          // Add MCP tools\n          if (\n            this.agent &&\n            'getMCPTools' in this.agent &&\n            typeof this.agent.getMCPTools === 'function'\n          ) {\n            const mcpTools = this.agent.getMCPTools();\n            for (const mcpTool of mcpTools) {\n              tools.push({\n                type: 'function',\n                function: {\n                  name: `mcp_${mcpTool.name}`,\n                  description: mcpTool.description,\n                  parameters: mcpTool.inputSchema || {\n                    type: 'object',\n                    properties: {},\n                  },\n                },\n              });\n            }\n          }\n\n          // Add plugin tools\n          if (this.agent && 'getTools' in this.agent && typeof this.agent.getTools === 'function') {\n            const pluginTools = this.agent.getTools();\n            for (const pluginTool of pluginTools) {\n              tools.push({\n                type: 'function',\n                function: {\n                  name: `plugin_${pluginTool.name}`,\n                  description: pluginTool.description,\n                  parameters: convertToolParametersToJsonSchema(pluginTool.parameters),\n                },\n              });\n            }\n          }\n        }\n\n        // Process attachments if present\n        let userMessageContent: LLMMessageContent = contextualPrompt;\n\n        if (task.metadata?.attachments) {\n          try {\n            const attachments = JSON.parse(task.metadata.attachments as string);\n            const imageAttachments = attachments.filter(\n              (att: { type: string; path: string }) => att.type === 'image'\n            );\n\n            if (imageAttachments.length > 0) {\n              // Use visionModel if specified, otherwise fall back to main model\n              const visionModel =\n                this.agent.config.visionModel ||\n                options?.model ||\n                this.agent.config.model ||\n                'gpt-4o';\n              const visionCapableModels = [\n                'gpt-4o',\n                'gpt-4o-mini',\n                'gpt-4-turbo',\n                'gpt-4-vision-preview',\n                'claude-3',\n                'gemini',\n              ];\n              const isVisionCapable = visionCapableModels.some((vm) => visionModel.includes(vm));\n\n              if (isVisionCapable) {\n                // Create multi-modal content\n                const contentParts: LLMMessageContentPart[] = [{ type: 'text', text: task.prompt }];\n\n                // Maximum image size limit (10MB) to prevent memory issues\n                const MAX_IMAGE_SIZE = 10 * 1024 * 1024;\n\n                // Add image parts\n                for (const imageAtt of imageAttachments) {\n                  try {\n                    const imagePath = path.resolve(imageAtt.path);\n\n                    // Check file size before loading to prevent memory issues\n                    const stats = await fs.stat(imagePath);\n                    if (stats.size > MAX_IMAGE_SIZE) {\n                      this.logger.warn('Image too large, skipping', {\n                        size: stats.size,\n                        maxSize: MAX_IMAGE_SIZE,\n                        path: imageAtt.path,\n                      });\n                      continue;\n                    }\n\n                    const imageData = await fs.readFile(imagePath);\n                    const base64Image = imageData.toString('base64');\n                    const mimeType = getMimeType(path.extname(imagePath));\n\n                    contentParts.push({\n                      type: 'image_url',\n                      image_url: {\n                        url: `data:${mimeType};base64,${base64Image}`,\n                        detail: 'auto',\n                      },\n                    });\n\n                    this.logger.debug('Added image to message', {\n                      imagePath: imageAtt.path,\n                      mimeType,\n                      base64Length: base64Image.length,\n                    });\n                  } catch {\n                    this.logger.warn(`Failed to read image attachment: ${imageAtt.path}`);\n                  }\n                }\n\n                userMessageContent = contentParts;\n              }\n            }\n          } catch {\n            this.logger.debug('Failed to parse attachments');\n          }\n        }\n\n        // Add current prompt with potential image content\n        llmMessages.push({ role: 'user', content: userMessageContent });\n\n        // Use visionModel if images are present, otherwise use regular model\n        let hasImages = false;\n        try {\n          hasImages =\n            task.metadata?.attachments &&\n            JSON.parse(task.metadata.attachments as string).some(\n              (att: { type: string }) => att.type === 'image'\n            );\n        } catch {\n          this.logger.debug('Failed to parse attachments for image detection');\n        }\n        const modelToUse =\n          hasImages && this.agent.config.visionModel\n            ? this.agent.config.visionModel\n            : options?.model || this.agent.config.model || DEFAULT_AGENT_CONFIG.model;\n\n        this.logger.debug('Model selection for task execution', {\n          hasImages: !!hasImages,\n          agentVisionModel: this.agent.config.visionModel || 'none',\n          agentMainModel: this.agent.config.model || 'none',\n          optionsModel: options?.model || 'none',\n          modelToUse: modelToUse,\n          taskId: taskId,\n        });\n\n        const llmOptions = {\n          model: modelToUse,\n          messages: llmMessages,\n          temperature: this.agent.config.temperature || DEFAULT_AGENT_CONFIG.temperature,\n          maxTokens: this.agent.config.maxTokens || DEFAULT_AGENT_CONFIG.maxTokens,\n          tools: tools.length > 0 ? tools : undefined,\n        };\n\n        if (options?.stream) {\n          // Handle streaming with tool support\n          let fullContent = '';\n          const streamToolCalls: ToolCall[] = [];\n          let streamUsage: LLMUsage | undefined;\n\n          for await (const chunk of llm.generateStreamResponse(llmOptions)) {\n            fullContent += chunk.content;\n            if (chunk.content) {\n              // Use onChunk callback if available, otherwise fallback to process.stdout\n              if (options?.onChunk) {\n                options.onChunk(chunk.content);\n              } else {\n                process.stdout.write(chunk.content);\n              }\n            }\n            if (chunk.toolCalls) {\n              // Merge tool calls instead of replacing to avoid losing calls across chunks\n              for (const tc of chunk.toolCalls) {\n                const existingIndex = streamToolCalls.findIndex((t) => t.id === tc.id);\n                if (existingIndex >= 0) {\n                  // Update existing tool call (may have more complete arguments)\n                  streamToolCalls[existingIndex] = tc;\n                } else {\n                  // Add bounds checking to prevent unbounded array growth\n                  if (streamToolCalls.length >= Task.MAX_TOOL_CALLS) {\n                    this.logger.warn(\n                      'Maximum tool calls limit reached, ignoring additional tool calls',\n                      {\n                        maxToolCalls: Task.MAX_TOOL_CALLS,\n                        taskId,\n                      }\n                    );\n                    break;\n                  }\n                  streamToolCalls.push(tc);\n                }\n              }\n            }\n            if (chunk.usage) {\n              streamUsage = chunk.usage;\n            }\n          }\n\n          // Handle tool calls with multi-turn agentic loop\n          const MAX_TOOL_ITERATIONS = DEFAULT_TASK_CONFIG.maxToolIterations; // Prevent infinite loops\n          let toolIteration = 0;\n          const allToolCalls: ToolCall[] = [...streamToolCalls];\n\n          while (streamToolCalls.length > 0 && toolIteration < MAX_TOOL_ITERATIONS) {\n            toolIteration++;\n            this.logger.debug(`Tool iteration ${toolIteration}`, {\n              toolCallCount: streamToolCalls.length,\n              toolNames: streamToolCalls.map((tc) => tc.function?.name),\n            });\n\n            // Add assistant message with tool calls (copy array to avoid mutation issues)\n            llmMessages.push({\n              role: 'assistant',\n              content: fullContent || '',\n              tool_calls: [...streamToolCalls], // Copy to avoid reference mutation\n            });\n\n            // Execute each tool call\n            for (const toolCall of streamToolCalls) {\n              // Define these outside try block for catch access\n              const toolName = toolCall.function?.name || 'unknown';\n              let toolArgs: Record<string, unknown> = {};\n\n              // Parse arguments once\n              try {\n                const argsStr = toolCall.function?.arguments;\n                if (argsStr && typeof argsStr === 'string') {\n                  toolArgs = JSON.parse(argsStr);\n                } else if (typeof argsStr === 'object' && argsStr !== null) {\n                  toolArgs = argsStr as Record<string, unknown>;\n                }\n              } catch {\n                toolArgs = {};\n              }\n\n              // Notify tool call start\n              if (options?.onToolCall) {\n                const displayName = toolName.replace(/^(mcp_|plugin_)/, '');\n                options.onToolCall(displayName, toolArgs, 'start');\n              }\n\n              try {\n                let toolResult: string;\n\n                // Validate tool call has required fields\n                if (!toolCall.function?.name) {\n                  toolResult = 'Error: Invalid tool call - missing function name';\n                } else if (toolCall.function.name.startsWith('mcp_')) {\n                  // Handle MCP tool\n                  const mcpToolName =\n                    toolCall.function.name.length > 4 ? toolCall.function.name.substring(4) : '';\n\n                  if (\n                    this.agent &&\n                    'callMCPTool' in this.agent &&\n                    typeof this.agent.callMCPTool === 'function'\n                  ) {\n                    const mcpResult = await this.agent.callMCPTool(mcpToolName, toolArgs);\n                    toolResult = mcpResult?.content\n                      ? mcpResult.content.map((c: { text?: string }) => c.text || '').join('\\n')\n                      : 'No content returned from MCP tool';\n                  } else {\n                    toolResult = 'Error: MCP tools not available';\n                  }\n                } else if (toolCall.function.name.startsWith('plugin_')) {\n                  // Handle plugin tool\n                  const pluginToolName =\n                    toolCall.function.name.length > 7 ? toolCall.function.name.substring(7) : '';\n\n                  if (\n                    this.agent &&\n                    'executeTool' in this.agent &&\n                    typeof this.agent.executeTool === 'function'\n                  ) {\n                    const pluginCallResult = await this.agent.executeTool({\n                      id:\n                        toolCall.id && toolCall.id.trim() !== ''\n                          ? toolCall.id\n                          : `tool-${crypto.randomUUID()}`,\n                      name: pluginToolName,\n                      parameters: toolArgs,\n                    });\n\n                    toolResult = pluginCallResult?.result\n                      ? pluginCallResult.result.success\n                        ? typeof pluginCallResult.result.data === 'string'\n                          ? pluginCallResult.result.data\n                          : JSON.stringify(pluginCallResult.result.data ?? null)\n                        : `Error: ${pluginCallResult.result.error || 'Unknown error'}`\n                      : 'Error: No result returned from plugin';\n                  } else {\n                    toolResult = 'Error: Plugin tools not available';\n                  }\n                } else {\n                  toolResult = `Unknown tool type: ${toolCall.function.name}`;\n                }\n\n                // Notify tool call end\n                if (options?.onToolCall) {\n                  const displayName = toolName.replace(/^(mcp_|plugin_)/, '');\n                  options.onToolCall(displayName, toolArgs, 'end', toolResult);\n                }\n\n                // Add tool result to messages\n                llmMessages.push({\n                  role: 'tool',\n                  content: toolResult,\n                  tool_call_id: toolCall.id,\n                });\n              } catch (error) {\n                const errorMessage = error instanceof Error ? error.message : String(error);\n                // Notify tool call error\n                if (options?.onToolCall) {\n                  const displayName = toolName.replace(/^(mcp_|plugin_)/, '');\n                  options.onToolCall(displayName, toolArgs, 'end', `Error: ${errorMessage}`);\n                }\n                llmMessages.push({\n                  role: 'tool',\n                  content: `Error: ${errorMessage}`,\n                  tool_call_id: toolCall.id,\n                });\n              }\n            }\n\n            // Get next response from LLM with tool results (keep tools for multi-turn)\n            const nextLlmOptions = {\n              ...llmOptions,\n              messages: llmMessages,\n              tools: tools.length > 0 ? tools : undefined, // Keep tools for multi-turn\n            };\n\n            // Reset for next iteration\n            streamToolCalls.length = 0;\n            fullContent = '';\n\n            try {\n              for await (const chunk of llm.generateStreamResponse(nextLlmOptions)) {\n                fullContent += chunk.content;\n                if (chunk.content) {\n                  if (options?.onChunk) {\n                    options.onChunk(chunk.content);\n                  } else {\n                    process.stdout.write(chunk.content);\n                  }\n                }\n                // Collect new tool calls for next iteration\n                if (chunk.toolCalls) {\n                  for (const tc of chunk.toolCalls) {\n                    const existingIndex = streamToolCalls.findIndex((t) => t.id === tc.id);\n                    if (existingIndex >= 0) {\n                      streamToolCalls[existingIndex] = tc;\n                    } else if (streamToolCalls.length < Task.MAX_TOOL_CALLS) {\n                      streamToolCalls.push(tc);\n                      allToolCalls.push(tc);\n                    }\n                  }\n                }\n                if (chunk.usage) {\n                  if (streamUsage) {\n                    streamUsage.promptTokens += chunk.usage.promptTokens;\n                    streamUsage.completionTokens += chunk.usage.completionTokens;\n                    streamUsage.totalTokens += chunk.usage.totalTokens;\n                    streamUsage.cost = (streamUsage.cost ?? 0) + (chunk.usage.cost ?? 0);\n                  } else {\n                    streamUsage = chunk.usage;\n                  }\n                }\n              }\n            } catch (llmError) {\n              const errorMessage = llmError instanceof Error ? llmError.message : String(llmError);\n              const toolErrorResponse = `\\n\\nError during tool execution: ${errorMessage}`;\n              fullContent += toolErrorResponse;\n              if (options?.onChunk) {\n                options.onChunk(toolErrorResponse);\n              } else {\n                process.stdout.write(toolErrorResponse);\n              }\n              break; // Exit loop on error\n            }\n          }\n\n          if (toolIteration >= MAX_TOOL_ITERATIONS) {\n            this.logger.warn('Maximum tool iterations reached', {\n              maxIterations: MAX_TOOL_ITERATIONS,\n              taskId,\n            });\n          }\n\n          llmResponse = {\n            content: fullContent,\n            model: modelToUse,\n            toolCalls: allToolCalls,\n            usage: streamUsage,\n          };\n        } else {\n          // Non-streaming with multi-turn tool handling\n          let currentResponse = await llm.generateResponse(llmOptions);\n          let finalResponse = currentResponse.content;\n          const allToolCallsExecuted: ToolCall[] = [];\n          const totalUsage = currentResponse.usage;\n\n          const MAX_TOOL_ITERATIONS = DEFAULT_TASK_CONFIG.maxToolIterations;\n          let toolIteration = 0;\n\n          while (\n            currentResponse.toolCalls &&\n            currentResponse.toolCalls.length > 0 &&\n            toolIteration < MAX_TOOL_ITERATIONS\n          ) {\n            toolIteration++;\n            this.logger.debug(`Non-streaming tool iteration ${toolIteration}`, {\n              toolCallCount: currentResponse.toolCalls.length,\n              toolNames: currentResponse.toolCalls.map((tc) => tc.function?.name),\n            });\n\n            const currentToolCalls = currentResponse.toolCalls.slice(0, Task.MAX_TOOL_CALLS);\n            allToolCallsExecuted.push(...currentToolCalls);\n\n            // Add assistant message with tool calls\n            llmMessages.push({\n              role: 'assistant',\n              content: currentResponse.content || '',\n              tool_calls: currentToolCalls,\n            });\n\n            // Execute each tool call\n            for (const toolCall of currentToolCalls) {\n              try {\n                let toolResult: string;\n\n                if (!toolCall.function?.name) {\n                  toolResult = 'Error: Invalid tool call - missing function name';\n                } else if (toolCall.function.name.startsWith('mcp_')) {\n                  const mcpToolName =\n                    toolCall.function.name.length > 4 ? toolCall.function.name.substring(4) : '';\n                  let mcpArgs: Record<string, unknown> = {};\n                  try {\n                    const argsStr = toolCall.function.arguments;\n                    if (argsStr && typeof argsStr === 'string') {\n                      mcpArgs = JSON.parse(argsStr);\n                    } else if (typeof argsStr === 'object' && argsStr !== null) {\n                      mcpArgs = argsStr as Record<string, unknown>;\n                    }\n                  } catch {\n                    mcpArgs = {};\n                  }\n\n                  if (\n                    this.agent &&\n                    'callMCPTool' in this.agent &&\n                    typeof this.agent.callMCPTool === 'function'\n                  ) {\n                    const mcpResult = await this.agent.callMCPTool(mcpToolName, mcpArgs);\n                    toolResult = mcpResult?.content\n                      ? mcpResult.content.map((c: { text?: string }) => c.text || '').join('\\n')\n                      : 'No content returned from MCP tool';\n                  } else {\n                    toolResult = 'Error: MCP tools not available';\n                  }\n                } else if (toolCall.function.name.startsWith('plugin_')) {\n                  const pluginToolName =\n                    toolCall.function.name.length > 7 ? toolCall.function.name.substring(7) : '';\n                  let pluginArgs: Record<string, unknown> = {};\n                  try {\n                    const argsStr = toolCall.function.arguments;\n                    if (argsStr && typeof argsStr === 'string') {\n                      pluginArgs = JSON.parse(argsStr);\n                    } else if (typeof argsStr === 'object' && argsStr !== null) {\n                      pluginArgs = argsStr as Record<string, unknown>;\n                    }\n                  } catch {\n                    pluginArgs = {};\n                  }\n\n                  if (\n                    this.agent &&\n                    'executeTool' in this.agent &&\n                    typeof this.agent.executeTool === 'function'\n                  ) {\n                    const pluginCallResult = await this.agent.executeTool({\n                      id:\n                        toolCall.id && toolCall.id.trim() !== ''\n                          ? toolCall.id\n                          : `tool-${crypto.randomUUID()}`,\n                      name: pluginToolName,\n                      parameters: pluginArgs,\n                    });\n\n                    toolResult = pluginCallResult?.result\n                      ? pluginCallResult.result.success\n                        ? typeof pluginCallResult.result.data === 'string'\n                          ? pluginCallResult.result.data\n                          : JSON.stringify(pluginCallResult.result.data ?? null)\n                        : `Error: ${pluginCallResult.result.error || 'Unknown error'}`\n                      : 'Error: No result returned from plugin';\n                  } else {\n                    toolResult = 'Error: Plugin tools not available';\n                  }\n                } else {\n                  toolResult = `Unknown tool type: ${toolCall.function.name}`;\n                }\n\n                llmMessages.push({\n                  role: 'tool',\n                  content: toolResult,\n                  tool_call_id: toolCall.id,\n                });\n              } catch (error) {\n                const errorMessage = error instanceof Error ? error.message : String(error);\n                llmMessages.push({\n                  role: 'tool',\n                  content: `Error: ${errorMessage}`,\n                  tool_call_id: toolCall.id,\n                });\n              }\n            }\n\n            // Get next response with tools still available for multi-turn\n            try {\n              currentResponse = await llm.generateResponse({\n                ...llmOptions,\n                messages: llmMessages,\n                tools: tools.length > 0 ? tools : undefined,\n              });\n              finalResponse = currentResponse.content;\n\n              if (currentResponse.usage && totalUsage) {\n                totalUsage.promptTokens += currentResponse.usage.promptTokens;\n                totalUsage.completionTokens += currentResponse.usage.completionTokens;\n                totalUsage.totalTokens += currentResponse.usage.totalTokens;\n                totalUsage.cost = (totalUsage.cost ?? 0) + (currentResponse.usage.cost ?? 0);\n              }\n            } catch (llmError) {\n              const errorMessage = llmError instanceof Error ? llmError.message : String(llmError);\n              finalResponse = `Error during tool execution: ${errorMessage}`;\n              break;\n            }\n          }\n\n          if (toolIteration >= MAX_TOOL_ITERATIONS) {\n            this.logger.warn('Maximum tool iterations reached (non-streaming)', {\n              maxIterations: MAX_TOOL_ITERATIONS,\n              taskId,\n            });\n          }\n\n          llmResponse = {\n            content: finalResponse,\n            model: modelToUse,\n            usage: totalUsage,\n            toolCalls: allToolCallsExecuted,\n          };\n        }\n      }\n\n      // Update task with response and mark as completed\n      const updatedTask = await this.updateTask(taskId, {\n        response: llmResponse.content,\n        status: 'completed',\n        completedAt: new Date(),\n      });\n\n      // User-facing success message\n      this.logger.info(`Task ${taskId} completed successfully`);\n\n      this.logger.debug('Task execution completed', {\n        taskId,\n        responseLength: llmResponse.content.length,\n        executionTimeMs: Date.now() - startTime,\n        status: 'completed',\n      });\n\n      // Add task conversation to memory/context\n      // Skip if task is part of a graph - graph module handles memory saving with proper context\n      if (\n        !task.graphId &&\n        this.agent &&\n        'addMemory' in this.agent &&\n        typeof this.agent.addMemory === 'function'\n      ) {\n        await this.agent.addMemory(task.prompt, {\n          role: 'user',\n          type: 'task_execution',\n          taskId: taskId,\n          source: 'task',\n        });\n\n        await this.agent.addMemory(llmResponse.content, {\n          role: 'assistant',\n          type: 'task_response',\n          taskId: taskId,\n          model: llmResponse.model || '',\n          source: 'task',\n        });\n      }\n\n      if (!updatedTask) {\n        throw new Error(`Failed to update task ${taskId} after execution`);\n      }\n\n      return {\n        task: updatedTask,\n        response: llmResponse.content,\n        model: llmResponse.model,\n        usage: llmResponse.usage,\n      };\n    } catch (error) {\n      // Mark task as failed\n      await this.updateTaskStatus(taskId, 'failed');\n\n      // User-facing error message\n      this.logger.error(`Task ${taskId} failed`, error instanceof Error ? error : undefined, {\n        taskId,\n        executionTimeMs: Date.now() - startTime,\n        agentId: this.agent.id,\n      });\n\n      throw error;\n    }\n  }\n\n  async getTask(id: string): Promise<TaskType | null> {\n    await this.ensureDatabase();\n    const tableName = 'tasks';\n\n    const task = await this.getKnex()(tableName).where({ id, agentId: this.agent.id }).first();\n\n    if (!task) return null;\n\n    // Decrypt sensitive fields\n    const decryptedTask = await decryptSensitiveFields(\n      task as Record<string, string | number | boolean | null>,\n      'tasks'\n    );\n    return this.formatTask(decryptedTask as unknown as TaskDbRow);\n  }\n\n  async listTasks(options: TaskSearchOptions = {}): Promise<TaskType[]> {\n    this.logger.info('Listing tasks');\n\n    this.logger.debug('Listing tasks with options', {\n      limit: options.limit || DEFAULT_TASK_CONFIG.searchLimit,\n      offset: options.offset || DEFAULT_TASK_CONFIG.searchOffset,\n      status: options.status || DEFAULT_TASK_CONFIG.logStatus,\n      graphId: options.graphId || 'all',\n      orderBy: options.orderBy || DEFAULT_TASK_CONFIG.searchOrderBy,\n      order: options.order || DEFAULT_TASK_CONFIG.searchOrder,\n      agentId: this.agent.id,\n    });\n\n    await this.ensureDatabase();\n    const tableName = 'tasks';\n\n    const {\n      limit: rawLimit,\n      offset: rawOffset,\n      status,\n      graphId,\n      orderBy = 'createdAt',\n      order = 'desc',\n    } = options;\n\n    // Use ?? for numeric values that could be 0\n    const limit = rawLimit ?? 100;\n    const offset = rawOffset ?? 0;\n\n    const orderColumn =\n      orderBy === 'createdAt'\n        ? 'created_at'\n        : orderBy === 'updatedAt'\n          ? 'updated_at'\n          : orderBy === 'completedAt'\n            ? 'completed_at'\n            : 'created_at';\n\n    let query = this.getKnex()(tableName)\n      .where({ agentId: this.agent.id })\n      .orderBy(orderColumn, order)\n      .limit(limit)\n      .offset(offset);\n\n    if (status) {\n      query = query.andWhere({ status });\n    }\n\n    if (graphId !== undefined) {\n      query = query.andWhere({ graphId });\n    }\n\n    const tasks = await query;\n\n    // Decrypt tasks using centralized decryption\n    const decryptedTasks = await Promise.all(\n      tasks.map(async (task) => {\n        try {\n          const decrypted = await decryptSensitiveFields(\n            task as Record<string, string | number | boolean | null>,\n            'tasks'\n          );\n          return this.formatTask(decrypted as unknown as TaskDbRow);\n        } catch {\n          // Handle unencrypted data gracefully\n          this.logger.debug('Failed to decrypt task during list', { taskId: task.id });\n          return this.formatTask(task);\n        }\n      })\n    );\n    return decryptedTasks;\n  }\n\n  async updateTask(id: string, updates: Partial<TaskType>): Promise<TaskType | null> {\n    await this.ensureDatabase();\n    const tableName = 'tasks';\n\n    const updateData: Partial<TaskDbRow> = {};\n\n    if (updates.prompt !== undefined) updateData.prompt = updates.prompt;\n    if (updates.response !== undefined) updateData.response = updates.response;\n    if (updates.status !== undefined) updateData.status = updates.status;\n    if (updates.metadata !== undefined) updateData.metadata = JSON.stringify(updates.metadata);\n    if (updates.completedAt !== undefined)\n      updateData.completedAt =\n        updates.completedAt instanceof Date\n          ? updates.completedAt.toISOString()\n          : updates.completedAt;\n\n    if (Object.keys(updateData).length === 0) {\n      return this.getTask(id);\n    }\n\n    // Encrypt sensitive fields in update data\n    const encryptedUpdateData = await encryptSensitiveFields(updateData, 'tasks');\n\n    const [task] = await this.getKnex()(tableName)\n      .where({ id, agentId: this.agent.id })\n      .update(encryptedUpdateData)\n      .returning('*');\n\n    if (!task) return null;\n\n    // Decrypt for response\n    const decryptedTask = await decryptSensitiveFields(\n      task as Record<string, string | number | boolean | null>,\n      'tasks'\n    );\n    return this.formatTask(decryptedTask as unknown as TaskDbRow);\n  }\n\n  private async updateTaskStatus(id: string, status: TaskStatus): Promise<TaskType | null> {\n    const updateData: Partial<TaskDbRow> = { status };\n\n    if (status === 'completed') {\n      updateData.completedAt = new Date().toISOString();\n    }\n\n    // Convert TaskDbRow format to TaskType format for the updateTask method\n    const taskTypeUpdate: Partial<TaskType> = {\n      status: updateData.status,\n      ...(updateData.completedAt && { completedAt: new Date(updateData.completedAt) }),\n    };\n\n    return this.updateTask(id, taskTypeUpdate);\n  }\n\n  async deleteTask(id: string): Promise<boolean> {\n    await this.ensureDatabase();\n    const tableName = 'tasks';\n\n    const deleted = await this.getKnex()(tableName).where({ id, agentId: this.agent.id }).delete();\n\n    return deleted > 0;\n  }\n\n  async clearTasks(): Promise<number> {\n    await this.ensureDatabase();\n    const tableName = 'tasks';\n\n    return await this.getKnex()(tableName).where({ agentId: this.agent.id }).delete();\n  }\n\n  private formatTask(task: TaskDbRow): TaskType {\n    // Safe JSON parse for metadata\n    let metadata: MetadataObject | undefined;\n    try {\n      if (task.metadata) {\n        metadata = typeof task.metadata === 'string' ? JSON.parse(task.metadata) : task.metadata;\n      }\n    } catch {\n      this.logger?.warn('Failed to parse task metadata', { taskId: task.id });\n      metadata = undefined;\n    }\n\n    // Safe JSON parse for executionContext\n    let executionContext: Record<string, unknown> | undefined;\n    try {\n      const execCtx = (task as unknown as Record<string, unknown>).executionContext;\n      if (execCtx) {\n        executionContext = typeof execCtx === 'string' ? JSON.parse(execCtx) : execCtx;\n      }\n    } catch {\n      this.logger?.warn('Failed to parse execution context', { taskId: task.id });\n      executionContext = undefined;\n    }\n\n    return {\n      id: task.id,\n      agentId: task.agentId,\n      graphId: (task as unknown as Record<string, unknown>).graphId as string | undefined,\n      graphNodeId: (task as unknown as Record<string, unknown>).graphNodeId as string | undefined,\n      prompt: task.prompt,\n      response: task.response ?? undefined,\n      status: task.status,\n      metadata,\n      executionContext,\n      createdAt: new Date(task.created_at),\n      updatedAt: new Date(task.updated_at),\n      completedAt: task.completedAt ? new Date(task.completedAt) : undefined,\n    };\n  }\n}\n\n// Helper function to get MIME type from file extension\nfunction getMimeType(extension: string): string {\n  const mimeTypes: Record<string, string> = {\n    '.jpg': 'image/jpeg',\n    '.jpeg': 'image/jpeg',\n    '.png': 'image/png',\n    '.gif': 'image/gif',\n    '.bmp': 'image/bmp',\n    '.webp': 'image/webp',\n  };\n\n  return mimeTypes[extension.toLowerCase()] || DEFAULT_TASK_CONFIG.defaultMimeType;\n}\n\n// Export types\nexport type {\n  Task as TaskType,\n  TaskRequest,\n  TaskResponse,\n  TaskSearchOptions,\n  TaskStatus,\n} from './types';\n","import knex, { Knex } from 'knex';\nimport crypto from 'crypto';\nimport { DatabaseConfig } from './types';\nimport { AgentConfig, AgentConfigInput } from '../agent/types';\nimport { DEFAULT_DATABASE_CONFIG } from './defaults';\nimport { createKnexConfig } from './knex';\nimport { Logger } from '../logger/types';\nimport { getLogger } from '../logger';\nimport { getEncryptionService } from './encryption';\nimport { encryptSensitiveFields, decryptSensitiveFields } from './utils';\nimport { validateEncryptionConsistency } from './sensitive-fields';\n\n/**\n * Schema version for database migrations.\n * Increment this when schema changes are made.\n * Each module should check this version to ensure compatibility.\n */\nexport const SCHEMA_VERSION = 1;\n\ninterface AgentDbRow {\n  id: string; // UUID\n  name: string;\n  description?: string;\n  model?: string;\n  embeddingModel?: string;\n  visionModel?: string;\n  temperature?: number;\n  maxTokens?: number;\n  systemPrompt?: string;\n  memory: boolean;\n  knowledge: boolean;\n  vision: boolean;\n  useTools: boolean;\n  autoContextCompression: boolean;\n  // Context compression options\n  maxContextLength?: number;\n  preserveLastN?: number;\n  compressionRatio?: number;\n  compressionStrategy?: string;\n  debug: boolean;\n  created_at: string;\n  updated_at: string;\n}\n\n/**\n * Type guard to validate if an object has the required AgentDbRow properties\n */\nfunction isValidAgentDbRow(obj: unknown): obj is AgentDbRow {\n  if (!obj || typeof obj !== 'object') return false;\n  const row = obj as Record<string, unknown>;\n  return (\n    typeof row.id === 'string' &&\n    typeof row.name === 'string' &&\n    typeof row.created_at === 'string' &&\n    typeof row.updated_at === 'string'\n  );\n}\n\n/**\n * Safely convert a record to AgentDbRow with validation\n */\nfunction toAgentDbRow(record: Record<string, unknown>): AgentDbRow {\n  if (!isValidAgentDbRow(record)) {\n    throw new Error(\n      'Invalid agent data: missing required fields (id, name, created_at, updated_at)'\n    );\n  }\n  return record;\n}\n\nexport class Database {\n  protected knex: Knex;\n  protected config: DatabaseConfig;\n  private logger: Logger;\n  private _encryption?: ReturnType<typeof getEncryptionService>;\n\n  private get encryption() {\n    if (!this._encryption) {\n      this._encryption = getEncryptionService();\n    }\n    return this._encryption;\n  }\n\n  /**\n   * Check if using SQLite database\n   */\n  isSQLite(): boolean {\n    return (\n      this.config.driver === 'sqlite' || (!this.config.connectionString && !this.config.driver)\n    );\n  }\n\n  /**\n   * Check if an index exists on a table\n   */\n  private async checkIndexExists(tableName: string, indexName: string): Promise<boolean> {\n    try {\n      if (this.isSQLite()) {\n        const result = await this.knex.raw(\n          `SELECT name FROM sqlite_master WHERE type='index' AND tbl_name=? AND name=?`,\n          [tableName, indexName]\n        );\n        return result && result.length > 0;\n      } else if (this.isPostgres()) {\n        const result = await this.knex.raw(\n          `SELECT indexname FROM pg_indexes WHERE tablename = ? AND indexname = ?`,\n          [tableName, indexName]\n        );\n        return result.rows && result.rows.length > 0;\n      }\n      return false;\n    } catch (error) {\n      // Log the error and assume index doesn't exist\n      // Note: this.logger is always defined in constructor via getLogger() fallback\n      this.logger.warn('Failed to check index existence', {\n        error: error instanceof Error ? error.message : String(error),\n        tableName,\n        indexName,\n      });\n      return false;\n    }\n  }\n\n  /**\n   * Check if using PostgreSQL database\n   */\n  isPostgres(): boolean {\n    return (\n      this.config.driver === 'pg' ||\n      this.config.driver === 'postgres' ||\n      (!!this.config.connectionString &&\n        (this.config.connectionString.includes('postgres') ||\n          this.config.connectionString.includes('postgresql')))\n    );\n  }\n\n  /**\n   * Generate a new UUID\n   */\n  generateUUID(): string {\n    return crypto.randomUUID();\n  }\n\n  /**\n   * Get the knex instance for direct database operations\n   */\n  getKnex(): Knex {\n    return this.knex;\n  }\n\n  constructor(config: DatabaseConfig, logger?: Logger) {\n    this.config = config;\n    this.logger = logger || getLogger();\n\n    // User-facing info log\n    this.logger.info('Initializing database connection');\n\n    this.logger.debug('Creating database instance', {\n      hasConnectionString: !!config.connectionString,\n      sqliteFilename: config.filename || 'none',\n      type: config.connectionString ? 'postgresql' : 'sqlite',\n    });\n\n    const knexConfig = createKnexConfig(config);\n    this.knex = knex(knexConfig);\n  }\n\n  async connect(): Promise<void> {\n    // User-facing info log\n    this.logger.info('Connecting to database');\n\n    this.logger.debug('Testing database connection');\n\n    try {\n      // Test connection\n      await this.knex.raw('SELECT 1');\n\n      // User-facing success message\n      this.logger.info('Database connected successfully');\n\n      this.logger.debug('Database connection test passed');\n    } catch (error) {\n      // User-facing error message\n      this.logger.error('Failed to connect to database');\n\n      this.logger.debug('Database connection failed', {\n        error: error instanceof Error ? error.message : String(error),\n        hasStack: error instanceof Error && !!error.stack,\n      });\n\n      throw error;\n    }\n  }\n\n  async disconnect(): Promise<void> {\n    // User-facing info log\n    this.logger.info('Disconnecting from database');\n\n    this.logger.debug('Destroying database connection pool');\n\n    try {\n      await this.knex.destroy();\n\n      // User-facing success message\n      this.logger.info('Database disconnected');\n\n      this.logger.debug('Database connection pool destroyed');\n    } catch (error) {\n      // User-facing error message\n      this.logger.error('Error during database disconnect');\n\n      this.logger.debug('Database disconnect failed', {\n        error: error instanceof Error ? error.message : String(error),\n      });\n\n      throw error;\n    }\n  }\n\n  async initialize(): Promise<void> {\n    // User-facing info log\n    this.logger.info('Initializing database schema');\n\n    this.logger.debug('Starting database schema initialization');\n\n    // Validate encryption configuration\n    const encryptionValidation = validateEncryptionConsistency();\n    if (!encryptionValidation.isValid) {\n      this.logger.error('Encryption configuration validation failed');\n      this.logger.debug('Encryption validation errors', {\n        errors: encryptionValidation.errors,\n      });\n      throw new Error(`Encryption validation failed: ${encryptionValidation.errors.join(', ')}`);\n    }\n\n    if (encryptionValidation.warnings.length > 0) {\n      this.logger.warn('Encryption configuration warnings');\n      this.logger.debug('Encryption validation warnings', {\n        warnings: encryptionValidation.warnings,\n      });\n    }\n\n    // Initialize agents table\n    const hasAgentsTable = await this.knex.schema.hasTable('agents');\n\n    this.logger.debug('Checking agents table', { exists: hasAgentsTable });\n\n    if (!hasAgentsTable) {\n      this.logger.info('Creating agents table');\n\n      this.logger.debug('Creating agents table with full schema');\n\n      // Enable UUID extension for PostgreSQL\n      if (this.isPostgres()) {\n        await this.knex.raw('CREATE EXTENSION IF NOT EXISTS \"uuid-ossp\"');\n      }\n\n      await this.knex.schema.createTable('agents', (table) => {\n        table.string('id', 36).primary(); // UUID generated in application layer\n        table.string('name').notNullable().unique();\n        table.text('description');\n        table.string('model');\n        table.string('embeddingModel');\n        table.string('visionModel');\n        table.float('temperature');\n        table.integer('maxTokens');\n        table.text('systemPrompt');\n        // Use boolean type - Knex handles SQLite conversion automatically\n        table.boolean('memory').defaultTo(false);\n        table.boolean('knowledge').defaultTo(false);\n        table.boolean('vision').defaultTo(false);\n        table.boolean('useTools').defaultTo(true);\n        table.boolean('autoContextCompression').defaultTo(false);\n        // Context compression options\n        table.integer('maxContextLength');\n        table.integer('preserveLastN');\n        table.float('compressionRatio');\n        table.string('compressionStrategy');\n        table.boolean('debug').defaultTo(false);\n        table.timestamps(true, true);\n      });\n\n      this.logger.info('Agents table created');\n      this.logger.debug('Agents table created successfully');\n    } else {\n      // Check and add missing columns\n      const hasVision = await this.knex.schema.hasColumn('agents', 'vision');\n      const hasAutoContextCompression = await this.knex.schema.hasColumn(\n        'agents',\n        'autoContextCompression'\n      );\n      const hasDebug = await this.knex.schema.hasColumn('agents', 'debug');\n      const hasEmbeddingModel = await this.knex.schema.hasColumn('agents', 'embeddingModel');\n      const hasVisionModel = await this.knex.schema.hasColumn('agents', 'visionModel');\n      // Check for new context compression columns\n      const hasMaxContextLength = await this.knex.schema.hasColumn('agents', 'maxContextLength');\n      const hasPreserveLastN = await this.knex.schema.hasColumn('agents', 'preserveLastN');\n      const hasCompressionRatio = await this.knex.schema.hasColumn('agents', 'compressionRatio');\n      const hasCompressionStrategy = await this.knex.schema.hasColumn(\n        'agents',\n        'compressionStrategy'\n      );\n\n      this.logger.debug('Checking agents table columns', {\n        hasVision,\n        hasAutoContextCompression,\n        hasDebug,\n        hasEmbeddingModel,\n        hasVisionModel,\n        hasMaxContextLength,\n        hasPreserveLastN,\n        hasCompressionRatio,\n        hasCompressionStrategy,\n      });\n\n      if (\n        !hasVision ||\n        !hasAutoContextCompression ||\n        !hasDebug ||\n        !hasEmbeddingModel ||\n        !hasVisionModel ||\n        !hasMaxContextLength ||\n        !hasPreserveLastN ||\n        !hasCompressionRatio ||\n        !hasCompressionStrategy\n      ) {\n        this.logger.info('Updating agents table schema');\n\n        this.logger.debug('Adding missing columns to agents table', {\n          needsVision: !hasVision,\n          needsAutoContextCompression: !hasAutoContextCompression,\n          needsDebug: !hasDebug,\n          needsEmbeddingModel: !hasEmbeddingModel,\n          needsVisionModel: !hasVisionModel,\n        });\n\n        await this.knex.schema.alterTable('agents', (table) => {\n          if (!hasVision) {\n            table.boolean('vision').defaultTo(false);\n          }\n          if (!hasAutoContextCompression) {\n            table.boolean('autoContextCompression').defaultTo(false);\n          }\n          if (!hasDebug) {\n            table.boolean('debug').defaultTo(false);\n          }\n          if (!hasEmbeddingModel) {\n            table.string('embeddingModel');\n          }\n          if (!hasVisionModel) {\n            table.string('visionModel');\n          }\n          // Add new context compression columns\n          if (!hasMaxContextLength) {\n            table.integer('maxContextLength');\n          }\n          if (!hasPreserveLastN) {\n            table.integer('preserveLastN');\n          }\n          if (!hasCompressionRatio) {\n            table.float('compressionRatio');\n          }\n          if (!hasCompressionStrategy) {\n            table.string('compressionStrategy');\n          }\n        });\n\n        this.logger.info('Agents table updated');\n        this.logger.debug('Agents table schema updated successfully');\n      }\n    }\n\n    // Initialize shared tasks table\n    const hasTasksTable = await this.knex.schema.hasTable('tasks');\n    this.logger.debug('Checking tasks table', { exists: hasTasksTable });\n\n    if (!hasTasksTable) {\n      this.logger.info('Creating tasks table');\n\n      this.logger.debug('Creating tasks table with schema');\n\n      await this.knex.schema.createTable('tasks', (table) => {\n        table.string('id', 36).primary(); // UUID generated in application layer\n        table\n          .string('agentId', 36)\n          .notNullable()\n          .references('id')\n          .inTable('agents')\n          .onDelete('CASCADE');\n        table.string('graphId', 36).nullable();\n        table.string('graphNodeId', 36).nullable();\n        table.text('prompt').notNullable();\n        table.text('response').nullable();\n        table.enu('status', ['pending', 'in_progress', 'completed', 'failed']).defaultTo('pending');\n        table.json('metadata');\n        table.json('executionContext');\n        table.timestamps(true, true);\n        table.timestamp('completedAt').nullable();\n        table.index(['agentId']);\n        table.index(['graphId']);\n        table.index(['graphNodeId']);\n        table.index(['status']);\n        table.index(['created_at']);\n      });\n\n      this.logger.info('Tasks table created');\n      this.logger.debug('Tasks table created successfully');\n    } else {\n      // Check and add graph relationship columns\n      const hasGraphId = await this.knex.schema.hasColumn('tasks', 'graphId');\n      const hasGraphNodeId = await this.knex.schema.hasColumn('tasks', 'graphNodeId');\n      const hasExecutionContext = await this.knex.schema.hasColumn('tasks', 'executionContext');\n\n      this.logger.debug('Checking tasks table columns', {\n        hasGraphId,\n        hasGraphNodeId,\n        hasExecutionContext,\n      });\n\n      if (!hasGraphId || !hasGraphNodeId || !hasExecutionContext) {\n        this.logger.info('Updating tasks table schema with graph relationships');\n\n        await this.knex.schema.alterTable('tasks', (table) => {\n          if (!hasGraphId) {\n            table.string('graphId', 36).nullable();\n            this.logger.debug('Adding graphId column (UUID) to tasks table');\n          }\n          if (!hasGraphNodeId) {\n            table.string('graphNodeId').nullable();\n            this.logger.debug('Adding graphNodeId column to tasks table');\n          }\n          if (!hasExecutionContext) {\n            table.json('executionContext').nullable();\n            this.logger.debug('Adding executionContext column to tasks table');\n          }\n        });\n\n        // Add indexes for new columns (only if column was just added)\n        if (!hasGraphId) {\n          await this.knex.schema.alterTable('tasks', (table) => {\n            table.index('graphId');\n          });\n        }\n        if (!hasGraphNodeId) {\n          await this.knex.schema.alterTable('tasks', (table) => {\n            table.index('graphNodeId');\n          });\n        }\n\n        // Add composite indexes (check if exists first)\n        const tasksIndexName = 'tasks_agentid_status_index';\n        const hasTasksCompositeIndex = await this.checkIndexExists('tasks', tasksIndexName);\n        if (!hasTasksCompositeIndex) {\n          await this.knex.schema.alterTable('tasks', (table) => {\n            table.index(['agentId', 'status'], tasksIndexName);\n          });\n        }\n\n        this.logger.info('Tasks table updated with graph relationships');\n        this.logger.debug('Tasks table schema updated successfully');\n      }\n    }\n\n    // Initialize shared memories table\n    const hasMemoriesTable = await this.knex.schema.hasTable('memories');\n    this.logger.debug('Checking memories table', { exists: hasMemoriesTable });\n\n    if (!hasMemoriesTable) {\n      this.logger.info('Creating memories table');\n\n      this.logger.debug('Creating memories table with schema');\n\n      await this.knex.schema.createTable('memories', (table) => {\n        table.string('id', 36).primary(); // UUID generated in application layer\n        table\n          .string('agentId', 36)\n          .notNullable()\n          .references('id')\n          .inTable('agents')\n          .onDelete('CASCADE');\n        table.string('graphId', 36).nullable();\n        table.string('taskId', 36).nullable();\n        table.string('sessionId', 255).nullable();\n        table.text('content').notNullable();\n        table.text('embedding').nullable(); // For vector similarity search\n        table.json('metadata');\n        table.timestamps(true, true);\n        table.index(['agentId']);\n        table.index(['graphId']);\n        table.index(['taskId']);\n        table.index(['sessionId']);\n        table.index(['created_at']);\n      });\n\n      this.logger.info('Memories table created');\n      this.logger.debug('Memories table created successfully');\n    } else {\n      // Check and add missing columns for memories\n      const hasEmbedding = await this.knex.schema.hasColumn('memories', 'embedding');\n      const hasGraphId = await this.knex.schema.hasColumn('memories', 'graphId');\n      const hasTaskId = await this.knex.schema.hasColumn('memories', 'taskId');\n      const hasSessionId = await this.knex.schema.hasColumn('memories', 'sessionId');\n\n      this.logger.debug('Checking memories table columns', {\n        hasEmbedding,\n        hasGraphId,\n        hasTaskId,\n        hasSessionId,\n      });\n\n      if (!hasEmbedding || !hasGraphId || !hasTaskId || !hasSessionId) {\n        this.logger.info('Updating memories table schema');\n\n        await this.knex.schema.alterTable('memories', (table) => {\n          if (!hasEmbedding) {\n            // Add embedding column for vector similarity search\n            // Note: For SQLite, we'll store as TEXT (JSON array),\n            // for PostgreSQL, this should be vector type\n            table.text('embedding').nullable();\n            this.logger.debug('Adding embedding column to memories table');\n          }\n          if (!hasGraphId) {\n            table.string('graphId', 36).nullable();\n            this.logger.debug('Adding graphId column (UUID) to memories table');\n          }\n          if (!hasTaskId) {\n            table.string('taskId', 36).nullable();\n            this.logger.debug('Adding taskId column (UUID) to memories table');\n          }\n          if (!hasSessionId) {\n            table.string('sessionId', 255).nullable();\n            this.logger.debug('Adding sessionId column to memories table');\n          }\n        });\n\n        // Add indexes for new columns (only if column was just added)\n        if (!hasGraphId) {\n          await this.knex.schema.alterTable('memories', (table) => {\n            table.index('graphId');\n          });\n        }\n        if (!hasTaskId) {\n          await this.knex.schema.alterTable('memories', (table) => {\n            table.index('taskId');\n          });\n        }\n        if (!hasSessionId) {\n          await this.knex.schema.alterTable('memories', (table) => {\n            table.index('sessionId');\n          });\n        }\n\n        // Add composite index for agent + session queries (check if exists first)\n        const memoriesIndexName = 'memories_agentid_sessionid_index';\n        const hasMemoriesCompositeIndex = await this.checkIndexExists(\n          'memories',\n          memoriesIndexName\n        );\n        if (!hasMemoriesCompositeIndex) {\n          await this.knex.schema.alterTable('memories', (table) => {\n            table.index(['agentId', 'sessionId'], memoriesIndexName);\n          });\n        }\n\n        this.logger.info('Memories table updated with embedding and relationship columns');\n        this.logger.debug('Memories table schema updated successfully');\n      }\n    }\n\n    // Initialize contexts table\n    const hasContextsTable = await this.knex.schema.hasTable('contexts');\n\n    this.logger.debug('Checking contexts table', { exists: hasContextsTable });\n\n    if (!hasContextsTable) {\n      this.logger.info('Creating contexts table');\n\n      this.logger.debug('Creating contexts table with full schema');\n\n      await this.knex.schema.createTable('contexts', (table) => {\n        table.string('id', 36).primary(); // UUID generated in application layer\n        table.string('agentId', 36).notNullable();\n        table.string('graphId', 36).nullable();\n        table.string('sessionId', 255).nullable();\n        table.json('contextData').nullable(); // Compressed context messages\n        table.text('summary').nullable(); // Context summary for very large contexts\n        table.integer('tokensUsed').defaultTo(0);\n        table.string('compressionVersion').nullable(); // Track compression strategy version\n        table.timestamp('lastCompressed').nullable();\n        table.timestamps(true, true); // created_at, updated_at\n\n        // Add foreign key constraint to agents table\n        table.foreign('agentId').references('id').inTable('agents').onDelete('CASCADE');\n\n        // Add indexes\n        table.index('agentId');\n        table.index('graphId');\n        table.index('sessionId');\n      });\n\n      this.logger.info('Contexts table created');\n      this.logger.debug('Contexts table created successfully');\n    } else {\n      // Check and add graph relationship columns\n      const hasGraphId = await this.knex.schema.hasColumn('contexts', 'graphId');\n      const hasSessionId = await this.knex.schema.hasColumn('contexts', 'sessionId');\n\n      this.logger.debug('Checking contexts table columns', {\n        hasGraphId,\n        hasSessionId,\n      });\n\n      if (!hasGraphId || !hasSessionId) {\n        this.logger.info('Updating contexts table schema with graph relationships');\n\n        await this.knex.schema.alterTable('contexts', (table) => {\n          if (!hasGraphId) {\n            table.string('graphId', 36).nullable();\n            this.logger.debug('Adding graphId column (UUID) to contexts table');\n          }\n          if (!hasSessionId) {\n            table.string('sessionId', 255).nullable();\n            this.logger.debug('Adding sessionId column to contexts table');\n          }\n        });\n\n        // Add indexes for new columns (only if column was just added)\n        if (!hasGraphId) {\n          await this.knex.schema.alterTable('contexts', (table) => {\n            table.index('graphId');\n          });\n        }\n        if (!hasSessionId) {\n          await this.knex.schema.alterTable('contexts', (table) => {\n            table.index('sessionId');\n          });\n        }\n\n        this.logger.info('Contexts table updated with graph relationships');\n        this.logger.debug('Contexts table schema updated successfully');\n      }\n    }\n\n    // User-facing completion message\n    this.logger.info('Database schema initialized');\n\n    this.logger.debug('Database schema initialization completed', {\n      tablesChecked: ['agents', 'tasks', 'memories', 'contexts'],\n    });\n  }\n\n  async createAgent(data: AgentConfigInput): Promise<AgentConfig> {\n    // User-facing info log\n    this.logger.info(`Creating agent: ${data.name}`);\n\n    this.logger.debug('Creating agent with data', {\n      name: data.name,\n      description: data.description || 'none',\n      model: data.model || 'default',\n      embeddingModel: data.embeddingModel || 'none',\n      visionModel: data.visionModel || 'none',\n      temperature: data.temperature || DEFAULT_DATABASE_CONFIG.defaultTemperature,\n      maxTokens: data.maxTokens || DEFAULT_DATABASE_CONFIG.defaultMaxTokens,\n      memory: !!data.memory,\n      knowledge: !!data.knowledge,\n      vision: !!data.vision,\n      useTools: data.useTools !== false,\n      autoContextCompression: !!data.autoContextCompression,\n      debug: !!data.debug,\n      hasSystemPrompt: !!data.systemPrompt,\n    });\n\n    // Prepare data for insertion with encryption\n    const insertData = {\n      id: this.generateUUID(),\n      name: data.name,\n      description: data.description,\n      model: data.model,\n      embeddingModel: data.embeddingModel,\n      visionModel: data.visionModel,\n      temperature: data.temperature,\n      maxTokens: data.maxTokens,\n      systemPrompt: data.systemPrompt,\n      memory: data.memory || false,\n      knowledge: data.knowledge || false,\n      vision: data.vision || false,\n      useTools: data.useTools !== undefined ? data.useTools : true,\n      autoContextCompression: data.autoContextCompression || false,\n      // Context compression options\n      maxContextLength: data.maxContextLength,\n      preserveLastN: data.preserveLastN,\n      compressionRatio: data.compressionRatio,\n      compressionStrategy: data.compressionStrategy,\n      debug: data.debug || false,\n    };\n\n    // Remove undefined values before encryption\n    const cleanedData = Object.fromEntries(\n      Object.entries(insertData).filter(([, value]) => value !== undefined)\n    ) as Record<string, string | number | boolean | null>;\n\n    // Encrypt sensitive fields\n    const encryptedData = await encryptSensitiveFields(cleanedData, 'agents');\n\n    let agent: AgentDbRow | undefined;\n\n    if (this.isSQLite()) {\n      // SQLite doesn't support RETURNING clause reliably\n      await this.knex('agents').insert(encryptedData);\n      agent = await this.knex('agents').where({ id: insertData.id }).first();\n    } else {\n      const [insertedAgent] = await this.knex('agents').insert(encryptedData).returning('*');\n      agent = insertedAgent as AgentDbRow;\n    }\n\n    if (!agent) {\n      throw new Error(`Failed to create agent: ${data.name}`);\n    }\n\n    // Decrypt for response\n    const decryptedAgent = await decryptSensitiveFields(\n      agent as unknown as Record<string, string | number | boolean | null>,\n      'agents'\n    );\n    const formattedAgent = this.formatAgent(\n      toAgentDbRow(decryptedAgent as Record<string, unknown>)\n    );\n\n    // User-facing success message\n    this.logger.info(`Agent created with ID: ${formattedAgent.id}`);\n\n    this.logger.debug('Agent created successfully', {\n      id: formattedAgent.id || 0,\n      name: formattedAgent.name,\n    });\n\n    return formattedAgent;\n  }\n\n  async getAgent(id: string): Promise<AgentConfig | null> {\n    this.logger.debug('Retrieving agent by ID', { id });\n\n    const agent = await this.knex('agents').where({ id }).first();\n\n    this.logger.debug('Agent retrieval by ID result', {\n      id,\n      found: !!agent,\n      name: agent?.name,\n    });\n\n    if (!agent) return null;\n\n    // Decrypt sensitive fields\n    const decryptedAgent = await decryptSensitiveFields(\n      agent as unknown as Record<string, string | number | boolean | null>,\n      'agents'\n    );\n    return this.formatAgent(toAgentDbRow(decryptedAgent as Record<string, unknown>));\n  }\n\n  async getAgentByName(name: string): Promise<AgentConfig | null> {\n    this.logger.debug('Retrieving agent by name', { name });\n\n    const agent = await this.knex('agents').where({ name }).first();\n\n    this.logger.debug('Agent retrieval by name result', {\n      name,\n      found: !!agent,\n      id: agent?.id,\n    });\n\n    if (!agent) return null;\n\n    // Decrypt sensitive fields\n    const decryptedAgent = await decryptSensitiveFields(\n      agent as unknown as Record<string, string | number | boolean | null>,\n      'agents'\n    );\n    return this.formatAgent(toAgentDbRow(decryptedAgent as Record<string, unknown>));\n  }\n\n  async listAgents(): Promise<AgentConfig[]> {\n    this.logger.debug('Listing all agents');\n\n    const agents = await this.knex('agents').orderBy('id', 'desc');\n\n    this.logger.debug('Agents list retrieved', {\n      count: agents.length,\n      names: agents.map((a) => a.name).slice(0, 10), // First 10 names\n    });\n\n    // Decrypt sensitive fields for each agent\n    const decryptedAgents = await Promise.all(\n      agents.map(async (agent) => {\n        const decrypted = await decryptSensitiveFields(\n          agent as unknown as Record<string, string | number | boolean | null>,\n          'agents'\n        );\n        return this.formatAgent(toAgentDbRow(decrypted as Record<string, unknown>));\n      })\n    );\n\n    return decryptedAgents;\n  }\n\n  async updateAgent(id: string, data: Partial<AgentConfig>): Promise<AgentConfig | null> {\n    // User-facing info log\n    this.logger.info(`Updating agent: ${id}`);\n\n    this.logger.debug('Updating agent with data', {\n      id,\n      updateFields: Object.keys(data),\n      fieldCount: Object.keys(data).length,\n      hasSystemPrompt: !!data.systemPrompt,\n    });\n\n    const updateData: Partial<AgentDbRow> = {};\n    const allowedFields = [\n      'name',\n      'description',\n      'model',\n      'embeddingModel',\n      'visionModel',\n      'temperature',\n      'maxTokens',\n      'systemPrompt',\n      'memory',\n      'knowledge',\n      'vision',\n      'useTools',\n      'autoContextCompression',\n      // Context compression options\n      'maxContextLength',\n      'preserveLastN',\n      'compressionRatio',\n      'compressionStrategy',\n      'debug',\n    ] as const;\n\n    for (const field of allowedFields) {\n      if (field in data) {\n        // Type-safe field assignment\n        switch (field) {\n          case 'name':\n            updateData.name = data.name;\n            break;\n          case 'description':\n            updateData.description = data.description;\n            break;\n          case 'model':\n            updateData.model = data.model;\n            break;\n          case 'embeddingModel':\n            updateData.embeddingModel = data.embeddingModel;\n            break;\n          case 'visionModel':\n            updateData.visionModel = data.visionModel;\n            break;\n          case 'temperature':\n            updateData.temperature = data.temperature;\n            break;\n          case 'maxTokens':\n            updateData.maxTokens = data.maxTokens;\n            break;\n          case 'systemPrompt':\n            updateData.systemPrompt = data.systemPrompt;\n            break;\n          case 'memory':\n            updateData.memory = data.memory ?? false;\n            break;\n          case 'knowledge':\n            updateData.knowledge = data.knowledge ?? false;\n            break;\n          case 'vision':\n            updateData.vision = data.vision ?? false;\n            break;\n          case 'useTools':\n            updateData.useTools = data.useTools ?? false;\n            break;\n          case 'autoContextCompression':\n            updateData.autoContextCompression = data.autoContextCompression ?? false;\n            break;\n          case 'maxContextLength':\n            updateData.maxContextLength = data.maxContextLength;\n            break;\n          case 'preserveLastN':\n            updateData.preserveLastN = data.preserveLastN;\n            break;\n          case 'compressionRatio':\n            updateData.compressionRatio = data.compressionRatio;\n            break;\n          case 'compressionStrategy':\n            updateData.compressionStrategy = data.compressionStrategy;\n            break;\n          case 'debug':\n            updateData.debug = data.debug ?? false;\n            break;\n        }\n      }\n    }\n\n    if (Object.keys(updateData).length === 0) {\n      this.logger.debug('No update data provided, returning current agent', { id });\n      return this.getAgent(id);\n    }\n\n    // Encrypt sensitive fields in update data\n    // Convert Partial<AgentDbRow> to Record<string, string | number | boolean | null | undefined | Date>\n    const updateDataForEncryption = Object.fromEntries(\n      Object.entries(updateData).filter(([, value]) => value !== undefined)\n    ) as Record<string, string | number | boolean | null | undefined | Date>;\n    const encryptedUpdateData = await encryptSensitiveFields(updateDataForEncryption, 'agents');\n\n    let agent: AgentDbRow | undefined;\n\n    if (this.isSQLite()) {\n      // SQLite doesn't support RETURNING clause reliably\n      const updatedCount = await this.knex('agents').where({ id }).update(encryptedUpdateData);\n\n      if (updatedCount > 0) {\n        agent = await this.knex('agents').where({ id }).first();\n      }\n    } else {\n      const [updatedAgent] = await this.knex('agents')\n        .where({ id })\n        .update(encryptedUpdateData)\n        .returning('*');\n      agent = updatedAgent as AgentDbRow;\n    }\n\n    if (agent) {\n      // Decrypt for response\n      const decryptedAgent = await decryptSensitiveFields(\n        agent as unknown as Record<string, string | number | boolean | null>,\n        'agents'\n      );\n      const formattedAgent = this.formatAgent(\n        toAgentDbRow(decryptedAgent as Record<string, unknown>)\n      );\n\n      // User-facing success message\n      this.logger.info(`Agent ${id} updated successfully`);\n\n      this.logger.debug('Agent updated successfully', {\n        id: formattedAgent.id || 0,\n        name: formattedAgent.name,\n        updatedFieldCount: Object.keys(updateData).length,\n      });\n\n      return formattedAgent;\n    }\n\n    this.logger.debug('Agent update failed - agent not found', { id });\n    return null;\n  }\n\n  async deleteAgent(id: string): Promise<boolean> {\n    // User-facing info log\n    this.logger.info(`Deleting agent: ${id}`);\n\n    this.logger.debug('Deleting agent', { id });\n\n    const deleted = await this.knex('agents').where({ id }).delete();\n\n    const success = deleted > 0;\n\n    if (success) {\n      // User-facing success message\n      this.logger.info(`Agent ${id} deleted successfully`);\n\n      this.logger.debug('Agent deleted successfully', { id, deletedCount: deleted });\n    } else {\n      this.logger.debug('Agent deletion failed - agent not found', { id });\n    }\n\n    return success;\n  }\n\n  private formatAgent(agent: AgentDbRow): AgentConfig {\n    return {\n      id: agent.id,\n      name: agent.name,\n      description: agent.description,\n      model: agent.model,\n      embeddingModel: agent.embeddingModel,\n      visionModel: agent.visionModel,\n      temperature: agent.temperature,\n      maxTokens: agent.maxTokens,\n      systemPrompt: agent.systemPrompt,\n      memory: Boolean(agent.memory), // Convert SQLite 0/1 to boolean\n      knowledge: Boolean(agent.knowledge), // Convert SQLite 0/1 to boolean\n      vision: Boolean(agent.vision), // Convert SQLite 0/1 to boolean\n      useTools: Boolean(agent.useTools), // Convert SQLite 0/1 to boolean\n      autoContextCompression: Boolean(agent.autoContextCompression), // Convert SQLite 0/1 to boolean\n      // Context compression options\n      maxContextLength: agent.maxContextLength,\n      preserveLastN: agent.preserveLastN,\n      compressionRatio: agent.compressionRatio,\n      compressionStrategy: (() => {\n        const validStrategies = ['summarize', 'selective', 'hybrid'] as const;\n        const strategy = agent.compressionStrategy;\n        return validStrategies.includes(strategy as (typeof validStrategies)[number])\n          ? (strategy as (typeof validStrategies)[number])\n          : undefined;\n      })(),\n      debug: Boolean(agent.debug), // Convert SQLite 0/1 to boolean\n      createdAt: new Date(agent.created_at),\n      updatedAt: new Date(agent.updated_at),\n    };\n  }\n}\n\n// Simple async mutex for protecting database initialization\nclass AsyncMutex {\n  private locked = false;\n  private queue: Array<() => void> = [];\n\n  async acquire(): Promise<void> {\n    if (!this.locked) {\n      this.locked = true;\n      return;\n    }\n    return new Promise<void>((resolve) => {\n      this.queue.push(resolve);\n    });\n  }\n\n  release(): void {\n    const next = this.queue.shift();\n    if (next) {\n      next();\n    } else {\n      this.locked = false;\n    }\n  }\n}\n\nlet database: Database | null = null;\nlet isInitializing: Promise<Database> | null = null;\nconst initMutex = new AsyncMutex();\n\nexport async function initializeDatabase(\n  config: DatabaseConfig,\n  logger?: Logger\n): Promise<Database> {\n  await initMutex.acquire();\n  try {\n    if (database) {\n      await database.disconnect();\n      database = null;\n    }\n\n    const newDatabase = new Database(config, logger);\n    try {\n      await newDatabase.connect();\n      await newDatabase.initialize();\n      database = newDatabase;\n      return database;\n    } catch (error) {\n      // Cleanup: disconnect if connect succeeded but initialize failed\n      await newDatabase.disconnect().catch((err) => {\n        const initLogger = logger || getLogger();\n        initLogger.warn('Failed to disconnect during cleanup', {\n          error: err instanceof Error ? err.message : String(err),\n        });\n      });\n      throw error;\n    }\n  } finally {\n    initMutex.release();\n  }\n}\n\nasync function ensureDatabaseInitialized(): Promise<Database> {\n  // Fast path: database already initialized\n  if (database) {\n    return database;\n  }\n\n  // Check if initialization is already in progress\n  if (isInitializing) {\n    return isInitializing;\n  }\n\n  await initMutex.acquire();\n  // Track if we've already released the mutex to prevent double release\n  let mutexReleased = false;\n\n  try {\n    // Double-check after acquiring lock\n    if (database) {\n      return database;\n    }\n\n    // Check again if initialization started while waiting for lock\n    if (isInitializing) {\n      // Release mutex before returning to avoid double release in finally\n      initMutex.release();\n      mutexReleased = true;\n      return isInitializing;\n    }\n\n    // Try to initialize from environment variable or use default SQLite\n    const dbUrl = process.env.DB_URL || 'sqlite://./astreus.db';\n\n    // Start initialization with error handling\n    const initPromise = (async () => {\n      const newDatabase = new Database({ connectionString: dbUrl });\n      try {\n        await newDatabase.connect();\n        await newDatabase.initialize();\n        database = newDatabase;\n        return database;\n      } catch (error) {\n        await newDatabase.disconnect().catch((err) => {\n          const ensureLogger = getLogger();\n          ensureLogger.warn('Failed to disconnect during cleanup', {\n            error: err instanceof Error ? err.message : String(err),\n          });\n        });\n        throw error;\n      }\n    })();\n\n    isInitializing = initPromise;\n\n    try {\n      const result = await initPromise;\n      isInitializing = null;\n      return result;\n    } catch (error) {\n      isInitializing = null;\n      database = null;\n      throw error;\n    }\n  } finally {\n    // Only release mutex if not already released\n    if (!mutexReleased) {\n      initMutex.release();\n    }\n  }\n}\n\nexport async function getDatabase(): Promise<Database> {\n  return ensureDatabaseInitialized();\n}\n\nexport * from './types';\nexport * from './sensitive-fields';\nexport { ConnectionPoolManager, getPoolManager } from './knex';\nexport default getDatabase;\n","/**\n * Default configuration values for database module\n */\nexport const DEFAULT_DATABASE_CONFIG = {\n  defaultTemperature: 0.7,\n  defaultMaxTokens: 2000,\n  defaultModel: 'gpt-4o-mini',\n  defaultBooleanValue: false,\n} as const;\n\n/**\n * Get default value for a database config property\n */\nexport function getDatabaseDefaultValue<K extends keyof typeof DEFAULT_DATABASE_CONFIG>(\n  key: K\n): (typeof DEFAULT_DATABASE_CONFIG)[K] {\n  return DEFAULT_DATABASE_CONFIG[key];\n}\n","import pino from 'pino';\nimport { Logger as ILogger, LoggerConfig, LogLevel, LogData } from './types';\n\nexport class Logger implements ILogger {\n  private pino: pino.Logger;\n  public config: LoggerConfig;\n  private transportWorker: pino.Logger | null = null;\n\n  constructor(config: Partial<LoggerConfig> = {}) {\n    const envLevel = process.env.LOG_LEVEL;\n    const validLevels: LogLevel[] = ['debug', 'info', 'warn', 'error', 'silent', 'success'];\n    const isValidLogLevel = (level: string | undefined): level is LogLevel =>\n      level !== undefined && validLevels.includes(level as LogLevel);\n\n    this.config = {\n      level: isValidLogLevel(envLevel) ? envLevel : 'info',\n      debug: config.debug ?? false,\n      enableConsole: true,\n      enableFile: false,\n      ...config,\n    };\n\n    // If LOG_LEVEL is 'silent', create a silent logger\n    if (envLevel === 'silent') {\n      this.pino = pino({ level: 'silent' });\n      return;\n    }\n\n    // Create pino instance with pretty printing in development\n    const isProduction = process.env.NODE_ENV === 'production';\n\n    const pinoConfig: pino.LoggerOptions = {\n      level: this.config.level === 'success' ? 'info' : this.config.level,\n      formatters: {\n        level: (label) => {\n          return { level: label };\n        },\n      },\n      base: {\n        framework: 'Astreus',\n      },\n      timestamp: this.config.debug ? pino.stdTimeFunctions.isoTime : false,\n    };\n\n    // Pretty print in development, JSON in production\n    if (!isProduction && this.config.enableConsole) {\n      this.pino = pino({\n        ...pinoConfig,\n        transport: {\n          target: 'pino-pretty',\n          options: {\n            colorize: true,\n            translateTime: false,\n            ignore: this.config.debug\n              ? 'pid,hostname,framework,level,time,module,agent,err'\n              : 'pid,hostname,framework,level,time,module,agent,data,err',\n            messageFormat:\n              '\\x1b[36mAstreus [\\x1b[34m{agent}\\x1b[36m] {module}\\x1b[0m → \\x1b[32m{msg}\\x1b[0m',\n            customColors: 'info:cyan,warn:yellow,error:red',\n            hideObject: !this.config.debug,\n            singleLine: false,\n            messageKey: 'msg',\n          },\n        },\n      });\n      // Store reference to transport worker for cleanup\n      this.transportWorker = this.pino;\n    } else {\n      this.pino = pino(pinoConfig);\n    }\n  }\n\n  private formatLogObject(\n    message: string,\n    module: string = 'Core',\n    data?: LogData,\n    error?: Error,\n    agentName?: string\n  ): Record<string, LogData> {\n    const logObject: Record<string, LogData> = {\n      msg: message,\n      module,\n      framework: 'Astreus',\n      agent: agentName ?? this.config.agentName ?? 'System',\n    };\n\n    if (data) {\n      logObject.data = data;\n    }\n\n    if (error) {\n      logObject.err = {\n        message: error.message,\n        stack: error.stack ?? null,\n        name: error.name,\n      };\n    }\n\n    return logObject;\n  }\n\n  debug(message: string, data?: LogData, agentName?: string): void {\n    const logObj = this.formatLogObject(message, 'Core', data, undefined, agentName);\n    this.pino.debug(logObj);\n  }\n\n  info(message: string, data?: LogData, agentName?: string): void {\n    const logObj = this.formatLogObject(message, 'Core', data, undefined, agentName);\n    this.pino.info(logObj);\n  }\n\n  warn(message: string, data?: LogData, agentName?: string): void {\n    const logObj = this.formatLogObject(message, 'Core', data, undefined, agentName);\n    this.pino.warn(logObj);\n  }\n\n  error(message: string, error?: Error, data?: LogData, agentName?: string): void {\n    const logObj = this.formatLogObject(message, 'Core', data, error, agentName);\n    this.pino.error(logObj);\n  }\n\n  success(message: string, data?: LogData, agentName?: string): void {\n    // Pino doesn't have success level, use info with success marker\n    const logObj = this.formatLogObject(message, 'Core', data, undefined, agentName);\n    logObj.level = 'success';\n    this.pino.info(logObj);\n  }\n\n  // Add a public log method for custom module names\n  log(\n    level: LogLevel,\n    message: string,\n    module: string = 'Core',\n    data?: LogData,\n    error?: Error,\n    agentName?: string\n  ): void {\n    const logObj = this.formatLogObject(message, module, data, error, agentName);\n\n    switch (level) {\n      case 'debug':\n        this.pino.debug(logObj);\n        break;\n      case 'info':\n      case 'success':\n        this.pino.info(logObj);\n        break;\n      case 'warn':\n        this.pino.warn(logObj);\n        break;\n      case 'error':\n        this.pino.error(logObj);\n        break;\n      case 'silent':\n        // Silent level - do not log anything\n        break;\n      default: {\n        // Exhaustive check - this ensures all LogLevel cases are handled\n        const _exhaustiveCheck: never = level;\n        throw new Error(`Unknown log level: ${_exhaustiveCheck}`);\n      }\n    }\n  }\n\n  setLevel(level: LogLevel): void {\n    this.config.level = level;\n    this.pino.level = level === 'success' ? 'info' : level;\n  }\n\n  setDebug(debug: boolean): void {\n    // Skip if no change\n    if (this.config.debug === debug) return;\n\n    // Cleanup old transport worker before replacing\n    this.cleanupTransportWorker();\n\n    this.config.debug = debug;\n    // Recreate pino instance with new debug setting\n    const isProduction = process.env.NODE_ENV === 'production';\n\n    const pinoConfig: pino.LoggerOptions = {\n      level: this.config.level === 'success' ? 'info' : this.config.level,\n      formatters: {\n        level: (label) => {\n          return { level: label };\n        },\n      },\n      base: {\n        framework: 'Astreus',\n      },\n      timestamp: debug ? pino.stdTimeFunctions.isoTime : false,\n    };\n\n    if (!isProduction && this.config.enableConsole) {\n      this.pino = pino({\n        ...pinoConfig,\n        transport: {\n          target: 'pino-pretty',\n          options: {\n            colorize: true,\n            translateTime: false,\n            ignore: debug\n              ? 'pid,hostname,framework,level,time,module,agent,err'\n              : 'pid,hostname,framework,level,time,module,agent,data,err',\n            messageFormat:\n              '\\x1b[36mAstreus [\\x1b[34m{agent}\\x1b[36m] {module}\\x1b[0m → \\x1b[32m{msg}\\x1b[0m',\n            customColors: 'info:cyan,warn:yellow,error:red',\n            hideObject: !debug,\n            singleLine: false,\n            messageKey: 'msg',\n          },\n        },\n      });\n      // Store reference to transport worker for cleanup\n      this.transportWorker = this.pino;\n    } else {\n      this.pino = pino(pinoConfig);\n      this.transportWorker = null;\n    }\n  }\n\n  /**\n   * Cleanup the transport worker to prevent memory leaks\n   */\n  private cleanupTransportWorker(): void {\n    if (this.transportWorker) {\n      // Flush any pending logs\n      if (this.transportWorker.flush) {\n        this.transportWorker.flush();\n      }\n      // End the transport stream if available (pino with transport uses destination stream)\n      // Access the internal stream property for cleanup\n      const pinoStreamSymbol = Symbol.for('pino.stream');\n      const transportInstance = this.transportWorker as unknown as Record<symbol, unknown>;\n      const destination = transportInstance[pinoStreamSymbol] as { end?: () => void } | undefined;\n      if (destination?.end) {\n        destination.end();\n      }\n      this.transportWorker = null;\n    }\n  }\n\n  /**\n   * Flush any pending log entries and cleanup resources.\n   * Call this before application shutdown.\n   */\n  async flush(): Promise<void> {\n    return new Promise((resolve, reject) => {\n      // pino.flush accepts a callback for async completion\n      if (this.pino.flush) {\n        this.pino.flush((err?: Error) => {\n          if (err) {\n            reject(err);\n          } else {\n            resolve();\n          }\n        });\n      } else {\n        resolve();\n      }\n    });\n  }\n\n  /**\n   * Dispose of the logger instance and cleanup resources.\n   */\n  dispose(): void {\n    // Cleanup transport worker (includes flush)\n    this.cleanupTransportWorker();\n\n    // Flush any pending logs synchronously if possible\n    if (this.pino.flush) {\n      this.pino.flush();\n    }\n  }\n}\n\n// Global logger instance\n// WARNING: This global logger is NOT thread-safe for concurrent initialization.\n// In multi-threaded environments (e.g., worker threads), each thread should create\n// its own Logger instance or synchronize access to the global logger.\n// For agent-specific logging, prefer creating agent-scoped Logger instances.\nlet globalLogger: Logger | null = null;\n\n// Proper async mutex implementation for thread-safe logger initialization\nclass AsyncMutex {\n  private locked = false;\n  private queue: (() => void)[] = [];\n\n  async acquire(): Promise<void> {\n    return new Promise((resolve) => {\n      if (!this.locked) {\n        this.locked = true;\n        resolve();\n      } else {\n        this.queue.push(resolve);\n      }\n    });\n  }\n\n  release(): void {\n    if (this.queue.length > 0) {\n      const next = this.queue.shift();\n      if (next) next();\n    } else {\n      this.locked = false;\n    }\n  }\n}\n\nconst loggerMutex = new AsyncMutex();\n\n// Synchronous getLogger - uses double-check locking pattern\nexport function getLogger(config?: Partial<LoggerConfig>): Logger {\n  // Fast path - already initialized (atomic read)\n  if (globalLogger) return globalLogger;\n\n  // For synchronous contexts, create immediately if not exists\n  // This is safe because Logger construction is synchronous\n  if (!globalLogger) {\n    globalLogger = new Logger({ agentName: 'System', ...config });\n  }\n  return globalLogger;\n}\n\n// Async version for proper mutex-protected initialization\nexport async function getLoggerAsync(config?: Partial<LoggerConfig>): Promise<Logger> {\n  // Fast path - already initialized\n  if (globalLogger) return globalLogger;\n\n  await loggerMutex.acquire();\n  try {\n    // Double-check after acquiring lock\n    if (!globalLogger) {\n      globalLogger = new Logger({ agentName: 'System', ...config });\n    }\n    return globalLogger;\n  } finally {\n    loggerMutex.release();\n  }\n}\n\nexport async function initializeLogger(config: Partial<LoggerConfig>): Promise<Logger> {\n  await loggerMutex.acquire();\n  try {\n    // Dispose of existing logger before creating new one to prevent memory leaks\n    if (globalLogger) {\n      globalLogger.dispose();\n    }\n    globalLogger = new Logger(config);\n    return globalLogger;\n  } finally {\n    loggerMutex.release();\n  }\n}\n\n// Synchronous initialization\nexport function initializeLoggerSync(config: Partial<LoggerConfig>): Logger {\n  // Dispose of existing logger before creating new one to prevent memory leaks\n  if (globalLogger) {\n    globalLogger.dispose();\n  }\n  globalLogger = new Logger(config);\n  return globalLogger;\n}\n\n/**\n * Cleanup the global logger instance.\n * Call this during application shutdown to ensure proper resource cleanup.\n */\nexport async function shutdownLogger(): Promise<void> {\n  // Capture reference and null first to prevent race conditions\n  const logger = globalLogger;\n  globalLogger = null;\n\n  if (logger) {\n    await logger.flush();\n    logger.dispose();\n  }\n}\n\n/**\n * Reset the global logger instance (useful for testing).\n */\nexport function resetLogger(): void {\n  if (globalLogger) {\n    globalLogger.dispose();\n    globalLogger = null;\n  }\n}\n\nexport * from './types';\n","import { Knex } from 'knex';\nimport { DatabaseConfig } from './types';\nimport { getLogger } from '../logger';\n\nfunction detectDatabaseType(config: DatabaseConfig): string {\n  if (config.type) {\n    return config.type;\n  }\n\n  if (config.connectionString) {\n    if (config.connectionString.startsWith('sqlite://')) {\n      return 'sqlite';\n    }\n    if (\n      config.connectionString.startsWith('postgresql://') ||\n      config.connectionString.startsWith('postgres://')\n    ) {\n      return 'postgres';\n    }\n  }\n\n  // Default to sqlite if no clear indication\n  return 'sqlite';\n}\n\n/**\n * Connection Pool Manager for tracking and managing database connections.\n * Provides connection pooling metrics, leak detection, and max limit control.\n *\n * Features:\n * - Connection usage tracking with acquire/release timestamps\n * - Leak detection for connections held longer than threshold\n * - Pool utilization metrics\n * - Max connection limit enforcement\n */\nexport class ConnectionPoolManager {\n  private static instance: ConnectionPoolManager | null = null;\n  private activeConnections: Map<string, { acquiredAt: number; stack?: string }> = new Map();\n  private totalAcquired = 0;\n  private totalReleased = 0;\n  private maxPoolSize: number;\n  private leakThresholdMs: number;\n  private leakCheckInterval: NodeJS.Timeout | null = null;\n  private logger = getLogger();\n\n  private constructor(maxPoolSize: number, leakThresholdMs: number = 30000) {\n    this.maxPoolSize = maxPoolSize;\n    this.leakThresholdMs = leakThresholdMs;\n    this.startLeakDetection();\n  }\n\n  static getInstance(\n    maxPoolSize: number = 10,\n    leakThresholdMs: number = 30000\n  ): ConnectionPoolManager {\n    if (!ConnectionPoolManager.instance) {\n      ConnectionPoolManager.instance = new ConnectionPoolManager(maxPoolSize, leakThresholdMs);\n    }\n    return ConnectionPoolManager.instance;\n  }\n\n  /**\n   * Track when a connection is acquired from the pool\n   */\n  onAcquire(connectionId?: string): void {\n    const id = connectionId || `conn_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n    const stack = new Error().stack; // Capture stack trace for debugging leaks\n\n    this.activeConnections.set(id, {\n      acquiredAt: Date.now(),\n      stack,\n    });\n    this.totalAcquired++;\n\n    // Check if we're approaching max pool size\n    if (this.activeConnections.size >= this.maxPoolSize * 0.8) {\n      this.logger.warn('Connection pool utilization high', {\n        active: this.activeConnections.size,\n        max: this.maxPoolSize,\n        utilization: `${((this.activeConnections.size / this.maxPoolSize) * 100).toFixed(1)}%`,\n      });\n    }\n\n    this.logger.debug('Database connection acquired', {\n      connectionId: id,\n      activeConnections: this.activeConnections.size,\n      totalAcquired: this.totalAcquired,\n    });\n  }\n\n  /**\n   * Track when a connection is released back to the pool\n   */\n  onRelease(connectionId?: string): void {\n    // If no specific ID, release the oldest connection\n    if (!connectionId && this.activeConnections.size > 0) {\n      const keysIterator = this.activeConnections.keys().next();\n      // Properly check for undefined - iterator may return {done: true, value: undefined}\n      if (!keysIterator.done && keysIterator.value !== undefined) {\n        connectionId = keysIterator.value;\n      }\n    }\n\n    if (connectionId && this.activeConnections.has(connectionId)) {\n      this.activeConnections.delete(connectionId);\n      this.totalReleased++;\n\n      this.logger.debug('Database connection released', {\n        connectionId,\n        activeConnections: this.activeConnections.size,\n        totalReleased: this.totalReleased,\n      });\n    }\n  }\n\n  /**\n   * Start periodic leak detection\n   */\n  private startLeakDetection(): void {\n    // Check for leaks every 10 seconds\n    this.leakCheckInterval = setInterval(() => {\n      this.detectLeaks();\n    }, 10000);\n\n    // Allow process to exit even if interval is running\n    this.leakCheckInterval.unref();\n  }\n\n  /**\n   * Detect and log potential connection leaks\n   */\n  private detectLeaks(): void {\n    const now = Date.now();\n    const leaks: Array<{ id: string; heldForMs: number; stack?: string }> = [];\n\n    for (const [id, info] of this.activeConnections.entries()) {\n      const heldForMs = now - info.acquiredAt;\n      if (heldForMs > this.leakThresholdMs) {\n        leaks.push({ id, heldForMs, stack: info.stack });\n      }\n    }\n\n    if (leaks.length > 0) {\n      // Convert leaks to LogData compatible format (serialize to JSON string)\n      const leakDetails = leaks.map((l) => ({\n        connectionId: l.id,\n        heldForSeconds: (l.heldForMs / 1000).toFixed(1),\n        stackPreview: l.stack?.split('\\n').slice(2, 5).join(' -> ') ?? null,\n      }));\n      this.logger.warn('Potential database connection leaks detected', {\n        leakCount: leaks.length,\n        leakSummary: JSON.stringify(leakDetails),\n      });\n    }\n  }\n\n  /**\n   * Check if pool can accept new connections\n   */\n  canAcquire(): boolean {\n    return this.activeConnections.size < this.maxPoolSize;\n  }\n\n  /**\n   * Get current pool statistics\n   */\n  getStats(): {\n    activeConnections: number;\n    maxPoolSize: number;\n    totalAcquired: number;\n    totalReleased: number;\n    utilization: number;\n  } {\n    return {\n      activeConnections: this.activeConnections.size,\n      maxPoolSize: this.maxPoolSize,\n      totalAcquired: this.totalAcquired,\n      totalReleased: this.totalReleased,\n      utilization: this.activeConnections.size / this.maxPoolSize,\n    };\n  }\n\n  /**\n   * Cleanup resources\n   */\n  destroy(): void {\n    if (this.leakCheckInterval) {\n      clearInterval(this.leakCheckInterval);\n      this.leakCheckInterval = null;\n    }\n    this.activeConnections.clear();\n    ConnectionPoolManager.instance = null;\n  }\n}\n\n// Global pool manager instance\nlet poolManager: ConnectionPoolManager | null = null;\n\n/**\n * Get the global connection pool manager\n */\nexport function getPoolManager(maxPoolSize: number = 10): ConnectionPoolManager {\n  if (!poolManager) {\n    poolManager = ConnectionPoolManager.getInstance(maxPoolSize);\n  }\n  return poolManager;\n}\n\nexport function createKnexConfig(config: DatabaseConfig): Knex.Config {\n  const dbType = detectDatabaseType(config);\n\n  switch (dbType) {\n    case 'sqlite': {\n      let filename = config.filename || ':memory:';\n\n      // Extract filename from sqlite:// URL\n      if (config.connectionString && config.connectionString.startsWith('sqlite://')) {\n        filename = config.connectionString.replace('sqlite://', '');\n      }\n\n      return {\n        client: 'sqlite3',\n        connection: {\n          filename: filename,\n        },\n        useNullAsDefault: true,\n        migrations: {\n          directory: './migrations',\n        },\n      };\n    }\n\n    case 'postgres': {\n      // Pool size from config with sensible defaults\n      const maxPoolSize = config.maxPoolSize ?? 10;\n      const minPoolSize = config.minPoolSize ?? 2;\n\n      // Initialize pool manager with configured max size\n      const manager = getPoolManager(maxPoolSize);\n\n      // PostgreSQL requires connection string (DB_URL) for configuration\n      if (!config.connectionString) {\n        throw new Error('PostgreSQL requires DB_URL connection string to be set');\n      }\n\n      return {\n        client: 'pg',\n        connection: config.connectionString,\n        pool: {\n          min: minPoolSize,\n          max: maxPoolSize,\n          acquireTimeoutMillis: 30000,\n          idleTimeoutMillis: 30000,\n          // Track connection creation for pool monitoring\n          // Note: Knex/tarn pool only supports afterCreate hook natively\n          // Release tracking is handled via periodic leak detection in ConnectionPoolManager\n          // The leak detection timer (every 10 seconds) will identify connections held too long\n          afterCreate: (conn: unknown, done: (err: Error | null, conn: unknown) => void) => {\n            manager.onAcquire();\n            done(null, conn);\n          },\n        },\n        migrations: {\n          directory: './migrations',\n        },\n      };\n    }\n\n    default:\n      throw new Error(`Unsupported database type: ${dbType}`);\n  }\n}\n","import { createCipheriv, createDecipheriv, randomBytes, scrypt, pbkdf2 } from 'crypto';\nimport { promisify } from 'util';\nimport { getLogger } from '../logger';\n\nconst scryptAsync = promisify(scrypt);\nconst pbkdf2Async = promisify(pbkdf2);\n\nexport interface EncryptionConfig {\n  enabled: boolean;\n  masterKey: string;\n  algorithm: string;\n}\n\nexport interface EncryptedData {\n  iv: string;\n  encrypted: string;\n  tag: string;\n  version: number;\n}\n\n/**\n * Encryption service for database field-level encryption\n * Uses AES-256-GCM for authenticated encryption\n */\nexport class EncryptionService {\n  private config: EncryptionConfig;\n  private keyCache: Map<string, Buffer> = new Map();\n  private static readonly MAX_CACHE_SIZE = 100; // Prevent unbounded memory growth\n\n  // Current encryption version for future key rotation support\n  private readonly CURRENT_VERSION = 1;\n  private readonly ALGORITHM = 'aes-256-gcm';\n  private readonly IV_LENGTH = 12; // 12 bytes for GCM\n  private readonly TAG_LENGTH = 16; // 16 bytes for GCM auth tag\n  private readonly SALT_LENGTH = 32; // 32 bytes for salt\n  private readonly PBKDF2_ITERATIONS = 100000; // OWASP recommended minimum\n\n  constructor(config: EncryptionConfig) {\n    this.config = config;\n\n    if (config.enabled && !config.masterKey) {\n      throw new Error('ENCRYPTION_MASTER_KEY is required when encryption is enabled');\n    }\n\n    if (config.enabled && config.masterKey.length < 32) {\n      throw new Error('ENCRYPTION_MASTER_KEY must be at least 32 characters long');\n    }\n  }\n\n  /**\n   * Check if encryption is enabled\n   */\n  isEnabled(): boolean {\n    return this.config.enabled;\n  }\n\n  /**\n   * Derive a field-specific encryption key using secure salt generation\n   * Uses LRU (Least Recently Used) cache eviction strategy\n   */\n  private async deriveKey(fieldName: string): Promise<Buffer> {\n    const cacheKey = `${fieldName}_v${this.CURRENT_VERSION}`;\n\n    if (this.keyCache.has(cacheKey)) {\n      // LRU: Move accessed key to end by deleting and re-adding\n      const cachedKey = this.keyCache.get(cacheKey)!;\n      this.keyCache.delete(cacheKey);\n      this.keyCache.set(cacheKey, cachedKey);\n      return cachedKey;\n    }\n\n    // Generate deterministic but secure salt from field name and master key\n    // This ensures same field gets same key while being cryptographically secure\n    const fieldBuffer = Buffer.from(fieldName, 'utf8');\n    const versionBuffer = Buffer.from(this.CURRENT_VERSION.toString(), 'utf8');\n    const contextBuffer = Buffer.concat([fieldBuffer, versionBuffer]);\n\n    // Use PBKDF2 to create a secure salt from the context\n    const salt = await pbkdf2Async(\n      this.config.masterKey,\n      contextBuffer,\n      this.PBKDF2_ITERATIONS,\n      this.SALT_LENGTH,\n      'sha256'\n    );\n\n    // Derive the actual encryption key using scrypt with the secure salt\n    const derivedKey = (await scryptAsync(this.config.masterKey, salt, 32)) as Buffer;\n\n    // Enforce cache size limit to prevent memory leaks (LRU eviction)\n    if (this.keyCache.size >= EncryptionService.MAX_CACHE_SIZE) {\n      // Remove least recently used entry (first key in Map iteration order)\n      const keysIterator = this.keyCache.keys().next();\n      if (!keysIterator.done && keysIterator.value !== undefined) {\n        this.keyCache.delete(keysIterator.value);\n      }\n    }\n    this.keyCache.set(cacheKey, derivedKey);\n    return derivedKey;\n  }\n\n  /**\n   * Encrypt a string value\n   */\n  async encrypt(value: string, fieldName: string): Promise<string> {\n    if (!this.config.enabled) {\n      return value; // Return original value if encryption is disabled\n    }\n\n    if (value === null || value === undefined || value === '') {\n      return value; // Don't encrypt empty values\n    }\n\n    // Check if value is already encrypted\n    if (this.isEncrypted(value)) {\n      return value; // Already encrypted, return as is\n    }\n\n    try {\n      const key = await this.deriveKey(fieldName);\n      const iv = randomBytes(this.IV_LENGTH);\n\n      const cipher = createCipheriv(this.ALGORITHM, key, iv);\n\n      let encrypted = cipher.update(value, 'utf8', 'base64');\n      encrypted += cipher.final('base64');\n\n      const tag = cipher.getAuthTag();\n\n      const encryptedData: EncryptedData = {\n        iv: iv.toString('base64'),\n        encrypted,\n        tag: tag.toString('base64'),\n        version: this.CURRENT_VERSION,\n      };\n\n      // Format: enc:version:iv:encrypted:tag\n      return `enc:${encryptedData.version}:${encryptedData.iv}:${encryptedData.encrypted}:${encryptedData.tag}`;\n    } catch (error) {\n      throw new Error(\n        `Encryption failed for field ${fieldName}: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  /**\n   * Decrypt a string value\n   */\n  async decrypt(value: string, fieldName: string): Promise<string> {\n    if (!this.config.enabled) {\n      return value; // Return original value if encryption is disabled\n    }\n\n    if (value === null || value === undefined || value === '') {\n      return value; // Return empty values as is\n    }\n\n    // Check if value is encrypted\n    if (!this.isEncrypted(value)) {\n      return value; // Not encrypted, return as is\n    }\n\n    try {\n      const encryptedData = this.parseEncryptedData(value);\n      const key = await this.deriveKey(fieldName);\n\n      const decipher = createDecipheriv(\n        this.ALGORITHM,\n        key,\n        Buffer.from(encryptedData.iv, 'base64')\n      );\n      decipher.setAuthTag(Buffer.from(encryptedData.tag, 'base64'));\n\n      let decrypted = decipher.update(encryptedData.encrypted, 'base64', 'utf8');\n      decrypted += decipher.final('utf8');\n\n      return decrypted;\n    } catch (error) {\n      throw new Error(\n        `Decryption failed for field ${fieldName}: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  /**\n   * Check if a value appears to be encrypted\n   */\n  isEncrypted(value: string): boolean {\n    if (typeof value !== 'string') return false;\n    return value.startsWith('enc:') && value.split(':').length === 5;\n  }\n\n  /**\n   * Parse encrypted data string into components\n   */\n  private parseEncryptedData(encryptedString: string): EncryptedData {\n    const parts = encryptedString.split(':');\n    if (parts.length !== 5 || parts[0] !== 'enc') {\n      throw new Error('Invalid encrypted data format');\n    }\n\n    return {\n      version: parseInt(parts[1], 10),\n      iv: parts[2],\n      encrypted: parts[3],\n      tag: parts[4],\n    };\n  }\n\n  /**\n   * Encrypt JSON metadata\n   */\n  async encryptJSON(\n    value: Record<string, string | number | boolean | null> | string | null,\n    fieldName: string\n  ): Promise<string | null> {\n    if (!value) return null;\n\n    const jsonString = typeof value === 'string' ? value : JSON.stringify(value);\n    return this.encrypt(jsonString, fieldName);\n  }\n\n  /**\n   * Decrypt JSON metadata\n   */\n  async decryptJSON(\n    value: string | null,\n    fieldName: string\n  ): Promise<string | Record<string, unknown> | null> {\n    if (!value) return null;\n\n    const decrypted = await this.decrypt(value, fieldName);\n    if (!decrypted) return null;\n\n    try {\n      const parsed = JSON.parse(decrypted);\n      // Validate parsed result is a valid object or primitive\n      if (typeof parsed !== 'object' || parsed === null) {\n        // Return primitives as-is (string, number, boolean)\n        if (\n          typeof parsed === 'string' ||\n          typeof parsed === 'number' ||\n          typeof parsed === 'boolean'\n        ) {\n          return decrypted; // Return original string for primitive types\n        }\n        throw new Error('Invalid decrypted data format: expected object or valid primitive');\n      }\n      return parsed;\n    } catch (error) {\n      // If parsing fails, return the decrypted string as-is\n      // But log the error for debugging\n      if (error instanceof SyntaxError) {\n        return decrypted;\n      }\n      // Re-throw validation errors\n      throw error;\n    }\n  }\n\n  /**\n   * Clear the key cache (useful for testing or key rotation)\n   */\n  clearCache(): void {\n    this.keyCache.clear();\n  }\n}\n\n// Singleton state management with proper mutex protection\nclass EncryptionServiceSingleton {\n  private static instance: EncryptionService | null = null;\n  private static cachedConfig: EncryptionConfig | null = null;\n  private static initializationPromise: Promise<EncryptionService> | null = null;\n  private static initializationLock = false;\n  private static waitingResolvers: Array<(instance: EncryptionService) => void> = [];\n\n  /**\n   * Get current encryption config from environment\n   */\n  private static getCurrentConfig(): EncryptionConfig {\n    return {\n      enabled: process.env.ENCRYPTION_ENABLED === 'true',\n      masterKey: process.env.ENCRYPTION_MASTER_KEY || '',\n      algorithm: process.env.ENCRYPTION_ALGORITHM || 'aes-256-gcm',\n    };\n  }\n\n  /**\n   * Check if config has changed\n   */\n  private static hasConfigChanged(newConfig: EncryptionConfig): boolean {\n    if (!this.cachedConfig) return true;\n    return (\n      this.cachedConfig.enabled !== newConfig.enabled ||\n      this.cachedConfig.masterKey !== newConfig.masterKey ||\n      this.cachedConfig.algorithm !== newConfig.algorithm\n    );\n  }\n\n  /**\n   * Get or create the encryption service instance\n   * Thread-safe singleton with proper mutex pattern for JavaScript async\n   */\n  static getInstance(): EncryptionService {\n    const currentConfig = this.getCurrentConfig();\n\n    // Fast path: return existing instance if config hasn't changed\n    if (this.instance && !this.hasConfigChanged(currentConfig)) {\n      return this.instance;\n    }\n\n    // If initialization is in progress, wait for it or return existing instance\n    if (this.initializationLock) {\n      // If we have an existing instance (config change in progress), return it\n      if (this.instance) {\n        return this.instance;\n      }\n      // Create instance synchronously as fallback - this ensures we always return something\n      // This handles the race condition where isInitializing is true but instance is null\n      const fallbackInstance = new EncryptionService(currentConfig);\n      return fallbackInstance;\n    }\n\n    // Acquire lock\n    this.initializationLock = true;\n    try {\n      // Double-check after acquiring lock\n      if (this.instance && !this.hasConfigChanged(currentConfig)) {\n        return this.instance;\n      }\n\n      this.instance = new EncryptionService(currentConfig);\n      this.cachedConfig = { ...currentConfig }; // Clone config to prevent mutations\n\n      // Log encryption status using proper logger\n      const logger = getLogger();\n      const status = currentConfig.enabled ? 'ENABLED' : 'DISABLED';\n      const keyStatus = currentConfig.masterKey ? '(key configured)' : '(no key)';\n      logger.debug(`Encryption service initialized: ${status} ${keyStatus}`);\n\n      // Notify any waiting callers\n      for (const resolver of this.waitingResolvers) {\n        resolver(this.instance);\n      }\n      this.waitingResolvers = [];\n\n      return this.instance;\n    } finally {\n      this.initializationLock = false;\n    }\n  }\n\n  /**\n   * Initialize encryption service with custom config (useful for testing)\n   * Replaces the singleton instance atomically\n   */\n  static initializeWithConfig(config: EncryptionConfig): EncryptionService {\n    // Wait if another initialization is in progress\n    while (this.initializationLock) {\n      // Spin-wait is safe here as initialization is synchronous and fast\n    }\n    this.initializationLock = true;\n    try {\n      this.instance = new EncryptionService(config);\n      this.cachedConfig = { ...config }; // Clone config to prevent mutations\n      return this.instance;\n    } finally {\n      this.initializationLock = false;\n    }\n  }\n\n  /**\n   * Reset the singleton (useful for testing)\n   */\n  static reset(): void {\n    this.instance = null;\n    this.cachedConfig = null;\n    this.initializationLock = false;\n    this.initializationPromise = null;\n    this.waitingResolvers = [];\n  }\n}\n\n/**\n * Get or create the encryption service instance\n * Automatically reinitializes if environment variables change\n */\nexport function getEncryptionService(): EncryptionService {\n  return EncryptionServiceSingleton.getInstance();\n}\n\n/**\n * Initialize encryption service with custom config (useful for testing)\n */\nexport function initializeEncryptionService(config: EncryptionConfig): EncryptionService {\n  return EncryptionServiceSingleton.initializeWithConfig(config);\n}\n\n/**\n * Reset the encryption service singleton (useful for testing)\n */\nexport function resetEncryptionService(): void {\n  EncryptionServiceSingleton.reset();\n}\n","import * as fs from 'fs';\nimport { getEncryptionService } from './encryption';\nimport { getSensitiveFields } from './sensitive-fields';\nimport { getLogger } from '../logger';\n\n/**\n * Validate table name to prevent injection attacks\n * Only allows alphanumeric characters and underscores\n */\nfunction isValidTableName(tableName: string): boolean {\n  return /^[a-zA-Z_][a-zA-Z0-9_]*$/.test(tableName);\n}\n\n/**\n * Simple token counting utility\n * This is a rough approximation - for production use, consider using tiktoken\n */\nexport function countTokens(text: string): number {\n  // Input validation\n  if (typeof text !== 'string') {\n    throw new TypeError('countTokens: text must be a string');\n  }\n\n  // Handle empty string case\n  if (text.length === 0) {\n    return 0;\n  }\n\n  // Check for potential overflow - text.length is already bounded by string max length\n  // but we add explicit check for safety with division result\n  const rawTokenCount = text.length / 4;\n\n  // Ensure we don't exceed safe integer bounds\n  if (rawTokenCount > Number.MAX_SAFE_INTEGER) {\n    return Number.MAX_SAFE_INTEGER;\n  }\n\n  // Simple estimation: 1 token ≈ 4 characters for English text\n  // This is a rough approximation - actual tokenization depends on the model\n  return Math.ceil(rawTokenCount);\n}\n\n/**\n * More accurate word-based token estimation\n */\nexport function countTokensWordBased(text: string): number {\n  // Input validation\n  if (typeof text !== 'string') {\n    throw new TypeError('countTokensWordBased: text must be a string');\n  }\n\n  const trimmed = text.trim();\n\n  // Handle empty string case\n  if (trimmed.length === 0) {\n    return 0;\n  }\n\n  const words = trimmed.split(/\\s+/);\n  // Rough estimation: 1 token ≈ 0.75 words\n  return Math.ceil(words.length / 0.75);\n}\n\n/**\n * Get file size from file path (async version - preferred)\n */\nexport async function getFileSizeAsync(filePath: string): Promise<number> {\n  // Input validation\n  if (typeof filePath !== 'string') {\n    throw new TypeError('getFileSizeAsync: filePath must be a string');\n  }\n\n  if (filePath.trim().length === 0) {\n    throw new Error('getFileSizeAsync: filePath cannot be empty');\n  }\n\n  // Prevent path traversal attacks\n  if (filePath.includes('\\0')) {\n    throw new Error('getFileSizeAsync: filePath contains invalid characters');\n  }\n\n  try {\n    const stats = await fs.promises.stat(filePath);\n    return stats.size;\n  } catch (error) {\n    // Return 0 for non-existent files\n    if (\n      error instanceof Error &&\n      'code' in error &&\n      (error as NodeJS.ErrnoException).code === 'ENOENT'\n    ) {\n      return 0;\n    }\n    // Re-throw other errors (permission issues, etc.)\n    throw error;\n  }\n}\n\n/**\n * Centralized encryption utility for database fields\n * Encrypts sensitive fields based on centralized configuration\n */\nexport async function encryptSensitiveFields(\n  data: Record<string, string | number | boolean | null | undefined | Date>,\n  tableName: string\n): Promise<Record<string, string | number | boolean | null | undefined | Date>> {\n  // Input validation\n  if (typeof tableName !== 'string' || tableName.trim().length === 0) {\n    throw new Error('encryptSensitiveFields: tableName must be a non-empty string');\n  }\n\n  if (!isValidTableName(tableName)) {\n    throw new Error('encryptSensitiveFields: tableName contains invalid characters');\n  }\n\n  // Handle null/undefined data gracefully\n  if (data === null || data === undefined) {\n    return data;\n  }\n\n  if (typeof data !== 'object') {\n    throw new TypeError('encryptSensitiveFields: data must be an object');\n  }\n\n  const encryption = getEncryptionService();\n\n  if (!encryption.isEnabled()) {\n    const logger = getLogger();\n    logger.debug(`Skipping encryption for ${tableName} (disabled)`);\n    return data;\n  }\n\n  const encrypted = { ...data };\n\n  // Get sensitive fields from centralized configuration\n  const fieldsToEncrypt = getSensitiveFields(tableName);\n\n  const encryptedFields: string[] = [];\n  for (const field of fieldsToEncrypt) {\n    const fieldValue = encrypted[field];\n    if (fieldValue !== undefined && fieldValue !== null) {\n      try {\n        if (field === 'metadata') {\n          // Handle JSON metadata fields - wrap encrypted string in JSON\n          const metadataStr =\n            typeof fieldValue === 'string' ? fieldValue : JSON.stringify(fieldValue);\n          const encryptedStr = await encryption.encrypt(\n            metadataStr as string,\n            `${tableName}.${field}`\n          );\n          // Wrap in JSON object for JSONB compatibility\n          encrypted[field] = JSON.stringify({ _encrypted: encryptedStr });\n          encryptedFields.push(field);\n        } else if (field === 'contextData' && typeof fieldValue === 'string') {\n          // Handle JSON contextData field (special case for contexts table)\n          encrypted[field] = await encryption.encryptJSON(fieldValue, `${tableName}.${field}`);\n          encryptedFields.push(field);\n        } else {\n          // Handle string fields\n          encrypted[field] = await encryption.encrypt(String(fieldValue), `${tableName}.${field}`);\n          encryptedFields.push(field);\n        }\n      } catch (error) {\n        // Log error and re-throw with more context\n        const errorMessage = error instanceof Error ? error.message : 'Unknown error';\n        throw new Error(\n          `Failed to encrypt field '${field}' in table '${tableName}': ${errorMessage}`\n        );\n      }\n    }\n  }\n\n  if (encryptedFields.length > 0) {\n    const logger = getLogger();\n    logger.debug(`Encrypted ${encryptedFields.length} field(s) in ${tableName}`, {\n      fields: encryptedFields,\n    });\n  }\n\n  return encrypted;\n}\n\n/**\n * Centralized decryption utility for database fields\n * Decrypts sensitive fields based on centralized configuration\n */\nexport async function decryptSensitiveFields(\n  data: Record<string, string | number | boolean | null | undefined | Date>,\n  tableName: string\n): Promise<Record<string, string | number | boolean | null | undefined | Date>> {\n  // Input validation\n  if (typeof tableName !== 'string' || tableName.trim().length === 0) {\n    throw new Error('decryptSensitiveFields: tableName must be a non-empty string');\n  }\n\n  if (!isValidTableName(tableName)) {\n    throw new Error('decryptSensitiveFields: tableName contains invalid characters');\n  }\n\n  // Handle null/undefined data gracefully\n  if (data === null || data === undefined) {\n    return data;\n  }\n\n  if (typeof data !== 'object') {\n    throw new TypeError('decryptSensitiveFields: data must be an object');\n  }\n\n  const encryption = getEncryptionService();\n\n  if (!encryption.isEnabled()) {\n    return data;\n  }\n\n  const decrypted = { ...data };\n\n  // Get sensitive fields from centralized configuration\n  const fieldsToDecrypt = getSensitiveFields(tableName);\n\n  for (const field of fieldsToDecrypt) {\n    const fieldValue = decrypted[field];\n    if (fieldValue !== undefined && fieldValue !== null) {\n      try {\n        if (field === 'metadata') {\n          // Handle JSON metadata fields - check for wrapped encrypted format\n          let parsedMetadata: unknown;\n\n          // Try to parse as JSON\n          if (typeof fieldValue === 'string') {\n            try {\n              parsedMetadata = JSON.parse(fieldValue);\n            } catch {\n              parsedMetadata = fieldValue;\n            }\n          } else {\n            // fieldValue could be an object, number, boolean, or Date\n            parsedMetadata = fieldValue;\n          }\n\n          // Check if it's our encrypted wrapper format\n          if (\n            parsedMetadata !== null &&\n            parsedMetadata !== undefined &&\n            typeof parsedMetadata === 'object' &&\n            !Array.isArray(parsedMetadata) &&\n            '_encrypted' in parsedMetadata\n          ) {\n            const encryptedWrapper = parsedMetadata as { _encrypted: unknown };\n            const encryptedStr = String(encryptedWrapper._encrypted);\n            const decryptedStr = await encryption.decrypt(encryptedStr, `${tableName}.${field}`);\n            // Parse the decrypted JSON string\n            try {\n              const parsedResult = JSON.parse(decryptedStr);\n              // Ensure the result is a valid field type\n              if (\n                typeof parsedResult === 'string' ||\n                typeof parsedResult === 'number' ||\n                typeof parsedResult === 'boolean' ||\n                parsedResult === null\n              ) {\n                decrypted[field] = parsedResult;\n              } else {\n                // For objects/arrays, stringify back\n                decrypted[field] = JSON.stringify(parsedResult);\n              }\n            } catch {\n              decrypted[field] = decryptedStr;\n            }\n          } else {\n            // Not encrypted or old format - convert to valid field type\n            if (\n              typeof parsedMetadata === 'string' ||\n              typeof parsedMetadata === 'number' ||\n              typeof parsedMetadata === 'boolean' ||\n              parsedMetadata === null ||\n              parsedMetadata === undefined ||\n              parsedMetadata instanceof Date\n            ) {\n              decrypted[field] = parsedMetadata;\n            } else {\n              // For objects/arrays, stringify\n              decrypted[field] = JSON.stringify(parsedMetadata);\n            }\n          }\n        } else if (field === 'contextData') {\n          // Handle JSON contextData field (special case for contexts table)\n          const decryptedData = await encryption.decryptJSON(\n            String(fieldValue),\n            `${tableName}.${field}`\n          );\n          decrypted[field] =\n            typeof decryptedData === 'string' ? decryptedData : JSON.stringify(decryptedData);\n        } else {\n          // Handle string fields\n          decrypted[field] = await encryption.decrypt(String(fieldValue), `${tableName}.${field}`);\n        }\n      } catch (error) {\n        // Log error with proper logger and throw to prevent silent data corruption\n        const errorMessage = error instanceof Error ? error.message : 'Unknown error';\n        const logger = getLogger();\n        logger.error(\n          `Decryption failed for field '${field}' in table '${tableName}': ${errorMessage}`\n        );\n        throw new Error(\n          `Failed to decrypt field '${field}' in table '${tableName}': ${errorMessage}`\n        );\n      }\n    }\n  }\n\n  return decrypted;\n}\n","import { getLogger } from '../logger';\n\n/**\n * Centralized configuration for sensitive database fields that require encryption\n */\n\nexport const SENSITIVE_FIELDS: Record<string, string[]> = {\n  // Agent configuration fields\n  agents: ['systemPrompt', 'description'],\n\n  // Memory system fields\n  memories: ['content', 'metadata'],\n\n  // Task system fields\n  tasks: ['prompt', 'response', 'metadata'],\n\n  // Knowledge system document fields\n  knowledge_documents: ['content', 'title', 'file_path', 'metadata'],\n\n  // Knowledge system chunk fields\n  knowledge_chunks: ['content', 'metadata'],\n\n  // Context system fields\n  contexts: ['contextData', 'summary'],\n\n  // Scheduler system fields\n  scheduled_items: ['metadata'],\n\n  // Graph system fields\n  graphs: ['description', 'metadata'],\n  graph_nodes: ['prompt', 'result', 'error', 'metadata'],\n  graph_edges: ['metadata'],\n};\n\n/**\n * Get sensitive fields for a specific table\n */\nexport function getSensitiveFields(tableName: string): string[] {\n  return SENSITIVE_FIELDS[tableName] || [];\n}\n\n/**\n * Check if a field is sensitive for a given table\n */\nexport function isFieldSensitive(tableName: string, fieldName: string): boolean {\n  const fields = getSensitiveFields(tableName);\n  return fields.includes(fieldName);\n}\n\n/**\n * Validate that all sensitive fields are consistently defined\n */\nexport function validateSensitiveFieldsConfig(): void {\n  const tables = Object.keys(SENSITIVE_FIELDS);\n\n  for (const table of tables) {\n    const fields = SENSITIVE_FIELDS[table];\n\n    if (!Array.isArray(fields)) {\n      throw new Error(`Sensitive fields for table '${table}' must be an array`);\n    }\n\n    if (fields.length === 0) {\n      const logger = getLogger();\n      logger.warn(`No sensitive fields defined for table '${table}'`);\n    }\n\n    // Check for duplicate field names\n    const uniqueFields = new Set(fields);\n    if (uniqueFields.size !== fields.length) {\n      throw new Error(`Duplicate sensitive fields found for table '${table}'`);\n    }\n\n    // Validate field names\n    for (const field of fields) {\n      if (typeof field !== 'string' || field.length === 0) {\n        throw new Error(\n          `Invalid field name '${field}' in table '${table}' - must be non-empty string`\n        );\n      }\n\n      // Check for reserved or problematic field names\n      const reservedFields = ['id', 'created_at', 'updated_at'];\n      if (reservedFields.includes(field.toLowerCase())) {\n        throw new Error(\n          `Field '${field}' in table '${table}' is reserved and should not be encrypted`\n        );\n      }\n    }\n  }\n}\n\n/**\n * Validate encryption configuration for consistency\n */\nexport function validateEncryptionConsistency(): {\n  isValid: boolean;\n  errors: string[];\n  warnings: string[];\n} {\n  const errors: string[] = [];\n  const warnings: string[] = [];\n\n  try {\n    validateSensitiveFieldsConfig();\n  } catch (error) {\n    errors.push(\n      `Sensitive fields validation failed: ${error instanceof Error ? error.message : String(error)}`\n    );\n  }\n\n  // Check for common sensitive field patterns that might be missing\n  const commonSensitivePatterns = ['password', 'secret', 'key', 'token', 'credential'];\n\n  for (const [tableName, fields] of Object.entries(SENSITIVE_FIELDS)) {\n    for (const commonPattern of commonSensitivePatterns) {\n      // Check if any field in this table matches the sensitive pattern\n      const hasPattern = fields.some((field) => field.toLowerCase().includes(commonPattern));\n      if (hasPattern) {\n        // Good - table has fields matching sensitive patterns, no warning needed\n        break;\n      }\n    }\n    // Note: Not having common patterns is not necessarily a warning -\n    // the table might legitimately not have such fields\n    void tableName; // Acknowledge we intentionally don't warn here\n  }\n\n  // Check for tables that might need encryption but aren't configured\n  const knownTables = Object.keys(SENSITIVE_FIELDS);\n  const expectedTables = [\n    'agents',\n    'memories',\n    'tasks',\n    'contexts',\n    'knowledge_documents',\n    'knowledge_chunks',\n  ];\n\n  for (const expectedTable of expectedTables) {\n    if (!knownTables.includes(expectedTable)) {\n      warnings.push(`Table '${expectedTable}' might need encryption configuration`);\n    }\n  }\n\n  return {\n    isValid: errors.length === 0,\n    errors,\n    warnings,\n  };\n}\n","import {\n  LLMProvider,\n  LLMRequestOptions,\n  LLMResponse,\n  LLMStreamChunk,\n  LLMConfig,\n  LLMUsage,\n  LLMMessage,\n  VisionAnalysisOptions,\n  VisionAnalysisResult,\n  EmbeddingResult,\n} from '../types';\nimport OpenAI from 'openai';\nimport { getLogger } from '../../logger';\nimport { Logger } from '../../logger/types';\nimport { LLMApiError, VisionError } from '../../errors';\nimport * as fs from 'fs';\nimport * as path from 'path';\n\n// Retry helper with exponential backoff\nasync function withRetry<T>(fn: () => Promise<T>, maxRetries = 3): Promise<T> {\n  let lastError: Error | undefined;\n  for (let i = 0; i < maxRetries; i++) {\n    try {\n      return await fn();\n    } catch (error) {\n      lastError = error as Error;\n      if (i < maxRetries - 1) {\n        await new Promise((r) => setTimeout(r, Math.pow(2, i) * 1000));\n      }\n    }\n  }\n  if (!lastError) {\n    throw new Error('No retry attempts made');\n  }\n  throw lastError;\n}\n\n// OpenAI-specific message type that accepts string arguments for tool calls\ninterface OpenAIMessage extends Omit<LLMMessage, 'tool_calls'> {\n  tool_calls?: Array<{\n    id: string;\n    type: 'function';\n    function: {\n      name: string;\n      arguments: string; // OpenAI requires string, not our Record type\n    };\n  }>;\n}\n\ninterface UsageWithOptionalCost {\n  prompt_tokens?: number;\n  completion_tokens?: number;\n  total_tokens?: number;\n  cost?: number | string;\n  total_cost?: number | string;\n  totalCost?: number | string;\n}\n\ninterface CompletionWithOptionalCost {\n  usage?: UsageWithOptionalCost;\n  cost?: number | string;\n  total_cost?: number | string;\n  totalCost?: number | string;\n}\n\nexport class OpenAIProvider implements LLMProvider {\n  name = 'openai';\n  private client: OpenAI;\n  private embeddingClient: OpenAI;\n  private visionClient: OpenAI;\n  private logger: Logger;\n\n  constructor(config?: LLMConfig) {\n    const apiKey = config?.apiKey || process.env.OPENAI_API_KEY;\n\n    // Use provided logger or fallback to global logger\n    this.logger = config?.logger || getLogger();\n\n    if (!apiKey) {\n      throw new Error('OpenAI API key is required. Set OPENAI_API_KEY environment variable.');\n    }\n\n    this.logger.info('OpenAI provider initialized');\n    this.logger.debug('OpenAI provider initialization', {\n      hasCustomBaseUrl: !!config?.baseUrl,\n      hasEmbeddingBaseUrl: !!process.env.OPENAI_EMBEDDING_BASE_URL,\n      hasVisionBaseUrl: !!process.env.OPENAI_VISION_BASE_URL,\n      supportsEmbeddings: true,\n      supportsVision: true,\n    });\n\n    // Default timeout: 2 minutes (120000ms)\n    const timeout = config?.timeout ?? 120000;\n\n    // Main client for chat completions (can use custom base URL like OpenRouter)\n    // If baseUrl is explicitly null, don't use OPENAI_BASE_URL fallback (for embedding/vision providers)\n    const chatBaseUrl =\n      config?.baseUrl === null ? undefined : config?.baseUrl || process.env.OPENAI_BASE_URL;\n    this.client = new OpenAI({\n      apiKey,\n      timeout,\n      ...(chatBaseUrl && { baseURL: chatBaseUrl }),\n    });\n\n    // Dedicated embedding client - NO fallback to OPENAI_BASE_URL\n    const embeddingApiKey = process.env.OPENAI_EMBEDDING_API_KEY || apiKey;\n    const embeddingBaseUrl = process.env.OPENAI_EMBEDDING_BASE_URL; // Only dedicated URL, no fallback\n\n    this.logger.debug('Creating embedding client', {\n      hasEmbeddingApiKey: !!embeddingApiKey,\n      usingDedicatedKey: !!process.env.OPENAI_EMBEDDING_API_KEY,\n      hasDedicatedBaseUrl: !!embeddingBaseUrl,\n      willUseDefaultEndpoint: !embeddingBaseUrl,\n    });\n\n    // Create embedding client with COMPLETELY isolated configuration\n    const embeddingClientConfig: { apiKey: string; baseURL?: string; timeout: number } = {\n      apiKey: embeddingApiKey,\n      timeout,\n    };\n\n    // Only add baseURL if we have a dedicated one, otherwise OpenAI client will use default\n    if (embeddingBaseUrl) {\n      embeddingClientConfig.baseURL = embeddingBaseUrl;\n    } else {\n      // Explicitly prevent OpenAI SDK from reading OPENAI_BASE_URL environment variable\n      embeddingClientConfig.baseURL = 'https://api.openai.com/v1';\n    }\n\n    this.embeddingClient = new OpenAI(embeddingClientConfig);\n\n    // Dedicated vision client - NO fallback to OPENAI_BASE_URL\n    const visionApiKey = process.env.OPENAI_VISION_API_KEY || apiKey;\n    const visionBaseUrl = process.env.OPENAI_VISION_BASE_URL; // Only dedicated URL, no fallback\n\n    // Create vision client with COMPLETELY isolated configuration\n    const visionClientConfig: { apiKey: string; baseURL?: string; timeout: number } = {\n      apiKey: visionApiKey,\n      timeout,\n    };\n\n    // Only add baseURL if we have a dedicated one, otherwise OpenAI client will use default\n    if (visionBaseUrl) {\n      visionClientConfig.baseURL = visionBaseUrl;\n    } else {\n      // Explicitly prevent OpenAI SDK from reading OPENAI_BASE_URL environment variable\n      visionClientConfig.baseURL = 'https://api.openai.com/v1';\n    }\n\n    this.visionClient = new OpenAI(visionClientConfig);\n  }\n\n  private safeJsonParse(jsonString: string): Record<string, string | number | boolean | null> {\n    try {\n      const parsed = JSON.parse(jsonString);\n      // Ensure all values are of allowed types\n      const sanitized: Record<string, string | number | boolean | null> = {};\n      for (const [key, value] of Object.entries(parsed)) {\n        if (\n          typeof value === 'string' ||\n          typeof value === 'number' ||\n          typeof value === 'boolean' ||\n          value === null\n        ) {\n          sanitized[key] = value;\n        } else {\n          sanitized[key] = String(value); // Convert complex types to string\n        }\n      }\n      return sanitized;\n    } catch {\n      this.logger.warn('Failed to parse tool call arguments', { jsonString });\n      return {}; // Return empty object as fallback\n    }\n  }\n\n  private readOptionalCost(source: unknown): number | undefined {\n    if (!source || typeof source !== 'object') {\n      return undefined;\n    }\n\n    const value = source as Record<string, unknown>;\n    const candidates = [value.cost, value.total_cost, value.totalCost];\n\n    for (const candidate of candidates) {\n      if (typeof candidate === 'number' && Number.isFinite(candidate)) {\n        return candidate;\n      }\n\n      if (typeof candidate === 'string') {\n        const parsed = Number(candidate);\n        if (Number.isFinite(parsed)) {\n          return parsed;\n        }\n      }\n    }\n\n    return undefined;\n  }\n\n  private resolveUsageCost(source: unknown): number | undefined {\n    if (!source || typeof source !== 'object') {\n      return undefined;\n    }\n\n    const completion = source as CompletionWithOptionalCost;\n    return this.readOptionalCost(completion.usage) ?? this.readOptionalCost(completion);\n  }\n\n  getSupportedModels(): string[] {\n    return [\n      'gpt-4.5',\n      'gpt-4.1',\n      'gpt-4.1-mini',\n      'gpt-4.1-nano',\n      'o4-mini',\n      'o4-mini-high',\n      'o3',\n      'gpt-4o',\n      'gpt-4o-mini',\n      'gpt-4-turbo',\n      'gpt-4',\n      'gpt-3.5-turbo',\n      'gpt-3.5-turbo-16k',\n      'gpt-3.5-turbo-instruct',\n    ];\n  }\n\n  getVisionModels(): string[] {\n    return [\n      'gpt-4o',\n      'gpt-4o-mini',\n      'gpt-4-turbo',\n      'gpt-4-vision-preview',\n      'gpt-4o-2024-08-06',\n      'gpt-4o-2024-05-13',\n    ];\n  }\n\n  getEmbeddingModels(): string[] {\n    return ['text-embedding-3-large', 'text-embedding-3-small', 'text-embedding-ada-002'];\n  }\n\n  async generateResponse(options: LLMRequestOptions): Promise<LLMResponse> {\n    const messages = this.prepareMessages(options);\n\n    try {\n      const completion = await withRetry(() =>\n        this.client.chat.completions.create({\n          model: options.model,\n          messages: messages as OpenAI.Chat.Completions.ChatCompletionMessageParam[],\n          temperature: options.temperature ?? 0.7,\n          max_tokens: options.maxTokens ?? 4096,\n          stream: false,\n          ...(options.tools &&\n            options.tools.length > 0 && {\n              tools: options.tools as OpenAI.Chat.Completions.ChatCompletionTool[],\n              tool_choice: 'auto',\n            }),\n        })\n      );\n\n      const message = completion.choices[0]?.message;\n\n      return {\n        content: message?.content || '',\n        model: completion.model,\n        toolCalls: message?.tool_calls?.map((tc) => ({\n          id: tc.id,\n          type: tc.type,\n          function: {\n            name: tc.function.name,\n            arguments:\n              typeof tc.function.arguments === 'string'\n                ? this.safeJsonParse(tc.function.arguments)\n                : tc.function.arguments,\n          },\n        })),\n        usage: {\n          promptTokens: completion.usage?.prompt_tokens ?? 0,\n          completionTokens: completion.usage?.completion_tokens ?? 0,\n          totalTokens: completion.usage?.total_tokens ?? 0,\n          cost: this.resolveUsageCost(completion),\n        },\n      };\n    } catch (error) {\n      const originalError = error instanceof Error ? error : new Error(String(error));\n      this.logger.error('OpenAI generateResponse failed', originalError, {\n        model: options.model,\n        errorMessage: originalError.message,\n      });\n      throw new LLMApiError(\n        `OpenAI API request failed: ${originalError.message}`,\n        this.name,\n        originalError\n      );\n    }\n  }\n\n  async *generateStreamResponse(options: LLMRequestOptions): AsyncIterableIterator<LLMStreamChunk> {\n    const messages = this.prepareMessages(options);\n\n    let stream:\n      | (Awaited<ReturnType<typeof this.client.chat.completions.create>> & {\n          controller?: AbortController;\n        })\n      | undefined;\n    try {\n      stream = await withRetry(() =>\n        this.client.chat.completions.create({\n          model: options.model,\n          messages: messages as OpenAI.Chat.Completions.ChatCompletionMessageParam[],\n          temperature: options.temperature ?? 0.7,\n          max_tokens: options.maxTokens ?? 4096,\n          stream: true,\n          stream_options: { include_usage: true }, // Enable usage tracking in streaming\n          ...(options.tools &&\n            options.tools.length > 0 && {\n              tools: options.tools as OpenAI.Chat.Completions.ChatCompletionTool[],\n              tool_choice: 'auto',\n            }),\n        })\n      );\n    } catch (error: unknown) {\n      // Log full error details including OpenAI API response\n      const errorObj = error as Record<string, unknown>;\n      this.logger.error('OpenAI API request failed', error instanceof Error ? error : undefined, {\n        model: options.model,\n        messageCount: messages.length,\n        errorMessage: String(errorObj?.message || 'Unknown error'),\n        errorType: String(errorObj?.constructor?.name || 'Unknown'),\n        status: String(errorObj?.status || errorObj?.statusCode || ''),\n        code: String(errorObj?.code || ''),\n        type: String(errorObj?.type || ''),\n        errorString: String(error),\n      });\n      this.logger.debug('OpenAI API error details', {\n        messageCount: messages.length,\n        roles: messages.map((m) => m.role).join(', '),\n      });\n      throw error;\n    }\n\n    const toolCalls: Array<{\n      id: string;\n      type: string;\n      function: { name: string; arguments: string };\n    }> = [];\n\n    let usage: LLMUsage | undefined;\n\n    // Helper function to abort stream safely\n    const abortStream = (): void => {\n      try {\n        // OpenAI SDK streams have a controller property for aborting\n        if (stream && 'controller' in stream && stream.controller instanceof AbortController) {\n          stream.controller.abort();\n        }\n      } catch {\n        // Ignore abort errors - stream may already be closed\n      }\n    };\n\n    try {\n      for await (const chunk of stream as AsyncIterable<OpenAI.Chat.Completions.ChatCompletionChunk>) {\n        const delta = chunk.choices?.[0]?.delta;\n        const content = delta?.content || '';\n\n        // Capture usage from final chunk (OpenAI includes this when stream_options.include_usage is true)\n        if (chunk.usage) {\n          usage = {\n            promptTokens: chunk.usage.prompt_tokens,\n            completionTokens: chunk.usage.completion_tokens,\n            totalTokens: chunk.usage.total_tokens,\n            cost: this.resolveUsageCost(chunk),\n          };\n        }\n\n        // Handle tool calls in streaming\n        if (delta?.tool_calls) {\n          for (const tc of delta.tool_calls) {\n            if (tc.index !== undefined) {\n              if (!toolCalls[tc.index]) {\n                toolCalls[tc.index] = {\n                  id: tc.id || '',\n                  type: tc.type || 'function',\n                  function: {\n                    name: tc.function?.name || '',\n                    arguments: tc.function?.arguments || '',\n                  },\n                };\n              } else {\n                if (tc.function?.arguments) {\n                  toolCalls[tc.index].function.arguments += tc.function.arguments;\n                }\n              }\n            }\n          }\n        }\n\n        if (content) {\n          yield { content, done: false, model: chunk.model };\n        }\n      }\n\n      // Final chunk with tool calls and usage\n      yield {\n        content: '',\n        done: true,\n        model: options.model,\n        toolCalls:\n          toolCalls.length > 0\n            ? toolCalls.map((tc) => ({\n                id: tc.id,\n                type: 'function' as const,\n                function: {\n                  name: tc.function.name,\n                  arguments:\n                    typeof tc.function.arguments === 'string'\n                      ? this.safeJsonParse(tc.function.arguments)\n                      : tc.function.arguments,\n                },\n              }))\n            : undefined,\n        usage,\n      };\n    } catch (error) {\n      // Abort the stream on error to prevent resource leak\n      abortStream();\n\n      // Log full error details for debugging\n      const originalError = error instanceof Error ? error : new Error(String(error));\n      this.logger.error(\n        'OpenAI streaming error details',\n        new Error(`${originalError.message} - ${JSON.stringify(error, null, 2)}`)\n      );\n\n      throw new LLMApiError(\n        `OpenAI streaming error: ${originalError.message}`,\n        this.name,\n        originalError\n      );\n    } finally {\n      // Ensure stream is aborted when generator is closed early (consumer breaks out of loop)\n      abortStream();\n    }\n  }\n\n  async generateEmbedding(text: string, model?: string): Promise<EmbeddingResult> {\n    const embeddingModel = model || this.getEmbeddingModels()[0]; // Use provided model or fallback to first available\n\n    this.logger.info(`Generating embedding with model: ${embeddingModel}`);\n    this.logger.debug('OpenAI embedding request', {\n      model: embeddingModel,\n      textLength: text.length,\n    });\n\n    try {\n      const response = await withRetry(() =>\n        this.embeddingClient.embeddings.create({\n          model: embeddingModel,\n          input: text,\n          encoding_format: 'float',\n        })\n      );\n\n      const embeddingData = response.data[0]?.embedding;\n      if (!embeddingData) {\n        throw new Error('No embedding data returned from OpenAI API');\n      }\n\n      const result: EmbeddingResult = {\n        embedding: embeddingData,\n        model: embeddingModel,\n        usage: {\n          promptTokens: response.usage?.prompt_tokens ?? 0,\n          totalTokens: response.usage?.total_tokens ?? 0,\n        },\n      };\n\n      this.logger.info('Embedding generated successfully');\n      this.logger.debug('OpenAI embedding result', {\n        model: embeddingModel,\n        dimensions: result.embedding.length,\n        promptTokens: result.usage?.promptTokens ?? 0,\n      });\n\n      return result;\n    } catch (error) {\n      const originalError = error instanceof Error ? error : new Error(String(error));\n      this.logger.error('Embedding generation failed');\n      this.logger.debug('OpenAI embedding error', {\n        model: embeddingModel,\n        error: originalError.message,\n        hasStack: !!originalError.stack,\n      });\n      throw new LLMApiError(\n        `OpenAI embedding generation failed: ${originalError.message}`,\n        this.name,\n        originalError\n      );\n    }\n  }\n\n  async analyzeImage(\n    imagePath: string,\n    options: VisionAnalysisOptions = {}\n  ): Promise<VisionAnalysisResult> {\n    const fileName = path.basename(imagePath);\n\n    this.logger.info(`Analyzing image: ${fileName}`);\n    this.logger.debug('OpenAI image analysis started', {\n      imagePath,\n      fileName,\n      hasPrompt: !!options.prompt,\n      detail: options.detail || 'auto',\n      maxTokens: options.maxTokens || 1000,\n    });\n\n    // Validate image file\n    try {\n      await fs.promises.access(imagePath);\n    } catch {\n      this.logger.error(`Image file not found: ${imagePath}`);\n      throw new Error(`Image file not found: ${imagePath}`);\n    }\n\n    const ext = path.extname(imagePath).toLowerCase();\n    const supportedFormats = ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp'];\n    if (!supportedFormats.includes(ext)) {\n      this.logger.error(`Unsupported image format: ${ext}`);\n      throw new Error(\n        `Unsupported image format: ${ext}. Supported: ${supportedFormats.join(', ')}`\n      );\n    }\n\n    // Read and encode image\n    const imageBuffer = await fs.promises.readFile(imagePath);\n    const base64Image = imageBuffer.toString('base64');\n    const mimeType = this.getMimeType(ext);\n    const dataUrl = `data:${mimeType};base64,${base64Image}`;\n\n    return this.analyzeImageFromBase64(dataUrl, options);\n  }\n\n  async analyzeImageFromBase64(\n    base64Data: string,\n    options: VisionAnalysisOptions = {}\n  ): Promise<VisionAnalysisResult> {\n    const startTime = Date.now();\n\n    this.logger.info('Analyzing base64 image');\n    this.logger.debug('OpenAI base64 image analysis started', {\n      base64Length: base64Data.length,\n      hasPrompt: !!options.prompt,\n      detail: options.detail || 'auto',\n      maxTokens: options.maxTokens || 1000,\n    });\n\n    try {\n      const model = options.model || this.getVisionModels()[0]; // Use agent's model or fallback to first available\n      const prompt = options.prompt || 'Analyze this image and describe what you see in detail.';\n\n      const response = await withRetry(() =>\n        this.visionClient.chat.completions.create({\n          model,\n          messages: [\n            {\n              role: 'user',\n              content: [\n                { type: 'text', text: prompt },\n                {\n                  type: 'image_url',\n                  image_url: {\n                    url: base64Data,\n                    detail: options.detail || 'auto',\n                  },\n                },\n              ],\n            },\n          ],\n          max_tokens: options.maxTokens ?? 1000,\n          temperature: options.temperature ?? 0.1,\n        })\n      );\n\n      const processingTime = Date.now() - startTime;\n      const content = response.choices[0]?.message?.content || 'No analysis available';\n\n      const result: VisionAnalysisResult = {\n        content,\n        confidence: 1.0,\n        metadata: {\n          model,\n          provider: this.name,\n          processingTime,\n          tokenUsage: response.usage\n            ? {\n                promptTokens: response.usage.prompt_tokens,\n                completionTokens: response.usage.completion_tokens,\n                totalTokens: response.usage.total_tokens,\n              }\n            : undefined,\n        },\n      };\n\n      this.logger.info('Image analysis completed');\n      this.logger.debug('OpenAI image analysis result', {\n        model,\n        processingTime,\n        contentLength: content.length,\n        promptTokens: response.usage?.prompt_tokens ?? 0,\n        completionTokens: response.usage?.completion_tokens ?? 0,\n        totalTokens: response.usage?.total_tokens ?? 0,\n      });\n\n      return result;\n    } catch (error) {\n      const processingTime = Date.now() - startTime;\n      const originalError = error instanceof Error ? error : new Error(String(error));\n\n      this.logger.error('Image analysis failed');\n      this.logger.debug('OpenAI image analysis error', {\n        processingTime,\n        error: originalError.message,\n        hasStack: !!originalError.stack,\n      });\n\n      throw new VisionError(\n        `OpenAI vision analysis failed: ${originalError.message}`,\n        this.name,\n        originalError\n      );\n    }\n  }\n\n  private getMimeType(extension: string): string {\n    const mimeTypes: Record<string, string> = {\n      '.jpg': 'image/jpeg',\n      '.jpeg': 'image/jpeg',\n      '.png': 'image/png',\n      '.gif': 'image/gif',\n      '.bmp': 'image/bmp',\n      '.webp': 'image/webp',\n    };\n\n    return mimeTypes[extension.toLowerCase()] || 'image/jpeg';\n  }\n\n  private prepareMessages(options: LLMRequestOptions): OpenAIMessage[] {\n    const messages = [...options.messages];\n\n    // Add system prompt if provided and no system message exists\n    if (options.systemPrompt && !messages.some((m) => m.role === 'system')) {\n      messages.unshift({ role: 'system', content: options.systemPrompt });\n    }\n\n    // Ensure tool_calls arguments are serialized as strings for OpenAI API\n    const processedMessages: OpenAIMessage[] = messages.map((message): OpenAIMessage => {\n      if (message.role === 'assistant' && message.tool_calls) {\n        return {\n          ...message,\n          tool_calls: message.tool_calls.map((tc) => ({\n            ...tc,\n            function: {\n              ...tc.function,\n              arguments:\n                typeof tc.function.arguments === 'string'\n                  ? tc.function.arguments\n                  : JSON.stringify(tc.function.arguments),\n            },\n          })),\n        };\n      }\n      return message as OpenAIMessage;\n    });\n\n    return processedMessages;\n  }\n\n  getEmbeddingProvider(): LLMProvider {\n    return {\n      name: 'openai-embedding',\n      generateResponse: this.generateResponse.bind(this),\n      generateStreamResponse: this.generateStreamResponse.bind(this),\n      getSupportedModels: () => [],\n      getVisionModels: () => [],\n      getEmbeddingModels: this.getEmbeddingModels.bind(this),\n      generateEmbedding: async (text: string, model?: string) => {\n        // Use the dedicated embedding client that was created with correct API key and base URL\n        const embeddingModel = model || this.getEmbeddingModels()[0]; // Use provided model or fallback to first available\n\n        this.logger.debug('Using dedicated embedding client', {\n          model: embeddingModel,\n          clientHasBaseURL: 'baseURL' in this.embeddingClient,\n          clientBaseURL: (this.embeddingClient as { baseURL?: string }).baseURL || 'none',\n          clientApiKey: '[REDACTED]',\n        });\n\n        const response = await this.embeddingClient.embeddings.create({\n          model: embeddingModel,\n          input: text,\n          encoding_format: 'float',\n        });\n\n        const embeddingData = response.data[0]?.embedding;\n        if (!embeddingData) {\n          throw new Error('No embedding data returned from OpenAI API');\n        }\n\n        return {\n          embedding: embeddingData,\n          model: embeddingModel,\n          usage: {\n            promptTokens: response.usage?.prompt_tokens ?? 0,\n            totalTokens: response.usage?.total_tokens ?? 0,\n          },\n        };\n      },\n    };\n  }\n\n  getVisionProvider(): LLMProvider {\n    return {\n      name: 'openai-vision',\n      generateResponse: this.generateResponse.bind(this),\n      generateStreamResponse: this.generateStreamResponse.bind(this),\n      getSupportedModels: () => [],\n      getVisionModels: this.getVisionModels.bind(this),\n      getEmbeddingModels: () => [],\n      analyzeImage: async (imagePath: string, options?: VisionAnalysisOptions) => {\n        const imageBuffer = await fs.promises.readFile(imagePath);\n        const base64Image = imageBuffer.toString('base64');\n        const ext = path.extname(imagePath).toLowerCase();\n        const mimeType = this.getMimeType(ext);\n        const dataUrl = `data:${mimeType};base64,${base64Image}`;\n\n        return this.analyzeImageFromBase64WithClient(dataUrl, options, this.visionClient);\n      },\n      analyzeImageFromBase64: async (base64Data: string, options?: VisionAnalysisOptions) => {\n        return this.analyzeImageFromBase64WithClient(base64Data, options, this.visionClient);\n      },\n    };\n  }\n\n  private async analyzeImageFromBase64WithClient(\n    base64Data: string,\n    options: VisionAnalysisOptions = {},\n    client: OpenAI\n  ): Promise<VisionAnalysisResult> {\n    const startTime = Date.now();\n\n    this.logger.debug('Using dedicated vision client', {\n      base64Length: base64Data.length,\n      hasPrompt: !!options.prompt,\n      clientHasBaseURL: 'baseURL' in client,\n    });\n\n    try {\n      const model = options.model || this.getVisionModels()[0]; // Use agent's model or fallback to first available\n      const prompt = options.prompt || 'Analyze this image and describe what you see in detail.';\n\n      const response = await withRetry(() =>\n        client.chat.completions.create({\n          model,\n          messages: [\n            {\n              role: 'user',\n              content: [\n                { type: 'text', text: prompt },\n                {\n                  type: 'image_url',\n                  image_url: {\n                    url: base64Data,\n                    detail: options.detail || 'auto',\n                  },\n                },\n              ],\n            },\n          ],\n          max_tokens: options.maxTokens ?? 1000,\n          temperature: options.temperature ?? 0.1,\n        })\n      );\n\n      const processingTime = Date.now() - startTime;\n      const content = response.choices[0]?.message?.content || 'No analysis available';\n\n      return {\n        content,\n        confidence: 1.0,\n        metadata: {\n          model,\n          provider: this.name,\n          processingTime,\n          tokenUsage: response.usage\n            ? {\n                promptTokens: response.usage.prompt_tokens,\n                completionTokens: response.usage.completion_tokens,\n                totalTokens: response.usage.total_tokens,\n              }\n            : undefined,\n        },\n      };\n    } catch (error) {\n      const processingTime = Date.now() - startTime;\n      const originalError = error instanceof Error ? error : new Error(String(error));\n\n      this.logger.error('OpenAI image analysis failed');\n      this.logger.debug('OpenAI image analysis error', {\n        processingTime,\n        error: originalError.message,\n        hasStack: !!originalError.stack,\n      });\n\n      throw new VisionError(\n        `OpenAI vision analysis failed: ${originalError.message}`,\n        this.name,\n        originalError\n      );\n    }\n  }\n}\n","export interface LLMMessageContentPart {\n  type: 'text' | 'image_url';\n  text?: string;\n  image_url?: {\n    url: string;\n    detail?: 'low' | 'high' | 'auto';\n  };\n}\n\nexport type LLMMessageContent = string | LLMMessageContentPart[];\n\nexport interface LLMMessage {\n  role: 'system' | 'user' | 'assistant' | 'tool';\n  content: LLMMessageContent;\n  tool_call_id?: string;\n  tool_calls?: ToolCall[];\n}\n\nexport interface ToolCall {\n  id: string;\n  type: 'function';\n  function: {\n    name: string;\n    arguments: Record<string, string | number | boolean | null>;\n  };\n}\n\nexport interface Tool {\n  type: 'function';\n  function: {\n    name: string;\n    description: string;\n    parameters: {\n      type: 'object';\n      properties: Record<\n        string,\n        {\n          type: 'string' | 'number' | 'boolean' | 'object' | 'array';\n          description?: string;\n          enum?: Array<string | number>;\n          items?: { type: string };\n          properties?: Record<\n            string,\n            {\n              type: 'string' | 'number' | 'boolean' | 'object' | 'array';\n              description?: string;\n            }\n          >;\n        }\n      >;\n      required?: string[];\n    };\n  };\n}\n\nexport interface LLMRequestOptions {\n  model: string;\n  messages: LLMMessage[];\n  temperature?: number;\n  maxTokens?: number;\n  stream?: boolean;\n  systemPrompt?: string;\n  tools?: Tool[];\n}\n\nexport interface LLMUsage {\n  promptTokens: number;\n  completionTokens: number;\n  totalTokens: number;\n  cost?: number;\n}\n\nexport interface LLMResponse {\n  content: string;\n  model: string;\n  toolCalls?: ToolCall[];\n  usage?: LLMUsage;\n}\n\nexport interface LLMStreamChunk {\n  content: string;\n  done: boolean;\n  model: string;\n  toolCalls?: ToolCall[];\n  usage?: LLMUsage;\n}\n\nexport interface VisionAnalysisOptions {\n  prompt?: string;\n  maxTokens?: number;\n  temperature?: number;\n  detail?: 'low' | 'high' | 'auto';\n  model?: string; // Model to use for vision analysis (from agent config)\n}\n\nexport interface VisionAnalysisResult {\n  content: string;\n  confidence?: number;\n  metadata?: {\n    model?: string;\n    provider?: string;\n    processingTime?: number;\n    tokenUsage?: {\n      promptTokens: number;\n      completionTokens: number;\n      totalTokens: number;\n    };\n  };\n}\n\nexport interface EmbeddingResult {\n  embedding: number[];\n  model: string;\n  usage?: {\n    promptTokens: number;\n    totalTokens: number;\n  };\n}\n\nexport interface LLMProvider {\n  name: string;\n  generateResponse(options: LLMRequestOptions): Promise<LLMResponse>;\n  generateStreamResponse(options: LLMRequestOptions): AsyncIterableIterator<LLMStreamChunk>;\n  getSupportedModels(): string[];\n  getVisionModels(): string[];\n  getEmbeddingModels(): string[];\n  generateEmbedding?(text: string, model?: string): Promise<EmbeddingResult>;\n  analyzeImage?(imagePath: string, options?: VisionAnalysisOptions): Promise<VisionAnalysisResult>;\n  analyzeImageFromBase64?(\n    base64Data: string,\n    options?: VisionAnalysisOptions\n  ): Promise<VisionAnalysisResult>;\n  getEmbeddingProvider?(): LLMProvider;\n  getVisionProvider?(): LLMProvider;\n}\n\nexport interface LLMConfig {\n  apiKey?: string;\n  baseUrl?: string | null;\n  defaultModel?: string;\n  timeout?: number;\n  logger?: import('../logger/types').Logger;\n}\n\n/**\n * Rate limiter configuration options\n */\nexport interface RateLimiterOptions {\n  /** Maximum concurrent requests allowed (default: 5) */\n  maxConcurrent?: number;\n  /** Maximum requests per minute (default: 60) */\n  maxRequestsPerMinute?: number;\n  /** Timeout in ms to wait for acquiring a slot (default: 30000) */\n  acquireTimeout?: number;\n  /** Maximum time in ms a low-priority request can wait before being promoted (default: 10000) */\n  maxStarvationTimeMs?: number;\n}\n\n// Type guard functions\nexport function isStringContent(content: LLMMessageContent): content is string {\n  return typeof content === 'string';\n}\n\nexport function isMultiModalContent(\n  content: LLMMessageContent\n): content is LLMMessageContentPart[] {\n  return Array.isArray(content);\n}\n\nexport function isTextContentPart(\n  part: LLMMessageContentPart\n): part is LLMMessageContentPart & { type: 'text'; text: string } {\n  return part.type === 'text' && typeof part.text === 'string';\n}\n\nexport function isImageContentPart(part: LLMMessageContentPart): part is LLMMessageContentPart & {\n  type: 'image_url';\n  image_url: { url: string; detail?: 'low' | 'high' | 'auto' };\n} {\n  return part.type === 'image_url' && !!part.image_url?.url;\n}\n","import {\n  LLMProvider,\n  LLMRequestOptions,\n  LLMResponse,\n  LLMStreamChunk,\n  LLMConfig,\n  VisionAnalysisOptions,\n  VisionAnalysisResult,\n  EmbeddingResult,\n  isStringContent,\n  isMultiModalContent,\n} from '../types';\nimport Anthropic from '@anthropic-ai/sdk';\nimport type { ContentBlockDeltaEvent, TextDelta } from '@anthropic-ai/sdk/resources/messages';\nimport type {\n  ToolUseBlock,\n  ToolsBetaContentBlock,\n  ToolsBetaMessageParam,\n} from '@anthropic-ai/sdk/resources/beta/tools/messages';\nimport { getLogger } from '../../logger';\nimport { Logger } from '../../logger/types';\nimport { LLMApiError, VisionError } from '../../errors';\nimport * as fs from 'fs';\nimport * as path from 'path';\n\n// Retry helper with exponential backoff\nasync function withRetry<T>(fn: () => Promise<T>, maxRetries = 3): Promise<T> {\n  let lastError: Error | undefined;\n  for (let i = 0; i < maxRetries; i++) {\n    try {\n      return await fn();\n    } catch (error) {\n      lastError = error as Error;\n      if (i < maxRetries - 1) {\n        await new Promise((r) => setTimeout(r, Math.pow(2, i) * 1000));\n      }\n    }\n  }\n  if (!lastError) {\n    throw new Error('No retry attempts made');\n  }\n  throw lastError;\n}\n\nexport class ClaudeProvider implements LLMProvider {\n  name = 'claude';\n  private client: Anthropic;\n  private visionClient: Anthropic;\n  private logger: Logger;\n\n  constructor(config?: LLMConfig) {\n    const apiKey = config?.apiKey || process.env.ANTHROPIC_API_KEY;\n\n    // Use provided logger or fallback to global logger\n    this.logger = config?.logger || getLogger();\n\n    if (!apiKey) {\n      throw new Error('Anthropic API key is required. Set ANTHROPIC_API_KEY environment variable.');\n    }\n\n    this.logger.info('Claude provider initialized');\n    this.logger.debug('Claude provider initialization', {\n      hasCustomBaseUrl: !!config?.baseUrl,\n      hasVisionBaseUrl: !!process.env.ANTHROPIC_VISION_BASE_URL,\n      supportsEmbeddings: false,\n      supportsVision: true,\n    });\n\n    // Default timeout: 2 minutes (120000ms)\n    const timeout = config?.timeout ?? 120000;\n\n    // Main client for chat completions (can use custom base URL)\n    // If baseUrl is explicitly null, don't use ANTHROPIC_BASE_URL fallback (for embedding/vision providers)\n    const chatBaseUrl =\n      config?.baseUrl === null ? undefined : config?.baseUrl || process.env.ANTHROPIC_BASE_URL;\n    this.client = new Anthropic({\n      apiKey,\n      timeout,\n      ...(chatBaseUrl && { baseURL: chatBaseUrl }),\n    });\n\n    // Dedicated vision client - NO fallback to ANTHROPIC_BASE_URL\n    const visionApiKey = process.env.ANTHROPIC_VISION_API_KEY || apiKey;\n    const visionBaseUrl = process.env.ANTHROPIC_VISION_BASE_URL; // Only dedicated URL, no fallback\n\n    // Create vision client with isolated configuration\n    const visionClientConfig: { apiKey: string; baseURL?: string; timeout: number } = {\n      apiKey: visionApiKey,\n      timeout,\n    };\n\n    // Only add baseURL if we have a dedicated one, otherwise use Anthropic default\n    if (visionBaseUrl) {\n      visionClientConfig.baseURL = visionBaseUrl;\n    }\n    // Note: Anthropic SDK doesn't auto-read env vars like OpenAI, so no explicit default needed\n\n    this.visionClient = new Anthropic(visionClientConfig);\n  }\n\n  private sanitizeArguments(input: object): Record<string, string | number | boolean | null> {\n    const sanitized: Record<string, string | number | boolean | null> = {};\n    for (const [key, value] of Object.entries(input)) {\n      if (\n        typeof value === 'string' ||\n        typeof value === 'number' ||\n        typeof value === 'boolean' ||\n        value === null\n      ) {\n        sanitized[key] = value;\n      } else {\n        sanitized[key] = String(value); // Convert complex types to string\n      }\n    }\n    return sanitized;\n  }\n\n  getSupportedModels(): string[] {\n    return [\n      'claude-sonnet-4-20250514',\n      'claude-opus-4-20250514',\n      'claude-3.7-sonnet-20250224',\n      'claude-3-5-sonnet-20241022',\n      'claude-3-5-sonnet-20240620',\n      'claude-3-5-haiku-20241022',\n      'claude-3-opus-20240229',\n      'claude-3-sonnet-20240229',\n      'claude-3-haiku-20240307',\n    ];\n  }\n\n  getVisionModels(): string[] {\n    return [\n      'claude-3-5-sonnet-20241022',\n      'claude-3-5-sonnet-20240620',\n      'claude-3-opus-20240229',\n      'claude-3-sonnet-20240229',\n      'claude-3-haiku-20240307',\n    ];\n  }\n\n  getEmbeddingModels(): string[] {\n    // Claude doesn't currently offer embedding models, but structure is ready for future support\n    return [];\n  }\n\n  // eslint-disable-next-line @typescript-eslint/no-unused-vars\n  async generateEmbedding(_text: string, _model?: string): Promise<EmbeddingResult> {\n    // Claude doesn't currently support embeddings, but this method is ready for future implementation\n    throw new Error(\n      'Claude provider does not currently support embedding generation. Please use OpenAI, Gemini, or Ollama providers for embeddings.'\n    );\n  }\n\n  async generateResponse(options: LLMRequestOptions): Promise<LLMResponse> {\n    const { system, messages } = this.prepareMessages(options);\n\n    try {\n      const message = await withRetry(() =>\n        this.client.beta.tools.messages.create({\n          model: options.model,\n          messages: messages as ToolsBetaMessageParam[],\n          system,\n          temperature: options.temperature ?? 0.7,\n          max_tokens: options.maxTokens ?? 4096,\n          stream: false,\n          ...(options.tools &&\n            options.tools.length > 0 && {\n              tools: options.tools.map((tool) => ({\n                name: tool.function.name,\n                description: tool.function.description,\n                input_schema: tool.function.parameters,\n              })),\n            }),\n        })\n      );\n\n      // Extract tool calls from Claude's response\n      const toolCalls = (message.content as ToolsBetaContentBlock[])\n        .filter((block): block is ToolUseBlock => block.type === 'tool_use')\n        .map((block) => ({\n          id: block.id,\n          type: 'function' as const,\n          function: {\n            name: block.name,\n            arguments: this.sanitizeArguments(block.input || {}),\n          },\n        }));\n\n      const textContent = (message.content as ToolsBetaContentBlock[])\n        .filter((block): block is Anthropic.Messages.TextBlock => block.type === 'text')\n        .map((block) => block.text)\n        .join('');\n\n      return {\n        content: textContent,\n        model: message.model,\n        toolCalls: toolCalls.length > 0 ? toolCalls : undefined,\n        usage: {\n          promptTokens: message.usage?.input_tokens ?? 0,\n          completionTokens: message.usage?.output_tokens ?? 0,\n          totalTokens: (message.usage?.input_tokens ?? 0) + (message.usage?.output_tokens ?? 0),\n        },\n      };\n    } catch (error) {\n      const originalError = error instanceof Error ? error : new Error(String(error));\n      this.logger.error('Claude generateResponse failed', originalError, {\n        model: options.model,\n        errorMessage: originalError.message,\n      });\n      throw new LLMApiError(\n        `Claude API request failed: ${originalError.message}`,\n        this.name,\n        originalError\n      );\n    }\n  }\n\n  async *generateStreamResponse(options: LLMRequestOptions): AsyncIterableIterator<LLMStreamChunk> {\n    const { system, messages } = this.prepareMessages(options);\n\n    let stream;\n    try {\n      stream = await withRetry(() =>\n        this.client.beta.tools.messages.create({\n          model: options.model,\n          messages: messages as ToolsBetaMessageParam[],\n          system,\n          temperature: options.temperature ?? 0.7,\n          max_tokens: options.maxTokens ?? 4096,\n          stream: true,\n          ...(options.tools &&\n            options.tools.length > 0 && {\n              tools: options.tools.map((tool) => ({\n                name: tool.function.name,\n                description: tool.function.description,\n                input_schema: tool.function.parameters,\n              })),\n            }),\n        })\n      );\n    } catch (error) {\n      const originalError = error instanceof Error ? error : new Error(String(error));\n      this.logger.error('Claude stream initialization failed', originalError, {\n        model: options.model,\n        errorMessage: originalError.message,\n      });\n      throw new LLMApiError(\n        `Claude API stream request failed: ${originalError.message}`,\n        this.name,\n        originalError\n      );\n    }\n\n    const toolCalls: Array<{\n      id: string;\n      type: 'function';\n      function: { name: string; arguments: Record<string, string | number | boolean | null> };\n    }> = [];\n\n    try {\n      for await (const event of stream) {\n        if (event.type === 'content_block_delta') {\n          const deltaEvent = event as ContentBlockDeltaEvent;\n          if (deltaEvent.delta.type === 'text_delta') {\n            const textDelta = deltaEvent.delta as TextDelta;\n            const content = textDelta.text || '';\n            if (content) {\n              yield { content, done: false, model: options.model };\n            }\n          }\n        } else if (event.type === 'content_block_start') {\n          // Standard streaming doesn't support tool_use in content_block_start\n          // Tool calls will be handled differently or in the final response\n        } else if (event.type === 'message_stop') {\n          yield {\n            content: '',\n            done: true,\n            model: options.model,\n            toolCalls: toolCalls.length > 0 ? toolCalls : undefined,\n          };\n          return;\n        }\n      }\n    } catch (error) {\n      const originalError = error instanceof Error ? error : new Error(String(error));\n      this.logger.error('Claude streaming error', originalError, {\n        model: options.model,\n        errorMessage: originalError.message,\n      });\n      throw new LLMApiError(\n        `Claude streaming error: ${originalError.message}`,\n        this.name,\n        originalError\n      );\n    }\n  }\n\n  private prepareMessages(options: LLMRequestOptions): {\n    system?: string;\n    messages: ToolsBetaMessageParam[];\n  } {\n    let system = options.systemPrompt;\n    const messages = options.messages.filter((m) => m.role !== 'system');\n\n    // Find system message if no explicit system prompt\n    if (!system) {\n      const systemMessage = options.messages.find((m) => m.role === 'system');\n      if (systemMessage) {\n        system = isStringContent(systemMessage.content) ? systemMessage.content : '';\n      }\n    }\n\n    // Convert messages to Claude format\n    return {\n      system,\n      messages: messages.map((msg) => {\n        if (msg.role === 'tool') {\n          const toolCallId = msg.tool_call_id;\n          // Safely extract content with null checks\n          const contentText =\n            msg.content != null && isStringContent(msg.content) ? msg.content : '';\n\n          if (!toolCallId) {\n            this.logger.warn('Tool message missing tool_call_id, converting to user message', {\n              content: contentText.substring(0, 100),\n            });\n            // Return as user message when tool_call_id is missing\n            return {\n              role: 'user' as const,\n              content: contentText || 'Tool result (missing tool_call_id)',\n            } as ToolsBetaMessageParam;\n          }\n          return {\n            role: 'user' as const,\n            content: [\n              {\n                type: 'tool_result' as const,\n                tool_use_id: toolCallId,\n                content: [{ type: 'text' as const, text: contentText }],\n              },\n            ],\n          } as ToolsBetaMessageParam;\n        }\n\n        if (msg.tool_calls && msg.tool_calls.length > 0) {\n          // Filter out tool calls with null/undefined function properties\n          const validToolCalls = msg.tool_calls.filter(\n            (tc) => tc != null && tc.function != null && tc.function.name != null\n          );\n\n          if (validToolCalls.length === 0) {\n            // No valid tool calls, return as regular assistant message\n            return {\n              role: 'assistant' as const,\n              content: msg.content != null && isStringContent(msg.content) ? msg.content : '',\n            } as ToolsBetaMessageParam;\n          }\n\n          return {\n            role: 'assistant' as const,\n            content: [\n              ...(msg.content != null && isStringContent(msg.content) && msg.content.length > 0\n                ? [{ type: 'text' as const, text: msg.content }]\n                : []),\n              ...validToolCalls.map((tc) => ({\n                type: 'tool_use' as const,\n                id: tc.id || `tool_${Date.now()}`,\n                name: tc.function.name,\n                input: tc.function.arguments ?? {},\n              })),\n            ],\n          } as ToolsBetaMessageParam;\n        }\n\n        // Handle multi-modal content\n        if (isMultiModalContent(msg.content)) {\n          const claudeContent = msg.content\n            .map((part) => {\n              if (part.type === 'text') {\n                return { type: 'text' as const, text: part.text || '' };\n              } else if (part.type === 'image_url' && part.image_url) {\n                // Extract base64 data from data URL\n                const base64Match = part.image_url.url.match(/^data:(.+);base64,(.+)$/);\n                if (base64Match) {\n                  const mediaType = base64Match[1];\n                  const data = base64Match[2];\n                  return {\n                    type: 'image' as const,\n                    source: {\n                      type: 'base64' as const,\n                      media_type: mediaType as\n                        | 'image/jpeg'\n                        | 'image/png'\n                        | 'image/gif'\n                        | 'image/webp',\n                      data,\n                    },\n                  };\n                }\n              }\n              return { type: 'text' as const, text: '' };\n            })\n            .filter((part) => (part.type === 'text' ? part.text !== '' : true));\n\n          return {\n            role: msg.role as 'user' | 'assistant',\n            content: claudeContent,\n          } as ToolsBetaMessageParam;\n        }\n\n        // Handle string content\n        return {\n          role: msg.role as 'user' | 'assistant',\n          content: isStringContent(msg.content) ? msg.content : '',\n        } as Anthropic.Messages.MessageParam;\n      }),\n    };\n  }\n\n  async analyzeImage(\n    imagePath: string,\n    options: VisionAnalysisOptions = {}\n  ): Promise<VisionAnalysisResult> {\n    const fileName = path.basename(imagePath);\n\n    this.logger.info(`Analyzing image: ${fileName}`);\n    this.logger.debug('Claude image analysis started', {\n      imagePath,\n      fileName,\n      hasPrompt: !!options.prompt,\n      maxTokens: options.maxTokens || 1000,\n    });\n\n    // Validate image file\n    try {\n      await fs.promises.access(imagePath);\n    } catch {\n      this.logger.error(`Image file not found: ${imagePath}`);\n      throw new Error(`Image file not found: ${imagePath}`);\n    }\n\n    const ext = path.extname(imagePath).toLowerCase();\n    const supportedFormats = ['.jpg', '.jpeg', '.png', '.gif', '.webp'];\n    if (!supportedFormats.includes(ext)) {\n      this.logger.error(`Unsupported image format: ${ext}`);\n      throw new Error(\n        `Unsupported image format: ${ext}. Supported: ${supportedFormats.join(', ')}`\n      );\n    }\n\n    // Read and encode image\n    const imageBuffer = await fs.promises.readFile(imagePath);\n    const base64Image = imageBuffer.toString('base64');\n    const mimeType = this.getMimeType(ext);\n\n    return this.analyzeImageFromBase64(base64Image, { ...options, mimeType });\n  }\n\n  async analyzeImageFromBase64(\n    base64Data: string,\n    options: VisionAnalysisOptions & { mimeType?: string } = {}\n  ): Promise<VisionAnalysisResult> {\n    const startTime = Date.now();\n\n    this.logger.info('Analyzing base64 image');\n    this.logger.debug('Claude base64 image analysis started', {\n      base64Length: base64Data.length,\n      hasPrompt: !!options.prompt,\n      maxTokens: options.maxTokens || 1000,\n      mimeType: options.mimeType || 'image/jpeg',\n    });\n\n    try {\n      const model = options.model || this.getVisionModels()[0]; // Use agent's model or fallback to first available\n      const prompt = options.prompt || 'Analyze this image and describe what you see in detail.';\n      const mimeType = options.mimeType || 'image/jpeg';\n\n      // Remove data URL prefix if present\n      const cleanBase64 = base64Data.replace(/^data:image\\/[a-zA-Z]+;base64,/, '');\n\n      const response = await withRetry(() =>\n        this.visionClient.messages.create({\n          model,\n          max_tokens: options.maxTokens ?? 1000,\n          temperature: options.temperature ?? 0.1,\n          messages: [\n            {\n              role: 'user',\n              content: [\n                {\n                  type: 'image',\n                  source: {\n                    type: 'base64',\n                    media_type: mimeType as 'image/jpeg' | 'image/png' | 'image/gif' | 'image/webp',\n                    data: cleanBase64,\n                  },\n                },\n                {\n                  type: 'text',\n                  text: prompt,\n                },\n              ],\n            },\n          ],\n        })\n      );\n\n      const processingTime = Date.now() - startTime;\n      const content =\n        response.content[0]?.type === 'text' ? response.content[0].text : 'No analysis available';\n\n      const result: VisionAnalysisResult = {\n        content,\n        confidence: 1.0,\n        metadata: {\n          model,\n          provider: this.name,\n          processingTime,\n          tokenUsage: response.usage\n            ? {\n                promptTokens: response.usage.input_tokens,\n                completionTokens: response.usage.output_tokens,\n                totalTokens: response.usage.input_tokens + response.usage.output_tokens,\n              }\n            : undefined,\n        },\n      };\n\n      this.logger.info('Image analysis completed');\n      this.logger.debug('Claude image analysis result', {\n        model,\n        processingTime,\n        contentLength: content.length,\n        inputTokens: response.usage?.input_tokens ?? 0,\n        outputTokens: response.usage?.output_tokens ?? 0,\n      });\n\n      return result;\n    } catch (error) {\n      const processingTime = Date.now() - startTime;\n      const originalError = error instanceof Error ? error : new Error(String(error));\n\n      this.logger.error('Image analysis failed');\n      this.logger.debug('Claude image analysis error', {\n        processingTime,\n        error: originalError.message,\n        hasStack: !!originalError.stack,\n      });\n\n      throw new VisionError(\n        `Claude vision analysis failed: ${originalError.message}`,\n        this.name,\n        originalError\n      );\n    }\n  }\n\n  private getMimeType(extension: string): string {\n    const mimeTypes: Record<string, string> = {\n      '.jpg': 'image/jpeg',\n      '.jpeg': 'image/jpeg',\n      '.png': 'image/png',\n      '.gif': 'image/gif',\n      '.webp': 'image/webp',\n    };\n\n    return mimeTypes[extension.toLowerCase()] || 'image/jpeg';\n  }\n\n  getEmbeddingProvider(): LLMProvider {\n    return {\n      name: 'claude-embedding',\n      generateResponse: this.generateResponse.bind(this),\n      generateStreamResponse: this.generateStreamResponse.bind(this),\n      getSupportedModels: () => [],\n      getVisionModels: () => [],\n      getEmbeddingModels: this.getEmbeddingModels.bind(this),\n      generateEmbedding: this.generateEmbedding.bind(this),\n    };\n  }\n\n  getVisionProvider(): LLMProvider {\n    return {\n      name: 'claude-vision',\n      generateResponse: this.generateResponse.bind(this),\n      generateStreamResponse: this.generateStreamResponse.bind(this),\n      getSupportedModels: () => [],\n      getVisionModels: this.getVisionModels.bind(this),\n      getEmbeddingModels: () => [],\n      analyzeImage: async (imagePath: string, options?: VisionAnalysisOptions) => {\n        const imageBuffer = await fs.promises.readFile(imagePath);\n        const base64Image = imageBuffer.toString('base64');\n        const ext = path.extname(imagePath).toLowerCase();\n        const mimeType = this.getMimeType(ext);\n\n        return this.analyzeImageFromBase64WithClient(\n          base64Image,\n          { ...options, mimeType },\n          this.visionClient\n        );\n      },\n      analyzeImageFromBase64: async (base64Data: string, options?: VisionAnalysisOptions) => {\n        return this.analyzeImageFromBase64WithClient(base64Data, options, this.visionClient);\n      },\n    };\n  }\n\n  private async analyzeImageFromBase64WithClient(\n    base64Data: string,\n    options: VisionAnalysisOptions & { mimeType?: string } = {},\n    client: Anthropic\n  ): Promise<VisionAnalysisResult> {\n    const startTime = Date.now();\n\n    this.logger.debug('Using dedicated vision client', {\n      base64Length: base64Data.length,\n      hasPrompt: !!options.prompt,\n      mimeType: options.mimeType || 'image/jpeg',\n      clientHasBaseURL: 'baseURL' in client,\n    });\n\n    try {\n      const model = options.model || this.getVisionModels()[0]; // Use agent's model or fallback to first available\n      const prompt = options.prompt || 'Analyze this image and describe what you see in detail.';\n      const mimeType = options.mimeType || 'image/jpeg';\n\n      // Remove data URL prefix if present\n      const cleanBase64 = base64Data.replace(/^data:image\\/[a-zA-Z]+;base64,/, '');\n\n      const response = await withRetry(() =>\n        client.messages.create({\n          model,\n          max_tokens: options.maxTokens ?? 1000,\n          temperature: options.temperature ?? 0.1,\n          messages: [\n            {\n              role: 'user',\n              content: [\n                {\n                  type: 'image',\n                  source: {\n                    type: 'base64',\n                    media_type: mimeType as 'image/jpeg' | 'image/png' | 'image/gif' | 'image/webp',\n                    data: cleanBase64,\n                  },\n                },\n                {\n                  type: 'text',\n                  text: prompt,\n                },\n              ],\n            },\n          ],\n        })\n      );\n\n      const processingTime = Date.now() - startTime;\n      const content =\n        response.content[0]?.type === 'text' ? response.content[0].text : 'No analysis available';\n\n      return {\n        content,\n        confidence: 1.0,\n        metadata: {\n          model,\n          provider: this.name,\n          processingTime,\n          tokenUsage: response.usage\n            ? {\n                promptTokens: response.usage.input_tokens,\n                completionTokens: response.usage.output_tokens,\n                totalTokens: response.usage.input_tokens + response.usage.output_tokens,\n              }\n            : undefined,\n        },\n      };\n    } catch (error) {\n      const processingTime = Date.now() - startTime;\n      const originalError = error instanceof Error ? error : new Error(String(error));\n\n      this.logger.error('Claude image analysis failed');\n      this.logger.debug('Claude image analysis error', {\n        processingTime,\n        error: originalError.message,\n        hasStack: !!originalError.stack,\n      });\n\n      throw new VisionError(\n        `Claude vision analysis failed: ${originalError.message}`,\n        this.name,\n        originalError\n      );\n    }\n  }\n}\n","import {\n  LLMProvider,\n  LLMRequestOptions,\n  LLMResponse,\n  LLMStreamChunk,\n  LLMConfig,\n  VisionAnalysisOptions,\n  VisionAnalysisResult,\n  EmbeddingResult,\n  isStringContent,\n} from '../types';\nimport { GoogleGenerativeAI } from '@google/generative-ai';\nimport { getLogger } from '../../logger';\nimport { Logger } from '../../logger/types';\nimport { LLMApiError, VisionError } from '../../errors';\nimport * as fs from 'fs';\nimport * as path from 'path';\n\n// Retry helper with exponential backoff\nasync function withRetry<T>(fn: () => Promise<T>, maxRetries = 3): Promise<T> {\n  let lastError: Error | undefined;\n  for (let i = 0; i < maxRetries; i++) {\n    try {\n      return await fn();\n    } catch (error) {\n      lastError = error as Error;\n      if (i < maxRetries - 1) {\n        await new Promise((r) => setTimeout(r, Math.pow(2, i) * 1000));\n      }\n    }\n  }\n  if (!lastError) {\n    throw new Error('No retry attempts made');\n  }\n  throw lastError;\n}\n\n// Gemini response type definitions\ninterface GeminiUsageMetadata {\n  promptTokenCount?: number;\n  candidatesTokenCount?: number;\n  totalTokenCount?: number;\n}\n\ninterface GeminiResponseWithUsage {\n  usageMetadata?: GeminiUsageMetadata;\n}\n\n// Type guard for Gemini response with usage metadata\nfunction hasUsageMetadata(response: object | null): response is GeminiResponseWithUsage {\n  return typeof response === 'object' && response !== null && 'usageMetadata' in response;\n}\n\nexport class GeminiProvider implements LLMProvider {\n  name = 'gemini';\n  private client: GoogleGenerativeAI;\n  private embeddingClient: GoogleGenerativeAI;\n  private visionClient: GoogleGenerativeAI;\n  private logger: Logger;\n\n  constructor(config?: LLMConfig) {\n    const apiKey = config?.apiKey || process.env.GEMINI_API_KEY;\n\n    // Use provided logger or fallback to global logger\n    this.logger = config?.logger || getLogger();\n\n    if (!apiKey) {\n      throw new Error('Gemini API key is required. Set GEMINI_API_KEY environment variable.');\n    }\n\n    this.logger.info('Gemini provider initialized');\n    this.logger.debug('Gemini provider initialization', {\n      hasConfigApiKey: !!config?.apiKey,\n      hasEnvApiKey: !!process.env.GEMINI_API_KEY,\n      hasEmbeddingApiKey: !!process.env.GEMINI_EMBEDDING_API_KEY,\n      hasVisionApiKey: !!process.env.GEMINI_VISION_API_KEY,\n      hasCustomBaseUrl: !!config?.baseUrl,\n      supportsEmbeddings: true,\n      supportsVision: true,\n    });\n\n    // Main client for chat completions\n    this.client = new GoogleGenerativeAI(apiKey);\n\n    // Dedicated embedding client with fallback logic\n    const embeddingApiKey = process.env.GEMINI_EMBEDDING_API_KEY || apiKey;\n    this.embeddingClient = new GoogleGenerativeAI(embeddingApiKey);\n\n    // Dedicated vision client with fallback logic\n    const visionApiKey = process.env.GEMINI_VISION_API_KEY || apiKey;\n    this.visionClient = new GoogleGenerativeAI(visionApiKey);\n  }\n\n  getSupportedModels(): string[] {\n    return [\n      'gemini-2.5-pro',\n      'gemini-2.5-pro-deep-think',\n      'gemini-2.5-flash',\n      'gemini-2.5-flash-lite',\n      'gemini-2.0-flash',\n      'gemini-2.0-flash-thinking',\n      'gemini-2.0-flash-lite',\n      'gemini-2.0-pro-experimental',\n      'gemini-1.5-pro',\n      'gemini-1.5-flash',\n      'gemini-1.5-flash-8b',\n      'gemini-pro',\n    ];\n  }\n\n  getVisionModels(): string[] {\n    return [\n      'gemini-1.5-pro',\n      'gemini-1.5-flash',\n      'gemini-1.0-pro-vision-latest',\n      'gemini-pro-vision',\n    ];\n  }\n\n  getEmbeddingModels(): string[] {\n    return ['text-embedding-004', 'embedding-001'];\n  }\n\n  // Helper to create generationConfig - prevents duplicate code\n  private createGenerationConfig(options: LLMRequestOptions): {\n    temperature: number;\n    maxOutputTokens: number;\n  } {\n    return {\n      temperature: options.temperature ?? 0.7,\n      maxOutputTokens: options.maxTokens ?? 4096,\n    };\n  }\n\n  async generateResponse(options: LLMRequestOptions): Promise<LLMResponse> {\n    const { systemInstruction, contents } = this.prepareMessages(options);\n    const generationConfig = this.createGenerationConfig(options);\n\n    try {\n      const model = this.client.getGenerativeModel({\n        model: options.model,\n        ...(systemInstruction && {\n          systemInstruction: { role: 'user', parts: [{ text: systemInstruction }] },\n        }),\n        generationConfig,\n      });\n\n      const result = await withRetry(() =>\n        model.generateContent({\n          contents,\n          generationConfig,\n        })\n      );\n\n      const response = result.response;\n      const text = response.text() || '';\n\n      return {\n        content: text,\n        model: options.model,\n        usage: {\n          promptTokens: hasUsageMetadata(response)\n            ? response.usageMetadata?.promptTokenCount || 0\n            : 0,\n          completionTokens: hasUsageMetadata(response)\n            ? response.usageMetadata?.candidatesTokenCount || 0\n            : 0,\n          totalTokens: hasUsageMetadata(response)\n            ? response.usageMetadata?.totalTokenCount || 0\n            : 0,\n        },\n      };\n    } catch (error) {\n      const originalError = error instanceof Error ? error : new Error(String(error));\n      this.logger.error('Gemini generateResponse failed', originalError, {\n        model: options.model,\n        errorMessage: originalError.message,\n      });\n      throw new LLMApiError(\n        `Gemini API request failed: ${originalError.message}`,\n        this.name,\n        originalError\n      );\n    }\n  }\n\n  async *generateStreamResponse(options: LLMRequestOptions): AsyncIterableIterator<LLMStreamChunk> {\n    const { systemInstruction, contents } = this.prepareMessages(options);\n    const generationConfig = this.createGenerationConfig(options);\n\n    const model = this.client.getGenerativeModel({\n      model: options.model,\n      ...(systemInstruction && {\n        systemInstruction: { role: 'user', parts: [{ text: systemInstruction }] },\n      }),\n      generationConfig,\n    });\n\n    let result;\n    try {\n      result = await withRetry(() =>\n        model.generateContentStream({\n          contents,\n          generationConfig,\n        })\n      );\n    } catch (error) {\n      const originalError = error instanceof Error ? error : new Error(String(error));\n      this.logger.error('Gemini stream initialization failed', originalError, {\n        model: options.model,\n        errorMessage: originalError.message,\n      });\n      throw new LLMApiError(\n        `Gemini API stream request failed: ${originalError.message}`,\n        this.name,\n        originalError\n      );\n    }\n\n    try {\n      for await (const chunk of result.stream) {\n        const text = chunk.text();\n\n        if (text) {\n          yield { content: text, done: false, model: options.model };\n        }\n      }\n\n      yield { content: '', done: true, model: options.model };\n    } catch (error) {\n      const originalError = error instanceof Error ? error : new Error(String(error));\n      throw new LLMApiError(\n        `Gemini streaming error: ${originalError.message}`,\n        this.name,\n        originalError\n      );\n    }\n  }\n\n  private prepareMessages(options: LLMRequestOptions): {\n    systemInstruction?: string;\n    contents: Array<{ role: string; parts: Array<{ text: string }> }>;\n  } {\n    let systemInstruction = options.systemPrompt;\n    const messages = options.messages.filter((m) => m.role !== 'system');\n\n    // Find system message if no explicit system prompt\n    if (!systemInstruction) {\n      const systemMessage = options.messages.find((m) => m.role === 'system');\n      if (systemMessage) {\n        systemInstruction = isStringContent(systemMessage.content) ? systemMessage.content : '';\n      }\n    }\n\n    // Convert messages to Gemini format\n    const contents = messages.map((msg) => ({\n      role: msg.role === 'assistant' ? 'model' : 'user',\n      parts: [\n        {\n          text: isStringContent(msg.content)\n            ? msg.content\n            : 'Multi-modal content not fully supported by Gemini provider',\n        },\n      ],\n    }));\n\n    return { systemInstruction, contents };\n  }\n\n  async generateEmbedding(text: string, model?: string): Promise<EmbeddingResult> {\n    const embeddingModel = model || this.getEmbeddingModels()[0]; // Use provided model or fallback to first available\n\n    this.logger.info(`Generating embedding with model: ${embeddingModel}`);\n    this.logger.debug('Gemini embedding request', {\n      model: embeddingModel,\n      textLength: text.length,\n    });\n\n    try {\n      const genModel = this.embeddingClient.getGenerativeModel({ model: embeddingModel });\n      const result = await genModel.embedContent(text);\n\n      const embeddingValues = result?.embedding?.values;\n      if (!embeddingValues || embeddingValues.length === 0) {\n        throw new Error('No embedding data returned from Gemini API');\n      }\n\n      const embeddingResult: EmbeddingResult = {\n        embedding: embeddingValues,\n        model: embeddingModel,\n        usage: {\n          promptTokens: 0, // Gemini doesn't provide detailed usage for embeddings\n          totalTokens: 0,\n        },\n      };\n\n      this.logger.info('Embedding generated successfully');\n      this.logger.debug('Gemini embedding result', {\n        model: embeddingModel,\n        dimensions: embeddingResult.embedding.length,\n      });\n\n      return embeddingResult;\n    } catch (error) {\n      const originalError = error instanceof Error ? error : new Error(String(error));\n      this.logger.error('Embedding generation failed');\n      this.logger.debug('Gemini embedding error', {\n        model: embeddingModel,\n        error: originalError.message,\n        hasStack: !!originalError.stack,\n      });\n      throw new LLMApiError(\n        `Gemini embedding generation failed: ${originalError.message}`,\n        this.name,\n        originalError\n      );\n    }\n  }\n\n  async analyzeImage(\n    imagePath: string,\n    options: VisionAnalysisOptions = {}\n  ): Promise<VisionAnalysisResult> {\n    const fileName = path.basename(imagePath);\n\n    this.logger.info(`Analyzing image: ${fileName}`);\n    this.logger.debug('Gemini image analysis started', {\n      imagePath,\n      fileName,\n      hasPrompt: !!options.prompt,\n      maxTokens: options.maxTokens || 1000,\n    });\n\n    // Validate image file (async)\n    try {\n      await fs.promises.access(imagePath);\n    } catch {\n      this.logger.error(`Image file not found: ${imagePath}`);\n      throw new Error(`Image file not found: ${imagePath}`);\n    }\n\n    const ext = path.extname(imagePath).toLowerCase();\n    const supportedFormats = ['.jpg', '.jpeg', '.png', '.gif', '.webp'];\n    if (!supportedFormats.includes(ext)) {\n      this.logger.error(`Unsupported image format: ${ext}`);\n      throw new Error(\n        `Unsupported image format: ${ext}. Supported: ${supportedFormats.join(', ')}`\n      );\n    }\n\n    // Read and encode image (async)\n    const imageBuffer = await fs.promises.readFile(imagePath);\n    const base64Image = imageBuffer.toString('base64');\n    const mimeType = this.getMimeType(ext);\n\n    return this.analyzeImageFromBase64(base64Image, { ...options, mimeType });\n  }\n\n  async analyzeImageFromBase64(\n    base64Data: string,\n    options: VisionAnalysisOptions & { mimeType?: string } = {}\n  ): Promise<VisionAnalysisResult> {\n    const startTime = Date.now();\n\n    this.logger.info('Analyzing base64 image');\n    this.logger.debug('Gemini base64 image analysis started', {\n      base64Length: base64Data.length,\n      hasPrompt: !!options.prompt,\n      maxTokens: options.maxTokens || 1000,\n      mimeType: options.mimeType || 'image/jpeg',\n    });\n\n    try {\n      const model = options.model || this.getVisionModels()[0]; // Use agent's model or fallback to first available\n      const prompt = options.prompt || 'Analyze this image and describe what you see in detail.';\n      const mimeType = options.mimeType || 'image/jpeg';\n\n      // Remove data URL prefix if present\n      const cleanBase64 = base64Data.replace(/^data:image\\/[a-zA-Z]+;base64,/, '');\n\n      const genModel = this.visionClient.getGenerativeModel({\n        model,\n        generationConfig: {\n          maxOutputTokens: options.maxTokens || 1000,\n          temperature: options.temperature || 0.1,\n        },\n      });\n\n      const imagePart = {\n        inlineData: {\n          data: cleanBase64,\n          mimeType: mimeType,\n        },\n      };\n\n      const result = await genModel.generateContent([prompt, imagePart]);\n      const response = await result.response;\n      const content = response.text() || 'No analysis available';\n\n      const processingTime = Date.now() - startTime;\n\n      const analysisResult: VisionAnalysisResult = {\n        content,\n        confidence: 1.0,\n        metadata: {\n          model,\n          provider: this.name,\n          processingTime,\n          tokenUsage:\n            hasUsageMetadata(response) && response.usageMetadata\n              ? {\n                  promptTokens: response.usageMetadata.promptTokenCount || 0,\n                  completionTokens: response.usageMetadata.candidatesTokenCount || 0,\n                  totalTokens: response.usageMetadata.totalTokenCount || 0,\n                }\n              : undefined,\n        },\n      };\n\n      this.logger.info('Image analysis completed');\n      this.logger.debug('Gemini image analysis result', {\n        model,\n        processingTime,\n        contentLength: content.length,\n        promptTokens: hasUsageMetadata(response)\n          ? response.usageMetadata?.promptTokenCount || 0\n          : 0,\n        candidatesTokens: hasUsageMetadata(response)\n          ? response.usageMetadata?.candidatesTokenCount || 0\n          : 0,\n        totalTokens: hasUsageMetadata(response) ? response.usageMetadata?.totalTokenCount || 0 : 0,\n      });\n\n      return analysisResult;\n    } catch (error) {\n      const processingTime = Date.now() - startTime;\n      const originalError = error instanceof Error ? error : new Error(String(error));\n\n      this.logger.error('Image analysis failed');\n      this.logger.debug('Gemini image analysis error', {\n        processingTime,\n        error: originalError.message,\n        hasStack: !!originalError.stack,\n      });\n\n      throw new VisionError(\n        `Gemini vision analysis failed: ${originalError.message}`,\n        this.name,\n        originalError\n      );\n    }\n  }\n\n  private getMimeType(extension: string): string {\n    const mimeTypes: Record<string, string> = {\n      '.jpg': 'image/jpeg',\n      '.jpeg': 'image/jpeg',\n      '.png': 'image/png',\n      '.gif': 'image/gif',\n      '.webp': 'image/webp',\n    };\n\n    return mimeTypes[extension.toLowerCase()] || 'image/jpeg';\n  }\n\n  getEmbeddingProvider(): LLMProvider {\n    return {\n      name: 'gemini-embedding',\n      generateResponse: this.generateResponse.bind(this),\n      generateStreamResponse: this.generateStreamResponse.bind(this),\n      getSupportedModels: () => [],\n      getVisionModels: () => [],\n      getEmbeddingModels: this.getEmbeddingModels.bind(this),\n      generateEmbedding: async (text: string, model?: string) => {\n        const embeddingModel = model || this.getEmbeddingModels()[0]; // Use provided model or fallback to first available\n\n        this.logger.debug('Using dedicated embedding client', {\n          model: embeddingModel,\n          textLength: text.length,\n        });\n\n        const genModel = this.embeddingClient.getGenerativeModel({ model: embeddingModel });\n        const result = await genModel.embedContent(text);\n\n        const embeddingValues = result?.embedding?.values;\n        if (!embeddingValues || embeddingValues.length === 0) {\n          throw new Error('No embedding data returned from Gemini API');\n        }\n\n        return {\n          embedding: embeddingValues,\n          model: embeddingModel,\n          usage: {\n            promptTokens: 0,\n            totalTokens: 0,\n          },\n        };\n      },\n    };\n  }\n\n  getVisionProvider(): LLMProvider {\n    return {\n      name: 'gemini-vision',\n      generateResponse: this.generateResponse.bind(this),\n      generateStreamResponse: this.generateStreamResponse.bind(this),\n      getSupportedModels: () => [],\n      getVisionModels: this.getVisionModels.bind(this),\n      getEmbeddingModels: () => [],\n      analyzeImage: async (imagePath: string, options?: VisionAnalysisOptions) => {\n        const imageBuffer = await fs.promises.readFile(imagePath);\n        const base64Image = imageBuffer.toString('base64');\n        const ext = path.extname(imagePath).toLowerCase();\n        const mimeType = this.getMimeType(ext);\n\n        return this.analyzeImageFromBase64WithClient(\n          base64Image,\n          { ...options, mimeType },\n          this.visionClient\n        );\n      },\n      analyzeImageFromBase64: async (base64Data: string, options?: VisionAnalysisOptions) => {\n        return this.analyzeImageFromBase64WithClient(base64Data, options, this.visionClient);\n      },\n    };\n  }\n\n  private async analyzeImageFromBase64WithClient(\n    base64Data: string,\n    options: VisionAnalysisOptions & { mimeType?: string } = {},\n    client: GoogleGenerativeAI\n  ): Promise<VisionAnalysisResult> {\n    const startTime = Date.now();\n\n    this.logger.debug('Using dedicated vision client', {\n      base64Length: base64Data.length,\n      hasPrompt: !!options.prompt,\n      mimeType: options.mimeType || 'image/jpeg',\n    });\n\n    try {\n      const model = options.model || this.getVisionModels()[0]; // Use agent's model or fallback to first available\n      const prompt = options.prompt || 'Analyze this image and describe what you see in detail.';\n      const mimeType = options.mimeType || 'image/jpeg';\n\n      // Remove data URL prefix if present\n      const cleanBase64 = base64Data.replace(/^data:image\\/[a-zA-Z]+;base64,/, '');\n\n      const genModel = client.getGenerativeModel({\n        model,\n        generationConfig: {\n          maxOutputTokens: options.maxTokens || 1000,\n          temperature: options.temperature || 0.1,\n        },\n      });\n\n      const imagePart = {\n        inlineData: {\n          data: cleanBase64,\n          mimeType: mimeType,\n        },\n      };\n\n      const result = await genModel.generateContent([prompt, imagePart]);\n      const response = await result.response;\n      const content = response.text() || 'No analysis available';\n\n      const processingTime = Date.now() - startTime;\n\n      return {\n        content,\n        confidence: 1.0,\n        metadata: {\n          model,\n          provider: this.name,\n          processingTime,\n          tokenUsage:\n            hasUsageMetadata(response) && response.usageMetadata\n              ? {\n                  promptTokens: response.usageMetadata.promptTokenCount || 0,\n                  completionTokens: response.usageMetadata.candidatesTokenCount || 0,\n                  totalTokens: response.usageMetadata.totalTokenCount || 0,\n                }\n              : undefined,\n        },\n      };\n    } catch (error) {\n      const processingTime = Date.now() - startTime;\n      const originalError = error instanceof Error ? error : new Error(String(error));\n\n      this.logger.error('Gemini image analysis failed');\n      this.logger.debug('Gemini image analysis error', {\n        processingTime,\n        error: originalError.message,\n        hasStack: !!originalError.stack,\n      });\n\n      throw new VisionError(\n        `Gemini vision analysis failed: ${originalError.message}`,\n        this.name,\n        originalError\n      );\n    }\n  }\n}\n","import {\n  LLMProvider,\n  LLMRequestOptions,\n  LLMResponse,\n  LLMStreamChunk,\n  LLMConfig,\n  VisionAnalysisOptions,\n  VisionAnalysisResult,\n  EmbeddingResult,\n  isStringContent,\n} from '../types';\nimport { getLogger } from '../../logger';\nimport { Logger } from '../../logger/types';\nimport { LLMApiError, VisionError } from '../../errors';\nimport * as fs from 'fs';\nimport * as path from 'path';\n\n// Ollama-specific tool parameter schema (matches JSON Schema format)\ninterface OllamaToolSchema {\n  type: string;\n  properties?: Record<string, OllamaToolParameter>;\n  required?: string[];\n  items?: OllamaToolParameter;\n  description?: string;\n  enum?: Array<string | number>;\n}\n\ninterface OllamaToolParameter {\n  type?: string | string[];\n  items?: { type: string };\n  description?: string;\n  enum?: Array<string | number>;\n  properties?: Record<string, OllamaToolParameter>;\n}\nimport { Ollama, Message, ChatResponse } from 'ollama';\n\n// Helper type for vision generation options\ninterface VisionGenerateOptions {\n  model: string;\n  prompt: string;\n  cleanBase64: string;\n  maxTokens?: number;\n  temperature?: number;\n}\n\nexport class OllamaProvider implements LLMProvider {\n  name = 'ollama';\n  private client: Ollama;\n  private logger: Logger;\n\n  constructor(config?: LLMConfig) {\n    // Use provided logger or fallback to global logger\n    this.logger = config?.logger || getLogger();\n\n    // If baseUrl is explicitly null, use default Ollama URL (for embedding/vision providers)\n    const baseUrl =\n      config?.baseUrl === null\n        ? 'http://localhost:11434'\n        : config?.baseUrl || process.env.OLLAMA_BASE_URL || 'http://localhost:11434';\n\n    this.logger.info('Ollama provider initialized');\n    this.logger.debug('Ollama provider initialization', {\n      hasConfigApiKey: false, // Ollama doesn't use API keys\n      hasCustomBaseUrl: !!config?.baseUrl,\n      hasEnvBaseUrl: !!process.env.OLLAMA_BASE_URL,\n      baseUrl: baseUrl,\n      supportsEmbeddings: true,\n      supportsVision: true,\n    });\n\n    this.client = new Ollama({\n      host: baseUrl,\n    });\n  }\n\n  getSupportedModels(): string[] {\n    return [\n      'deepseek-r1',\n      'deepseek-v3',\n      'deepseek-v2.5',\n      'deepseek-coder',\n      'deepseek-coder-v2',\n      'qwen3',\n      'qwen2.5-coder',\n      'llama3.3',\n      'gemma3',\n      'phi4',\n      'mistral-small',\n      'codellama',\n      'llama3.2',\n      'llama3.1',\n      'qwen2.5',\n      'gemma2',\n      'phi3',\n      'mistral',\n      'codegemma',\n      'wizardlm2',\n      'dolphin-mistral',\n      'openhermes',\n      'deepcoder',\n      'stable-code',\n      'wizardcoder',\n      'magicoder',\n      'solar',\n      'yi',\n      'zephyr',\n      'orca-mini',\n      'vicuna',\n    ];\n  }\n\n  getVisionModels(): string[] {\n    return [\n      'llava',\n      'llava:7b',\n      'llava:13b',\n      'llava:34b',\n      'llava-llama3',\n      'llava-phi3',\n      'moondream',\n    ];\n  }\n\n  getEmbeddingModels(): string[] {\n    return ['nomic-embed-text', 'mxbai-embed-large', 'all-minilm', 'snowflake-arctic-embed'];\n  }\n\n  /**\n   * Helper function for vision generation with retry logic for model-not-found errors\n   * Consolidates duplicate retry logic from analyzeImageFromBase64 and analyzeImageFromBase64WithClient\n   */\n  private async executeVisionWithRetry(\n    client: Ollama,\n    opts: VisionGenerateOptions,\n    maxRetries = 2\n  ): Promise<{\n    response: string;\n    promptEvalCount: number;\n    evalCount: number;\n    totalDuration: number;\n  }> {\n    let lastError: Error | undefined;\n\n    for (let attempt = 0; attempt <= maxRetries; attempt++) {\n      try {\n        const response = await client.generate({\n          model: opts.model,\n          prompt: opts.prompt,\n          images: [opts.cleanBase64],\n          options: {\n            num_predict: opts.maxTokens || 1000,\n            temperature: opts.temperature || 0.1,\n          },\n          stream: false,\n        });\n\n        return {\n          response: response.response || 'No analysis available',\n          promptEvalCount: response.prompt_eval_count || 0,\n          evalCount: response.eval_count || 0,\n          totalDuration: response.total_duration || 0,\n        };\n      } catch (error) {\n        lastError = error as Error;\n        const errorMessage = lastError.message.toLowerCase();\n\n        // If it's a model not found error and we have retries left\n        if (\n          (errorMessage.includes('model') && errorMessage.includes('not found')) ||\n          errorMessage.includes('does not exist')\n        ) {\n          if (attempt < maxRetries) {\n            this.logger.warn(\n              `Model ${opts.model} not found, retrying... (attempt ${attempt + 1}/${maxRetries})`\n            );\n            await new Promise((resolve) => setTimeout(resolve, 500));\n            continue;\n          }\n          // After retries exhausted, provide helpful error message\n          const availableModels = await client.list();\n          throw new Error(\n            `Model '${opts.model}' not found after ${maxRetries + 1} attempts. Available models: ${availableModels.models.map((m) => m.name).join(', ')}`\n          );\n        }\n        throw lastError;\n      }\n    }\n\n    // This should not be reached, but TypeScript needs it\n    throw lastError || new Error('Unknown error during image analysis');\n  }\n\n  async generateResponse(options: LLMRequestOptions): Promise<LLMResponse> {\n    const messages = this.prepareMessages(options);\n\n    const response = (await this.client.chat({\n      model: options.model,\n      messages,\n      options: {\n        temperature: options.temperature ?? 0.7,\n        num_predict: options.maxTokens ?? 4096,\n      },\n      stream: false,\n      tools: options.tools?.map((tool) => ({\n        type: 'function',\n        function: {\n          name: tool.function.name,\n          description: tool.function.description,\n          parameters: tool.function.parameters as OllamaToolSchema,\n        },\n      })),\n    })) as ChatResponse;\n\n    // Extract tool calls from Ollama's response (if supported) with proper type safety\n    const toolCalls: Array<{\n      id: string;\n      type: 'function';\n      function: { name: string; arguments: Record<string, string | number | boolean | null> };\n    }> = [];\n\n    if (response.message?.tool_calls) {\n      for (const tc of response.message.tool_calls) {\n        // Skip tool calls with null/undefined function\n        if (tc.function == null || tc.function.name == null) {\n          continue;\n        }\n        toolCalls.push({\n          id: tc.function.name || `tool-${Date.now()}`,\n          type: 'function' as const,\n          function: {\n            name: tc.function.name,\n            arguments:\n              (tc.function.arguments as Record<string, string | number | boolean | null>) || {},\n          },\n        });\n      }\n    }\n\n    return {\n      content: response.message?.content || '',\n      model: response.model || options.model,\n      toolCalls: toolCalls.length > 0 ? toolCalls : undefined,\n      usage: {\n        promptTokens: response.prompt_eval_count || 0,\n        completionTokens: response.eval_count || 0,\n        totalTokens: (response.prompt_eval_count || 0) + (response.eval_count || 0),\n      },\n    };\n  }\n\n  async *generateStreamResponse(options: LLMRequestOptions): AsyncIterableIterator<LLMStreamChunk> {\n    const messages = this.prepareMessages(options);\n\n    const stream = await this.client.chat({\n      model: options.model,\n      messages,\n      options: {\n        temperature: options.temperature ?? 0.7,\n        num_predict: options.maxTokens ?? 4096,\n      },\n      stream: true,\n      tools: options.tools?.map((tool) => ({\n        type: 'function',\n        function: {\n          name: tool.function.name,\n          description: tool.function.description,\n          parameters: tool.function.parameters as OllamaToolSchema,\n        },\n      })),\n    });\n\n    const toolCalls: Array<{\n      id: string;\n      type: 'function';\n      function: { name: string; arguments: Record<string, string | number | boolean | null> };\n    }> = [];\n\n    try {\n      for await (const chunk of stream) {\n        const content = chunk.message?.content || '';\n\n        // Handle tool calls if present\n        if (chunk.message?.tool_calls) {\n          for (const tc of chunk.message.tool_calls) {\n            // Skip tool calls with null/undefined function\n            if (tc.function == null) {\n              continue;\n            }\n            toolCalls.push({\n              id: tc.function.name || 'tool-call',\n              type: 'function',\n              function: {\n                name: tc.function.name,\n                arguments: tc.function.arguments || {},\n              },\n            });\n          }\n        }\n\n        if (chunk.done) {\n          yield {\n            content: '',\n            done: true,\n            model: options.model,\n            toolCalls: toolCalls.length > 0 ? toolCalls : undefined,\n          };\n          return;\n        } else if (content) {\n          yield { content, done: false, model: options.model };\n        }\n      }\n    } catch (error) {\n      const originalError = error instanceof Error ? error : new Error(String(error));\n      throw new LLMApiError(\n        `Ollama streaming error: ${originalError.message}`,\n        this.name,\n        originalError\n      );\n    }\n  }\n\n  private prepareMessages(options: LLMRequestOptions): Message[] {\n    const messages = [...options.messages];\n\n    // Add system prompt if provided and no system message exists\n    if (options.systemPrompt && !messages.some((m) => m.role === 'system')) {\n      messages.unshift({ role: 'system', content: options.systemPrompt });\n    }\n\n    // Convert messages to Ollama format (handles tool messages)\n    return messages.map((msg) => {\n      if (msg.role === 'tool') {\n        return {\n          role: 'tool',\n          content: isStringContent(msg.content) ? msg.content : 'Multi-modal content not supported',\n        } as Message;\n      }\n\n      if (msg.tool_calls && msg.tool_calls.length > 0) {\n        return {\n          role: msg.role,\n          content: (isStringContent(msg.content) ? msg.content : '') || '',\n          tool_calls: msg.tool_calls.map((tc) => ({\n            function: {\n              name: tc.function.name,\n              arguments: tc.function.arguments,\n            },\n          })),\n        } as Message;\n      }\n\n      return {\n        role: msg.role,\n        content: isStringContent(msg.content)\n          ? msg.content\n          : 'Multi-modal content not fully supported by Ollama provider',\n      } as Message;\n    });\n  }\n\n  async generateEmbedding(text: string, model?: string): Promise<EmbeddingResult> {\n    const embeddingModel = model || this.getEmbeddingModels()[0]; // Use provided model or fallback to first available\n\n    this.logger.info(`Generating embedding with model: ${embeddingModel}`);\n    this.logger.debug('Ollama embedding request', {\n      model: embeddingModel,\n      textLength: text.length,\n    });\n\n    try {\n      const response = await this.client.embeddings({\n        model: embeddingModel,\n        prompt: text,\n      });\n\n      const result: EmbeddingResult = {\n        embedding: response.embedding,\n        model: embeddingModel,\n        usage: {\n          promptTokens: 0, // Ollama doesn't provide detailed usage\n          totalTokens: 0,\n        },\n      };\n\n      this.logger.info('Embedding generated successfully');\n      this.logger.debug('Ollama embedding result', {\n        model: embeddingModel,\n        dimensions: result.embedding.length,\n      });\n\n      return result;\n    } catch (error) {\n      const originalError = error instanceof Error ? error : new Error(String(error));\n      this.logger.error('Embedding generation failed');\n      this.logger.debug('Ollama embedding error', {\n        model: embeddingModel,\n        error: originalError.message,\n        hasStack: !!originalError.stack,\n      });\n      throw new LLMApiError(\n        `Ollama embedding generation failed: ${originalError.message}`,\n        this.name,\n        originalError\n      );\n    }\n  }\n\n  async analyzeImage(\n    imagePath: string,\n    options: VisionAnalysisOptions = {}\n  ): Promise<VisionAnalysisResult> {\n    const fileName = path.basename(imagePath);\n\n    this.logger.info(`Analyzing image: ${fileName}`);\n    this.logger.debug('Ollama image analysis started', {\n      imagePath,\n      fileName,\n      hasPrompt: !!options.prompt,\n      maxTokens: options.maxTokens || 1000,\n    });\n\n    // Validate image file (async)\n    try {\n      await fs.promises.access(imagePath);\n    } catch {\n      this.logger.error(`Image file not found: ${imagePath}`);\n      throw new Error(`Image file not found: ${imagePath}`);\n    }\n\n    const ext = path.extname(imagePath).toLowerCase();\n    const supportedFormats = ['.jpg', '.jpeg', '.png'];\n    if (!supportedFormats.includes(ext)) {\n      this.logger.error(`Unsupported image format: ${ext}`);\n      throw new Error(\n        `Unsupported image format: ${ext}. Supported: ${supportedFormats.join(', ')}`\n      );\n    }\n\n    // Read and encode image (async)\n    const imageBuffer = await fs.promises.readFile(imagePath);\n    const base64Image = imageBuffer.toString('base64');\n\n    return this.analyzeImageFromBase64(base64Image, options);\n  }\n\n  async analyzeImageFromBase64(\n    base64Data: string,\n    options: VisionAnalysisOptions = {}\n  ): Promise<VisionAnalysisResult> {\n    const startTime = Date.now();\n\n    this.logger.info('Analyzing base64 image');\n    this.logger.debug('Ollama base64 image analysis started', {\n      base64Length: base64Data.length,\n      hasPrompt: !!options.prompt,\n      maxTokens: options.maxTokens || 1000,\n    });\n\n    try {\n      const model = options.model || this.getVisionModels()[0];\n      const prompt = options.prompt || 'Analyze this image and describe what you see in detail.';\n      const cleanBase64 = base64Data.replace(/^data:image\\/[a-zA-Z]+;base64,/, '');\n\n      // Use consolidated retry helper\n      const response = await this.executeVisionWithRetry(this.client, {\n        model,\n        prompt,\n        cleanBase64,\n        maxTokens: options.maxTokens,\n        temperature: options.temperature,\n      });\n\n      const processingTime = Date.now() - startTime;\n\n      const result: VisionAnalysisResult = {\n        content: response.response,\n        confidence: 1.0,\n        metadata: {\n          model,\n          provider: this.name,\n          processingTime,\n          tokenUsage: {\n            promptTokens: response.promptEvalCount,\n            completionTokens: response.evalCount,\n            totalTokens: response.promptEvalCount + response.evalCount,\n          },\n        },\n      };\n\n      this.logger.info('Image analysis completed');\n      this.logger.debug('Ollama image analysis result', {\n        model,\n        processingTime,\n        contentLength: response.response.length,\n        promptEvalCount: response.promptEvalCount,\n        evalCount: response.evalCount,\n        totalDuration: response.totalDuration,\n      });\n\n      return result;\n    } catch (error) {\n      const processingTime = Date.now() - startTime;\n      const originalError = error instanceof Error ? error : new Error(String(error));\n\n      this.logger.error('Image analysis failed');\n      this.logger.debug('Ollama image analysis error', {\n        processingTime,\n        error: originalError.message,\n        hasStack: !!originalError.stack,\n      });\n\n      throw new VisionError(\n        `Ollama vision analysis failed: ${originalError.message}`,\n        this.name,\n        originalError\n      );\n    }\n  }\n\n  getEmbeddingProvider(): LLMProvider {\n    return {\n      name: 'ollama-embedding',\n      generateResponse: this.generateResponse.bind(this),\n      generateStreamResponse: this.generateStreamResponse.bind(this),\n      getSupportedModels: () => [],\n      getVisionModels: () => [],\n      getEmbeddingModels: this.getEmbeddingModels.bind(this),\n      generateEmbedding: async (text: string, model?: string) => {\n        const embeddingModel = model || this.getEmbeddingModels()[0]; // Use provided model or fallback to first available\n\n        this.logger.debug('Using Ollama client for embeddings', {\n          model: embeddingModel,\n          textLength: text.length,\n        });\n\n        const response = await this.client.embeddings({\n          model: embeddingModel,\n          prompt: text,\n        });\n\n        return {\n          embedding: response.embedding,\n          model: embeddingModel,\n          usage: {\n            promptTokens: 0,\n            totalTokens: 0,\n          },\n        };\n      },\n    };\n  }\n\n  getVisionProvider(): LLMProvider {\n    return {\n      name: 'ollama-vision',\n      generateResponse: this.generateResponse.bind(this),\n      generateStreamResponse: this.generateStreamResponse.bind(this),\n      getSupportedModels: () => [],\n      getVisionModels: this.getVisionModels.bind(this),\n      getEmbeddingModels: () => [],\n      analyzeImage: async (imagePath: string, options?: VisionAnalysisOptions) => {\n        const imageBuffer = await fs.promises.readFile(imagePath);\n        const base64Image = imageBuffer.toString('base64');\n\n        return this.analyzeImageFromBase64WithClient(base64Image, options, this.client);\n      },\n      analyzeImageFromBase64: async (base64Data: string, options?: VisionAnalysisOptions) => {\n        return this.analyzeImageFromBase64WithClient(base64Data, options, this.client);\n      },\n    };\n  }\n\n  private async analyzeImageFromBase64WithClient(\n    base64Data: string,\n    options: VisionAnalysisOptions = {},\n    client: Ollama\n  ): Promise<VisionAnalysisResult> {\n    const startTime = Date.now();\n\n    this.logger.debug('Using Ollama client for vision', {\n      base64Length: base64Data.length,\n      hasPrompt: !!options.prompt,\n    });\n\n    try {\n      const model = options.model || this.getVisionModels()[0];\n      const prompt = options.prompt || 'Analyze this image and describe what you see in detail.';\n      const cleanBase64 = base64Data.replace(/^data:image\\/[a-zA-Z]+;base64,/, '');\n\n      // Use consolidated retry helper\n      const response = await this.executeVisionWithRetry(client, {\n        model,\n        prompt,\n        cleanBase64,\n        maxTokens: options.maxTokens,\n        temperature: options.temperature,\n      });\n\n      const processingTime = Date.now() - startTime;\n\n      return {\n        content: response.response,\n        confidence: 1.0,\n        metadata: {\n          model,\n          provider: this.name,\n          processingTime,\n          tokenUsage: {\n            promptTokens: response.promptEvalCount,\n            completionTokens: response.evalCount,\n            totalTokens: response.promptEvalCount + response.evalCount,\n          },\n        },\n      };\n    } catch (error) {\n      const processingTime = Date.now() - startTime;\n      const originalError = error instanceof Error ? error : new Error(String(error));\n\n      this.logger.error('Ollama image analysis failed');\n      this.logger.debug('Ollama image analysis error', {\n        processingTime,\n        error: originalError.message,\n        hasStack: !!originalError.stack,\n      });\n\n      // Use VisionError for consistency with other providers\n      throw new VisionError(\n        `Ollama vision analysis failed: ${originalError.message}`,\n        this.name,\n        originalError\n      );\n    }\n  }\n}\n","import { OpenAIProvider } from './providers/openai';\nimport { ClaudeProvider } from './providers/claude';\nimport { GeminiProvider } from './providers/gemini';\nimport { OllamaProvider } from './providers/ollama';\n\nexport type ProviderType = 'openai' | 'claude' | 'gemini' | 'ollama';\n\n// Cache for provider models to avoid creating new instances on every call\nlet cachedProviderModels: Record<ProviderType, string[]> | null = null;\n\n// Mutex for thread-safe initialization\nlet initializationPromise: Promise<Record<ProviderType, string[]>> | null = null;\n\n// Create provider instances to get their supported models (cached with proper mutex)\nfunction getProviderModels(): Record<ProviderType, string[]> {\n  // Return cached result if available (fast path)\n  if (cachedProviderModels !== null) {\n    return cachedProviderModels;\n  }\n\n  // Synchronous fallback - create providers on demand\n  // This is safe because getSupportedModels() is synchronous\n  const providers: Record<ProviderType, string[]> = {\n    openai: [],\n    claude: [],\n    gemini: [],\n    ollama: [],\n  };\n\n  // Silently try to load providers - missing API keys are expected behavior\n  // Users only need API keys for providers they actually use\n  try {\n    providers.openai = new OpenAIProvider().getSupportedModels();\n  } catch {\n    // OpenAI provider not available - API key may not be configured\n  }\n\n  try {\n    providers.claude = new ClaudeProvider().getSupportedModels();\n  } catch {\n    // Claude provider not available - API key may not be configured\n  }\n\n  try {\n    providers.gemini = new GeminiProvider().getSupportedModels();\n  } catch {\n    // Gemini provider not available - API key may not be configured\n  }\n\n  try {\n    providers.ollama = new OllamaProvider().getSupportedModels();\n  } catch {\n    // Ollama provider not available - Ollama may not be running\n  }\n\n  // Cache the result\n  cachedProviderModels = providers;\n  return providers;\n}\n\n// Async initialization with proper mutex to prevent race conditions\nasync function getProviderModelsAsync(): Promise<Record<ProviderType, string[]>> {\n  // Return cached result if available (fast path)\n  if (cachedProviderModels !== null) {\n    return cachedProviderModels;\n  }\n\n  // If initialization is in progress, wait for it\n  if (initializationPromise !== null) {\n    return initializationPromise;\n  }\n\n  // Start initialization with mutex\n  initializationPromise = (async () => {\n    try {\n      // Double-check after acquiring \"lock\"\n      if (cachedProviderModels !== null) {\n        return cachedProviderModels;\n      }\n\n      const result = getProviderModels();\n      return result;\n    } finally {\n      // Clear the promise after initialization completes\n      initializationPromise = null;\n    }\n  })();\n\n  return initializationPromise;\n}\n\n// Create reverse lookup map\nconst MODEL_TO_PROVIDER: Record<string, ProviderType> = {};\nlet PROVIDER_MODELS: Record<ProviderType, string[]> = {\n  openai: [],\n  claude: [],\n  gemini: [],\n  ollama: [],\n};\n\n// Mutex promise for atomic initialization\nlet initializationMutex: Promise<void> | null = null;\nlet isInitialized = false;\n\nfunction initializeModelMappings() {\n  // Fast path: already initialized\n  if (isInitialized) {\n    return;\n  }\n\n  // Use synchronous initialization with proper guard\n  // The Promise-based mutex is for async scenarios\n  if (initializationMutex !== null) {\n    // Another initialization is in progress, wait would be async\n    // For sync call, just return - the data will be populated by the other caller\n    return;\n  }\n\n  // Set flag immediately to prevent concurrent entries\n  isInitialized = true;\n\n  try {\n    PROVIDER_MODELS = getProviderModels();\n\n    Object.entries(PROVIDER_MODELS).forEach(([provider, models]) => {\n      models.forEach((model) => {\n        MODEL_TO_PROVIDER[model] = provider as ProviderType;\n      });\n    });\n  } catch (error) {\n    // Reset flag on error so retry is possible\n    isInitialized = false;\n    throw error;\n  }\n}\n\n// Async version with proper mutex for concurrent scenarios\n// Exported for use in async initialization contexts (e.g., server startup)\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nasync function initializeModelMappingsAsync(): Promise<void> {\n  // Fast path: already initialized\n  if (isInitialized) {\n    return;\n  }\n\n  // If initialization is in progress, wait for it\n  if (initializationMutex !== null) {\n    return initializationMutex;\n  }\n\n  // Start initialization with mutex\n  initializationMutex = (async () => {\n    try {\n      // Double-check after acquiring mutex\n      if (isInitialized) {\n        return;\n      }\n\n      PROVIDER_MODELS = await getProviderModelsAsync();\n\n      Object.entries(PROVIDER_MODELS).forEach(([provider, models]) => {\n        models.forEach((model) => {\n          MODEL_TO_PROVIDER[model] = provider as ProviderType;\n        });\n      });\n\n      isInitialized = true;\n    } finally {\n      initializationMutex = null;\n    }\n  })();\n\n  return initializationMutex;\n}\n\n// Model name patterns for fallback provider detection\nconst MODEL_MAPPINGS: Record<ProviderType, string[]> = {\n  openai: ['gpt', 'o1', 'davinci', 'curie', 'babbage', 'ada', 'text-embedding'],\n  claude: ['claude'],\n  gemini: ['gemini'],\n  ollama: ['llama', 'mistral', 'codellama', 'vicuna', 'orca', 'phi'],\n};\n\nexport function getProviderForModel(model: string): ProviderType | null {\n  initializeModelMappings();\n\n  // First check exact model mappings from providers\n  if (MODEL_TO_PROVIDER[model]) {\n    return MODEL_TO_PROVIDER[model];\n  }\n\n  // Then check model name patterns\n  const modelLower = model.toLowerCase();\n  for (const [provider, patterns] of Object.entries(MODEL_MAPPINGS)) {\n    if (patterns.some((p) => modelLower.includes(p.toLowerCase()))) {\n      return provider as ProviderType;\n    }\n  }\n\n  // Fallback to additional pattern matching\n  if (modelLower.includes('gpt') || modelLower.includes('o1')) return 'openai';\n  if (modelLower.includes('claude')) return 'claude';\n  if (modelLower.includes('gemini')) return 'gemini';\n  if (modelLower.includes('llama') || modelLower.includes('mistral')) return 'ollama';\n\n  return null;\n}\n\nexport function getSupportedModelsList(): string[] {\n  initializeModelMappings();\n  return Object.values(PROVIDER_MODELS).flat();\n}\n\nexport function getModelsByProvider(provider: ProviderType): string[] {\n  initializeModelMappings();\n  return [...PROVIDER_MODELS[provider]];\n}\n","/**\n * Default configuration values for LLM module\n */\nexport const DEFAULT_LLM_CONFIG = {\n  defaultTemperature: 0.7,\n  defaultMaxTokens: 2000,\n  visionMaxTokens: 1000,\n  visionTemperature: 0.1,\n  embeddingMaxTokens: 1000,\n  fallbackModel: 'gpt-4o-mini',\n  /** Default embedding model when none specified */\n  defaultEmbeddingModel: 'text-embedding-ada-002',\n} as const;\n\n/**\n * Get default value for a LLM config property\n */\nexport function getLLMDefaultValue<K extends keyof typeof DEFAULT_LLM_CONFIG>(\n  key: K\n): (typeof DEFAULT_LLM_CONFIG)[K] {\n  return DEFAULT_LLM_CONFIG[key];\n}\n","import {\n  LLMProvider,\n  LLMRequestOptions,\n  LLMResponse,\n  LLMStreamChunk,\n  RateLimiterOptions,\n} from './types';\nimport { getProviderForModel, getSupportedModelsList } from './models';\nimport { OpenAIProvider } from './providers/openai';\nimport { ClaudeProvider } from './providers/claude';\nimport { GeminiProvider } from './providers/gemini';\nimport { OllamaProvider } from './providers/ollama';\nimport { Logger } from '../logger/types';\nimport { getLogger } from '../logger';\nimport { DEFAULT_LLM_CONFIG } from './defaults';\n\n/**\n * Request priority levels for fair scheduling\n */\nexport enum RequestPriority {\n  /** High priority - Agent.ask() direct user interactions */\n  HIGH = 0,\n  /** Normal priority - Task execution, SubAgent operations */\n  NORMAL = 1,\n  /** Low priority - Background tasks like context compression */\n  LOW = 2,\n}\n\ninterface QueuedRequest {\n  resolve: () => void;\n  reject: (error: Error) => void;\n  timeoutId: NodeJS.Timeout;\n  priority: RequestPriority;\n  enqueuedAt: number;\n  caller?: string;\n}\n\n/**\n * Rate limiter for coordinating concurrent LLM API calls across modules.\n * Prevents API rate limit errors (429) when multiple modules call LLM simultaneously.\n *\n * Features:\n * - Concurrent request limiting\n * - Requests per minute limiting\n * - Fair scheduling with priority queues\n * - Starvation prevention for low-priority requests\n *\n * Used by:\n * - Agent.ask()\n * - Task.executeTask()\n * - ContextManager.compressContext()\n * - SubAgent.executeWithSubAgents()\n */\nexport class RateLimiter {\n  private queues: Map<RequestPriority, QueuedRequest[]> = new Map([\n    [RequestPriority.HIGH, []],\n    [RequestPriority.NORMAL, []],\n    [RequestPriority.LOW, []],\n  ]);\n  private running = 0;\n  private requestTimestamps: number[] = [];\n  private readonly maxConcurrent: number;\n  private readonly maxRequestsPerMinute: number;\n  private readonly acquireTimeout: number;\n  /** Maximum time a low-priority request can wait before being promoted (prevents starvation) */\n  private readonly maxStarvationTimeMs: number;\n  /** How often to check for starvation (ms) */\n  private readonly starvationCheckInterval: number = 1000;\n  private starvationTimer: NodeJS.Timeout | null = null;\n  /** Flag to track if instance is destroyed */\n  private isDestroyed = false;\n  /** Lock for queue operations to prevent race conditions */\n  private queueLock = false;\n\n  constructor(options: RateLimiterOptions = {}) {\n    this.maxConcurrent = options.maxConcurrent ?? 5;\n    this.maxRequestsPerMinute = options.maxRequestsPerMinute ?? 60;\n    this.acquireTimeout = options.acquireTimeout ?? 30000;\n    this.maxStarvationTimeMs = options.maxStarvationTimeMs ?? 10000;\n    this.startStarvationPrevention();\n  }\n\n  /**\n   * Destroy the rate limiter and cleanup all resources\n   */\n  destroy(): void {\n    if (this.isDestroyed) {\n      return;\n    }\n    this.isDestroyed = true;\n    this.clear();\n  }\n\n  /**\n   * Start the starvation prevention timer\n   */\n  private startStarvationPrevention(): void {\n    if (this.starvationTimer) return;\n\n    this.starvationTimer = setInterval(() => {\n      this.promoteStarvedRequests();\n    }, this.starvationCheckInterval);\n\n    // Allow process to exit\n    this.starvationTimer.unref();\n  }\n\n  /**\n   * Promote requests that have been waiting too long to prevent starvation\n   */\n  private promoteStarvedRequests(): void {\n    const now = Date.now();\n\n    // Check LOW priority queue for starvation\n    const lowQueue = this.queues.get(RequestPriority.LOW) || [];\n    const normalQueue = this.queues.get(RequestPriority.NORMAL) || [];\n\n    // Promote starved LOW -> NORMAL\n    const starvedFromLow = lowQueue.filter(\n      (req) => now - req.enqueuedAt > this.maxStarvationTimeMs\n    );\n    for (const req of starvedFromLow) {\n      const index = lowQueue.indexOf(req);\n      if (index !== -1) {\n        lowQueue.splice(index, 1);\n        req.priority = RequestPriority.NORMAL;\n        normalQueue.push(req);\n      }\n    }\n\n    // Check NORMAL priority queue for extreme starvation (2x threshold)\n    const highQueue = this.queues.get(RequestPriority.HIGH) || [];\n    const starvedFromNormal = normalQueue.filter(\n      (req) => now - req.enqueuedAt > this.maxStarvationTimeMs * 2\n    );\n    for (const req of starvedFromNormal) {\n      const index = normalQueue.indexOf(req);\n      if (index !== -1) {\n        normalQueue.splice(index, 1);\n        req.priority = RequestPriority.HIGH;\n        highQueue.push(req);\n      }\n    }\n  }\n\n  /**\n   * Get total number of queued requests across all priorities\n   */\n  private getTotalQueued(): number {\n    let total = 0;\n    for (const queue of this.queues.values()) {\n      total += queue.length;\n    }\n    return total;\n  }\n\n  /**\n   * Get the next request from the priority queues (fair scheduling)\n   * Returns requests in priority order: HIGH -> NORMAL -> LOW\n   */\n  private getNextFromQueue(): QueuedRequest | undefined {\n    // Process in priority order\n    for (const priority of [RequestPriority.HIGH, RequestPriority.NORMAL, RequestPriority.LOW]) {\n      const queue = this.queues.get(priority);\n      if (queue && queue.length > 0) {\n        return queue.shift();\n      }\n    }\n    return undefined;\n  }\n\n  /**\n   * Acquire a slot for making an LLM request.\n   * Waits if maximum concurrent requests are in progress or rate limit exceeded.\n   * @param priority - Request priority for fair scheduling (default: NORMAL)\n   * @param caller - Optional identifier for the caller (for debugging)\n   * @throws Error if acquire timeout is exceeded\n   */\n  async acquire(\n    priority: RequestPriority = RequestPriority.NORMAL,\n    caller?: string\n  ): Promise<void> {\n    // Clean up old timestamps (older than 1 minute)\n    const now = Date.now();\n    this.requestTimestamps = this.requestTimestamps.filter((ts) => now - ts < 60000);\n\n    // Check rate limit (requests per minute)\n    if (this.requestTimestamps.length >= this.maxRequestsPerMinute) {\n      const oldestTimestamp = this.requestTimestamps[0];\n      const waitTime = 60000 - (now - oldestTimestamp);\n      if (waitTime > 0) {\n        await new Promise<void>((resolve) => setTimeout(resolve, waitTime));\n        // Re-check after waiting\n        return this.acquire(priority, caller);\n      }\n    }\n\n    // Check concurrent limit\n    if (this.running < this.maxConcurrent) {\n      this.running++;\n      this.requestTimestamps.push(Date.now());\n      return;\n    }\n\n    // Wait in priority queue with proper locking\n    return new Promise<void>((resolve, reject) => {\n      // Check if destroyed\n      if (this.isDestroyed) {\n        reject(new Error('Rate limiter has been destroyed'));\n        return;\n      }\n\n      const request: QueuedRequest = {\n        resolve,\n        reject,\n        timeoutId: null as unknown as NodeJS.Timeout, // Will be set below\n        priority,\n        enqueuedAt: Date.now(),\n        caller,\n      };\n\n      const timeoutId = setTimeout(() => {\n        // Use lock to prevent race condition during removal\n        this.withQueueLock(() => {\n          // Find request in current priority queue (may have been promoted)\n          for (const [, queue] of this.queues) {\n            const index = queue.findIndex((item) => item === request);\n            if (index !== -1) {\n              queue.splice(index, 1);\n              break;\n            }\n          }\n        });\n        reject(\n          new Error(\n            `Rate limiter acquire timeout after ${this.acquireTimeout}ms (priority: ${RequestPriority[priority]}, caller: ${caller || 'unknown'})`\n          )\n        );\n      }, this.acquireTimeout);\n\n      request.timeoutId = timeoutId;\n\n      // Use lock when adding to queue\n      this.withQueueLock(() => {\n        const queue = this.queues.get(priority);\n        if (queue) {\n          queue.push(request);\n        }\n      });\n    });\n  }\n\n  /**\n   * Execute a function with queue lock to prevent race conditions\n   */\n  private withQueueLock<T>(fn: () => T): T {\n    // Simple spinlock for synchronous queue operations\n    // In JS single-threaded environment, this prevents interleaving during async boundaries\n    while (this.queueLock) {\n      // This shouldn't happen in practice due to JS single-threadedness\n      // but provides safety for edge cases\n    }\n    this.queueLock = true;\n    try {\n      return fn();\n    } finally {\n      this.queueLock = false;\n    }\n  }\n\n  /**\n   * Release a slot after completing an LLM request.\n   */\n  release(): void {\n    this.running = Math.max(0, this.running - 1);\n\n    const next = this.getNextFromQueue();\n    if (next) {\n      clearTimeout(next.timeoutId);\n      this.running++;\n      this.requestTimestamps.push(Date.now());\n      next.resolve();\n    }\n  }\n\n  /**\n   * Get current rate limiter status\n   */\n  getStatus(): {\n    running: number;\n    queued: number;\n    queuedByPriority: { high: number; normal: number; low: number };\n    requestsInLastMinute: number;\n  } {\n    const now = Date.now();\n    const recentRequests = this.requestTimestamps.filter((ts) => now - ts < 60000);\n    return {\n      running: this.running,\n      queued: this.getTotalQueued(),\n      queuedByPriority: {\n        high: this.queues.get(RequestPriority.HIGH)?.length || 0,\n        normal: this.queues.get(RequestPriority.NORMAL)?.length || 0,\n        low: this.queues.get(RequestPriority.LOW)?.length || 0,\n      },\n      requestsInLastMinute: recentRequests.length,\n    };\n  }\n\n  /**\n   * Clear all queued requests (useful for cleanup)\n   */\n  clear(): void {\n    for (const queue of this.queues.values()) {\n      for (const item of queue) {\n        clearTimeout(item.timeoutId);\n        item.reject(new Error('Rate limiter cleared'));\n      }\n      queue.length = 0;\n    }\n    this.running = 0;\n    this.requestTimestamps = [];\n    if (this.starvationTimer) {\n      clearInterval(this.starvationTimer);\n      this.starvationTimer = null;\n    }\n  }\n}\n\n// Global rate limiter instance for LLM requests\nlet globalRateLimiter: RateLimiter | null = null;\n\n/**\n * Get the global rate limiter instance.\n * Creates one if it doesn't exist.\n */\nexport function getRateLimiter(options?: RateLimiterOptions): RateLimiter {\n  if (!globalRateLimiter) {\n    globalRateLimiter = new RateLimiter(options);\n  }\n  return globalRateLimiter;\n}\n\n/**\n * Reset the global rate limiter (useful for testing or configuration changes)\n */\nexport function resetRateLimiter(options?: RateLimiterOptions): RateLimiter {\n  if (globalRateLimiter) {\n    globalRateLimiter.clear();\n  }\n  globalRateLimiter = new RateLimiter(options);\n  return globalRateLimiter;\n}\n\nexport class LLM {\n  private providers: Map<string, LLMProvider> = new Map();\n  private logger: Logger;\n\n  constructor(logger?: Logger) {\n    this.logger = logger || getLogger();\n\n    // User-facing info log\n    this.logger.info('LLM service initialized');\n\n    this.logger.debug('LLM service initialized', {\n      providersInitialized: 0,\n      supportedModels: this.getSupportedModels().length,\n    });\n  }\n\n  private initializeProvider(providerName: string): LLMProvider {\n    const existingProvider = this.providers.get(providerName);\n    if (existingProvider) {\n      this.logger.debug('Provider already initialized', { providerName });\n      return existingProvider;\n    }\n\n    // User-facing info log\n    this.logger.info(`Initializing ${providerName} provider`);\n\n    try {\n      let provider: LLMProvider;\n\n      this.logger.debug('Creating provider instance', {\n        providerName,\n        existingProviders: Array.from(this.providers.keys()),\n      });\n\n      switch (providerName) {\n        case 'openai':\n          provider = new OpenAIProvider({ logger: this.logger });\n          break;\n        case 'claude':\n          provider = new ClaudeProvider({ logger: this.logger });\n          break;\n        case 'gemini':\n          provider = new GeminiProvider({ logger: this.logger });\n          break;\n        case 'ollama':\n          provider = new OllamaProvider({ logger: this.logger });\n          break;\n        default:\n          throw new Error(`Unsupported provider: ${providerName}`);\n      }\n\n      this.providers.set(providerName, provider);\n\n      // User-facing success message\n      this.logger.info(`${providerName} provider ready`);\n\n      this.logger.debug('Provider initialized successfully', {\n        providerName,\n        totalProviders: this.providers.size,\n      });\n\n      return provider;\n    } catch (error) {\n      const message = error instanceof Error ? error.message : 'Unknown error';\n\n      // User-facing error message\n      this.logger.error(`Failed to initialize ${providerName} provider`);\n\n      this.logger.debug('Provider initialization failed', {\n        providerName,\n        error: message,\n        hasStack: error instanceof Error && !!error.stack,\n      });\n\n      throw new Error(`Provider ${providerName} initialization failed: ${message}`);\n    }\n  }\n\n  async generateResponse(\n    options: LLMRequestOptions,\n    priority: RequestPriority = RequestPriority.NORMAL,\n    caller?: string\n  ): Promise<LLMResponse> {\n    // User-facing info log\n    this.logger.info(`Generating response with ${options.model}`);\n\n    this.logger.debug('Generating LLM response', {\n      model: options.model,\n      messageCount: options.messages.length,\n      temperature: options.temperature || DEFAULT_LLM_CONFIG.defaultTemperature,\n      maxTokens: options.maxTokens || DEFAULT_LLM_CONFIG.defaultMaxTokens,\n      stream: !!options.stream,\n      hasSystemPrompt: !!options.systemPrompt,\n      priority: RequestPriority[priority],\n      caller: caller ?? null,\n    });\n\n    const provider = this.getProviderForModel(options.model);\n\n    // Use rate limiter to coordinate concurrent requests with fair scheduling\n    const rateLimiter = getRateLimiter();\n    await rateLimiter.acquire(priority, caller || 'LLM.generateResponse');\n\n    let response: LLMResponse;\n    try {\n      response = await provider.generateResponse(options);\n    } finally {\n      rateLimiter.release();\n    }\n\n    // User-facing success message\n    if (response.content.length === 0 && response.toolCalls && response.toolCalls.length > 0) {\n      this.logger.info(\n        `Tools called: ${response.toolCalls.map((tc) => tc.function?.name || 'unnamed').join(', ')}`\n      );\n    } else {\n      this.logger.info(`Response generated (${response.content.length} chars)`);\n    }\n\n    this.logger.debug('LLM response generated', {\n      model: response.model,\n      contentLength: response.content.length,\n      promptTokens: response.usage?.promptTokens || 0,\n      completionTokens: response.usage?.completionTokens || 0,\n      totalTokens: response.usage?.totalTokens || 0,\n      hasToolCalls: !!response.toolCalls?.length,\n    });\n\n    return response;\n  }\n\n  async *generateStreamResponse(\n    options: LLMRequestOptions,\n    priority: RequestPriority = RequestPriority.NORMAL,\n    caller?: string\n  ): AsyncIterableIterator<LLMStreamChunk> {\n    // User-facing info log\n    this.logger.info(`Starting stream response with ${options.model}`);\n\n    this.logger.debug('Generating streaming LLM response', {\n      model: options.model,\n      messageCount: options.messages.length,\n      temperature: options.temperature || DEFAULT_LLM_CONFIG.defaultTemperature,\n      maxTokens: options.maxTokens || DEFAULT_LLM_CONFIG.defaultMaxTokens,\n      hasSystemPrompt: !!options.systemPrompt,\n      priority: RequestPriority[priority],\n      caller: caller ?? null,\n    });\n\n    const provider = this.getProviderForModel(options.model);\n    let chunkCount = 0;\n    let totalContent = '';\n\n    // Use rate limiter to coordinate concurrent requests with fair scheduling\n    const rateLimiter = getRateLimiter();\n    await rateLimiter.acquire(priority, caller || 'LLM.generateStreamResponse');\n\n    try {\n      for await (const chunk of provider.generateStreamResponse(options)) {\n        chunkCount++;\n        totalContent += chunk.content;\n        yield chunk;\n      }\n\n      // User-facing completion message\n      this.logger.info(`Stream completed (${chunkCount} chunks, ${totalContent.length} chars)`);\n\n      this.logger.debug('Streaming response completed', {\n        model: options.model,\n        chunkCount,\n        totalContentLength: totalContent.length,\n      });\n    } catch (error) {\n      // User-facing error message\n      this.logger.error('Stream response failed');\n\n      this.logger.debug('Streaming response failed', {\n        model: options.model,\n        chunkCount,\n        error: error instanceof Error ? error.message : String(error),\n      });\n\n      throw error;\n    } finally {\n      rateLimiter.release();\n    }\n  }\n\n  getSupportedModels(): string[] {\n    const models = getSupportedModelsList();\n\n    this.logger.debug('Retrieved supported models', {\n      modelCount: models.length,\n      models: models.slice(0, 10), // Log first 10 models to avoid clutter\n    });\n\n    return models;\n  }\n\n  getAvailableProviders(): string[] {\n    const providers = Array.from(this.providers.keys());\n\n    this.logger.debug('Retrieved available providers', {\n      providerCount: providers.length,\n      providers,\n    });\n\n    return providers;\n  }\n\n  async generateEmbedding(text: string, model?: string): Promise<{ embedding: number[] }> {\n    const modelToUse = model || DEFAULT_LLM_CONFIG.defaultEmbeddingModel;\n    const provider = this.getProviderForModel(modelToUse);\n\n    if (!provider.generateEmbedding) {\n      throw new Error(`Provider for model ${modelToUse} does not support embedding generation`);\n    }\n\n    // Use rate limiter to coordinate concurrent requests\n    const rateLimiter = getRateLimiter();\n    await rateLimiter.acquire();\n\n    try {\n      const result = await provider.generateEmbedding(text, modelToUse);\n      return { embedding: result.embedding };\n    } finally {\n      rateLimiter.release();\n    }\n  }\n\n  private getProviderForModel(model: string): LLMProvider {\n    this.logger.debug('Looking up provider for model', { model });\n\n    const providerType = getProviderForModel(model);\n\n    if (!providerType) {\n      // User-facing error message\n      this.logger.error(`Unsupported model: ${model}`);\n\n      this.logger.debug('Model not supported', {\n        requestedModel: model,\n        supportedModels: this.getSupportedModels(),\n      });\n\n      throw new Error(\n        `Unsupported model: ${model}. Supported models: ${this.getSupportedModels().join(', ')}`\n      );\n    }\n\n    this.logger.debug('Provider found for model', {\n      model,\n      providerType,\n      isProviderInitialized: this.providers.has(providerType),\n    });\n\n    // Lazy initialize the provider when first needed\n    return this.initializeProvider(providerType);\n  }\n}\n\n// Singleton instances using string ID to avoid memory leak with Logger object keys\ninterface LLMInstanceEntry {\n  instance: LLM;\n  lastAccessTime: number;\n  logger?: Logger;\n}\n\n// Use string ID for Map key instead of Logger object reference to prevent memory leak\nconst llmInstances: Map<string, LLMInstanceEntry> = new Map();\nconst CLEANUP_INTERVAL = 10 * 60 * 1000; // 10 minutes\nconst MAX_INSTANCES = 50; // Prevent unlimited growth\nconst INSTANCE_TTL = 30 * 60 * 1000; // 30 minutes TTL for unused instances\n\n// Counter for generating unique instance IDs\nlet instanceIdCounter = 0;\n\n// WeakMap to track logger -> instanceId mapping (allows GC of logger objects)\nconst loggerToInstanceId: WeakMap<Logger, string> = new WeakMap();\n\n// Cleanup old instances periodically\nlet cleanupTimer: NodeJS.Timeout | null = null;\nlet exitHandlerRegistered = false;\n\n// Mutex promise for timer creation to prevent race conditions\nlet timerCreationMutex: Promise<void> | null = null;\n\n// Store reference to handler for removal\nconst cleanupHandler = (): void => {\n  cleanupResources();\n};\n\nfunction cleanupResources(): void {\n  if (cleanupTimer) {\n    clearInterval(cleanupTimer);\n    cleanupTimer = null;\n  }\n  llmInstances.clear();\n  // Reset mutex when cleaning up\n  timerCreationMutex = null;\n}\n\nfunction startCleanupTimer(): void {\n  // Fast path: timer already exists\n  if (cleanupTimer !== null) {\n    return;\n  }\n\n  // If creation is in progress, don't start another\n  if (timerCreationMutex !== null) {\n    return;\n  }\n\n  // Use mutex to prevent multiple timer creations\n  timerCreationMutex = (async () => {\n    try {\n      // Double-check after acquiring mutex\n      if (cleanupTimer !== null) {\n        return;\n      }\n\n      cleanupTimer = setInterval(() => {\n        const now = Date.now();\n\n        // Remove instances that haven't been accessed within TTL\n        for (const [key, entry] of llmInstances.entries()) {\n          if (now - entry.lastAccessTime > INSTANCE_TTL) {\n            llmInstances.delete(key);\n          }\n        }\n\n        // If still over MAX_INSTANCES, remove oldest entries\n        if (llmInstances.size > MAX_INSTANCES) {\n          const entries = Array.from(llmInstances.entries()).sort(\n            (a, b) => a[1].lastAccessTime - b[1].lastAccessTime\n          );\n          // Remove oldest entries until we're at MAX_INSTANCES/2\n          const toRemove = entries.slice(0, entries.length - Math.floor(MAX_INSTANCES / 2));\n          toRemove.forEach(([key]) => llmInstances.delete(key));\n        }\n\n        // If no instances left, stop the timer to allow process to exit\n        if (llmInstances.size === 0) {\n          if (cleanupTimer) {\n            clearInterval(cleanupTimer);\n            cleanupTimer = null;\n          }\n        }\n      }, CLEANUP_INTERVAL);\n\n      // Prevent the timer from keeping the process alive\n      cleanupTimer.unref();\n\n      // Ensure cleanup on process exit (register only once)\n      if (!exitHandlerRegistered) {\n        exitHandlerRegistered = true;\n        process.once('beforeExit', cleanupHandler);\n      }\n    } finally {\n      // Clear mutex after timer is created\n      timerCreationMutex = null;\n    }\n  })();\n}\n\n// Helper function to get or create instance ID for a logger\nfunction getInstanceId(logger?: Logger): string {\n  if (!logger) {\n    return '__default__';\n  }\n\n  let instanceId = loggerToInstanceId.get(logger);\n  if (!instanceId) {\n    instanceId = `logger_${++instanceIdCounter}`;\n    loggerToInstanceId.set(logger, instanceId);\n  }\n  return instanceId;\n}\n\nexport function getLLM(logger?: Logger): LLM {\n  startCleanupTimer();\n\n  const instanceId = getInstanceId(logger);\n  const existingEntry = llmInstances.get(instanceId);\n  if (existingEntry) {\n    // Update last access time\n    existingEntry.lastAccessTime = Date.now();\n    return existingEntry.instance;\n  }\n\n  const newInstance = new LLM(logger);\n  llmInstances.set(instanceId, {\n    instance: newInstance,\n    lastAccessTime: Date.now(),\n    logger,\n  });\n  return newInstance;\n}\n\n// Manual cleanup function for testing or explicit cleanup\nexport function clearLLMInstances(): void {\n  llmInstances.clear();\n  if (cleanupTimer) {\n    clearInterval(cleanupTimer);\n    cleanupTimer = null;\n  }\n  // Remove the beforeExit handler to prevent memory leaks\n  if (exitHandlerRegistered) {\n    process.removeListener('beforeExit', cleanupHandler);\n    exitHandlerRegistered = false;\n  }\n}\n\nexport async function getLLMProvider(\n  providerName: string,\n  config?: { apiKey?: string; baseUrl?: string | null; logger?: Logger }\n): Promise<LLMProvider> {\n  let provider: LLMProvider;\n\n  switch (providerName) {\n    case 'openai':\n      provider = new OpenAIProvider(config);\n      break;\n    case 'claude':\n      provider = new ClaudeProvider(config);\n      break;\n    case 'gemini':\n      provider = new GeminiProvider(config);\n      break;\n    case 'ollama':\n      provider = new OllamaProvider(config);\n      break;\n    default:\n      throw new Error(`Unsupported provider: ${providerName}`);\n  }\n\n  return provider;\n}\n\n// Export types and utilities\nexport * from './types';\nexport * from './models';\nexport { OpenAIProvider, ClaudeProvider, GeminiProvider, OllamaProvider };\n","/**\n * Default configuration values for memory module\n */\nexport const DEFAULT_MEMORY_CONFIG = {\n  searchLimit: 20,\n  orderBy: 'createdAt',\n  order: 'asc',\n  defaultEmbeddingModel: 'text-embedding-ada-002',\n} as const;\n\n/**\n * Get default value for a memory config property\n */\nexport function getMemoryDefaultValue<K extends keyof typeof DEFAULT_MEMORY_CONFIG>(\n  key: K\n): (typeof DEFAULT_MEMORY_CONFIG)[K] {\n  return DEFAULT_MEMORY_CONFIG[key];\n}\n","import { IAgentModule, IAgent } from '../agent/types';\nimport { Memory as MemoryType, MemorySearchOptions } from './types';\nimport { getDatabase } from '../database';\nimport { MetadataObject } from '../types';\nimport { Logger } from '../logger/types';\nimport { DEFAULT_MEMORY_CONFIG } from './defaults';\nimport { Knex } from 'knex';\nimport { getEncryptionService } from '../database/encryption';\nimport { encryptSensitiveFields, decryptSensitiveFields } from '../database/utils';\nimport { getLLM } from '../llm';\n\n/**\n * Read-Write Lock for managing concurrent access to shared resources.\n * Supports multiple concurrent readers but exclusive writers.\n *\n * Features:\n * - Multiple concurrent readers allowed\n * - Writers have exclusive access (no concurrent readers/writers)\n * - Deadlock prevention via timeouts\n * - Starvation prevention via writer priority aging\n */\nclass ReadWriteLock {\n  private readers = 0;\n  private writer = false;\n  private writerQueue: Array<{ resolve: () => void; enqueuedAt: number }> = [];\n  private readerQueue: Array<{ resolve: () => void; enqueuedAt: number }> = [];\n  private readonly lockTimeout: number;\n  private readonly starvationThreshold: number;\n\n  constructor(lockTimeout: number = 5000, starvationThreshold: number = 3000) {\n    this.lockTimeout = lockTimeout;\n    this.starvationThreshold = starvationThreshold;\n  }\n\n  /**\n   * Acquire a read lock. Multiple readers can hold the lock simultaneously.\n   * @throws Error if lock acquisition times out (deadlock prevention)\n   */\n  async acquireRead(): Promise<void> {\n    const startTime = Date.now();\n\n    // If there's a writer or waiting writers (to prevent writer starvation), wait\n    while (this.writer || this.hasStarvedWriters()) {\n      if (Date.now() - startTime > this.lockTimeout) {\n        throw new Error(\n          `Read lock acquisition timeout after ${this.lockTimeout}ms (deadlock prevention)`\n        );\n      }\n\n      // Create queue entry with cleanup capability\n      let queueEntry: { resolve: () => void; enqueuedAt: number } | null = null;\n\n      await new Promise<void>((resolve, reject) => {\n        queueEntry = { resolve, enqueuedAt: Date.now() };\n        this.readerQueue.push(queueEntry);\n\n        // Set up timeout cleanup to remove from queue if timeout occurs\n        const timeoutId = setTimeout(\n          () => {\n            if (queueEntry) {\n              const index = this.readerQueue.indexOf(queueEntry);\n              if (index !== -1) {\n                this.readerQueue.splice(index, 1);\n              }\n            }\n            reject(\n              new Error(\n                `Read lock acquisition timeout after ${this.lockTimeout}ms (deadlock prevention)`\n              )\n            );\n          },\n          this.lockTimeout - (Date.now() - startTime)\n        );\n\n        // Override resolve to clear timeout\n        const originalResolve = resolve;\n        queueEntry.resolve = () => {\n          clearTimeout(timeoutId);\n          originalResolve();\n        };\n      });\n    }\n\n    this.readers++;\n  }\n\n  /**\n   * Release a read lock.\n   */\n  releaseRead(): void {\n    this.readers = Math.max(0, this.readers - 1);\n\n    // If no more readers, wake up waiting writers\n    if (this.readers === 0 && this.writerQueue.length > 0) {\n      const next = this.writerQueue.shift();\n      if (next) {\n        next.resolve();\n      }\n    }\n  }\n\n  /**\n   * Acquire a write lock. Only one writer can hold the lock.\n   * @throws Error if lock acquisition times out (deadlock prevention)\n   */\n  async acquireWrite(): Promise<void> {\n    const startTime = Date.now();\n\n    // Wait for all readers and current writer to finish\n    while (this.readers > 0 || this.writer) {\n      if (Date.now() - startTime > this.lockTimeout) {\n        throw new Error(\n          `Write lock acquisition timeout after ${this.lockTimeout}ms (deadlock prevention)`\n        );\n      }\n\n      // Create queue entry with cleanup capability\n      let queueEntry: { resolve: () => void; enqueuedAt: number } | null = null;\n\n      await new Promise<void>((resolve, reject) => {\n        queueEntry = { resolve, enqueuedAt: Date.now() };\n        this.writerQueue.push(queueEntry);\n\n        // Set up timeout cleanup to remove from queue if timeout occurs\n        const timeoutId = setTimeout(\n          () => {\n            if (queueEntry) {\n              const index = this.writerQueue.indexOf(queueEntry);\n              if (index !== -1) {\n                this.writerQueue.splice(index, 1);\n              }\n            }\n            reject(\n              new Error(\n                `Write lock acquisition timeout after ${this.lockTimeout}ms (deadlock prevention)`\n              )\n            );\n          },\n          this.lockTimeout - (Date.now() - startTime)\n        );\n\n        // Override resolve to clear timeout\n        const originalResolve = resolve;\n        queueEntry.resolve = () => {\n          clearTimeout(timeoutId);\n          originalResolve();\n        };\n      });\n    }\n\n    this.writer = true;\n  }\n\n  /**\n   * Release a write lock.\n   * Uses writer priority to prevent writer starvation:\n   * - If writers are waiting, wake up the next writer first\n   * - Only wake up readers if no writers are waiting\n   */\n  releaseWrite(): void {\n    this.writer = false;\n\n    // Writer priority: Check waiting writers first to prevent starvation\n    if (this.writerQueue.length > 0) {\n      const next = this.writerQueue.shift();\n      if (next) {\n        next.resolve();\n        return; // Don't wake up readers when a writer is taking over\n      }\n    }\n\n    // No waiting writers, wake up all waiting readers (they can proceed in parallel)\n    while (this.readerQueue.length > 0) {\n      const next = this.readerQueue.shift();\n      if (next) {\n        next.resolve();\n      }\n    }\n  }\n\n  /**\n   * Check if there are writers that have been waiting too long (starvation prevention)\n   */\n  private hasStarvedWriters(): boolean {\n    if (this.writerQueue.length === 0) return false;\n    const now = Date.now();\n    return this.writerQueue.some((w) => now - w.enqueuedAt > this.starvationThreshold);\n  }\n\n  /**\n   * Get current lock status\n   */\n  getStatus(): {\n    readers: number;\n    hasWriter: boolean;\n    pendingWriters: number;\n    pendingReaders: number;\n  } {\n    return {\n      readers: this.readers,\n      hasWriter: this.writer,\n      pendingWriters: this.writerQueue.length,\n      pendingReaders: this.readerQueue.length,\n    };\n  }\n}\n\n/**\n * Simple async mutex for protecting initialization.\n * Replaces spin-wait anti-pattern with proper promise-based waiting.\n * Includes deadlock prevention via timeouts.\n */\nclass AsyncMutex {\n  private locked = false;\n  private queue: Array<{ resolve: () => void; reject: (err: Error) => void }> = [];\n  private readonly lockTimeout: number;\n\n  constructor(lockTimeout: number = 10000) {\n    this.lockTimeout = lockTimeout;\n  }\n\n  /**\n   * Acquire the mutex with timeout for deadlock prevention\n   * @throws Error if lock acquisition times out\n   */\n  async acquire(): Promise<void> {\n    if (!this.locked) {\n      this.locked = true;\n      return;\n    }\n\n    return new Promise<void>((resolve, reject) => {\n      const timeoutId = setTimeout(() => {\n        const index = this.queue.findIndex((item) => item.resolve === resolve);\n        if (index !== -1) {\n          this.queue.splice(index, 1);\n        }\n        reject(\n          new Error(`Mutex acquisition timeout after ${this.lockTimeout}ms (deadlock prevention)`)\n        );\n      }, this.lockTimeout);\n\n      this.queue.push({\n        resolve: () => {\n          clearTimeout(timeoutId);\n          resolve();\n        },\n        reject,\n      });\n    });\n  }\n\n  release(): void {\n    const next = this.queue.shift();\n    if (next) {\n      next.resolve();\n    } else {\n      this.locked = false;\n    }\n  }\n}\n\ninterface MemoryDbRow {\n  id: string; // UUID\n  agentId: string; // UUID\n  graphId?: string; // UUID - Graph relationship\n  taskId?: string; // UUID - Task relationship\n  sessionId?: string; // Session ID\n  content: string;\n  embedding: string | null;\n  metadata: string | null;\n  created_at: string;\n  updated_at: string;\n}\n\n/**\n * Callback type for memory change events\n */\nexport type MemoryChangeCallback = (\n  event: 'update' | 'delete' | 'clear',\n  data: { memoryId?: string; content?: string; metadata?: MetadataObject }\n) => void | Promise<void>;\n\n/**\n * Memory module for agent conversation memory\n *\n * Features:\n * - Read-write locking for concurrent access\n * - Deadlock prevention via lock timeouts\n * - Starvation prevention for write operations\n */\nexport class Memory implements IAgentModule {\n  readonly name = 'memory';\n  private knex: Knex | null = null;\n  private logger: Logger;\n  private _encryption?: ReturnType<typeof getEncryptionService>;\n  private static readonly MAX_MEMORIES_FETCH = 10000; // Bounds limit for unbounded fetches\n\n  // AsyncMutex pattern for race condition prevention (replaces spin-wait)\n  private static initMutex = new AsyncMutex();\n  private static initPromise: Promise<void> | null = null;\n\n  // Read-write lock for concurrent memory access\n  // Allows multiple concurrent reads but exclusive writes\n  private rwLock = new ReadWriteLock(5000, 3000);\n\n  // Callback for memory change events (used by Agent to sync with Context)\n  private onChangeCallback: MemoryChangeCallback | null = null;\n\n  private get encryption() {\n    if (!this._encryption) {\n      this._encryption = getEncryptionService();\n    }\n    return this._encryption;\n  }\n\n  constructor(private agent: IAgent) {\n    this.logger = agent.logger;\n  }\n\n  /**\n   * Register a callback for memory change events\n   * This allows the Agent to synchronize Context when memories are updated/deleted\n   */\n  onMemoryChange(callback: MemoryChangeCallback): void {\n    this.onChangeCallback = callback;\n  }\n\n  /**\n   * Notify registered callback about memory changes\n   */\n  private async notifyChange(\n    event: 'update' | 'delete' | 'clear',\n    data: { memoryId?: string; content?: string; metadata?: MetadataObject }\n  ): Promise<void> {\n    if (this.onChangeCallback) {\n      try {\n        await this.onChangeCallback(event, data);\n      } catch (error) {\n        this.logger.warn('Memory change callback failed', {\n          event,\n          error: error instanceof Error ? error.message : String(error),\n        });\n      }\n    }\n  }\n\n  async initialize(): Promise<void> {\n    await this.ensureDatabase();\n  }\n\n  private async ensureDatabase(): Promise<void> {\n    if (this.knex) return;\n\n    // Check if another instance is already initializing\n    if (Memory.initPromise) {\n      await Memory.initPromise;\n      // After waiting, get the knex instance from the initialized database\n      const db = await getDatabase();\n      this.knex = db.getKnex();\n      return;\n    }\n\n    // Use AsyncMutex instead of spin-wait for proper synchronization\n    await Memory.initMutex.acquire();\n    let lockReleased = false;\n    try {\n      // Double-check after acquiring lock\n      if (this.knex) return;\n\n      // Check again if initialization started while waiting for lock\n      if (Memory.initPromise) {\n        // Release lock before awaiting to prevent deadlock\n        Memory.initMutex.release();\n        lockReleased = true;\n        await Memory.initPromise;\n        const db = await getDatabase();\n        this.knex = db.getKnex();\n        return;\n      }\n\n      // Start initialization\n      Memory.initPromise = this.doInitialize();\n      try {\n        await Memory.initPromise;\n      } finally {\n        Memory.initPromise = null;\n      }\n    } finally {\n      // Only release if not already released\n      if (!lockReleased) {\n        Memory.initMutex.release();\n      }\n    }\n  }\n\n  private async doInitialize(): Promise<void> {\n    const db = await getDatabase();\n    this.knex = db.getKnex();\n  }\n\n  /**\n   * Generate embedding for memory content\n   */\n  private async generateEmbedding(content: string): Promise<number[] | null> {\n    try {\n      // Import knowledge system to access embedding generation\n\n      // Check if agent has knowledge/embedding capabilities\n      if (!this.agent || typeof this.agent.config.embeddingModel !== 'string') {\n        this.logger.debug('No embedding model configured for agent, skipping embedding generation');\n        return null;\n      }\n\n      // Get embedding provider from knowledge system\n      // This is a bit indirect but reuses existing embedding infrastructure\n      const embeddingProvider = {\n        name: this.agent.config.embeddingModel || DEFAULT_MEMORY_CONFIG.defaultEmbeddingModel,\n        generateEmbedding: async (text: string) => {\n          // Import and use the same embedding logic as knowledge system\n          const llm = getLLM(this.logger);\n          const result = await llm.generateEmbedding(text, this.agent.config.embeddingModel);\n          return result;\n        },\n      };\n\n      const result = await embeddingProvider.generateEmbedding(content);\n      return result.embedding;\n    } catch (error) {\n      this.logger.debug('Failed to generate embedding for memory', {\n        error: error instanceof Error ? error.message : String(error),\n        contentLength: content.length,\n      });\n      return null;\n    }\n  }\n\n  /**\n   * Add a memory\n   */\n  async addMemory(\n    content: string,\n    metadata?: MetadataObject,\n    context?: { graphId?: string; taskId?: string; sessionId?: string }\n  ): Promise<MemoryType> {\n    // User-facing info log\n    const memoryType = metadata?.type || 'general';\n    this.logger.info(`Adding new ${memoryType} memory`);\n\n    this.logger.debug('Adding memory', {\n      contentLength: content.length,\n      agentId: this.agent.id,\n      graphId: context?.graphId || 'none',\n      taskId: context?.taskId || 'none',\n      sessionId: context?.sessionId || 'none',\n      contentPreview: content.slice(0, 100) + '...',\n      type: metadata?.type ? String(metadata.type) : 'general',\n      hasMetadata: !!metadata,\n    });\n\n    await this.ensureDatabase();\n    const tableName = 'memories';\n\n    // Generate embedding for content (before encryption)\n    const embedding = await this.generateEmbedding(content);\n\n    // Prepare data for encryption\n    const insertData = {\n      id: crypto.randomUUID(), // Generate UUID for memory\n      agentId: this.agent.id,\n      graphId: context?.graphId || null, // Graph relationship\n      taskId: context?.taskId || null, // Task relationship\n      sessionId: context?.sessionId || null, // Session ID\n      content,\n      embedding: embedding ? JSON.stringify(embedding) : null,\n      metadata: metadata ? JSON.stringify(metadata) : null,\n    };\n\n    if (!this.knex) {\n      throw new Error('Database not initialized');\n    }\n\n    // Acquire write lock for exclusive access during insert\n    await this.rwLock.acquireWrite();\n    try {\n      // Encrypt sensitive fields using centralized encryption (embedding stays unencrypted for search)\n      const encryptedData = await encryptSensitiveFields(insertData, 'memories');\n\n      // Use transaction for atomicity - ensures data consistency\n      const memory = await this.knex.transaction(async (trx) => {\n        const [inserted] = await trx(tableName).insert(encryptedData).returning('*');\n        return inserted;\n      });\n\n      // Decrypt for response using centralized decryption\n      const decryptedMemory = await decryptSensitiveFields(\n        memory as Record<string, string | number | boolean | null>,\n        'memories'\n      );\n      const formattedMemory = this.formatMemory(decryptedMemory as unknown as MemoryDbRow);\n\n      this.logger.debug('Memory added successfully', {\n        memoryId: formattedMemory.id || 0,\n        type: String(memoryType),\n      });\n\n      return formattedMemory;\n    } finally {\n      this.rwLock.releaseWrite();\n    }\n  }\n\n  /**\n   * Remember a conversation (alias for add with conversation metadata)\n   */\n  async rememberConversation(\n    content: string,\n    role: 'user' | 'assistant' = 'user'\n  ): Promise<MemoryType> {\n    return this.addMemory(content, { type: 'conversation', role });\n  }\n\n  /**\n   * Get a memory by ID\n   */\n  async getMemory(id: string): Promise<MemoryType | null> {\n    await this.ensureDatabase();\n    const tableName = 'memories';\n\n    if (!this.knex) {\n      throw new Error('Database not initialized');\n    }\n\n    // Acquire read lock for concurrent read access\n    await this.rwLock.acquireRead();\n    try {\n      const memory = await this.knex(tableName).where({ id, agentId: this.agent.id }).first();\n\n      if (!memory) return null;\n\n      // Decrypt sensitive fields using centralized decryption\n      const decryptedMemory = await decryptSensitiveFields(\n        memory as Record<string, string | number | boolean | null>,\n        'memories'\n      );\n      return this.formatMemory(decryptedMemory as unknown as MemoryDbRow);\n    } finally {\n      this.rwLock.releaseRead();\n    }\n  }\n\n  /**\n   * Search memories\n   */\n  async searchMemories(query: string, options?: MemorySearchOptions): Promise<MemoryType[]> {\n    // Check if we should use embedding search\n    if (options?.useEmbedding !== false) {\n      // Try embedding search first, fallback to text search if needed\n      try {\n        return await this.searchMemoriesBySimilarity(query, options);\n      } catch (error) {\n        this.logger.warn('Embedding search failed, falling back to text search', {\n          error: error instanceof Error ? error.message : String(error),\n        });\n      }\n    }\n\n    // User-facing info log\n    this.logger.info(`Searching memories for: \"${query}\"`);\n\n    this.logger.debug('Searching memories', {\n      query,\n      ...(options?.limit && { limit: options.limit }),\n      ...(options?.startDate && { startDate: options.startDate }),\n      ...(options?.endDate && { endDate: options.endDate }),\n      agentId: this.agent.id,\n    });\n\n    await this.ensureDatabase();\n    const tableName = 'memories';\n\n    if (!this.knex) {\n      throw new Error('Database not initialized');\n    }\n\n    const limit = options?.limit ?? 10;\n    const offset = options?.offset ?? 0;\n\n    let dbQuery = this.knex(tableName)\n      .where({ agentId: this.agent.id })\n      .orderBy('created_at', 'desc')\n      .limit(limit)\n      .offset(offset);\n\n    // Apply graphId/taskId/sessionId filters for memory isolation\n    if (options?.graphId !== undefined) {\n      dbQuery = dbQuery.andWhere({ graphId: options.graphId });\n    }\n\n    if (options?.taskId !== undefined) {\n      dbQuery = dbQuery.andWhere({ taskId: options.taskId });\n    }\n\n    if (options?.sessionId !== undefined) {\n      dbQuery = dbQuery.andWhere({ sessionId: options.sessionId });\n    }\n\n    // When encryption is enabled, we can't search encrypted content directly in SQL\n    // We need to retrieve all memories and search after decryption\n    if (this.encryption.isEnabled()) {\n      // Remove the SQL LIKE search and do it in memory after decryption\n      if (options?.startDate) {\n        dbQuery = dbQuery.where('created_at', '>=', options.startDate);\n      }\n\n      if (options?.endDate) {\n        dbQuery = dbQuery.where('created_at', '<=', options.endDate);\n      }\n\n      // Get all memories for this agent (with date filters if applicable)\n      // Apply bounds limit to prevent unbounded memory growth\n      const allMemories = await dbQuery.limit(Memory.MAX_MEMORIES_FETCH);\n\n      // Decrypt and search in memory\n      const matchingMemories: Record<\n        string,\n        string | number | boolean | Date | null | undefined\n      >[] = [];\n      for (const memory of allMemories) {\n        try {\n          const decryptedMemory = await decryptSensitiveFields(memory, 'memories');\n          if (\n            decryptedMemory.content &&\n            typeof decryptedMemory.content === 'string' &&\n            decryptedMemory.content.toLowerCase().includes(query.toLowerCase())\n          ) {\n            matchingMemories.push(decryptedMemory);\n            if (matchingMemories.length >= limit) break;\n          }\n        } catch {\n          // Handle unencrypted data gracefully - skip on decryption failure\n          this.logger.warn('Failed to decrypt memory during search, skipping', {\n            memoryId: memory.id,\n          });\n        }\n      }\n\n      // User-facing result summary\n      this.logger.info(\n        `Found ${matchingMemories.length} matching ${matchingMemories.length === 1 ? 'memory' : 'memories'}`\n      );\n\n      this.logger.debug(`Found ${matchingMemories.length} memories`, {\n        resultCount: matchingMemories.length,\n        sampleIds: matchingMemories.slice(0, 3).map((m) => Number(m.id)),\n        hasResults: matchingMemories.length > 0,\n      });\n\n      return matchingMemories.map((memory) => this.formatMemory(memory as unknown as MemoryDbRow));\n    } else {\n      // Encryption not enabled, use traditional SQL search\n      // Escape special SQL LIKE characters to prevent injection\n      const escapedQuery = query.replace(/[%_\\\\]/g, '\\\\$&');\n      dbQuery = dbQuery.where('content', 'like', `%${escapedQuery}%`);\n\n      if (options?.startDate) {\n        dbQuery = dbQuery.where('created_at', '>=', options.startDate);\n      }\n\n      if (options?.endDate) {\n        dbQuery = dbQuery.where('created_at', '<=', options.endDate);\n      }\n\n      const memories = await dbQuery;\n\n      // User-facing result summary\n      this.logger.info(\n        `Found ${memories.length} matching ${memories.length === 1 ? 'memory' : 'memories'}`\n      );\n\n      this.logger.debug(`Found ${memories.length} memories`, {\n        resultCount: memories.length,\n        sampleIds: memories.slice(0, 3).map((m) => Number(m.id)),\n        hasResults: memories.length > 0,\n      });\n\n      return memories.map((memory) => this.formatMemory(memory));\n    }\n  }\n\n  /**\n   * List memories\n   */\n  async listMemories(options?: MemorySearchOptions): Promise<MemoryType[]> {\n    // User-facing info log\n    this.logger.info('Listing memories');\n\n    this.logger.debug('Listing memories', {\n      ...(options?.limit && { limit: options.limit }),\n      ...(options?.graphId && { graphId: options.graphId }),\n      ...(options?.taskId && { taskId: options.taskId }),\n      ...(options?.sessionId && { sessionId: options.sessionId }),\n      ...(options?.orderBy && { orderBy: options.orderBy }),\n      ...(options?.startDate && { startDate: options.startDate }),\n      ...(options?.endDate && { endDate: options.endDate }),\n      agentId: this.agent.id,\n    });\n\n    await this.ensureDatabase();\n    const tableName = 'memories';\n\n    if (!this.knex) {\n      throw new Error('Database not initialized');\n    }\n\n    const limit = options?.limit ?? 100;\n    const offset = options?.offset ?? 0;\n\n    // Respect orderBy and order options, default to created_at desc\n    // Map TypeScript property names to database column names\n    let orderColumn = 'created_at';\n    if (options?.orderBy === 'createdAt') {\n      orderColumn = 'created_at';\n    } else if (options?.orderBy === 'updatedAt') {\n      orderColumn = 'updated_at';\n    }\n    const orderDirection = options?.order === 'asc' ? 'asc' : 'desc';\n\n    let query = this.knex(tableName)\n      .where({ agentId: this.agent.id })\n      .orderBy(orderColumn, orderDirection)\n      .limit(limit)\n      .offset(offset);\n\n    if (options?.graphId !== undefined) {\n      query = query.andWhere({ graphId: options.graphId });\n    }\n\n    if (options?.taskId !== undefined) {\n      query = query.andWhere({ taskId: options.taskId });\n    }\n\n    if (options?.sessionId !== undefined) {\n      query = query.andWhere({ sessionId: options.sessionId });\n    }\n\n    if (options?.startDate) {\n      query = query.where('created_at', '>=', options.startDate);\n    }\n\n    if (options?.endDate) {\n      query = query.where('created_at', '<=', options.endDate);\n    }\n\n    const memories = await query;\n\n    // Decrypt memories if encryption is enabled\n    if (this.encryption.isEnabled()) {\n      const decryptedMemories = await Promise.all(\n        memories.map(async (memory) => {\n          try {\n            const decrypted = await decryptSensitiveFields(\n              memory as Record<string, string | number | boolean | null>,\n              'memories'\n            );\n            return this.formatMemory(decrypted as unknown as MemoryDbRow);\n          } catch {\n            // Handle unencrypted data gracefully\n            this.logger.warn('Failed to decrypt memory during list, returning raw data', {\n              memoryId: memory.id,\n            });\n            return this.formatMemory(memory);\n          }\n        })\n      );\n      return decryptedMemories;\n    } else {\n      return memories.map((memory) => this.formatMemory(memory));\n    }\n  }\n\n  /**\n   * Update a memory\n   */\n  async updateMemory(\n    id: string,\n    updates: { content?: string; metadata?: MetadataObject }\n  ): Promise<MemoryType | null> {\n    await this.ensureDatabase();\n    const tableName = 'memories';\n\n    const updateData: Partial<MemoryDbRow> = {};\n\n    // If content is being updated, regenerate embedding\n    if (updates.content !== undefined) {\n      updateData.content = updates.content;\n      // Generate new embedding for updated content\n      const embedding = await this.generateEmbedding(updates.content);\n      updateData.embedding = embedding ? JSON.stringify(embedding) : null;\n    }\n\n    if (updates.metadata !== undefined) {\n      updateData.metadata = JSON.stringify(updates.metadata);\n    }\n\n    if (Object.keys(updateData).length === 0) {\n      return this.getMemory(id);\n    }\n\n    if (!this.knex) {\n      throw new Error('Database not initialized');\n    }\n\n    // Acquire write lock for exclusive access during update\n    await this.rwLock.acquireWrite();\n    try {\n      // Encrypt sensitive fields using centralized encryption (embedding stays unencrypted)\n      const encryptedUpdateData = await encryptSensitiveFields(updateData, 'memories');\n\n      const [memory] = await this.knex(tableName)\n        .where({ id, agentId: this.agent.id })\n        .update(encryptedUpdateData)\n        .returning('*');\n\n      if (!memory) return null;\n\n      // Decrypt for response using centralized decryption\n      const decryptedMemory = await decryptSensitiveFields(\n        memory as Record<string, string | number | boolean | null>,\n        'memories'\n      );\n      const formattedMemory = this.formatMemory(decryptedMemory as unknown as MemoryDbRow);\n\n      // Notify listeners about the update (for Context synchronization)\n      await this.notifyChange('update', {\n        memoryId: id,\n        content: formattedMemory.content,\n        metadata: formattedMemory.metadata,\n      });\n\n      return formattedMemory;\n    } finally {\n      this.rwLock.releaseWrite();\n    }\n  }\n\n  /**\n   * Delete a memory\n   */\n  async deleteMemory(id: string): Promise<boolean> {\n    this.logger.info(`Deleting memory: ${id}`);\n\n    await this.ensureDatabase();\n    const tableName = 'memories';\n\n    if (!this.knex) {\n      throw new Error('Database not initialized');\n    }\n\n    // Acquire write lock for exclusive access during delete\n    await this.rwLock.acquireWrite();\n    try {\n      const deleted = await this.knex(tableName).where({ id, agentId: this.agent.id }).delete();\n\n      const success = deleted > 0;\n\n      if (success) {\n        this.logger.info(`Memory ${id} deleted successfully`);\n\n        // Notify listeners about the deletion (for Context synchronization)\n        await this.notifyChange('delete', { memoryId: id });\n      } else {\n        this.logger.warn(`Failed to delete memory ${id} - not found or unauthorized`);\n      }\n\n      this.logger.debug('Delete memory result', {\n        memoryId: id,\n        success,\n        agentId: this.agent.id,\n      });\n\n      return success;\n    } finally {\n      this.rwLock.releaseWrite();\n    }\n  }\n\n  /**\n   * Search memories using vector similarity with pagination to prevent memory leaks\n   */\n  async searchMemoriesBySimilarity(\n    query: string,\n    options?: MemorySearchOptions\n  ): Promise<MemoryType[]> {\n    // User-facing info log\n    this.logger.info(`Searching memories by similarity for: \"${query}\"`);\n\n    this.logger.debug('Vector similarity search for memories', {\n      query,\n      threshold: options?.similarityThreshold || 0.7,\n      limit: options?.limit || 10,\n      agentId: this.agent.id,\n    });\n\n    await this.ensureDatabase();\n    const tableName = 'memories';\n\n    if (!this.knex) {\n      throw new Error('Database not initialized');\n    }\n\n    // Generate embedding for search query\n    const queryEmbedding = await this.generateEmbedding(query);\n\n    if (!queryEmbedding) {\n      this.logger.warn('Could not generate embedding for query, falling back to text search');\n      return this.searchMemories(query, { ...options, useEmbedding: false });\n    }\n\n    const limit = options?.limit ?? 10;\n    const threshold = options?.similarityThreshold ?? 0.7;\n    const pageSize = options?.pageSize || 100;\n\n    // For SQLite: Calculate similarity in memory with pagination (prevents memory leak)\n    // For PostgreSQL: Use pgvector for efficient similarity search\n    const memoriesWithSimilarity: Array<{\n      memory: MemoryDbRow;\n      similarity: number;\n    }> = [];\n    let offset = 0;\n    let hasMore = true;\n\n    // Paginated fetch to prevent loading all memories into memory at once\n    while (hasMore && memoriesWithSimilarity.length < limit * 10) {\n      const batch = await this.knex(tableName)\n        .where({ agentId: this.agent.id })\n        .whereNotNull('embedding')\n        .orderBy('created_at', 'desc')\n        .limit(pageSize)\n        .offset(offset);\n\n      if (batch.length < pageSize) {\n        hasMore = false;\n      }\n\n      // Process batch and calculate similarities\n      for (const memory of batch) {\n        if (!memory.embedding) continue;\n\n        try {\n          const memoryEmbedding = JSON.parse(memory.embedding);\n          const similarity = this.cosineSimilarity(queryEmbedding, memoryEmbedding);\n\n          if (similarity >= threshold) {\n            memoriesWithSimilarity.push({ memory, similarity });\n          }\n        } catch {\n          this.logger.debug('Failed to parse embedding for memory', { memoryId: memory.id });\n        }\n      }\n\n      offset += pageSize;\n\n      // Early exit if we have enough high-similarity results\n      if (memoriesWithSimilarity.length >= limit * 2) {\n        break;\n      }\n    }\n\n    // Sort by similarity and take top results\n    const topResults = memoriesWithSimilarity\n      .sort((a, b) => b.similarity - a.similarity)\n      .slice(0, limit);\n\n    // Decrypt and format results\n    const decryptedMemories = await Promise.all(\n      topResults.map(async ({ memory }) => {\n        try {\n          const decrypted = await decryptSensitiveFields(\n            memory as unknown as Record<string, string | number | boolean | null>,\n            'memories'\n          );\n          return this.formatMemory(decrypted as unknown as MemoryDbRow);\n        } catch {\n          this.logger.debug('Failed to decrypt memory during similarity search', {\n            memoryId: memory.id,\n          });\n          return this.formatMemory(memory);\n        }\n      })\n    );\n\n    // User-facing result summary\n    this.logger.info(\n      `Found ${decryptedMemories.length} similar ${decryptedMemories.length === 1 ? 'memory' : 'memories'}`\n    );\n\n    this.logger.debug(`Vector similarity search completed`, {\n      resultCount: decryptedMemories.length,\n      sampleIds: decryptedMemories.slice(0, 3).map((m) => Number(m.id)),\n      hasResults: decryptedMemories.length > 0,\n    });\n\n    return decryptedMemories;\n  }\n\n  /**\n   * Calculate cosine similarity between two vectors\n   * @throws Error if embedding dimensions do not match\n   */\n  private cosineSimilarity(a: number[], b: number[]): number {\n    if (a.length !== b.length) {\n      throw new Error(`Embedding dimension mismatch: ${a.length} vs ${b.length}`);\n    }\n\n    let dotProduct = 0;\n    let normA = 0;\n    let normB = 0;\n\n    for (let i = 0; i < a.length; i++) {\n      dotProduct += a[i] * b[i];\n      normA += a[i] * a[i];\n      normB += b[i] * b[i];\n    }\n\n    if (normA === 0 || normB === 0) {\n      return 0;\n    }\n\n    return dotProduct / (Math.sqrt(normA) * Math.sqrt(normB));\n  }\n\n  /**\n   * Generate embedding for a specific memory\n   */\n  async generateEmbeddingForMemory(memoryId: string): Promise<{\n    success: boolean;\n    message: string;\n    embedding?: number[];\n  }> {\n    this.logger.info(`Generating embedding for memory: ${memoryId}`);\n\n    await this.ensureDatabase();\n    const tableName = 'memories';\n\n    if (!this.knex) {\n      throw new Error('Database not initialized');\n    }\n\n    // Get memory by ID\n    const memory = await this.knex(tableName)\n      .where({ id: memoryId, agentId: this.agent.id })\n      .first();\n\n    if (!memory) {\n      this.logger.debug('Memory not found for embedding generation', {\n        memoryId,\n        agentId: this.agent.id,\n      });\n      return {\n        success: false,\n        message: 'Memory not found',\n      };\n    }\n\n    // Check if memory already has embedding\n    if (memory.embedding) {\n      this.logger.debug('Memory already has embedding', { memoryId });\n      return {\n        success: false,\n        message: 'Memory already has embedding',\n      };\n    }\n\n    // Decrypt content for embedding generation using centralized decryption\n    let content: string;\n    try {\n      const decryptedMemory = await decryptSensitiveFields(\n        memory as Record<string, string | number | boolean | null>,\n        'memories'\n      );\n      content = String(decryptedMemory.content);\n    } catch (error) {\n      this.logger.debug('Failed to decrypt memory content', {\n        memoryId,\n        error: error instanceof Error ? error.message : String(error),\n      });\n      return {\n        success: false,\n        message: 'Failed to decrypt memory content',\n      };\n    }\n\n    // Generate embedding for the content\n    const embedding = await this.generateEmbedding(content);\n\n    if (!embedding) {\n      this.logger.debug('Failed to generate embedding', {\n        memoryId,\n        contentLength: content.length,\n      });\n      return {\n        success: false,\n        message: 'Failed to generate embedding',\n      };\n    }\n\n    // Update memory with embedding\n    try {\n      await this.knex(tableName)\n        .where({ id: memoryId, agentId: this.agent.id })\n        .update({ embedding: JSON.stringify(embedding) });\n\n      this.logger.info(`Embedding generated successfully for memory: ${memoryId}`);\n\n      this.logger.debug('Embedding generation completed', {\n        memoryId,\n        embeddingDimensions: embedding.length,\n        contentLength: content.length,\n      });\n\n      return {\n        success: true,\n        message: 'Embedding generated successfully',\n        embedding,\n      };\n    } catch (error) {\n      this.logger.debug('Failed to update memory with embedding', {\n        memoryId,\n        error: error instanceof Error ? error.message : String(error),\n      });\n      return {\n        success: false,\n        message: 'Failed to store embedding',\n      };\n    }\n  }\n\n  /**\n   * Clear all memories\n   * @param options - Optional settings for clearing memories\n   * @param options.syncWithContext - If true (default), notifies Context to also clear. Set to false to clear only Memory.\n   */\n  async clearMemories(options?: { syncWithContext?: boolean }): Promise<number> {\n    this.logger.info('Clearing all memories');\n\n    await this.ensureDatabase();\n    const tableName = 'memories';\n\n    if (!this.knex) {\n      throw new Error('Database not initialized');\n    }\n\n    // Acquire write lock for exclusive access during bulk delete\n    await this.rwLock.acquireWrite();\n    try {\n      const deletedCount = await this.knex(tableName).where({ agentId: this.agent.id }).delete();\n\n      this.logger.info(`Cleared ${deletedCount} ${deletedCount === 1 ? 'memory' : 'memories'}`);\n\n      this.logger.debug('Clear memories result', {\n        deletedCount,\n        agentId: this.agent.id,\n        syncWithContext: options?.syncWithContext !== false,\n      });\n\n      // Notify listeners about the clear operation (for Context synchronization)\n      // Default: sync with context. Set syncWithContext: false to skip.\n      if (deletedCount > 0 && options?.syncWithContext !== false) {\n        await this.notifyChange('clear', {});\n      }\n\n      return deletedCount;\n    } finally {\n      this.rwLock.releaseWrite();\n    }\n  }\n\n  /**\n   * Format memory from database\n   */\n  private formatMemory(memory: MemoryDbRow): MemoryType {\n    let parsedEmbedding: number[] | undefined;\n    let parsedMetadata: MetadataObject | undefined;\n\n    // Parse embedding with error handling\n    if (memory.embedding) {\n      try {\n        parsedEmbedding =\n          typeof memory.embedding === 'string' ? JSON.parse(memory.embedding) : memory.embedding;\n      } catch {\n        this.logger.debug('Failed to parse embedding JSON', { memoryId: memory.id });\n        parsedEmbedding = undefined;\n      }\n    }\n\n    // Parse metadata with error handling\n    if (memory.metadata) {\n      try {\n        parsedMetadata =\n          typeof memory.metadata === 'string' ? JSON.parse(memory.metadata) : memory.metadata;\n      } catch {\n        this.logger.debug('Failed to parse metadata JSON', { memoryId: memory.id });\n        parsedMetadata = undefined;\n      }\n    }\n\n    return {\n      id: memory.id,\n      agentId: memory.agentId,\n      graphId: memory.graphId,\n      taskId: memory.taskId,\n      sessionId: memory.sessionId,\n      content: memory.content,\n      embedding: parsedEmbedding,\n      metadata: parsedMetadata,\n      createdAt: new Date(memory.created_at),\n      updatedAt: new Date(memory.updated_at),\n    };\n  }\n\n  /**\n   * Destroy Memory module and free resources.\n   * Call this when the module is no longer needed.\n   */\n  async destroy(): Promise<void> {\n    // Clear the memory change callback to prevent memory leaks\n    this.onChangeCallback = null;\n\n    // Clear the knex reference (shared database, don't close)\n    this.knex = null;\n\n    // Clear the encryption service reference\n    this._encryption = undefined;\n  }\n}\n\n// Export types\nexport type { Memory as MemoryType, MemorySearchOptions } from './types';\n","/**\n * Default configuration values for task module\n */\nexport const DEFAULT_TASK_CONFIG = {\n  searchLimit: 100,\n  searchOffset: 0,\n  searchOrderBy: 'createdAt',\n  searchOrder: 'desc',\n  defaultMimeType: 'image/jpeg',\n  logMode: 'default',\n  logStatus: 'all',\n  maxToolIterations: 9999,\n  maxToolCalls: 9999,\n} as const;\n\n/**\n * Get default value for a task config property\n */\nexport function getTaskDefaultValue<K extends keyof typeof DEFAULT_TASK_CONFIG>(\n  key: K\n): (typeof DEFAULT_TASK_CONFIG)[K] {\n  return DEFAULT_TASK_CONFIG[key];\n}\n","import { spawn, ChildProcess } from 'child_process';\nimport { randomUUID } from 'crypto';\nimport { IAgentModule, IAgent } from '../agent/types';\nimport { MCPValue } from './types';\nimport {\n  MCPServerConfig,\n  MCPTool,\n  MCPToolResult,\n  MCPServerDefinition,\n  MCPJsonSchema,\n} from './types';\nimport { Logger } from '../logger/types';\nimport * as fs from 'fs';\nimport { ToolError } from '../errors';\n\n// Default timeout for MCP tool calls (in milliseconds)\nconst DEFAULT_TOOL_CALL_TIMEOUT = 30000;\n// Maximum number of MCP servers allowed\nconst MAX_MCP_SERVERS = 10;\n// Maximum buffer size for stdout (10MB)\nconst MAX_BUFFER_SIZE = 10 * 1024 * 1024;\n\ninterface MCPMessage {\n  jsonrpc: string;\n  id?: string | number;\n  method?: string;\n  params?: Record<string, MCPValue>;\n  result?: {\n    tools?: MCPTool[];\n  } & Record<string, MCPValue>;\n  error?: {\n    code: number;\n    message: string;\n    data?: MCPValue;\n  };\n}\n\nexport class MCP implements IAgentModule {\n  readonly name = 'mcp';\n  public processes: Map<string, ChildProcess> = new Map();\n  public tools: Map<string, MCPTool> = new Map();\n  public servers: Map<string, MCPServerConfig> = new Map();\n  private logger: Logger;\n  private pendingCallbacks: Map<\n    string,\n    { resolve: (result: MCPToolResult) => void; timeoutId: NodeJS.Timeout }\n  > = new Map();\n  private messageHandlers: Map<string, (data: Buffer) => void> = new Map();\n  private toolCallTimeout: number = DEFAULT_TOOL_CALL_TIMEOUT;\n  private forceKillTimers: Map<number, NodeJS.Timeout> = new Map();\n\n  constructor(private agent: IAgent) {\n    this.logger = agent.logger;\n\n    // User-facing info log\n    this.logger.info('MCP module initialized');\n\n    this.logger.debug('MCP module initialized', {\n      agentId: agent.id,\n      agentName: agent.name,\n    });\n  }\n\n  async initialize(): Promise<void> {\n    // User-facing info log\n    this.logger.info('MCP module ready');\n\n    this.logger.debug('MCP module initialization completed');\n  }\n\n  /**\n   * Set the timeout for MCP tool calls\n   * @param timeoutMs Timeout in milliseconds\n   */\n  setToolCallTimeout(timeoutMs: number): void {\n    if (timeoutMs <= 0) {\n      this.logger.warn('Invalid timeout value, using default');\n      this.toolCallTimeout = DEFAULT_TOOL_CALL_TIMEOUT;\n      return;\n    }\n    this.toolCallTimeout = timeoutMs;\n    this.logger.debug('Tool call timeout set', { timeoutMs });\n  }\n\n  /**\n   * Cleanup resources for a specific server\n   * @param name Server name\n   */\n  private cleanupServerResources(name: string): void {\n    // Remove message handler\n    const handler = this.messageHandlers.get(name);\n    if (handler) {\n      const proc = this.processes.get(name);\n      if (proc?.stdout) {\n        proc.stdout.off('data', handler);\n      }\n      this.messageHandlers.delete(name);\n    }\n\n    // Cancel pending callbacks for this server\n    // This prevents memory leaks and hanging promises when server crashes\n    for (const [callId, callback] of this.pendingCallbacks.entries()) {\n      // Check if this callback is related to the server being cleaned up\n      // We can't directly check server association, so we cancel all pending callbacks\n      // when a server crashes to be safe\n      clearTimeout(callback.timeoutId);\n      callback.resolve({\n        content: [{ type: 'text', text: `Server '${name}' crashed or was terminated` }],\n        isError: true,\n      });\n      this.pendingCallbacks.delete(callId);\n      this.logger.debug('Cancelled pending callback due to server cleanup', {\n        serverName: name,\n        callId,\n      });\n    }\n\n    // Remove process\n    this.processes.delete(name);\n\n    // Remove tools from this server\n    for (const [toolName] of this.tools.entries()) {\n      if (toolName.startsWith(`${name}:`)) {\n        this.tools.delete(toolName);\n      }\n    }\n  }\n\n  /**\n   * Cleanup all resources - call this before destroying the MCP instance\n   */\n  async cleanup(): Promise<void> {\n    this.logger.info('Cleaning up MCP module');\n\n    // Cancel all pending callbacks\n    for (const [callId, callback] of this.pendingCallbacks.entries()) {\n      clearTimeout(callback.timeoutId);\n      callback.resolve({\n        content: [{ type: 'text', text: 'MCP cleanup - call cancelled' }],\n        isError: true,\n      });\n      this.pendingCallbacks.delete(callId);\n    }\n\n    // Remove all message handlers\n    for (const [serverName, handler] of this.messageHandlers.entries()) {\n      const proc = this.processes.get(serverName);\n      if (proc?.stdout) {\n        proc.stdout.off('data', handler);\n      }\n      this.messageHandlers.delete(serverName);\n    }\n\n    // Clear any existing force kill timers\n    for (const [pid, timer] of this.forceKillTimers.entries()) {\n      clearTimeout(timer);\n      this.forceKillTimers.delete(pid);\n    }\n\n    // Kill all processes and wait for them to exit\n    const exitPromises: Promise<void>[] = [];\n\n    for (const [name, proc] of this.processes.entries()) {\n      this.logger.debug('Killing MCP server process during cleanup', { name, pid: proc.pid ?? 0 });\n\n      // Create a promise that resolves when the process exits\n      const exitPromise = new Promise<void>((resolve) => {\n        // If already killed, resolve immediately\n        if (proc.killed) {\n          resolve();\n          return;\n        }\n\n        // Set up exit handler\n        const exitHandler = () => {\n          // Clean up force kill timer if it exists\n          if (proc.pid) {\n            const timer = this.forceKillTimers.get(proc.pid);\n            if (timer) {\n              clearTimeout(timer);\n              this.forceKillTimers.delete(proc.pid);\n            }\n          }\n          resolve();\n        };\n\n        proc.once('exit', exitHandler);\n        proc.once('error', exitHandler);\n\n        // Send SIGTERM for graceful shutdown\n        proc.kill('SIGTERM');\n\n        // Set up force kill timer if process has a PID\n        if (proc.pid) {\n          const forceKillTimer = setTimeout(() => {\n            if (!proc.killed) {\n              proc.kill('SIGKILL');\n            }\n            this.forceKillTimers.delete(proc.pid!);\n            // If still not exited after SIGKILL, resolve anyway\n            setTimeout(() => resolve(), 500);\n          }, 5000);\n          this.forceKillTimers.set(proc.pid, forceKillTimer);\n        } else {\n          // No PID, resolve after a short delay\n          setTimeout(() => resolve(), 100);\n        }\n      });\n\n      exitPromises.push(exitPromise);\n    }\n\n    // Wait for all processes to exit (with a maximum timeout)\n    await Promise.race([\n      Promise.all(exitPromises),\n      new Promise<void>((resolve) => setTimeout(resolve, 10000)), // 10 second max wait\n    ]);\n\n    // Clear any remaining force kill timers\n    for (const [pid, timer] of this.forceKillTimers.entries()) {\n      clearTimeout(timer);\n      this.forceKillTimers.delete(pid);\n    }\n\n    this.processes.clear();\n    this.tools.clear();\n    this.servers.clear();\n\n    this.logger.info('MCP module cleanup completed');\n  }\n\n  /**\n   * Alias for cleanup() - for consistent destroy() method naming across modules\n   */\n  async destroy(): Promise<void> {\n    return this.cleanup();\n  }\n\n  public async startMCPServer(name: string, config: MCPServerConfig): Promise<void> {\n    // User-facing info log\n    this.logger.info(`Starting MCP server: ${name}`);\n\n    this.logger.debug('Starting MCP server', {\n      name,\n      command: config.command ?? 'none',\n      hasArgs: !!config.args?.length,\n      hasUrl: !!config.url,\n      hasCwd: !!config.cwd,\n      hasEnv: !!config.env,\n    });\n\n    if (config.url) {\n      // SSE server - tools will be fetched when needed\n      this.logger.info(`SSE MCP server registered: ${name}`);\n      this.logger.debug('SSE MCP server registered (deferred start)', { name, url: config.url });\n      return;\n    }\n\n    if (!config.command) {\n      this.logger.debug('No command provided for MCP server', { name });\n      return;\n    }\n\n    // Validate command and args to prevent command injection\n    if (typeof config.command !== 'string' || config.command.trim() === '') {\n      this.logger.error(`Invalid command for MCP server: ${name}`);\n      this.logger.debug('MCP server command validation failed', {\n        name,\n        command: config.command,\n        commandType: typeof config.command,\n      });\n      throw new Error(\n        `Invalid command for MCP server '${name}': command must be a non-empty string`\n      );\n    }\n\n    // Strict command validation - only allow absolute paths or simple command names\n    const command = config.command.trim();\n    const isAbsolutePath = command.startsWith('/');\n    const isSimpleCommand = /^[a-zA-Z0-9_-]+$/.test(command);\n\n    if (!isAbsolutePath && !isSimpleCommand) {\n      this.logger.error(`Unsafe command for MCP server: ${name}`);\n      this.logger.debug(\n        'MCP server command validation failed - not absolute path or simple command',\n        {\n          name,\n          command,\n          isAbsolutePath,\n          isSimpleCommand,\n        }\n      );\n      throw new Error(\n        `Invalid command for MCP server '${name}': command must be an absolute path or simple command name`\n      );\n    }\n\n    // For absolute paths, ensure they exist and are executable\n    if (isAbsolutePath) {\n      try {\n        const stats = fs.statSync(command);\n        if (!stats.isFile()) {\n          throw new Error(`Command is not a file: ${command}`);\n        }\n        // Check if file is executable (basic check)\n        fs.accessSync(command, fs.constants.F_OK | fs.constants.X_OK);\n      } catch (error) {\n        this.logger.error(`Command file validation failed for MCP server: ${name}`);\n        this.logger.debug('MCP server command file validation failed', {\n          name,\n          command,\n          error: error instanceof Error ? error.message : String(error),\n        });\n        throw new Error(\n          `Invalid command file for MCP server '${name}': ${error instanceof Error ? error.message : 'file access error'}`\n        );\n      }\n    }\n\n    // Validate args array\n    const args = config.args ?? [];\n    if (!Array.isArray(args)) {\n      this.logger.error(`Invalid args for MCP server: ${name}`);\n      this.logger.debug('MCP server args validation failed', {\n        name,\n        args,\n        argsType: typeof args,\n      });\n      throw new Error(`Invalid args for MCP server '${name}': args must be an array`);\n    }\n\n    // Validate each argument to prevent injection\n    for (let i = 0; i < args.length; i++) {\n      const arg = args[i];\n      if (typeof arg !== 'string') {\n        this.logger.error(`Invalid argument for MCP server: ${name}`);\n        this.logger.debug('MCP server argument validation failed', {\n          name,\n          invalidArg: arg,\n          argType: typeof arg,\n          argIndex: i,\n        });\n        throw new Error(`Invalid argument for MCP server '${name}': all arguments must be strings`);\n      }\n\n      // Check for dangerous patterns in arguments\n      // Only block specific dangerous options/patterns, allow normal CLI args\n      const dangerousPatterns = [\n        /[;&|`$(){}[\\]]/, // Shell metacharacters\n        /\\.\\./, // Directory traversal\n        /\\/etc\\/|\\/proc\\/|\\/sys\\//, // System directories\n      ];\n\n      // Dangerous command-line options that could lead to code execution\n      const dangerousOptions = [\n        '--eval',\n        '-e', // Node.js eval\n        '--exec', // Execute command\n        '--import', // Dynamic import (Node.js)\n        '-c', // Python/Ruby command execution\n        '--command', // Shell command execution\n        '-i', // Interactive mode (some interpreters)\n      ];\n\n      for (const pattern of dangerousPatterns) {\n        if (pattern.test(arg)) {\n          this.logger.error(`Dangerous argument detected for MCP server: ${name}`);\n          this.logger.debug('MCP server dangerous argument detected', {\n            name,\n            arg: arg.slice(0, 50), // Truncate for logging\n            argIndex: i,\n            pattern: pattern.toString(),\n          });\n          throw new Error(\n            `Dangerous argument for MCP server '${name}': argument contains unsafe characters or patterns`\n          );\n        }\n      }\n\n      // Check for dangerous options (case-insensitive for options, exact match for values)\n      const lowerArg = arg.toLowerCase();\n      for (const dangerousOpt of dangerousOptions) {\n        if (lowerArg === dangerousOpt || lowerArg.startsWith(`${dangerousOpt}=`)) {\n          this.logger.error(`Dangerous option detected for MCP server: ${name}`);\n          this.logger.debug('MCP server dangerous option detected', {\n            name,\n            arg: arg.slice(0, 50),\n            argIndex: i,\n            matchedOption: dangerousOpt,\n          });\n          throw new Error(\n            `Dangerous argument for MCP server '${name}': option '${dangerousOpt}' is not allowed`\n          );\n        }\n      }\n\n      // Limit argument length to prevent buffer overflow attacks\n      if (arg.length > 1000) {\n        this.logger.error(`Argument too long for MCP server: ${name}`);\n        this.logger.debug('MCP server argument too long', {\n          name,\n          argIndex: i,\n          argLength: arg.length,\n          maxLength: 1000,\n        });\n        throw new Error(\n          `Argument too long for MCP server '${name}': maximum length is 1000 characters`\n        );\n      }\n    }\n\n    // Validate environment variables to prevent injection\n    if (config.env) {\n      for (const [key, value] of Object.entries(config.env)) {\n        // Validate environment variable key\n        if (!/^[A-Z_][A-Z0-9_]*$/i.test(key)) {\n          this.logger.error(`Invalid environment variable key for MCP server: ${name}`);\n          this.logger.debug('MCP server environment variable key validation failed', {\n            name,\n            envKey: key,\n          });\n          throw new Error(\n            `Invalid environment variable key for MCP server '${name}': '${key}' contains invalid characters`\n          );\n        }\n\n        // Validate environment variable value\n        if (typeof value !== 'string' && value !== undefined) {\n          this.logger.error(`Invalid environment variable value for MCP server: ${name}`);\n          this.logger.debug('MCP server environment variable value validation failed', {\n            name,\n            envKey: key,\n            valueType: typeof value,\n          });\n          throw new Error(\n            `Invalid environment variable value for MCP server '${name}': '${key}' must be a string`\n          );\n        }\n\n        // Check for dangerous patterns in environment values\n        if (value && typeof value === 'string') {\n          if (value.includes('\\x00') || value.length > 10000) {\n            this.logger.error(`Dangerous environment variable value for MCP server: ${name}`);\n            this.logger.debug('MCP server dangerous environment variable detected', {\n              name,\n              envKey: key,\n              valueLength: value.length,\n            });\n            throw new Error(\n              `Dangerous environment variable value for MCP server '${name}': '${key}' contains unsafe content`\n            );\n          }\n        }\n      }\n    }\n\n    // Use process.env by default, only override if explicitly provided\n    const envVars = config.env ? { ...process.env, ...config.env } : process.env;\n\n    // Check process limits to prevent resource exhaustion\n    if (this.processes.size >= MAX_MCP_SERVERS) {\n      this.logger.error(`Too many MCP servers running for agent: ${this.agent.name}`);\n      this.logger.debug('MCP server limit reached', {\n        name,\n        currentProcesses: this.processes.size,\n        maxProcesses: MAX_MCP_SERVERS,\n        agentId: this.agent.id,\n      });\n      throw new Error(\n        `Cannot start MCP server '${name}': maximum number of MCP servers (${MAX_MCP_SERVERS}) reached`\n      );\n    }\n\n    this.logger.debug('Spawning MCP server process', {\n      name,\n      command: config.command,\n      argCount: args.length,\n      cwd: config.cwd ?? 'default',\n      hasCustomEnv: !!config.env,\n    });\n\n    let childProcess: ChildProcess;\n    try {\n      // Check Node.js version for spawn timeout support (Node.js 15+)\n      const nodeVersion = process.versions.node.split('.').map(Number);\n      const supportsSpawnTimeout = nodeVersion[0] >= 15;\n\n      interface SpawnOptionsWithTimeout {\n        stdio: ['pipe', 'pipe', 'pipe'];\n        env: NodeJS.ProcessEnv;\n        cwd?: string;\n        detached: boolean;\n        timeout?: number;\n      }\n\n      const spawnOptions: SpawnOptionsWithTimeout = {\n        stdio: ['pipe', 'pipe', 'pipe'],\n        env: envVars,\n        cwd: config.cwd,\n        detached: false, // Prevent process from becoming session leader\n      };\n\n      // Only add timeout option if Node.js version supports it\n      if (supportsSpawnTimeout) {\n        spawnOptions.timeout = 5000; // Timeout for process startup\n      } else {\n        this.logger.debug('Node.js version does not support spawn timeout', {\n          nodeVersion: process.versions.node,\n          requiredVersion: '15.0.0',\n        });\n      }\n\n      childProcess = spawn(config.command, args, spawnOptions);\n    } catch (spawnError) {\n      this.logger.error(`Failed to spawn MCP server process: ${name}`);\n      this.logger.debug('MCP server spawn error', {\n        name,\n        error: spawnError instanceof Error ? spawnError.message : String(spawnError),\n      });\n      throw new Error(\n        `Failed to spawn MCP server '${name}': ${spawnError instanceof Error ? spawnError.message : String(spawnError)}`\n      );\n    }\n\n    // Verify the process was created successfully\n    if (!childProcess.pid) {\n      this.logger.error(`MCP server process failed to start: ${name}`);\n      throw new Error(`MCP server '${name}' process failed to start - no PID assigned`);\n    }\n\n    let buffer = '';\n    const stdout = childProcess.stdout;\n    if (stdout) {\n      stdout.on('data', (data: Buffer) => {\n        buffer += data.toString();\n\n        // Prevent buffer overflow by truncating if it exceeds the limit\n        if (buffer.length > MAX_BUFFER_SIZE) {\n          const originalLength = buffer.length;\n          const truncatedBytes = originalLength - MAX_BUFFER_SIZE;\n          buffer = buffer.slice(-MAX_BUFFER_SIZE);\n          this.logger.warn(\n            `MCP buffer truncated due to size limit for server: ${name}. Discarded ${truncatedBytes} bytes (${(truncatedBytes / 1024 / 1024).toFixed(2)} MB). This may indicate the server is producing excessive output or malformed JSON.`\n          );\n          this.logger.debug('MCP buffer truncation details', {\n            serverName: name,\n            originalLength,\n            truncatedBytes,\n            maxBufferSize: MAX_BUFFER_SIZE,\n            retainedLength: buffer.length,\n          });\n        }\n\n        const lines = buffer.split('\\n');\n        buffer = lines.pop() ?? '';\n\n        for (const line of lines) {\n          if (line.trim()) {\n            try {\n              const message = JSON.parse(line);\n              this.logger.debug('Received MCP message', {\n                serverName: name,\n                method: message.method,\n                id: message.id,\n                hasResult: !!message.result,\n              });\n              this.handleMessage(name, message);\n            } catch (error) {\n              this.logger.debug('Failed to parse MCP message', {\n                serverName: name,\n                line,\n                error: error instanceof Error ? error.message : String(error),\n              });\n            }\n          }\n        }\n      });\n    } else {\n      this.logger.warn(`MCP server '${name}' has no stdout - communication may be limited`);\n    }\n\n    const stderr = childProcess.stderr;\n    if (stderr) {\n      stderr.on('data', (data: Buffer) => {\n        const stderrOutput = data.toString().trim();\n        this.logger.error(`MCP server stderr (${name}): ${stderrOutput}`);\n        this.logger.debug('MCP server stderr', {\n          serverName: name,\n          stderr: stderrOutput,\n        });\n      });\n    }\n\n    childProcess.on('error', (error) => {\n      this.logger.error(`MCP server error: ${name}`);\n      this.logger.debug('MCP server process error', {\n        serverName: name,\n        error: error.message,\n        hasStack: !!error.stack,\n      });\n      // Clean up associated resources\n      this.cleanupServerResources(name);\n    });\n\n    childProcess.on('exit', (code, signal) => {\n      this.logger.info(`MCP server exited: ${name}`);\n      this.logger.debug('MCP server process exit', {\n        serverName: name,\n        exitCode: code ?? null,\n        signal: signal ?? null,\n      });\n      // Clean up associated resources\n      this.cleanupServerResources(name);\n    });\n\n    this.processes.set(name, childProcess);\n\n    // User-facing success message\n    this.logger.info(`MCP server started: ${name}`);\n\n    this.logger.debug('MCP server process started', {\n      name,\n      pid: childProcess.pid ?? 0,\n      processCount: this.processes.size,\n    });\n\n    // Initialize\n    this.logger.debug(`Sending initialize message to MCP server: ${name}`);\n    this.sendToServer(name, {\n      jsonrpc: '2.0',\n      id: 1,\n      method: 'initialize',\n      params: {\n        protocolVersion: '2024-11-05',\n        capabilities: {},\n        clientInfo: { name: 'astreus', version: '1.0.0' },\n      },\n    });\n\n    // List tools\n    this.logger.debug(`Requesting tools list from MCP server: ${name}`);\n    this.sendToServer(name, {\n      jsonrpc: '2.0',\n      id: 2,\n      method: 'tools/list',\n    });\n  }\n\n  public handleMessage(serverName: string, message: MCPMessage): void {\n    this.logger.debug(\n      `Received MCP message from ${serverName}: method=${message.method}, id=${message.id}`\n    );\n    this.logger.debug('Full MCP message', { serverName, message: JSON.stringify(message) });\n\n    // Handle tools/list response - can be either method response or result-only message\n    if (\n      (message.method === 'tools/list' || (message.id === 2 && message.result?.tools)) &&\n      message.result?.tools\n    ) {\n      // User-facing info log\n      this.logger.info(`Discovered ${message.result.tools.length} tools from ${serverName}`);\n\n      this.logger.debug('Processing tools list from MCP server', {\n        serverName,\n        toolCount: message.result.tools.length,\n        toolNames: message.result.tools.map((t) => t.name),\n      });\n\n      for (const tool of message.result.tools) {\n        const toolKey = `${serverName}:${tool.name}`;\n        this.tools.set(toolKey, tool);\n\n        this.logger.debug(`Registered MCP tool: ${serverName}:${tool.name} - ${tool.description}`);\n        this.logger.debug('Registered MCP tool', {\n          serverName,\n          toolName: tool.name,\n          toolKey,\n          description: tool.description,\n        });\n      }\n\n      this.logger.info(\n        `MCP tools registration completed for ${serverName}: ${this.tools.size} total tools`\n      );\n      this.logger.debug('MCP tools registration completed', {\n        serverName,\n        totalTools: this.tools.size,\n        serverTools: Array.from(this.tools.keys()).filter((k) => k.startsWith(`${serverName}:`)),\n      });\n    } else if (message.result) {\n      this.logger.debug(`MCP message result from ${serverName}: ${JSON.stringify(message.result)}`);\n    } else if (message.error) {\n      this.logger.error(`MCP error from ${serverName}: ${JSON.stringify(message.error)}`);\n    } else {\n      this.logger.debug(\n        `MCP message from ${serverName} (no result/error): ${JSON.stringify(message)}`\n      );\n    }\n  }\n\n  public sendToServer(name: string, message: MCPMessage): void {\n    const childProcess = this.processes.get(name);\n    if (childProcess?.stdin) {\n      this.logger.debug(`Sending to ${name}: ${message.method} (id: ${message.id})`);\n      this.logger.debug('Sending message to MCP server', {\n        serverName: name,\n        method: message.method ?? 'unknown',\n        id: message.id ?? 0,\n        hasParams: !!message.params,\n        message: JSON.stringify(message),\n      });\n      childProcess.stdin.write(JSON.stringify(message) + '\\n');\n    } else {\n      this.logger.error(`Cannot send message to ${name} - MCP server not available`);\n      this.logger.debug('Cannot send message - MCP server not available', {\n        serverName: name,\n        method: message.method ?? 'unknown',\n        processExists: !!childProcess,\n        hasStdin: !!childProcess?.stdin,\n      });\n    }\n  }\n\n  getMCPTools(): MCPTool[] {\n    const tools = Array.from(this.tools.values());\n\n    this.logger.debug(\n      `MCP has ${tools.length} tools available: ${tools.map((t) => t.name).join(', ')}`\n    );\n    this.logger.debug('Retrieved MCP tools', {\n      toolCount: tools.length,\n      toolNames: tools.map((t) => t.name),\n    });\n\n    return tools;\n  }\n\n  /**\n   * Validate a server definition before adding it\n   * @param serverDef The server definition to validate\n   * @throws Error if the server definition is invalid\n   */\n  private validateServerDefinition(serverDef: MCPServerDefinition): void {\n    // Validate name\n    if (!serverDef.name || typeof serverDef.name !== 'string') {\n      throw new Error('Server definition must have a valid name');\n    }\n\n    if (serverDef.name.trim() === '') {\n      throw new Error('Server name cannot be empty');\n    }\n\n    // Check for invalid characters in name\n    if (!/^[a-zA-Z0-9_-]+$/.test(serverDef.name)) {\n      throw new Error(\n        `Server name '${serverDef.name}' contains invalid characters. Use only alphanumeric, underscore, and dash.`\n      );\n    }\n\n    // Must have either command or url\n    if (!serverDef.command && !serverDef.url) {\n      throw new Error(`Server '${serverDef.name}' must have either a command or url`);\n    }\n\n    // Cannot have both command and url\n    if (serverDef.command && serverDef.url) {\n      throw new Error(`Server '${serverDef.name}' cannot have both command and url`);\n    }\n\n    // Validate url format if provided\n    if (serverDef.url) {\n      try {\n        new URL(serverDef.url);\n      } catch {\n        throw new Error(`Server '${serverDef.name}' has invalid URL: ${serverDef.url}`);\n      }\n    }\n\n    // Check for duplicate server names\n    if (this.servers.has(serverDef.name)) {\n      throw new Error(`Server '${serverDef.name}' already exists`);\n    }\n  }\n\n  // Framework-style: Add single MCP server\n  async addMCPServer(serverDef: MCPServerDefinition): Promise<void> {\n    // Validate server definition first\n    this.validateServerDefinition(serverDef);\n\n    // User-facing info log\n    this.logger.info(`Adding MCP server: ${serverDef.name}`);\n\n    this.logger.debug('Adding MCP server definition', {\n      name: serverDef.name,\n      command: serverDef.command ?? 'none',\n      hasArgs: !!serverDef.args?.length,\n      hasUrl: !!serverDef.url,\n      hasCwd: !!serverDef.cwd,\n      hasEnv: !!serverDef.env,\n    });\n\n    const config: MCPServerConfig = {\n      command: serverDef.command,\n      args: serverDef.args,\n      env: serverDef.env,\n      url: serverDef.url,\n      cwd: serverDef.cwd,\n    };\n\n    this.servers.set(serverDef.name, config);\n\n    try {\n      await this.startMCPServer(serverDef.name, config);\n    } catch (error) {\n      // Rollback on failure\n      this.servers.delete(serverDef.name);\n      throw error;\n    }\n\n    // User-facing success message\n    this.logger.info(`MCP server added: ${serverDef.name}`);\n\n    this.logger.debug('MCP server added successfully', {\n      name: serverDef.name,\n      totalServers: this.servers.size,\n    });\n  }\n\n  // Framework-style: Add multiple servers from array\n  async addMCPServers(servers: MCPServerDefinition[]): Promise<void> {\n    // User-facing info log\n    this.logger.info(`Adding ${servers.length} MCP servers`);\n\n    this.logger.debug('Adding multiple MCP servers', {\n      serverCount: servers.length,\n      serverNames: servers.map((s) => s.name),\n    });\n\n    for (const serverDef of servers) {\n      await this.addMCPServer(serverDef);\n    }\n\n    // User-facing success message\n    this.logger.info(`Added ${servers.length} MCP servers`);\n\n    this.logger.debug('Multiple MCP servers added successfully', {\n      addedCount: servers.length,\n      totalServers: this.servers.size,\n    });\n  }\n\n  // Framework-style: Remove runtime server\n  removeMCPServer(name: string): void {\n    // User-facing info log\n    this.logger.info(`Removing MCP server: ${name}`);\n\n    this.logger.debug('Removing MCP server', {\n      name,\n      hasProcess: this.processes.has(name),\n      hasServerConfig: this.servers.has(name),\n    });\n\n    // Remove message handler first to prevent memory leaks\n    const handler = this.messageHandlers.get(name);\n    const childProcess = this.processes.get(name);\n    if (handler && childProcess?.stdout) {\n      childProcess.stdout.off('data', handler);\n      this.messageHandlers.delete(name);\n    }\n\n    if (childProcess) {\n      this.logger.debug('Killing MCP server process', {\n        name,\n        pid: childProcess.pid ?? 0,\n      });\n      childProcess.kill('SIGTERM');\n      this.processes.delete(name);\n    }\n    this.servers.delete(name);\n\n    // Remove tools from this server\n    const toolsToRemove: string[] = [];\n    for (const [toolName] of this.tools.entries()) {\n      if (toolName.startsWith(`${name}:`)) {\n        toolsToRemove.push(toolName);\n        this.tools.delete(toolName);\n      }\n    }\n\n    // User-facing success message\n    this.logger.info(`MCP server removed: ${name}`);\n\n    this.logger.debug('MCP server removed successfully', {\n      name,\n      removedTools: toolsToRemove,\n      remainingServers: this.servers.size,\n      remainingTools: this.tools.size,\n    });\n  }\n\n  /**\n   * Validate MCP tool parameters against inputSchema (JSON Schema)\n   * @param tool The MCP tool definition\n   * @param args The arguments to validate\n   * @returns Error message if validation fails, null if successful\n   */\n  private validateMCPToolParameters(tool: MCPTool, args: Record<string, MCPValue>): string | null {\n    const schema = tool.inputSchema;\n\n    if (!schema || !schema.properties) {\n      // No schema defined, skip validation\n      return null;\n    }\n\n    this.logger.debug('Validating MCP tool parameters', {\n      toolName: tool.name,\n      expectedParams: Object.keys(schema.properties || {}),\n      providedParams: Object.keys(args),\n      requiredParams: schema.required || [],\n    });\n\n    // Check required parameters\n    if (schema.required && Array.isArray(schema.required)) {\n      for (const requiredParam of schema.required) {\n        if (args[requiredParam] === undefined || args[requiredParam] === null) {\n          this.logger.debug('Required MCP parameter missing', {\n            toolName: tool.name,\n            paramName: requiredParam,\n          });\n          return `Required parameter '${requiredParam}' is missing`;\n        }\n      }\n    }\n\n    // Validate parameter types against schema\n    for (const [paramName, paramValue] of Object.entries(args)) {\n      const paramSchema = schema.properties?.[paramName];\n\n      if (!paramSchema) {\n        // Unknown parameter - log warning but allow (some tools accept additional params)\n        this.logger.debug('Unknown parameter provided to MCP tool', {\n          toolName: tool.name,\n          paramName,\n        });\n        continue;\n      }\n\n      const typeError = this.validateMCPParameterType(paramValue, paramSchema, paramName);\n      if (typeError) {\n        return typeError;\n      }\n    }\n\n    this.logger.debug('MCP tool parameter validation successful', {\n      toolName: tool.name,\n      validatedParams: Object.keys(args).length,\n    });\n\n    return null;\n  }\n\n  /**\n   * Validate a single parameter value against its JSON schema\n   */\n  private validateMCPParameterType(\n    value: MCPValue,\n    schema: MCPJsonSchema,\n    paramName: string\n  ): string | null {\n    if (value === null) {\n      // null is generally allowed unless schema explicitly forbids it\n      return null;\n    }\n\n    const expectedType = schema.type;\n    const actualType = Array.isArray(value) ? 'array' : typeof value;\n\n    switch (expectedType) {\n      case 'string':\n        if (typeof value !== 'string') {\n          return `Parameter '${paramName}' expected string, got ${actualType}`;\n        }\n        // Validate enum if present\n        if (schema.enum && !schema.enum.includes(value)) {\n          return `Parameter '${paramName}' must be one of: ${schema.enum.join(', ')}`;\n        }\n        break;\n      case 'number':\n      case 'integer':\n        if (typeof value !== 'number') {\n          return `Parameter '${paramName}' expected ${expectedType}, got ${actualType}`;\n        }\n        if (expectedType === 'integer' && !Number.isInteger(value)) {\n          return `Parameter '${paramName}' expected integer, got float`;\n        }\n        break;\n      case 'boolean':\n        if (typeof value !== 'boolean') {\n          return `Parameter '${paramName}' expected boolean, got ${actualType}`;\n        }\n        break;\n      case 'array':\n        if (!Array.isArray(value)) {\n          return `Parameter '${paramName}' expected array, got ${actualType}`;\n        }\n        // Validate array items if schema.items is defined\n        if (schema.items && Array.isArray(value)) {\n          for (let i = 0; i < value.length; i++) {\n            const itemError = this.validateMCPParameterType(\n              value[i] as MCPValue,\n              schema.items,\n              `${paramName}[${i}]`\n            );\n            if (itemError) {\n              return itemError;\n            }\n          }\n        }\n        break;\n      case 'object':\n        if (typeof value !== 'object' || Array.isArray(value)) {\n          return `Parameter '${paramName}' expected object, got ${actualType}`;\n        }\n        // Validate nested properties if defined\n        if (schema.properties && typeof value === 'object' && value !== null) {\n          const objValue = value as Record<string, MCPValue>;\n          for (const [nestedKey, nestedSchema] of Object.entries(schema.properties)) {\n            if (objValue[nestedKey] !== undefined) {\n              const nestedError = this.validateMCPParameterType(\n                objValue[nestedKey],\n                nestedSchema,\n                `${paramName}.${nestedKey}`\n              );\n              if (nestedError) {\n                return nestedError;\n              }\n            }\n          }\n        }\n        break;\n      default:\n        // Unknown type, skip validation\n        break;\n    }\n\n    return null;\n  }\n\n  async callMCPTool(toolName: string, args: Record<string, MCPValue>): Promise<MCPToolResult> {\n    // Handle both formats: \"tool_name\" and \"server:tool_name\"\n    let serverName: string;\n    let actualToolName: string;\n    let toolKey: string;\n\n    if (toolName.includes(':')) {\n      [serverName, actualToolName] = toolName.split(':');\n      toolKey = toolName;\n    } else {\n      // Find all tools with this name across servers\n      const matchingTools = Array.from(this.tools.keys()).filter((key) =>\n        key.endsWith(`:${toolName}`)\n      );\n\n      if (matchingTools.length === 0) {\n        // Create normalized ToolError for consistent error handling\n        const toolError = new ToolError(\n          `MCP tool '${toolName}' not found`,\n          toolName,\n          'mcp',\n          'not_found',\n          false\n        );\n        this.logger.error(`MCP tool not found: ${toolName}`, toolError);\n        this.logger.debug('MCP tool not found', {\n          requestedTool: toolName,\n          availableTools: Array.from(this.tools.keys()),\n        });\n        return { content: [{ type: 'text', text: toolError.message }], isError: true };\n      }\n\n      if (matchingTools.length > 1) {\n        // Multiple tools with same name - warn and use deterministic selection (alphabetical)\n        matchingTools.sort();\n        this.logger.warn(\n          `MCP tool name '${toolName}' is ambiguous - found in ${matchingTools.length} servers: ${matchingTools.join(', ')}. Using '${matchingTools[0]}' (alphabetically first). Consider using full name with server prefix.`\n        );\n        this.logger.debug('MCP tool name ambiguity detected', {\n          requestedTool: toolName,\n          matchingTools,\n          selectedTool: matchingTools[0],\n        });\n      }\n\n      toolKey = matchingTools[0];\n      [serverName, actualToolName] = toolKey.split(':');\n    }\n\n    // Get tool definition for validation\n    const tool = this.tools.get(toolKey);\n    if (tool) {\n      // Validate parameters against inputSchema\n      const validationError = this.validateMCPToolParameters(tool, args);\n      if (validationError) {\n        // Create normalized ToolError for validation failures\n        const toolError = new ToolError(\n          `MCP tool '${actualToolName}' validation failed: ${validationError}`,\n          actualToolName,\n          'mcp',\n          'validation',\n          true // Validation errors are recoverable - LLM can try with correct parameters\n        );\n        this.logger.error(`MCP tool parameter validation failed: ${actualToolName}`, toolError);\n        this.logger.debug('MCP tool parameter validation error', {\n          toolName: actualToolName,\n          serverName,\n          validationError,\n          providedArgs: Object.keys(args),\n        });\n        return { content: [{ type: 'text', text: toolError.message }], isError: true };\n      }\n    }\n\n    // User-facing info log\n    this.logger.debug(`Calling MCP tool: ${actualToolName} on ${serverName}`);\n\n    this.logger.debug('Calling MCP tool', {\n      fullToolName: toolName,\n      serverName,\n      actualToolName,\n      args: Object.keys(args),\n      argCount: Object.keys(args).length,\n    });\n\n    // Check if server exists (either from config or runtime)\n    const childProcess = this.processes.get(serverName);\n    if (!childProcess) {\n      this.logger.debug('MCP server not running, attempting to start', { serverName });\n\n      // Try to start server if it exists\n      const serverConfig = this.servers.get(serverName);\n      if (serverConfig) {\n        await this.startMCPServer(serverName, serverConfig);\n      } else {\n        // Create normalized ToolError for server not found\n        const toolError = new ToolError(\n          `MCP server '${serverName}' not found for tool '${actualToolName}'`,\n          actualToolName,\n          'mcp',\n          'not_found',\n          false\n        );\n        this.logger.error(`MCP server not found: ${serverName}`, toolError);\n        this.logger.debug('MCP server not found in configuration', {\n          serverName,\n          availableServers: Array.from(this.servers.keys()),\n        });\n        return { content: [{ type: 'text', text: toolError.message }], isError: true };\n      }\n    }\n\n    return new Promise((resolve) => {\n      // Use UUID for unique message ID to avoid collisions with concurrent calls\n      const id = randomUUID();\n      const proc = this.processes.get(serverName);\n\n      if (!proc) {\n        this.logger.error(`MCP server not available: ${serverName}`);\n        this.logger.debug('MCP server process not available after start attempt', { serverName });\n        resolve({ content: [{ type: 'text', text: 'Server not available' }], isError: true });\n        return;\n      }\n\n      // Ensure stdout is available\n      const stdout = proc.stdout;\n      if (!stdout) {\n        this.logger.error(`MCP server stdout not available: ${serverName}`);\n        resolve({\n          content: [{ type: 'text', text: 'Server stdout not available' }],\n          isError: true,\n        });\n        return;\n      }\n\n      this.logger.debug('Setting up MCP tool call handler', {\n        serverName,\n        actualToolName,\n        callId: id,\n      });\n\n      let resolved = false;\n\n      const cleanup = () => {\n        if (!resolved) {\n          resolved = true;\n          stdout.off('data', handler);\n          const pendingCallback = this.pendingCallbacks.get(id);\n          if (pendingCallback) {\n            clearTimeout(pendingCallback.timeoutId);\n            this.pendingCallbacks.delete(id);\n          }\n        }\n      };\n\n      const handler = (data: Buffer) => {\n        if (resolved) return;\n\n        const lines = data.toString().split('\\n');\n        for (const line of lines) {\n          if (line.trim()) {\n            try {\n              const response = JSON.parse(line);\n              if (response.id === id) {\n                cleanup();\n\n                const result = response.result ?? {\n                  content: [{ type: 'text', text: 'No result' }],\n                };\n                const isError = !!response.error;\n\n                if (isError) {\n                  this.logger.error(`MCP tool call failed: ${actualToolName}`);\n                  this.logger.debug('MCP tool call error response', {\n                    serverName,\n                    actualToolName,\n                    callId: id,\n                    error: response.error,\n                  });\n                } else {\n                  // User-facing success message\n                  this.logger.debug(`MCP tool completed: ${actualToolName}`);\n\n                  this.logger.debug('MCP tool call successful', {\n                    serverName,\n                    actualToolName,\n                    callId: id,\n                    hasContent: !!result.content,\n                  });\n                }\n\n                resolve(result);\n                return;\n              }\n            } catch (error) {\n              this.logger.debug('Failed to parse MCP tool response', {\n                serverName,\n                actualToolName,\n                callId: id,\n                line,\n                error: error instanceof Error ? error.message : String(error),\n              });\n            }\n          }\n        }\n      };\n\n      stdout.on('data', handler);\n\n      // Set up timeout with configurable duration\n      const timeoutId = setTimeout(() => {\n        if (!resolved) {\n          cleanup();\n\n          // Create normalized ToolError for timeout\n          const toolError = new ToolError(\n            `MCP tool '${actualToolName}' timed out after ${this.toolCallTimeout}ms`,\n            actualToolName,\n            'mcp',\n            'timeout',\n            true // Timeout errors are recoverable - can retry\n          );\n          this.logger.error(`MCP tool call timeout: ${actualToolName}`, toolError);\n          this.logger.debug('MCP tool call timeout', {\n            serverName,\n            actualToolName,\n            callId: id,\n            timeoutMs: this.toolCallTimeout,\n          });\n\n          resolve({ content: [{ type: 'text', text: toolError.message }], isError: true });\n        }\n      }, this.toolCallTimeout);\n\n      // Store callback for cleanup\n      this.pendingCallbacks.set(id, { resolve, timeoutId });\n\n      this.logger.debug('Sending MCP tool call request', {\n        serverName,\n        actualToolName,\n        callId: id,\n      });\n\n      this.sendToServer(serverName, {\n        jsonrpc: '2.0',\n        id,\n        method: 'tools/call',\n        params: { name: actualToolName, arguments: args },\n      });\n    });\n  }\n}\n\n// Agent-based MCP instances - each agent gets its own MCP instance\nconst mcpInstances = new Map<string, MCP>();\n\n/**\n * Get or create an MCP instance for a specific agent.\n * Each agent has its own isolated MCP instance to prevent cross-contamination.\n * @param agent The agent to get the MCP instance for (required)\n * @returns The MCP instance for the agent\n */\nexport function getMCP(agent?: IAgent): MCP {\n  if (!agent) {\n    throw new Error('Agent is required to get MCP instance');\n  }\n  const agentId = agent.id;\n  let instance = mcpInstances.get(agentId);\n  if (!instance) {\n    instance = new MCP(agent);\n    mcpInstances.set(agentId, instance);\n  }\n  return instance;\n}\n\n/**\n * Reset the MCP instance for a specific agent - cleans up all resources\n * @param agentId The agent ID to reset MCP for. If not provided, resets all instances.\n */\nexport async function resetMCPInstance(agentId?: string): Promise<void> {\n  if (agentId) {\n    const instance = mcpInstances.get(agentId);\n    if (instance) {\n      await instance.cleanup();\n      mcpInstances.delete(agentId);\n    }\n  } else {\n    // Reset all instances\n    for (const [id, instance] of mcpInstances.entries()) {\n      await instance.cleanup();\n      mcpInstances.delete(id);\n    }\n  }\n}\n\n/**\n * Cleanup MCP instance for a specific agent\n * @param agentId The agent ID to cleanup MCP for\n */\nexport async function cleanupMCPForAgent(agentId: string): Promise<void> {\n  const mcp = mcpInstances.get(agentId);\n  if (mcp) {\n    // Wait for async cleanup to complete properly\n    try {\n      await mcp.cleanup?.();\n    } catch {\n      // Ignore cleanup errors during destruction\n    }\n    mcpInstances.delete(agentId);\n  }\n}\n\nexport * from './types';\n","import { Pool } from 'pg';\nimport { MetadataObject } from '../types';\nimport { getLogger } from '../logger';\nimport { getEncryptionService } from '../database/encryption';\nimport { getSensitiveFields } from '../database/sensitive-fields';\nimport { countTokens } from '../database/utils';\n\ninterface KnowledgeSearchResult {\n  id: number;\n  content: string;\n  token_count: number;\n  chunk_index: number;\n  chunk_metadata: MetadataObject;\n  document_id: number;\n  document_title: string;\n  file_type: string | null;\n  document_metadata: MetadataObject;\n  similarity: number;\n}\n\ninterface KnowledgeDocument {\n  id: string; // UUID\n  agent_id: string; // UUID\n  title: string | null;\n  content: string;\n  file_type: string | null;\n  file_size: number | null;\n  metadata: MetadataObject;\n  token_count: number;\n  chunk_count: number;\n  created_at: string;\n  updated_at: string;\n}\n\ninterface KnowledgeChunk {\n  id: string; // UUID\n  document_id: string; // UUID\n  agent_id: string; // UUID\n  content: string;\n  token_count: number;\n  chunk_index: number;\n  embedding: number[];\n  metadata: MetadataObject;\n  created_at: string;\n}\n\nexport interface KnowledgeDatabaseConfig {\n  url?: string;\n  embeddingProvider?: {\n    name: string;\n    generateEmbedding?: (text: string, model?: string) => Promise<{ embedding: number[] }>;\n  };\n  embeddingModel?: string;\n}\n\nexport class KnowledgeDatabase {\n  private pool: Pool;\n  private tableName: string = 'knowledge_vectors';\n  private embeddingProvider: {\n    name: string;\n    generateEmbedding?: (text: string, model?: string) => Promise<{ embedding: number[] }>;\n  } | null = null;\n  private embeddingModel: string | null = null;\n  private embeddingDimensions: number | null = null;\n  private tableDimensions: number | null = null;\n  private logger = getLogger();\n  private encryption = getEncryptionService();\n\n  constructor(config?: KnowledgeDatabaseConfig) {\n    const connectionString = config?.url || process.env.KNOWLEDGE_DB_URL;\n\n    if (!connectionString) {\n      throw new Error('KNOWLEDGE_DB_URL environment variable is required for knowledge features');\n    }\n\n    this.pool = new Pool({\n      connectionString,\n      ssl: process.env.NODE_ENV === 'production' ? { rejectUnauthorized: false } : false,\n    });\n\n    this.embeddingProvider = config?.embeddingProvider || null;\n    this.embeddingModel = config?.embeddingModel || null;\n    if (!this.embeddingProvider) {\n      throw new Error('Embedding provider is required for knowledge database');\n    }\n  }\n\n  /**\n   * Encrypt sensitive knowledge fields before storing\n   */\n  private async encryptKnowledgeData(\n    data: Record<string, string | number | boolean | null>,\n    tableName: string\n  ): Promise<Record<string, string | number | boolean | null>> {\n    if (!this.encryption.isEnabled()) {\n      return data;\n    }\n\n    const encrypted = { ...data };\n\n    // Get sensitive fields from centralized configuration\n    const fieldsToEncrypt = getSensitiveFields(tableName);\n\n    for (const field of fieldsToEncrypt) {\n      if (encrypted[field] !== undefined && encrypted[field] !== null) {\n        if (field === 'metadata' && typeof encrypted[field] === 'object') {\n          // Handle JSON metadata fields\n          encrypted[field] = await this.encryption.encryptJSON(\n            encrypted[field],\n            `${tableName}.${field}`\n          );\n        } else {\n          // Handle string fields\n          encrypted[field] = await this.encryption.encrypt(\n            String(encrypted[field]),\n            `${tableName}.${field}`\n          );\n        }\n      }\n    }\n\n    return encrypted;\n  }\n\n  /**\n   * Decrypt sensitive knowledge fields after retrieving\n   */\n  private async decryptKnowledgeData(\n    data: Record<string, string | number | boolean | null>,\n    tableName: string\n  ): Promise<Record<string, string | number | boolean | null>> {\n    if (!this.encryption.isEnabled() || !data) {\n      return data;\n    }\n\n    const decrypted = { ...data };\n\n    // Get sensitive fields from centralized configuration\n    const fieldsToDecrypt = getSensitiveFields(tableName);\n\n    for (const field of fieldsToDecrypt) {\n      if (decrypted[field] !== undefined && decrypted[field] !== null) {\n        if (field === 'metadata') {\n          // Handle JSON metadata fields\n          try {\n            const decryptedMetadata = await this.encryption.decryptJSON(\n              String(decrypted[field]),\n              `${tableName}.${field}`\n            );\n            // Handle null/undefined decryption result gracefully\n            if (decryptedMetadata !== null && decryptedMetadata !== undefined) {\n              decrypted[field] = JSON.stringify(decryptedMetadata);\n            } else {\n              // Keep original value if decryption returns null (might be unencrypted data)\n              this.logger.debug(\n                `Decryption returned null for ${tableName}.${field}, keeping original value`\n              );\n            }\n          } catch (metadataError) {\n            // Handle unencrypted data gracefully - keep original value\n            this.logger.debug(`Failed to decrypt ${tableName}.${field}, keeping original value`, {\n              error: metadataError instanceof Error ? metadataError.message : String(metadataError),\n            });\n          }\n        } else {\n          // Handle string fields\n          try {\n            const decryptedValue = await this.encryption.decrypt(\n              String(decrypted[field]),\n              `${tableName}.${field}`\n            );\n            // Handle null/undefined decryption result gracefully\n            if (decryptedValue !== null && decryptedValue !== undefined) {\n              decrypted[field] = decryptedValue;\n            } else {\n              // Keep original value if decryption returns null\n              this.logger.debug(\n                `Decryption returned null for ${tableName}.${field}, keeping original value`\n              );\n            }\n          } catch (fieldError) {\n            // Handle unencrypted data gracefully - keep original value\n            this.logger.debug(`Failed to decrypt ${tableName}.${field}, keeping original value`, {\n              error: fieldError instanceof Error ? fieldError.message : String(fieldError),\n            });\n          }\n        }\n      }\n    }\n\n    return decrypted;\n  }\n\n  async initialize(): Promise<void> {\n    // Get embedding dimensions from a test embedding\n    if (!this.embeddingDimensions) {\n      // Generate a test embedding to determine dimensions\n      if (!this.embeddingProvider?.generateEmbedding) {\n        throw new Error('Embedding provider not properly initialized');\n      }\n      const testResult = await this.embeddingProvider.generateEmbedding(\n        'test',\n        this.embeddingModel || undefined\n      );\n      this.embeddingDimensions = testResult.embedding.length;\n      this.logger.debug('Detected embedding dimensions', { dimensions: this.embeddingDimensions });\n    }\n\n    const client = await this.pool.connect();\n    try {\n      // Start transaction for atomic initialization\n      await client.query('BEGIN');\n\n      // Enable vector and UUID extensions\n      await client.query('CREATE EXTENSION IF NOT EXISTS vector');\n      await client.query('CREATE EXTENSION IF NOT EXISTS \"uuid-ossp\"');\n\n      // Create documents table\n      await client.query(`\n        CREATE TABLE IF NOT EXISTS knowledge_documents (\n          id UUID PRIMARY KEY DEFAULT gen_random_uuid(),\n          agent_id UUID NOT NULL,\n          title VARCHAR(255),\n          content TEXT NOT NULL,\n          file_type VARCHAR(20),\n          file_size INTEGER,\n          metadata JSONB,\n          token_count INTEGER,\n          chunk_count INTEGER DEFAULT 0,\n          created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,\n          updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP\n        )\n      `);\n\n      // Handle chunks table with dynamic dimensions\n      const chunksTableExists = await client.query(`\n        SELECT EXISTS (\n          SELECT FROM information_schema.tables \n          WHERE table_name = 'knowledge_chunks'\n        )\n      `);\n\n      if (chunksTableExists.rows[0].exists) {\n        // Check if existing table has correct dimensions\n        const columnInfo = await client.query(`\n          SELECT atttypmod \n          FROM pg_attribute \n          WHERE attrelid = 'knowledge_chunks'::regclass \n          AND attname = 'embedding'\n        `);\n\n        const existingDimensions = columnInfo.rows[0]?.atttypmod;\n        this.tableDimensions = existingDimensions;\n\n        if (existingDimensions && existingDimensions !== this.embeddingDimensions) {\n          this.logger.warn(\n            `Dimension mismatch: knowledge_chunks table has ${existingDimensions} dimensions but embedding provider uses ${this.embeddingDimensions} dimensions`\n          );\n          this.logger.warn('This will cause embedding insertion errors. Consider:');\n          this.logger.warn('1. Switch to an embedding provider with matching dimensions');\n          this.logger.warn('2. Or backup data and recreate table with new dimensions');\n          this.logger.warn('3. Or regenerate embeddings with new provider');\n\n          // Check if table has any data\n          const dataCount = await client.query('SELECT COUNT(*) FROM knowledge_chunks');\n          const hasData = parseInt(dataCount.rows[0].count) > 0;\n\n          if (hasData) {\n            this.logger.info(\n              `Table contains ${dataCount.rows[0].count} records. Data will be preserved.`\n            );\n            this.logger.info(\n              'To force recreation with data loss, you can manually drop the table.'\n            );\n            // Don't auto-drop if there's data - let user decide\n            return;\n          } else {\n            this.logger.info('Table is empty, safely recreating with new dimensions...');\n            await client.query('DROP TABLE knowledge_chunks CASCADE');\n            await client.query(`\n              CREATE TABLE knowledge_chunks (\n                id UUID PRIMARY KEY DEFAULT gen_random_uuid(),\n                document_id UUID NOT NULL REFERENCES knowledge_documents(id) ON DELETE CASCADE,\n                agent_id UUID NOT NULL,\n                content TEXT NOT NULL,\n                token_count INTEGER,\n                chunk_index INTEGER,\n                embedding vector(${this.embeddingDimensions}),\n                metadata JSONB,\n                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP\n              )\n            `);\n            this.tableDimensions = this.embeddingDimensions;\n          }\n        } else {\n          this.tableDimensions = this.embeddingDimensions;\n        }\n      } else {\n        // Create new table with correct dimensions\n        await client.query(`\n          CREATE TABLE knowledge_chunks (\n            id UUID PRIMARY KEY DEFAULT gen_random_uuid(),\n            document_id UUID NOT NULL REFERENCES knowledge_documents(id) ON DELETE CASCADE,\n            agent_id UUID NOT NULL,\n            content TEXT NOT NULL,\n            token_count INTEGER,\n            chunk_index INTEGER,\n            embedding vector(${this.embeddingDimensions}),\n            metadata JSONB,\n            created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP\n          )\n        `);\n      }\n\n      // Create indexes for documents\n      await client.query(`\n        CREATE INDEX IF NOT EXISTS knowledge_documents_agent_id_idx \n        ON knowledge_documents (agent_id)\n      `);\n\n      await client.query(`\n        CREATE INDEX IF NOT EXISTS knowledge_documents_file_type_idx \n        ON knowledge_documents (file_type)\n      `);\n\n      // Create indexes for chunks\n      await client.query(`\n        CREATE INDEX IF NOT EXISTS knowledge_chunks_agent_id_idx \n        ON knowledge_chunks (agent_id)\n      `);\n\n      await client.query(`\n        CREATE INDEX IF NOT EXISTS knowledge_chunks_document_id_idx \n        ON knowledge_chunks (document_id)\n      `);\n\n      // Try HNSW index first (better for high dimensions), fallback to IVFFlat\n      try {\n        await client.query(`\n          CREATE INDEX IF NOT EXISTS knowledge_chunks_embedding_idx \n          ON knowledge_chunks \n          USING hnsw (embedding vector_cosine_ops)\n          WITH (m = 16, ef_construction = 64)\n        `);\n      } catch (hnswError) {\n        this.logger.warn('HNSW index creation failed, falling back to IVFFlat');\n        this.logger.debug('HNSW error details', {\n          error: hnswError instanceof Error ? hnswError.message : String(hnswError),\n        });\n\n        // Fallback to IVFFlat with dimension check\n        if (this.embeddingDimensions && this.embeddingDimensions > 2000) {\n          this.logger.error(\n            `Cannot create IVFFlat index: embedding dimensions (${this.embeddingDimensions}) exceed 2000 limit`\n          );\n          throw new Error(\n            `Embedding dimensions (${this.embeddingDimensions}) exceed IVFFlat limit of 2000. ` +\n              'Please use a smaller embedding model or upgrade to PostgreSQL with HNSW support (pgvector 0.5.0+)'\n          );\n        }\n\n        await client.query(`\n          CREATE INDEX IF NOT EXISTS knowledge_chunks_embedding_idx \n          ON knowledge_chunks \n          USING ivfflat (embedding vector_cosine_ops)\n          WITH (lists = 100)\n        `);\n      }\n\n      // Commit transaction on success\n      await client.query('COMMIT');\n      // Knowledge database initialized successfully\n    } catch (error) {\n      // Rollback transaction on failure\n      try {\n        await client.query('ROLLBACK');\n      } catch (rollbackError) {\n        // Logger.error signature: (message, error?, data?, agentName?)\n        const rollbackErr =\n          rollbackError instanceof Error ? rollbackError : new Error(String(rollbackError));\n        this.logger.error('Failed to rollback knowledge database initialization', rollbackErr, {\n          originalError: error instanceof Error ? error.message : String(error),\n        });\n      }\n      // Failed to initialize knowledge database\n      throw new Error(`Knowledge database initialization failed: ${error}`);\n    } finally {\n      client.release();\n    }\n  }\n\n  async addDocument(\n    agentId: string, // UUID\n    title: string,\n    content: string,\n    fileType?: string,\n    fileSize?: number,\n    metadata?: MetadataObject\n  ): Promise<string> {\n    // Returns UUID\n    const client = await this.pool.connect();\n    try {\n      const tokenCount = countTokens(content);\n\n      // Prepare data for encryption\n      const documentData = {\n        agent_id: agentId,\n        title,\n        content,\n        file_type: fileType,\n        file_size: fileSize,\n        metadata: metadata || {},\n        token_count: tokenCount,\n      };\n\n      // Remove undefined values before encryption\n      const cleanedDocumentData = Object.fromEntries(\n        Object.entries(documentData).filter(([, value]) => value !== undefined)\n      ) as Record<string, string | number | boolean | null>;\n\n      // Encrypt sensitive fields\n      const encryptedData = await this.encryptKnowledgeData(\n        cleanedDocumentData,\n        'knowledge_documents'\n      );\n\n      const result = await client.query(\n        `INSERT INTO knowledge_documents (agent_id, title, content, file_type, file_size, metadata, token_count) \n         VALUES ($1, $2, $3, $4, $5, $6, $7) \n         RETURNING id`,\n        [\n          encryptedData.agent_id,\n          encryptedData.title,\n          encryptedData.content,\n          encryptedData.file_type,\n          encryptedData.file_size,\n          encryptedData.metadata,\n          encryptedData.token_count,\n        ]\n      );\n      return result.rows[0].id;\n    } finally {\n      client.release();\n    }\n  }\n\n  async addChunk(\n    documentId: string, // UUID\n    agentId: string, // UUID\n    content: string,\n    embedding: number[],\n    chunkIndex: number,\n    metadata?: MetadataObject\n  ): Promise<string> {\n    // Returns UUID\n    // Check dimension compatibility\n    if (this.tableDimensions && embedding.length !== this.tableDimensions) {\n      throw new Error(\n        `Embedding dimension mismatch: got ${embedding.length} dimensions but table expects ${this.tableDimensions}. ` +\n          `Current embedding provider: ${this.embeddingProvider?.name || 'unknown'} (${this.embeddingDimensions} dimensions). ` +\n          `Please ensure embedding provider matches table schema or recreate table.`\n      );\n    }\n\n    const client = await this.pool.connect();\n    try {\n      const tokenCount = countTokens(content);\n\n      // Prepare data for encryption\n      const chunkData = {\n        document_id: documentId,\n        agent_id: agentId,\n        content,\n        token_count: tokenCount,\n        chunk_index: chunkIndex,\n        embedding: `[${embedding.join(',')}]`, // Keep embedding as is - it's not sensitive\n        metadata: metadata || {},\n      };\n\n      // Convert metadata to string for encryption compatibility\n      const cleanedChunkData = {\n        ...chunkData,\n        metadata: JSON.stringify(chunkData.metadata),\n      } as Record<string, string | number | boolean | null>;\n\n      // Encrypt sensitive fields (not embedding)\n      const encryptedData = await this.encryptKnowledgeData(cleanedChunkData, 'knowledge_chunks');\n\n      const result = await client.query(\n        `INSERT INTO knowledge_chunks (document_id, agent_id, content, token_count, chunk_index, embedding, metadata) \n         VALUES ($1, $2, $3, $4, $5, $6, $7) \n         RETURNING id`,\n        [\n          encryptedData.document_id,\n          encryptedData.agent_id,\n          encryptedData.content,\n          encryptedData.token_count,\n          encryptedData.chunk_index,\n          encryptedData.embedding,\n          encryptedData.metadata,\n        ]\n      );\n\n      // Update document chunk count\n      await client.query(\n        `UPDATE knowledge_documents \n         SET chunk_count = (SELECT COUNT(*) FROM knowledge_chunks WHERE document_id = $1),\n             updated_at = CURRENT_TIMESTAMP\n         WHERE id = $1`,\n        [documentId]\n      );\n\n      return result.rows[0].id;\n    } finally {\n      client.release();\n    }\n  }\n\n  async searchKnowledge(\n    agentId: string, // UUID\n    embedding: number[],\n    limit: number = 10,\n    threshold: number = 0.7\n  ): Promise<KnowledgeSearchResult[]> {\n    const client = await this.pool.connect();\n    try {\n      const result = await client.query(\n        `SELECT \n           c.id,\n           c.content,\n           c.token_count,\n           c.chunk_index,\n           c.metadata as chunk_metadata,\n           d.id as document_id,\n           d.title as document_title,\n           d.file_type,\n           d.metadata as document_metadata,\n           1 - (c.embedding <=> $1::vector) as similarity\n         FROM knowledge_chunks c\n         JOIN knowledge_documents d ON c.document_id = d.id\n         WHERE c.agent_id = $2\n         AND 1 - (c.embedding <=> $1::vector) > $3\n         ORDER BY c.embedding <=> $1::vector\n         LIMIT $4`,\n        [`[${embedding.join(',')}]`, agentId, threshold, limit]\n      );\n\n      // Decrypt sensitive fields in search results\n      if (this.encryption.isEnabled()) {\n        const decryptedResults = await Promise.all(\n          result.rows.map(async (row) => {\n            try {\n              // Decrypt chunk content and metadata\n              const decryptedChunk = await this.decryptKnowledgeData(\n                { content: row.content, metadata: row.chunk_metadata },\n                'knowledge_chunks'\n              );\n\n              // Decrypt document title and metadata\n              const decryptedDoc = await this.decryptKnowledgeData(\n                {\n                  title: row.document_title,\n                  metadata: row.document_metadata,\n                },\n                'knowledge_documents'\n              );\n\n              return {\n                ...row,\n                content: decryptedChunk.content,\n                chunk_metadata: decryptedChunk.metadata,\n                document_title: decryptedDoc.title,\n                document_metadata: decryptedDoc.metadata,\n              };\n            } catch {\n              // Handle unencrypted data gracefully\n              this.logger.debug('Failed to decrypt knowledge search result', {\n                chunkId: row.id,\n                documentId: row.document_id,\n              });\n              return row;\n            }\n          })\n        );\n        return decryptedResults;\n      }\n\n      return result.rows;\n    } finally {\n      client.release();\n    }\n  }\n\n  async getDocuments(agentId: string): Promise<KnowledgeDocument[]> {\n    // UUID\n    const client = await this.pool.connect();\n    try {\n      const result = await client.query(\n        `SELECT * FROM knowledge_documents \n         WHERE agent_id = $1 \n         ORDER BY created_at DESC`,\n        [agentId]\n      );\n\n      // Decrypt sensitive fields in documents\n      if (this.encryption.isEnabled()) {\n        const decryptedDocuments = await Promise.all(\n          result.rows.map(async (document) => {\n            try {\n              return await this.decryptKnowledgeData(document, 'knowledge_documents');\n            } catch {\n              // Handle unencrypted data gracefully\n              this.logger.debug('Failed to decrypt document', { documentId: document.id });\n              return document;\n            }\n          })\n        );\n        return decryptedDocuments;\n      }\n\n      return result.rows;\n    } finally {\n      client.release();\n    }\n  }\n\n  async getDocumentChunks(documentId: string): Promise<KnowledgeChunk[]> {\n    // UUID\n    const client = await this.pool.connect();\n    try {\n      const result = await client.query(\n        `SELECT * FROM knowledge_chunks \n         WHERE document_id = $1 \n         ORDER BY chunk_index`,\n        [documentId]\n      );\n\n      // Decrypt sensitive fields in chunks\n      if (this.encryption.isEnabled()) {\n        const decryptedChunks = await Promise.all(\n          result.rows.map(async (chunk) => {\n            try {\n              return await this.decryptKnowledgeData(chunk, 'knowledge_chunks');\n            } catch {\n              // Handle unencrypted data gracefully\n              this.logger.debug('Failed to decrypt chunk', { chunkId: chunk.id });\n              return chunk;\n            }\n          })\n        );\n        return decryptedChunks;\n      }\n\n      return result.rows;\n    } finally {\n      client.release();\n    }\n  }\n\n  async deleteDocument(documentId: string): Promise<boolean> {\n    // UUID\n    const client = await this.pool.connect();\n    try {\n      const result = await client.query(`DELETE FROM knowledge_documents WHERE id = $1`, [\n        documentId,\n      ]);\n      return (result.rowCount || 0) > 0;\n    } finally {\n      client.release();\n    }\n  }\n\n  async deleteChunk(chunkId: string): Promise<boolean> {\n    // UUID\n    const client = await this.pool.connect();\n    try {\n      const result = await client.query(`DELETE FROM knowledge_chunks WHERE id = $1`, [chunkId]);\n      return (result.rowCount || 0) > 0;\n    } finally {\n      client.release();\n    }\n  }\n\n  async clearAgentKnowledge(agentId: string): Promise<void> {\n    // UUID\n    const client = await this.pool.connect();\n    try {\n      await client.query(`DELETE FROM knowledge_documents WHERE agent_id = $1`, [agentId]);\n    } finally {\n      client.release();\n    }\n  }\n\n  async expandKnowledgeContext(\n    documentId: string, // UUID\n    chunkIndex: number,\n    expandBefore: number = 1,\n    expandAfter: number = 1\n  ): Promise<string[]> {\n    const client = await this.pool.connect();\n    try {\n      const result = await client.query(\n        `SELECT content, chunk_index \n         FROM knowledge_chunks \n         WHERE document_id = $1 \n         AND chunk_index BETWEEN $2 AND $3\n         ORDER BY chunk_index`,\n        [documentId, Math.max(0, chunkIndex - expandBefore), chunkIndex + expandAfter]\n      );\n\n      return result.rows.map((row) => row.content);\n    } finally {\n      client.release();\n    }\n  }\n\n  async close(): Promise<void> {\n    await this.pool.end();\n  }\n}\n\n// Singleton instance with mutex for race condition prevention\nlet knowledgeDb: KnowledgeDatabase | null = null;\nlet initializationPromise: Promise<KnowledgeDatabase> | null = null;\nlet currentConfig: KnowledgeDatabaseConfig | undefined = undefined;\n\n/**\n * Get the singleton knowledge database instance.\n * Uses a mutex pattern to prevent race conditions when multiple\n * callers request the database simultaneously.\n *\n * @param config - Optional configuration for the database.\n *                 Note: If the database is already initialized, a new config\n *                 will be ignored. A warning will be logged if configs differ.\n * @returns Promise resolving to the KnowledgeDatabase instance\n */\nexport async function getKnowledgeDatabase(\n  config?: KnowledgeDatabaseConfig\n): Promise<KnowledgeDatabase> {\n  // If already initialized, return existing instance\n  if (knowledgeDb) {\n    // Warn if different config is provided after initialization\n    if (config && currentConfig) {\n      const configChanged =\n        config.url !== currentConfig.url ||\n        config.embeddingModel !== currentConfig.embeddingModel ||\n        config.embeddingProvider?.name !== currentConfig.embeddingProvider?.name;\n\n      if (configChanged) {\n        const logger = getLogger();\n        logger.warn(\n          'getKnowledgeDatabase called with different config after initialization. ' +\n            'The new config will be ignored. To use a different config, restart the application.',\n          {\n            existingProvider: currentConfig.embeddingProvider?.name,\n            newProvider: config.embeddingProvider?.name,\n            existingModel: currentConfig.embeddingModel,\n            newModel: config.embeddingModel,\n          }\n        );\n      }\n    }\n    return knowledgeDb;\n  }\n\n  // If initialization is in progress, wait for it (mutex pattern)\n  if (initializationPromise) {\n    return initializationPromise;\n  }\n\n  // Start initialization with mutex\n  initializationPromise = (async () => {\n    try {\n      const db = new KnowledgeDatabase(config);\n      await db.initialize();\n      knowledgeDb = db;\n      currentConfig = config;\n      return db;\n    } catch (error) {\n      // Reset on failure so next call can retry\n      initializationPromise = null;\n      throw error;\n    }\n  })();\n\n  return initializationPromise;\n}\n","/**\n * Default configuration values for knowledge module\n */\nexport const DEFAULT_KNOWLEDGE_CONFIG = {\n  chunkSize: 1500,\n  chunkOverlap: 300,\n  searchLimit: 5,\n  searchThreshold: 0.7,\n  defaultTitle: 'Untitled Document',\n} as const;\n\n/**\n * Get default value for a knowledge config property\n */\nexport function getKnowledgeDefaultValue<K extends keyof typeof DEFAULT_KNOWLEDGE_CONFIG>(\n  key: K\n): (typeof DEFAULT_KNOWLEDGE_CONFIG)[K] {\n  return DEFAULT_KNOWLEDGE_CONFIG[key];\n}\n","import { ToolDefinition, ToolResult, ToolContext, ToolParameterValue } from '../plugin/types';\nimport { DEFAULT_KNOWLEDGE_CONFIG } from './defaults';\n\ninterface KnowledgeResult {\n  content: string;\n  similarity: number;\n  metadata?: Record<string, string | number | boolean | null>;\n}\n\ninterface AgentWithKnowledge {\n  hasKnowledge(): boolean;\n  searchKnowledge?(query: string, limit: number, threshold: number): Promise<KnowledgeResult[]>;\n  /**\n   * Expand knowledge context by including surrounding chunks from the same document.\n   * @param documentId - UUID string of the document (storage returns UUIDs as strings)\n   * @param chunkIndex - Index of the chunk to expand around\n   * @param expandBefore - Number of chunks to include before\n   * @param expandAfter - Number of chunks to include after\n   */\n  expandKnowledgeContext?(\n    documentId: string,\n    chunkIndex: number,\n    expandBefore?: number,\n    expandAfter?: number\n  ): Promise<string[]>;\n}\n\nexport const knowledgeSearchTool: ToolDefinition = {\n  name: 'search_knowledge',\n  description:\n    \"Search through the agent's knowledge base for relevant information. Start with default threshold (0.7), but if you get 0 results, immediately retry with a lower threshold like 0.5 or 0.4 to find more results.\",\n  parameters: {\n    query: {\n      name: 'query',\n      type: 'string',\n      description: 'The search query to find relevant information in the knowledge base',\n      required: true,\n    },\n    limit: {\n      name: 'limit',\n      type: 'number',\n      description: 'Maximum number of results to return (default: 5)',\n    },\n    threshold: {\n      name: 'threshold',\n      type: 'number',\n      description:\n        'Similarity threshold for results (0.0-1.0, default: 0.4). Lower values (0.3-0.5) return more results but less precise matches. Higher values (0.7-0.9) return fewer, more precise matches.',\n    },\n    expand_context: {\n      name: 'expand_context',\n      type: 'boolean',\n      description:\n        'Whether to expand context by including surrounding chunks from the same document for richer context (default: false)',\n    },\n    expand_before: {\n      name: 'expand_before',\n      type: 'number',\n      description:\n        'Number of chunks to include before each result when expanding context (default: 1)',\n    },\n    expand_after: {\n      name: 'expand_after',\n      type: 'number',\n      description:\n        'Number of chunks to include after each result when expanding context (default: 1)',\n    },\n  },\n  handler: async (\n    params: Record<string, ToolParameterValue>,\n    context?: ToolContext\n  ): Promise<ToolResult> => {\n    try {\n      // Extract and validate parameters\n      const query = params.query as string;\n      const limit = (params.limit as number) || DEFAULT_KNOWLEDGE_CONFIG.searchLimit;\n      const threshold = (params.threshold as number) || DEFAULT_KNOWLEDGE_CONFIG.searchThreshold;\n      const expandContext = (params.expand_context as boolean) || false;\n      const expandBefore = (params.expand_before as number) || 1;\n      const expandAfter = (params.expand_after as number) || 1;\n\n      // Get agent instance from context\n      const agent = context?.agent as AgentWithKnowledge;\n\n      if (!agent) {\n        throw new Error('Agent context not available');\n      }\n\n      // Check if agent has knowledge capability\n      if (!agent.hasKnowledge() || !agent.searchKnowledge) {\n        return {\n          success: false,\n          data: null,\n          error: 'Agent does not have knowledge capabilities enabled',\n        };\n      }\n\n      const results = await agent.searchKnowledge(query, limit, threshold);\n\n      // Auto-retry with lower threshold if no results and threshold >= 0.4\n      let finalResults = results;\n      let retryMessage = '';\n\n      if (results.length === 0 && threshold > 0.4) {\n        const retryThreshold = 0.4;\n        const retryResults = await agent.searchKnowledge(query, limit, retryThreshold);\n        if (retryResults.length > 0) {\n          finalResults = retryResults;\n          retryMessage = ` (found with lower threshold ${retryThreshold})`;\n        }\n      }\n\n      if (finalResults.length === 0) {\n        return {\n          success: true,\n          data: JSON.stringify({\n            message: 'No relevant information found in knowledge base',\n            results: [],\n            query,\n          }),\n        };\n      }\n\n      // Process results with optional context expansion\n      let processedResults = finalResults.map((result: KnowledgeResult) => ({\n        content: result.content,\n        similarity: result.similarity,\n        metadata: result.metadata,\n      }));\n\n      // Expand context if requested and agent supports it\n      if (\n        expandContext &&\n        'expandKnowledgeContext' in agent &&\n        typeof agent.expandKnowledgeContext === 'function'\n      ) {\n        try {\n          processedResults = await Promise.all(\n            finalResults.map(async (result: KnowledgeResult) => {\n              // Extract document ID and chunk index from metadata\n              const documentId = result.metadata?.documentId;\n              const chunkIndex = result.metadata?.chunkIndex;\n\n              if (\n                typeof documentId === 'string' &&\n                typeof chunkIndex === 'number' &&\n                agent.expandKnowledgeContext\n              ) {\n                try {\n                  const expandedChunks = await agent.expandKnowledgeContext(\n                    documentId,\n                    chunkIndex,\n                    expandBefore,\n                    expandAfter\n                  );\n\n                  // Combine expanded chunks into single content\n                  const expandedContent = expandedChunks.join('\\n\\n');\n\n                  return {\n                    content: expandedContent,\n                    similarity: result.similarity,\n                    metadata: {\n                      ...result.metadata,\n                      expanded: true,\n                      originalContent: result.content,\n                      expandedChunks: expandedChunks.length,\n                    },\n                  };\n                } catch (expandError) {\n                  // If expansion fails, return original result\n                  return {\n                    content: result.content,\n                    similarity: result.similarity,\n                    metadata: {\n                      ...result.metadata,\n                      expandError:\n                        expandError instanceof Error ? expandError.message : 'Expansion failed',\n                    },\n                  };\n                }\n              }\n\n              // If no document ID or chunk index, return original\n              return {\n                content: result.content,\n                similarity: result.similarity,\n                metadata: result.metadata,\n              };\n            })\n          );\n        } catch {\n          // If context expansion fails completely, continue with original results\n          processedResults = finalResults.map((result: KnowledgeResult) => ({\n            content: result.content,\n            similarity: result.similarity,\n            metadata: {\n              ...result.metadata,\n              expandError: 'Context expansion not supported',\n            },\n          }));\n        }\n      }\n\n      return {\n        success: true,\n        data: JSON.stringify({\n          message: `Found ${finalResults.length} relevant result(s)${expandContext ? ' with expanded context' : ''}${retryMessage}`,\n          results: processedResults,\n          query,\n          expandedContext: expandContext,\n        }),\n      };\n    } catch (error) {\n      return {\n        success: false,\n        data: null,\n        error: `Knowledge search failed: ${error}`,\n      };\n    }\n  },\n};\n\nexport const knowledgeTools = [knowledgeSearchTool];\n","import { IAgentModule, IAgent } from '../agent/types';\nimport { getLLMProvider } from '../llm';\nimport { OpenAIProvider } from '../llm/providers/openai';\nimport { GeminiProvider } from '../llm/providers/gemini';\nimport { OllamaProvider } from '../llm/providers/ollama';\nimport { KnowledgeDatabase, KnowledgeDatabaseConfig, getKnowledgeDatabase } from './storage';\nimport { MetadataObject } from '../types';\nimport { knowledgeTools } from './plugin';\nimport { ToolDefinition } from '../plugin/types';\nimport { Logger } from '../logger/types';\nimport { DEFAULT_KNOWLEDGE_CONFIG } from './defaults';\nimport type { TextItem, TextMarkedContent } from 'pdfjs-dist/types/src/display/api';\nimport { getFileSizeAsync } from '../database/utils';\nimport * as fs from 'fs';\nimport * as path from 'path';\n\nexport interface KnowledgeConfig {\n  database?: KnowledgeDatabaseConfig;\n  embeddingProvider?: 'openai' | 'gemini' | 'ollama';\n  embeddingModel?: string;\n  embeddingApiKey?: string;\n  chunkSize?: number;\n  chunkOverlap?: number;\n}\n\n/**\n * Cache for LLM provider instances used during model detection.\n * Prevents creating multiple instances of the same provider which is wasteful\n * and can cause issues with connection pooling.\n */\nconst providerInstanceCache: {\n  openai?: OpenAIProvider;\n  gemini?: GeminiProvider;\n  ollama?: OllamaProvider;\n} = {};\n\nexport class Knowledge implements IAgentModule {\n  readonly name = 'knowledge';\n  private database: KnowledgeDatabase | null = null;\n  private embeddingProvider: {\n    name: string;\n    generateEmbedding?: (text: string, model?: string) => Promise<{ embedding: number[] }>;\n  } | null = null;\n  private embeddingModel: string;\n  private chunkSize: number;\n  private chunkOverlap: number;\n  private logger: Logger;\n  private config: KnowledgeConfig;\n\n  constructor(\n    private agent: IAgent,\n    config?: KnowledgeConfig\n  ) {\n    this.config = config ?? {};\n    this.chunkSize = config?.chunkSize ?? DEFAULT_KNOWLEDGE_CONFIG.chunkSize;\n    this.chunkOverlap = config?.chunkOverlap ?? DEFAULT_KNOWLEDGE_CONFIG.chunkOverlap;\n    this.logger = agent.logger;\n    // Initialize embedding model from agent config or config parameter\n    this.embeddingModel = this.agent.config.embeddingModel || config?.embeddingModel || '';\n  }\n\n  async initialize(): Promise<void> {\n    // Initialize embedding provider\n    await this.initializeEmbeddingProvider();\n\n    // Register knowledge tools if agent has plugin system\n    if (this.agent && 'registerPlugin' in this.agent) {\n      try {\n        const knowledgePlugin = {\n          name: 'knowledge-tools',\n          version: '1.0.0',\n          description: 'Built-in knowledge search tools',\n          tools: knowledgeTools,\n        };\n        await (\n          this.agent as IAgent & {\n            registerPlugin: (plugin: {\n              name: string;\n              version: string;\n              description?: string;\n              tools?: ToolDefinition[];\n            }) => Promise<void>;\n          }\n        ).registerPlugin(knowledgePlugin);\n      } catch (error) {\n        // Plugin registration failed, but knowledge module can still work\n        this.logger.debug('Failed to register knowledge tools', {\n          error: error instanceof Error ? error.message : String(error),\n        });\n      }\n    }\n  }\n\n  private async initializeEmbeddingProvider(): Promise<void> {\n    // Use agent's embeddingModel if specified\n    this.logger.debug(\n      `Initializing embedding provider. Config model: ${this.agent.config.embeddingModel || 'none'}`\n    );\n\n    if (this.agent.config.embeddingModel) {\n      this.embeddingModel = this.agent.config.embeddingModel;\n      this.logger.info(`Using specified embedding model: ${this.embeddingModel}`);\n      // Auto-detect provider based on model\n      const providerConfig = this.detectProviderFromModel(this.embeddingModel);\n\n      // Create provider with dedicated embedding configuration - NEVER use main OPENAI_BASE_URL\n      const config: { apiKey?: string; baseUrl?: string | null; logger?: Logger } = {\n        apiKey: providerConfig.apiKey,\n        baseUrl: providerConfig.baseUrl || null, // Explicitly set to null to prevent fallback to OPENAI_BASE_URL\n        logger: this.logger,\n      };\n\n      const mainProvider = await getLLMProvider(providerConfig.provider, config);\n      this.embeddingProvider = mainProvider.getEmbeddingProvider?.() || mainProvider;\n    } else {\n      // Auto-detect based on available API keys and config\n      this.logger.warn('No embeddingModel specified, using auto-detection');\n      const providerConfig = this.autoDetectEmbeddingProvider();\n\n      // Create provider with dedicated embedding configuration - NEVER use main OPENAI_BASE_URL\n      const config: { apiKey?: string; baseUrl?: string | null; logger?: Logger } = {\n        apiKey: providerConfig.apiKey,\n        baseUrl: providerConfig.baseUrl || null, // Explicitly set to null to prevent fallback to OPENAI_BASE_URL\n        logger: this.logger,\n      };\n\n      const mainProvider = await getLLMProvider(providerConfig.provider, config);\n      this.embeddingProvider = mainProvider.getEmbeddingProvider?.() || mainProvider;\n      this.embeddingModel = providerConfig.model;\n    }\n\n    this.logger.info(`Knowledge system using ${this.embeddingProvider.name} embeddings`);\n    this.logger.debug('Embedding provider initialized', {\n      provider: this.embeddingProvider.name,\n      model: this.embeddingModel,\n      agentId: this.agent.id,\n      usingDedicatedProvider: !!this.embeddingProvider.name.includes('-embedding'),\n    });\n  }\n\n  /**\n   * Get or create a cached OpenAI provider instance\n   */\n  private getCachedOpenAIProvider(apiKey: string): OpenAIProvider {\n    if (!providerInstanceCache.openai) {\n      providerInstanceCache.openai = new OpenAIProvider({ apiKey });\n    }\n    return providerInstanceCache.openai;\n  }\n\n  /**\n   * Get or create a cached Gemini provider instance\n   */\n  private getCachedGeminiProvider(apiKey: string): GeminiProvider {\n    if (!providerInstanceCache.gemini) {\n      providerInstanceCache.gemini = new GeminiProvider({ apiKey });\n    }\n    return providerInstanceCache.gemini;\n  }\n\n  /**\n   * Get or create a cached Ollama provider instance\n   */\n  private getCachedOllamaProvider(baseUrl?: string): OllamaProvider {\n    if (!providerInstanceCache.ollama) {\n      providerInstanceCache.ollama = new OllamaProvider({ baseUrl });\n    }\n    return providerInstanceCache.ollama;\n  }\n\n  private detectProviderFromModel(model: string): {\n    provider: 'openai' | 'gemini' | 'ollama';\n    apiKey?: string;\n    baseUrl?: string;\n    model: string;\n  } {\n    try {\n      // Check OpenAI provider - prioritize dedicated embedding API key\n      if (process.env.OPENAI_EMBEDDING_API_KEY) {\n        const apiKey = process.env.OPENAI_EMBEDDING_API_KEY;\n        const openaiProvider = this.getCachedOpenAIProvider(apiKey);\n        if (openaiProvider.getEmbeddingModels().includes(model)) {\n          return {\n            provider: 'openai',\n            apiKey,\n            baseUrl: process.env.OPENAI_EMBEDDING_BASE_URL, // Only dedicated URL, no fallback\n            model,\n          };\n        }\n      }\n\n      // Only use main OPENAI_API_KEY if it's not an OpenRouter key (which would have a base URL set)\n      if (process.env.OPENAI_API_KEY && !process.env.OPENAI_BASE_URL) {\n        const apiKey = process.env.OPENAI_API_KEY;\n        const openaiProvider = this.getCachedOpenAIProvider(apiKey);\n        if (openaiProvider.getEmbeddingModels().includes(model)) {\n          return {\n            provider: 'openai',\n            apiKey,\n            baseUrl: process.env.OPENAI_EMBEDDING_BASE_URL, // Only dedicated URL, no fallback\n            model,\n          };\n        }\n      }\n    } catch {\n      // OpenAI provider not available, continue to next\n    }\n\n    try {\n      // Check Gemini provider\n      const geminiApiKey = process.env.GEMINI_EMBEDDING_API_KEY || process.env.GEMINI_API_KEY;\n      if (geminiApiKey) {\n        const geminiProvider = this.getCachedGeminiProvider(geminiApiKey);\n        if (geminiProvider.getEmbeddingModels().includes(model)) {\n          return {\n            provider: 'gemini',\n            apiKey: geminiApiKey,\n            baseUrl: process.env.GEMINI_EMBEDDING_BASE_URL, // Only dedicated URL, no fallback\n            model,\n          };\n        }\n      }\n    } catch {\n      // Gemini provider not available, continue to next\n    }\n\n    try {\n      // Check Ollama provider (always try as fallback)\n      const ollamaProvider = this.getCachedOllamaProvider(process.env.OLLAMA_BASE_URL);\n      if (ollamaProvider.getEmbeddingModels().includes(model)) {\n        return {\n          provider: 'ollama',\n          baseUrl: process.env.OLLAMA_BASE_URL,\n          model,\n        };\n      }\n    } catch {\n      // Ollama provider not available\n    }\n\n    // If no provider supports this model, throw error\n    throw new Error(`No embedding provider found that supports model: ${model}`);\n  }\n\n  private autoDetectEmbeddingProvider(): {\n    provider: 'openai' | 'gemini' | 'ollama';\n    apiKey?: string;\n    baseUrl?: string;\n    model: string;\n  } {\n    // Priority: OpenAI -> Gemini -> Ollama\n    try {\n      // Try OpenAI first - prioritize dedicated embedding API key\n      if (process.env.OPENAI_EMBEDDING_API_KEY) {\n        const apiKey = process.env.OPENAI_EMBEDDING_API_KEY;\n        const openaiProvider = this.getCachedOpenAIProvider(apiKey);\n        const models = openaiProvider.getEmbeddingModels();\n        if (models.length > 0) {\n          return {\n            provider: 'openai',\n            apiKey,\n            baseUrl: process.env.OPENAI_EMBEDDING_BASE_URL, // Only dedicated URL, no fallback\n            model: models[0], // Use first available model as default\n          };\n        }\n      }\n\n      // Only use main OPENAI_API_KEY if it's not an OpenRouter key (which would have a base URL set)\n      if (process.env.OPENAI_API_KEY && !process.env.OPENAI_BASE_URL) {\n        const apiKey = process.env.OPENAI_API_KEY;\n        const openaiProvider = this.getCachedOpenAIProvider(apiKey);\n        const models = openaiProvider.getEmbeddingModels();\n        if (models.length > 0) {\n          return {\n            provider: 'openai',\n            apiKey,\n            baseUrl: process.env.OPENAI_EMBEDDING_BASE_URL, // Only dedicated URL, no fallback\n            model: models[0], // Use first available model as default\n          };\n        }\n      }\n    } catch {\n      // OpenAI provider not available, continue to next\n    }\n\n    try {\n      // Try Gemini second\n      const geminiKey = process.env.GEMINI_EMBEDDING_API_KEY || process.env.GEMINI_API_KEY;\n      if (geminiKey) {\n        const geminiProvider = this.getCachedGeminiProvider(geminiKey);\n        const models = geminiProvider.getEmbeddingModels();\n        if (models.length > 0) {\n          return {\n            provider: 'gemini',\n            apiKey: geminiKey,\n            baseUrl: process.env.GEMINI_EMBEDDING_BASE_URL, // Only dedicated URL, no fallback\n            model: models[0], // Use first available model as default\n          };\n        }\n      }\n    } catch {\n      // Gemini provider not available, continue to next\n    }\n\n    try {\n      // Default to Ollama (local)\n      const ollamaProvider = this.getCachedOllamaProvider(process.env.OLLAMA_BASE_URL);\n      const models = ollamaProvider.getEmbeddingModels();\n      if (models.length > 0) {\n        return {\n          provider: 'ollama',\n          baseUrl: process.env.OLLAMA_BASE_URL,\n          model: models[0], // Use first available model as default\n        };\n      }\n    } catch {\n      // Ollama provider not available\n    }\n\n    // If no provider is available, throw error\n    throw new Error(\n      'No embedding provider available. Please configure at least one embedding provider.'\n    );\n  }\n\n  private async getDatabase(): Promise<KnowledgeDatabase> {\n    this.logger.debug('Getting knowledge database instance');\n    if (!this.database) {\n      this.logger.debug('Database not cached, creating new instance');\n      if (!this.embeddingProvider) {\n        this.logger.error('Embedding provider not initialized for database');\n        throw new Error('Embedding provider not initialized');\n      }\n      try {\n        this.logger.debug('Creating knowledge database', {\n          embeddingModel: this.embeddingModel,\n          providerName: this.embeddingProvider.name,\n        });\n        this.database = await getKnowledgeDatabase({\n          embeddingProvider: this.embeddingProvider,\n          embeddingModel: this.embeddingModel,\n        });\n        this.logger.debug('Knowledge database created successfully');\n      } catch (dbError) {\n        this.logger.error('Failed to create knowledge database');\n        this.logger.debug('Database creation error', {\n          errorMessage: dbError instanceof Error ? dbError.message : String(dbError),\n          embeddingModel: this.embeddingModel,\n        });\n        throw dbError;\n      }\n    } else {\n      this.logger.debug('Using cached database instance');\n    }\n    return this.database;\n  }\n\n  async addKnowledge(content: string, title?: string, metadata?: MetadataObject): Promise<string> {\n    // Returns UUID\n    const startTime = Date.now();\n\n    // User-facing info log\n    this.logger.info(\n      `Creating knowledge document: ${title || DEFAULT_KNOWLEDGE_CONFIG.defaultTitle}`\n    );\n\n    // Detailed debug log with all data\n    this.logger.debug('Creating knowledge document', {\n      title: title || 'none',\n      contentLength: content.length,\n      agentId: this.agent.id,\n      hasMetadata: !!metadata,\n    });\n\n    const db = await this.getDatabase();\n\n    // Add document first\n    const documentId = await db.addDocument(\n      this.agent.id,\n      title || 'Untitled Document',\n      content,\n      typeof metadata?.fileType === 'string' ? metadata.fileType : undefined,\n      typeof metadata?.fileSize === 'number' ? metadata.fileSize : undefined,\n      metadata\n    );\n\n    // Create and add chunks\n    const chunks = this.chunkText(content);\n\n    // User-facing info about chunk processing\n    this.logger.info(`Processing document into ${chunks.length} chunks for indexing`);\n\n    this.logger.debug(`Splitting content into ${chunks.length} chunks`, {\n      chunkSize: this.chunkSize,\n      chunkOverlap: this.chunkOverlap,\n      totalChunks: chunks.length,\n      firstChunkPreview: chunks.length > 0 ? chunks[0].slice(0, 100) + '...' : '(empty)',\n    });\n\n    for (let i = 0; i < chunks.length; i++) {\n      const chunk = chunks[i];\n\n      // Bounds check for chunk array access\n      if (chunk === undefined) {\n        this.logger.warn(`Skipping undefined chunk at index ${i}`);\n        continue;\n      }\n\n      // Show progress for long documents\n      if (i % 5 === 0 && chunks.length > 10) {\n        this.logger.info(`Processing chunk ${i + 1} of ${chunks.length}`);\n      }\n\n      this.logger.debug(`Generating embedding for chunk ${i + 1}/${chunks.length}`, {\n        chunkIndex: i,\n        chunkLength: chunk.length,\n        chunkPreview: chunk.slice(0, 50) + '...',\n      });\n\n      if (!this.embeddingProvider?.generateEmbedding) {\n        throw new Error('Embedding provider not properly initialized');\n      }\n      const embeddingResult = await this.embeddingProvider.generateEmbedding(\n        chunk,\n        this.embeddingModel\n      );\n      const embedding = embeddingResult.embedding;\n\n      await db.addChunk(documentId, this.agent.id, chunk, embedding, i, {\n        totalChunks: chunks.length,\n        ...metadata,\n      });\n    }\n\n    // User-facing success message\n    this.logger.info(`Knowledge document created successfully with ID: ${documentId}`);\n\n    this.logger.debug('Knowledge document created successfully', {\n      documentId,\n      totalChunks: chunks.length,\n      ...(title && { title }),\n      processingTime: Date.now() - startTime,\n    });\n\n    return documentId;\n  }\n\n  async searchKnowledge(\n    query: string,\n    limit: number = 5,\n    threshold: number = 0.7\n  ): Promise<\n    Array<{\n      content: string;\n      metadata: MetadataObject;\n      similarity: number;\n    }>\n  > {\n    try {\n      const startTime = Date.now();\n\n      // User-facing info log\n      this.logger.info(`Searching knowledge base for: \"${query}\"`);\n\n      this.logger.debug('Starting knowledge search', {\n        query,\n        limit,\n        threshold,\n        agentId: this.agent.id,\n        embeddingModel: this.embeddingModel,\n        hasEmbeddingProvider: !!this.embeddingProvider,\n      });\n      let db: KnowledgeDatabase;\n      try {\n        db = await this.getDatabase();\n        this.logger.debug('Database instance obtained for search');\n      } catch (dbError) {\n        this.logger.error('Failed to get database for search');\n        this.logger.debug('Database error in search', {\n          errorMessage: dbError instanceof Error ? dbError.message : String(dbError),\n        });\n        throw dbError;\n      }\n\n      this.logger.debug('Generating query embedding');\n      this.logger.debug('Query embedding details', {\n        queryLength: query.length,\n        embeddingModel: this.embeddingModel,\n        providerName: this.embeddingProvider?.name || 'unknown',\n        hasGenerateEmbedding: !!this.embeddingProvider?.generateEmbedding,\n      });\n\n      if (!this.embeddingProvider?.generateEmbedding) {\n        this.logger.error('Embedding provider not properly initialized');\n        throw new Error('Embedding provider not properly initialized');\n      }\n\n      let queryEmbedding: number[];\n      try {\n        const queryEmbeddingResult = await this.embeddingProvider.generateEmbedding(\n          query,\n          this.embeddingModel\n        );\n        queryEmbedding = queryEmbeddingResult.embedding;\n        this.logger.debug('Query embedding generated successfully', {\n          embeddingDimensions: queryEmbedding.length,\n          embeddingModel: this.embeddingModel,\n        });\n      } catch (embeddingError) {\n        this.logger.error('Failed to generate query embedding');\n        this.logger.debug('Embedding error details', {\n          errorMessage:\n            embeddingError instanceof Error ? embeddingError.message : String(embeddingError),\n          embeddingModel: this.embeddingModel,\n          queryLength: query.length,\n        });\n        throw embeddingError;\n      }\n\n      const results = await db.searchKnowledge(this.agent.id, queryEmbedding, limit, threshold);\n\n      // User-facing result summary\n      this.logger.info(\n        `Found ${results.length} relevant knowledge ${results.length === 1 ? 'result' : 'results'} (threshold: ${threshold})`\n      );\n\n      this.logger.debug(`Found ${results.length} knowledge results`, {\n        resultCount: results.length,\n        topSimilarity: results.length > 0 ? results[0].similarity : 0,\n        searchTime: Date.now() - startTime,\n        hasResults: results.length > 0,\n      });\n\n      // Transform KnowledgeSearchResult to the expected format\n      return results.map((result) => ({\n        content: result.content,\n        metadata: {\n          ...result.chunk_metadata,\n          documentId: result.document_id,\n          chunkIndex: result.chunk_index,\n          documentTitle: result.document_title,\n          fileType: result.file_type,\n          documentMetadata: result.document_metadata,\n        },\n        similarity: result.similarity,\n      }));\n    } catch (searchError) {\n      this.logger.error('Knowledge search failed with exception');\n      this.logger.debug('Search error details', {\n        errorMessage: searchError instanceof Error ? searchError.message : String(searchError),\n        errorType: typeof searchError,\n        query,\n        limit,\n        threshold,\n      });\n      if (searchError instanceof Error && searchError.stack) {\n        this.logger.debug('Search error stack trace', { stack: searchError.stack });\n      }\n      // Return empty results instead of throwing to prevent breaking the agent\n      return [];\n    }\n  }\n\n  async getKnowledgeContext(query: string, limit: number = 5): Promise<string> {\n    const results = await this.searchKnowledge(query, limit);\n\n    if (results.length === 0) {\n      return '';\n    }\n\n    return results.map((r) => r.content).join('\\n\\n---\\n\\n');\n  }\n\n  async getKnowledgeDocuments(): Promise<Array<{ id: string; title: string; created_at: string }>> {\n    const db = await this.getDatabase();\n    const documents = await db.getDocuments(this.agent.id);\n\n    // Transform KnowledgeDocument to expected format, handling null titles\n    return documents.map((doc) => ({\n      id: doc.id,\n      title: doc.title || 'Untitled Document',\n      created_at: doc.created_at,\n    }));\n  }\n\n  async deleteKnowledgeDocument(documentId: string): Promise<boolean> {\n    this.logger.info(`Deleting knowledge document: ${documentId}`);\n\n    const db = await this.getDatabase();\n    const result = await db.deleteDocument(documentId);\n\n    if (result) {\n      this.logger.info(`Knowledge document ${documentId} deleted successfully`);\n    } else {\n      this.logger.warn(`Failed to delete knowledge document ${documentId}`);\n    }\n\n    this.logger.debug('Delete knowledge document result', {\n      documentId,\n      success: result,\n      agentId: this.agent.id,\n    });\n\n    return result;\n  }\n\n  async deleteKnowledgeChunk(chunkId: string): Promise<boolean> {\n    const db = await this.getDatabase();\n    return db.deleteChunk(chunkId);\n  }\n\n  async clearKnowledge(): Promise<void> {\n    this.logger.info('Clearing all knowledge documents');\n\n    const db = await this.getDatabase();\n    await db.clearAgentKnowledge(this.agent.id);\n\n    this.logger.info('All knowledge documents cleared successfully');\n\n    this.logger.debug('Cleared knowledge for agent', {\n      agentId: this.agent.id,\n    });\n  }\n\n  async expandKnowledgeContext(\n    documentId: string,\n    chunkIndex: number,\n    expandBefore: number = 1,\n    expandAfter: number = 1\n  ): Promise<string[]> {\n    this.logger.debug('Expanding knowledge context', {\n      documentId,\n      chunkIndex,\n      expandBefore,\n      expandAfter,\n      agentId: this.agent.id,\n    });\n\n    const db = await this.getDatabase();\n    return db.expandKnowledgeContext(documentId, chunkIndex, expandBefore, expandAfter);\n  }\n\n  async addKnowledgeFromFile(filePath: string, metadata?: MetadataObject): Promise<void> {\n    // Validate file path to prevent path injection attacks\n    const resolvedPath = path.resolve(filePath);\n    if (!resolvedPath || resolvedPath.includes('\\0')) {\n      throw new Error('Invalid file path: path contains invalid characters');\n    }\n\n    // Validate that the path doesn't traverse outside expected boundaries\n    const normalizedPath = path.normalize(resolvedPath);\n    if (normalizedPath !== resolvedPath) {\n      this.logger.warn('File path normalization detected potential path traversal', {\n        originalPath: filePath,\n        resolvedPath,\n        normalizedPath,\n      });\n    }\n\n    const fileName = path.basename(resolvedPath);\n\n    // Validate filename is not empty and doesn't contain path separators\n    if (!fileName || fileName === '.' || fileName === '..') {\n      throw new Error('Invalid file path: invalid filename');\n    }\n\n    // Check if document with same filename already exists for this agent\n    const db = await this.getDatabase();\n    const existingDocs = await db.getDocuments(this.agent.id);\n    const existingDoc = existingDocs.find((doc) => doc.title === fileName);\n\n    if (existingDoc) {\n      this.logger.info(`Skipping file: ${fileName} - already exists in knowledge base`);\n      return;\n    }\n\n    this.logger.info(`Adding knowledge from file: ${fileName}`);\n\n    const fileExtension = path.extname(resolvedPath).toLowerCase();\n\n    // Validate file exists and is accessible before processing\n    try {\n      await fs.promises.access(resolvedPath, fs.constants.R_OK);\n    } catch {\n      throw new Error(`File does not exist or is not readable: ${resolvedPath}`);\n    }\n\n    // Validate file is actually a file (not a directory or symlink to directory)\n    const fileStat = await fs.promises.stat(resolvedPath);\n    if (!fileStat.isFile()) {\n      throw new Error(`Path is not a file: ${resolvedPath}`);\n    }\n\n    let content: string;\n\n    try {\n      switch (fileExtension) {\n        case '.txt':\n        case '.md':\n        case '.json':\n          content = await this.readTextFile(resolvedPath);\n          break;\n        case '.pdf':\n          content = await this.readPdfFile(resolvedPath);\n          break;\n        default:\n          throw new Error(\n            `Unsupported file type: ${fileExtension}. Supported types: .txt, .md, .json, .pdf`\n          );\n      }\n\n      // Validate content is not empty\n      if (!content || content.trim().length === 0) {\n        throw new Error('File content is empty');\n      }\n\n      const title = typeof metadata?.title === 'string' ? metadata.title : fileName;\n\n      const fileMetadata = {\n        ...metadata,\n        fileName,\n        fileType: fileExtension,\n        fileSize: await getFileSizeAsync(resolvedPath),\n        addedAt: new Date().toISOString(),\n      };\n\n      await this.addKnowledge(content, title, fileMetadata);\n    } catch (error) {\n      throw new Error(\n        `Failed to process file ${resolvedPath}: ${error instanceof Error ? error.message : String(error)}`\n      );\n    }\n  }\n\n  async addKnowledgeFromDirectory(dirPath: string, metadata?: MetadataObject): Promise<void> {\n    // Validate directory path to prevent path injection attacks\n    const resolvedDirPath = path.resolve(dirPath);\n    if (!resolvedDirPath || resolvedDirPath.includes('\\0')) {\n      throw new Error('Invalid directory path: path contains invalid characters');\n    }\n\n    this.logger.info(`Adding knowledge from directory: ${resolvedDirPath}`);\n\n    try {\n      await fs.promises.access(resolvedDirPath, fs.constants.R_OK);\n    } catch {\n      throw new Error(`Directory does not exist or is not readable: ${resolvedDirPath}`);\n    }\n\n    // Validate that path is actually a directory\n    const dirStat = await fs.promises.stat(resolvedDirPath);\n    if (!dirStat.isDirectory()) {\n      throw new Error(`Path is not a directory: ${resolvedDirPath}`);\n    }\n\n    const files = await fs.promises.readdir(resolvedDirPath);\n    const supportedExtensions = ['.txt', '.md', '.json', '.pdf'];\n    let processedCount = 0;\n\n    for (const file of files) {\n      // Validate filename to prevent path traversal via directory entries\n      if (\n        !file ||\n        file === '.' ||\n        file === '..' ||\n        file.includes('\\0') ||\n        file.includes(path.sep)\n      ) {\n        this.logger.warn(`Skipping invalid filename: ${file}`);\n        continue;\n      }\n\n      const fullPath = path.join(resolvedDirPath, file);\n\n      // Verify the resolved path is still within the target directory\n      const resolvedFullPath = path.resolve(fullPath);\n      if (!resolvedFullPath.startsWith(resolvedDirPath + path.sep)) {\n        this.logger.warn(`Skipping file with path traversal attempt: ${file}`);\n        continue;\n      }\n\n      try {\n        const stat = await fs.promises.stat(resolvedFullPath);\n\n        if (stat.isFile()) {\n          const ext = path.extname(file).toLowerCase();\n          if (supportedExtensions.includes(ext)) {\n            try {\n              await this.addKnowledgeFromFile(resolvedFullPath, metadata);\n              processedCount++;\n            } catch (error) {\n              this.logger.warn(`Failed to process file ${file}`, {\n                error: error instanceof Error ? error.message : String(error),\n              });\n            }\n          }\n        }\n      } catch (statError) {\n        this.logger.warn(`Failed to stat file ${file}`, {\n          error: statError instanceof Error ? statError.message : String(statError),\n        });\n      }\n    }\n\n    this.logger.info(`Processed ${processedCount} files from directory`);\n\n    this.logger.debug('Directory processing complete', {\n      directory: resolvedDirPath,\n      totalFiles: files.length,\n      processedFiles: processedCount,\n      agentId: this.agent.id,\n    });\n  }\n\n  private async readTextFile(filePath: string): Promise<string> {\n    try {\n      const content = await fs.promises.readFile(filePath, 'utf-8');\n      return content;\n    } catch (error) {\n      if (error instanceof Error) {\n        if ('code' in error && error.code === 'ENOENT') {\n          throw new Error(`File not found: ${filePath}`);\n        }\n        if ('code' in error && error.code === 'EACCES') {\n          throw new Error(`Permission denied reading file: ${filePath}`);\n        }\n        throw new Error(`Failed to read text file: ${error.message}`);\n      }\n      throw new Error(`Failed to read text file: ${String(error)}`);\n    }\n  }\n\n  private async readPdfFile(filePath: string): Promise<string> {\n    try {\n      const pdfBuffer = await fs.promises.readFile(filePath);\n\n      // Dynamic import for ES Module compatibility\n      // Note: Using legacy build required for Node.js environment (no browser APIs)\n      const pdfjs = await import('pdfjs-dist/legacy/build/pdf.mjs');\n\n      // Convert Buffer to Uint8Array for pdfjs-dist\n      const uint8Array = new Uint8Array(pdfBuffer);\n\n      // Load PDF document\n      const loadingTask = pdfjs.getDocument({\n        data: uint8Array,\n        isEvalSupported: false, // Security: disable eval for CVE-2024-4367 mitigation\n      });\n\n      const pdf = await loadingTask.promise;\n      let fullText = '';\n\n      // Extract text from all pages\n      for (let pageNum = 1; pageNum <= pdf.numPages; pageNum++) {\n        const page = await pdf.getPage(pageNum);\n        const textContent = await page.getTextContent();\n\n        const pageText = textContent.items\n          .map((item: TextItem | TextMarkedContent) => ('str' in item ? item.str : ''))\n          .join(' ')\n          .replace(/\\0/g, '') // Remove null bytes that cause UTF8 encoding errors\n          .replace(/[\\p{Cc}\\p{Cf}]/gu, ' ') // Replace control and format characters with spaces\n          .trim();\n\n        if (pageText) {\n          fullText += pageText + '\\n';\n        }\n      }\n\n      return fullText.trim();\n    } catch (error) {\n      throw new Error(\n        `Failed to parse PDF file: ${error instanceof Error ? error.message : 'Unknown error'}`\n      );\n    }\n  }\n\n  private chunkText(text: string): string[] {\n    const chunks: string[] = [];\n\n    // Better sentence splitting - handles abbreviations and decimals\n    const sentences = text.match(/[^.!?]*[.!?]+(?:\\s|$)/g) || [text];\n\n    // Clean up sentences\n    const cleanSentences = sentences.map((s) => s.trim()).filter((s) => s.length > 0);\n\n    let currentChunk = '';\n\n    for (const sentence of cleanSentences) {\n      // Check if adding this sentence would exceed chunk size\n      if (currentChunk.length + sentence.length > this.chunkSize && currentChunk) {\n        chunks.push(currentChunk.trim());\n\n        // Create overlap by keeping last portion of current chunk\n        const words = currentChunk.trim().split(' ');\n        const overlapWordCount = Math.floor(words.length * (this.chunkOverlap / this.chunkSize));\n\n        if (overlapWordCount > 0) {\n          currentChunk = words.slice(-overlapWordCount).join(' ') + ' ';\n        } else {\n          currentChunk = '';\n        }\n      }\n\n      currentChunk += sentence + ' ';\n    }\n\n    // Add final chunk if it has content\n    if (currentChunk.trim()) {\n      chunks.push(currentChunk.trim());\n    }\n\n    // Filter out very short chunks that won't be useful\n    return chunks.filter((chunk) => chunk.length >= 50);\n  }\n}\n\nexport { knowledgeSearchTool, knowledgeTools } from './plugin';\n","import { ToolDefinition, ToolResult, ToolParameterValue } from '../plugin/types';\nimport { Vision, ALLOWED_IMAGE_EXTENSIONS } from './index';\nimport * as fs from 'fs';\nimport * as path from 'path';\n\n// Agent-based Vision instances with proper lifecycle management\n// Instances are stored with timestamps for TTL-based cleanup\ninterface VisionInstanceEntry {\n  instance: Vision;\n  lastAccessed: number;\n}\n\nconst visionInstances = new Map<string, VisionInstanceEntry>();\nconst INSTANCE_TTL_MS = 30 * 60 * 1000; // 30 minutes TTL\nlet cleanupIntervalId: ReturnType<typeof setInterval> | null = null;\n\n/**\n * Starts the periodic cleanup timer if not already running\n */\nfunction ensureCleanupTimer(): void {\n  if (cleanupIntervalId === null) {\n    cleanupIntervalId = setInterval(\n      () => {\n        const now = Date.now();\n        for (const [key, entry] of visionInstances.entries()) {\n          if (now - entry.lastAccessed > INSTANCE_TTL_MS) {\n            visionInstances.delete(key);\n          }\n        }\n        // Stop timer if no instances remain\n        if (visionInstances.size === 0 && cleanupIntervalId !== null) {\n          clearInterval(cleanupIntervalId);\n          cleanupIntervalId = null;\n        }\n      },\n      5 * 60 * 1000\n    ); // Check every 5 minutes\n    // Allow Node.js to exit even if timer is running\n    if (cleanupIntervalId.unref) {\n      cleanupIntervalId.unref();\n    }\n  }\n}\n\nexport function getVision(agentId?: string): Vision {\n  const key = agentId || 'default';\n  const entry = visionInstances.get(key);\n\n  if (entry) {\n    // Update last accessed time\n    entry.lastAccessed = Date.now();\n    return entry.instance;\n  }\n\n  // Create new instance\n  const newInstance = new Vision();\n  visionInstances.set(key, {\n    instance: newInstance,\n    lastAccessed: Date.now(),\n  });\n\n  // Start cleanup timer\n  ensureCleanupTimer();\n\n  return newInstance;\n}\n\nexport function cleanupVision(agentId?: string): void {\n  const key = agentId || 'default';\n  visionInstances.delete(key);\n}\n\n/**\n * Cleanup all vision instances - call during shutdown\n */\nexport function cleanupAllVisionInstances(): void {\n  visionInstances.clear();\n  if (cleanupIntervalId !== null) {\n    clearInterval(cleanupIntervalId);\n    cleanupIntervalId = null;\n  }\n}\n\n// Valid detail levels for image analysis\nconst VALID_DETAIL_LEVELS = ['low', 'high'] as const;\ntype DetailLevel = (typeof VALID_DETAIL_LEVELS)[number];\n\nfunction validateDetail(detail: string | undefined): DetailLevel | undefined {\n  if (!detail) return undefined;\n  return VALID_DETAIL_LEVELS.includes(detail as DetailLevel) ? (detail as DetailLevel) : 'low';\n}\n\ninterface AnalysisParams {\n  image_path: string;\n  prompt?: string;\n  detail?: string;\n}\n\ninterface DescriptionParams {\n  image_path: string;\n  style?: string;\n}\n\ninterface ExtractTextParams {\n  image_path: string;\n  language?: string;\n}\n\n// Type guard functions for vision tool parameters\nfunction isAnalysisParams(\n  params: Record<string, ToolParameterValue>\n): params is Record<string, ToolParameterValue> & AnalysisParams {\n  return (\n    typeof params.image_path === 'string' &&\n    (params.prompt === undefined || typeof params.prompt === 'string') &&\n    (params.detail === undefined || typeof params.detail === 'string')\n  );\n}\n\nfunction isDescriptionParams(\n  params: Record<string, ToolParameterValue>\n): params is Record<string, ToolParameterValue> & DescriptionParams {\n  return (\n    typeof params.image_path === 'string' &&\n    (params.style === undefined || typeof params.style === 'string')\n  );\n}\n\nfunction isExtractTextParams(\n  params: Record<string, ToolParameterValue>\n): params is Record<string, ToolParameterValue> & ExtractTextParams {\n  return (\n    typeof params.image_path === 'string' &&\n    (params.language === undefined || typeof params.language === 'string')\n  );\n}\n\nexport const analyzeImageTool: ToolDefinition = {\n  name: 'analyze_image',\n  description:\n    'Analyze an image using computer vision to extract information, describe contents, read text, etc.',\n  parameters: {\n    image_path: {\n      name: 'image_path',\n      type: 'string',\n      description: 'Path to the image file to analyze',\n      required: true,\n    },\n    prompt: {\n      name: 'prompt',\n      type: 'string',\n      description:\n        'Specific analysis prompt (optional). If not provided, will do general image analysis',\n    },\n    detail: {\n      name: 'detail',\n      type: 'string',\n      description: 'Analysis detail level: \"low\" or \"high\" (default: auto)',\n    },\n  },\n  handler: async (params: Record<string, ToolParameterValue>): Promise<ToolResult> => {\n    if (!isAnalysisParams(params)) {\n      return {\n        success: false,\n        data: null,\n        error: 'Invalid parameters for image analysis',\n      };\n    }\n\n    const { image_path, prompt, detail } = params;\n\n    try {\n      // Validate and sanitize image path\n      if (!image_path || typeof image_path !== 'string') {\n        return {\n          success: false,\n          data: null,\n          error: 'Invalid image path provided',\n        };\n      }\n\n      // Resolve and normalize path to prevent traversal attacks\n      const normalizedPath = path.resolve(path.normalize(image_path));\n      const fileExtension = path.extname(normalizedPath).toLowerCase();\n\n      if (!ALLOWED_IMAGE_EXTENSIONS.includes(fileExtension)) {\n        return {\n          success: false,\n          data: null,\n          error: `Unsupported image format: ${fileExtension}. Allowed: ${ALLOWED_IMAGE_EXTENSIONS.join(', ')}`,\n        };\n      }\n\n      const visionService = getVision();\n\n      try {\n        await fs.promises.access(normalizedPath);\n      } catch {\n        return {\n          success: false,\n          data: null,\n          error: `Image file not found: ${normalizedPath}`,\n        };\n      }\n\n      // Validate detail level - default to 'low' if invalid\n      const safeDetail = validateDetail(detail);\n\n      const analysis = await visionService.analyzeImage(normalizedPath, {\n        prompt,\n        detail: safeDetail,\n        maxTokens: 1000,\n      });\n\n      const fileName = path.basename(normalizedPath);\n\n      return {\n        success: true,\n        data: {\n          fileName,\n          filePath: normalizedPath,\n          analysis,\n          prompt: prompt || 'General image analysis',\n        },\n      };\n    } catch (error) {\n      const errorMessage = error instanceof Error ? error.message : String(error);\n      return {\n        success: false,\n        data: null,\n        error: `Image analysis failed: ${errorMessage}`,\n      };\n    }\n  },\n};\n\nexport const describeImageTool: ToolDefinition = {\n  name: 'describe_image',\n  description:\n    'Generate a detailed description of an image for accessibility or documentation purposes',\n  parameters: {\n    image_path: {\n      name: 'image_path',\n      type: 'string',\n      description: 'Path to the image file to describe',\n      required: true,\n    },\n    style: {\n      name: 'style',\n      type: 'string',\n      description: 'Description style: \"detailed\", \"concise\", \"accessibility\", or \"technical\"',\n    },\n  },\n  handler: async (params: Record<string, ToolParameterValue>): Promise<ToolResult> => {\n    if (!isDescriptionParams(params)) {\n      return {\n        success: false,\n        data: null,\n        error: 'Invalid parameters for image description',\n      };\n    }\n\n    const { image_path, style = 'detailed' } = params;\n\n    try {\n      // Validate and sanitize image path\n      if (!image_path || typeof image_path !== 'string') {\n        return {\n          success: false,\n          data: null,\n          error: 'Invalid image path provided',\n        };\n      }\n\n      // Resolve and normalize path to prevent traversal attacks\n      const normalizedPath = path.resolve(path.normalize(image_path));\n      const fileExtension = path.extname(normalizedPath).toLowerCase();\n\n      if (!ALLOWED_IMAGE_EXTENSIONS.includes(fileExtension)) {\n        return {\n          success: false,\n          data: null,\n          error: `Unsupported image format: ${fileExtension}. Allowed: ${ALLOWED_IMAGE_EXTENSIONS.join(', ')}`,\n        };\n      }\n\n      const visionService = getVision();\n\n      try {\n        await fs.promises.access(normalizedPath);\n      } catch {\n        return {\n          success: false,\n          data: null,\n          error: `Image file not found: ${normalizedPath}`,\n        };\n      }\n\n      const prompts = {\n        detailed:\n          'Provide a detailed description of this image, including all visual elements, colors, objects, people, text, and context.',\n        concise: 'Provide a brief, concise description of the main elements in this image.',\n        accessibility:\n          'Create an accessibility-friendly description of this image for visually impaired users, focusing on the most important visual information.',\n        technical:\n          'Provide a technical analysis of this image including composition, lighting, objects, text, and any technical elements visible.',\n      };\n\n      const prompt = prompts[style as keyof typeof prompts] || prompts.detailed;\n\n      const description = await visionService.analyzeImage(normalizedPath, {\n        prompt,\n        maxTokens: 800,\n      });\n\n      const fileName = path.basename(normalizedPath);\n\n      return {\n        success: true,\n        data: {\n          fileName,\n          filePath: normalizedPath,\n          style,\n          description,\n        },\n      };\n    } catch (error) {\n      const errorMessage = error instanceof Error ? error.message : String(error);\n      return {\n        success: false,\n        data: null,\n        error: `Image description failed: ${errorMessage}`,\n      };\n    }\n  },\n};\n\nexport const extractTextFromImageTool: ToolDefinition = {\n  name: 'extract_text_from_image',\n  description: 'Extract and transcribe text from an image using OCR capabilities',\n  parameters: {\n    image_path: {\n      name: 'image_path',\n      type: 'string',\n      description: 'Path to the image file containing text',\n      required: true,\n    },\n    language: {\n      name: 'language',\n      type: 'string',\n      description: 'Expected language of the text (optional, helps with accuracy)',\n    },\n  },\n  handler: async (params: Record<string, ToolParameterValue>): Promise<ToolResult> => {\n    if (!isExtractTextParams(params)) {\n      return {\n        success: false,\n        data: null,\n        error: 'Invalid parameters for text extraction',\n      };\n    }\n\n    const { image_path, language } = params;\n\n    try {\n      // Validate and sanitize image path\n      if (!image_path || typeof image_path !== 'string') {\n        return {\n          success: false,\n          data: null,\n          error: 'Invalid image path provided',\n        };\n      }\n\n      // Resolve and normalize path to prevent traversal attacks\n      const normalizedPath = path.resolve(path.normalize(image_path));\n      const fileExtension = path.extname(normalizedPath).toLowerCase();\n\n      if (!ALLOWED_IMAGE_EXTENSIONS.includes(fileExtension)) {\n        return {\n          success: false,\n          data: null,\n          error: `Unsupported image format: ${fileExtension}. Allowed: ${ALLOWED_IMAGE_EXTENSIONS.join(', ')}`,\n        };\n      }\n\n      const visionService = getVision();\n\n      try {\n        await fs.promises.access(normalizedPath);\n      } catch {\n        return {\n          success: false,\n          data: null,\n          error: `Image file not found: ${normalizedPath}`,\n        };\n      }\n\n      const languageHint = language ? ` The text is likely in ${language}.` : '';\n      const prompt = `Extract and transcribe all text from this image. Maintain the original formatting, line breaks, and structure as much as possible.${languageHint} Only return the extracted text, no additional commentary.`;\n\n      const extractedText = await visionService.analyzeImage(normalizedPath, {\n        prompt,\n        maxTokens: 1500,\n      });\n\n      const fileName = path.basename(normalizedPath);\n\n      return {\n        success: true,\n        data: {\n          fileName,\n          filePath: normalizedPath,\n          language: language || 'auto-detect',\n          extractedText,\n        },\n      };\n    } catch (error) {\n      const errorMessage = error instanceof Error ? error.message : String(error);\n      return {\n        success: false,\n        data: null,\n        error: `Text extraction failed: ${errorMessage}`,\n      };\n    }\n  },\n};\n\n// Function to create vision tools with a specific Vision instance\nexport function createVisionTools(visionInstance: Vision): ToolDefinition[] {\n  const analyzeImageToolWithInstance: ToolDefinition = {\n    ...analyzeImageTool,\n    handler: async (params: Record<string, ToolParameterValue>): Promise<ToolResult> => {\n      if (!isAnalysisParams(params)) {\n        return {\n          success: false,\n          data: null,\n          error: 'Invalid parameters for image analysis',\n        };\n      }\n\n      const { image_path, prompt, detail } = params;\n\n      try {\n        // Validate and sanitize image path\n        if (!image_path || typeof image_path !== 'string') {\n          return {\n            success: false,\n            data: null,\n            error: 'Invalid image path provided',\n          };\n        }\n\n        // Resolve and normalize path to prevent traversal attacks\n        const normalizedPath = path.resolve(path.normalize(image_path));\n        const fileExtension = path.extname(normalizedPath).toLowerCase();\n\n        if (!ALLOWED_IMAGE_EXTENSIONS.includes(fileExtension)) {\n          return {\n            success: false,\n            data: null,\n            error: `Unsupported image format: ${fileExtension}. Allowed: ${ALLOWED_IMAGE_EXTENSIONS.join(', ')}`,\n          };\n        }\n\n        if (!fs.existsSync(normalizedPath)) {\n          return {\n            success: false,\n            data: null,\n            error: `Image file not found: ${normalizedPath}`,\n          };\n        }\n\n        // Validate detail level - default to undefined if not 'low' or 'high'\n        const safeDetail = detail === 'low' || detail === 'high' ? detail : undefined;\n\n        const analysis = await visionInstance.analyzeImage(normalizedPath, {\n          prompt,\n          detail: safeDetail,\n          maxTokens: 1000,\n        });\n\n        const fileName = path.basename(normalizedPath);\n\n        return {\n          success: true,\n          data: {\n            fileName,\n            filePath: normalizedPath,\n            analysis,\n            prompt: prompt || 'General image analysis',\n          },\n        };\n      } catch (error) {\n        const errorMessage = error instanceof Error ? error.message : String(error);\n        return {\n          success: false,\n          data: null,\n          error: `Image analysis failed: ${errorMessage}`,\n        };\n      }\n    },\n  };\n\n  const describeImageToolWithInstance: ToolDefinition = {\n    ...describeImageTool,\n    handler: async (params: Record<string, ToolParameterValue>): Promise<ToolResult> => {\n      if (!isDescriptionParams(params)) {\n        return {\n          success: false,\n          data: null,\n          error: 'Invalid parameters for image description',\n        };\n      }\n\n      const { image_path, style = 'detailed' } = params;\n\n      try {\n        // Validate and sanitize image path\n        if (!image_path || typeof image_path !== 'string') {\n          return {\n            success: false,\n            data: null,\n            error: 'Invalid image path provided',\n          };\n        }\n\n        // Resolve and normalize path to prevent traversal attacks\n        const normalizedPath = path.resolve(path.normalize(image_path));\n        const fileExtension = path.extname(normalizedPath).toLowerCase();\n\n        if (!ALLOWED_IMAGE_EXTENSIONS.includes(fileExtension)) {\n          return {\n            success: false,\n            data: null,\n            error: `Unsupported image format: ${fileExtension}. Allowed: ${ALLOWED_IMAGE_EXTENSIONS.join(', ')}`,\n          };\n        }\n\n        if (!fs.existsSync(normalizedPath)) {\n          return {\n            success: false,\n            data: null,\n            error: `Image file not found: ${normalizedPath}`,\n          };\n        }\n\n        const prompts = {\n          detailed:\n            'Provide a detailed description of this image, including all visual elements, colors, objects, people, text, and context.',\n          concise: 'Provide a brief, concise description of the main elements in this image.',\n          accessibility:\n            'Create an accessibility-friendly description of this image for visually impaired users, focusing on the most important visual information.',\n          technical:\n            'Provide a technical analysis of this image including composition, lighting, objects, text, and any technical elements visible.',\n        };\n\n        const prompt = prompts[style as keyof typeof prompts] || prompts.detailed;\n\n        const description = await visionInstance.analyzeImage(normalizedPath, {\n          prompt,\n          maxTokens: 800,\n        });\n\n        const fileName = path.basename(normalizedPath);\n\n        return {\n          success: true,\n          data: {\n            fileName,\n            filePath: normalizedPath,\n            style,\n            description,\n          },\n        };\n      } catch (error) {\n        const errorMessage = error instanceof Error ? error.message : String(error);\n        return {\n          success: false,\n          data: null,\n          error: `Image description failed: ${errorMessage}`,\n        };\n      }\n    },\n  };\n\n  const extractTextFromImageToolWithInstance: ToolDefinition = {\n    ...extractTextFromImageTool,\n    handler: async (params: Record<string, ToolParameterValue>): Promise<ToolResult> => {\n      if (!isExtractTextParams(params)) {\n        return {\n          success: false,\n          data: null,\n          error: 'Invalid parameters for text extraction',\n        };\n      }\n\n      const { image_path, language } = params;\n\n      try {\n        // Validate and sanitize image path\n        if (!image_path || typeof image_path !== 'string') {\n          return {\n            success: false,\n            data: null,\n            error: 'Invalid image path provided',\n          };\n        }\n\n        // Resolve and normalize path to prevent traversal attacks\n        const normalizedPath = path.resolve(path.normalize(image_path));\n        const fileExtension = path.extname(normalizedPath).toLowerCase();\n\n        if (!ALLOWED_IMAGE_EXTENSIONS.includes(fileExtension)) {\n          return {\n            success: false,\n            data: null,\n            error: `Unsupported image format: ${fileExtension}. Allowed: ${ALLOWED_IMAGE_EXTENSIONS.join(', ')}`,\n          };\n        }\n\n        if (!fs.existsSync(normalizedPath)) {\n          return {\n            success: false,\n            data: null,\n            error: `Image file not found: ${normalizedPath}`,\n          };\n        }\n\n        const languageHint = language ? ` The text is likely in ${language}.` : '';\n        const prompt = `Extract and transcribe all text from this image. Maintain the original formatting, line breaks, and structure as much as possible.${languageHint} Only return the extracted text, no additional commentary.`;\n\n        const extractedText = await visionInstance.analyzeImage(normalizedPath, {\n          prompt,\n          maxTokens: 1500,\n        });\n\n        const fileName = path.basename(normalizedPath);\n\n        return {\n          success: true,\n          data: {\n            fileName,\n            filePath: normalizedPath,\n            language: language || 'auto-detect',\n            extractedText,\n          },\n        };\n      } catch (error) {\n        const errorMessage = error instanceof Error ? error.message : String(error);\n        return {\n          success: false,\n          data: null,\n          error: `Text extraction failed: ${errorMessage}`,\n        };\n      }\n    },\n  };\n\n  return [\n    analyzeImageToolWithInstance,\n    describeImageToolWithInstance,\n    extractTextFromImageToolWithInstance,\n  ];\n}\n\nexport const visionTools = [analyzeImageTool, describeImageTool, extractTextFromImageTool];\n","import { IAgentModule, IAgent } from '../agent/types';\nimport { ToolDefinition } from '../plugin/types';\nimport { createVisionTools } from './tools';\nimport { Logger } from '../logger/types';\nimport { getLogger } from '../logger';\nimport { getLLMProvider } from '../llm';\nimport { VisionAnalysisOptions } from '../llm/types';\nimport * as path from 'path';\nimport * as fs from 'fs';\nimport { DEFAULT_VISION_CONFIG } from './defaults';\n\n// Allowed image extensions for validation\nexport const ALLOWED_IMAGE_EXTENSIONS = [\n  '.png',\n  '.jpg',\n  '.jpeg',\n  '.gif',\n  '.webp',\n  '.bmp',\n  '.tiff',\n  '.svg',\n];\n\n/**\n * Validates an image path for security and existence\n * Uses atomic file descriptor operations to prevent TOCTOU race conditions\n * @throws Error if path is invalid or insecure\n */\nfunction validateImagePath(imagePath: string): void {\n  // Resolve and normalize the path to get absolute path\n  const resolvedPath = path.resolve(imagePath);\n  const cwd = path.resolve(process.cwd());\n\n  // Check if resolved path is within the current working directory\n  // This prevents path traversal attacks even with normalized paths\n  if (!resolvedPath.startsWith(cwd)) {\n    throw new Error('Invalid image path: image path must be within working directory');\n  }\n\n  // Validate file extension\n  const ext = path.extname(resolvedPath).toLowerCase();\n  if (!ALLOWED_IMAGE_EXTENSIONS.includes(ext)) {\n    throw new Error(\n      `Invalid image format: ${ext}. Allowed formats: ${ALLOWED_IMAGE_EXTENSIONS.join(', ')}`\n    );\n  }\n\n  // Use atomic file descriptor operation to prevent TOCTOU race condition\n  // Open the file with read-only flag, which atomically checks existence and opens\n  let fd: number | null = null;\n  try {\n    // O_RDONLY | O_NOFOLLOW equivalent - open read-only, don't follow symlinks\n    fd = fs.openSync(resolvedPath, fs.constants.O_RDONLY);\n\n    // Now use fstatSync on the file descriptor (not the path) to avoid TOCTOU\n    const stats = fs.fstatSync(fd);\n\n    if (!stats.isFile()) {\n      throw new Error(`Path is not a file: ${resolvedPath}`);\n    }\n  } catch (error) {\n    if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n      throw new Error(`Image file not found: ${resolvedPath}`);\n    }\n    if ((error as NodeJS.ErrnoException).code === 'ELOOP') {\n      throw new Error(`Too many symbolic links in path: ${resolvedPath}`);\n    }\n    throw error;\n  } finally {\n    // Always close the file descriptor\n    if (fd !== null) {\n      try {\n        fs.closeSync(fd);\n      } catch {\n        // Ignore close errors\n      }\n    }\n  }\n}\n\nexport interface VisionConfig {\n  provider?: 'openai' | 'claude' | 'gemini' | 'ollama';\n  model?: string;\n  apiKey?: string;\n  baseURL?: string;\n}\n\nexport interface AnalysisOptions {\n  prompt?: string;\n  maxTokens?: number;\n  detail?: 'low' | 'high' | 'auto';\n}\n\nexport class Vision implements IAgentModule {\n  readonly name = 'vision';\n  private config: VisionConfig;\n  private logger: Logger;\n\n  constructor(\n    private agent?: IAgent,\n    config?: VisionConfig\n  ) {\n    this.logger = agent?.logger || getLogger();\n\n    // Handle agent-provided config\n    if (!config && agent?.config) {\n      // Use agent's visionModel if specified\n      if (agent.config.visionModel) {\n        config = { model: agent.config.visionModel };\n      } else {\n        // Auto-detect based on available providers\n        config = this.autoDetectVisionConfig();\n      }\n    }\n\n    this.config = config || this.getConfigFromEnv();\n\n    // User-facing info log\n    this.logger.info('Vision module initialized');\n\n    this.logger.debug('Vision module initialized', {\n      agentId: agent?.id ?? 0,\n      agentName: agent?.name || 'standalone',\n      provider: this.config.provider || 'auto',\n      model: this.config.model || 'auto',\n      hasApiKey: !!this.config.apiKey,\n      hasBaseURL: !!this.config.baseURL,\n      agentModel: agent?.config?.model || 'none',\n      agentVisionModel: agent?.config?.visionModel || 'none',\n    });\n  }\n\n  async initialize(): Promise<void> {\n    // Register vision tools if agent has plugin system\n    if (this.agent && 'registerPlugin' in this.agent) {\n      try {\n        // Create vision tools with this instance so they have access to agent config\n        const toolsWithInstance = createVisionTools(this);\n\n        const visionPlugin = {\n          name: 'vision-tools',\n          version: '1.0.0',\n          description: 'Built-in vision analysis tools',\n          tools: toolsWithInstance,\n        };\n        await (\n          this.agent as IAgent & {\n            registerPlugin: (plugin: {\n              name: string;\n              version: string;\n              description?: string;\n              tools?: ToolDefinition[];\n            }) => Promise<void>;\n          }\n        ).registerPlugin(visionPlugin);\n      } catch (error) {\n        // Plugin registration failed, but vision module can still work\n        this.logger.debug('Failed to register vision tools', {\n          error: error instanceof Error ? error.message : String(error),\n        });\n      }\n    }\n  }\n\n  private autoDetectVisionConfig(): VisionConfig {\n    // Priority order: OpenAI -> Claude -> Gemini -> Ollama\n    if (process.env.OPENAI_VISION_API_KEY) {\n      // Use dedicated vision API key if available\n      return {\n        provider: 'openai',\n        model: DEFAULT_VISION_CONFIG.defaultModel,\n        apiKey: process.env.OPENAI_VISION_API_KEY,\n      };\n    }\n\n    // Only use main OPENAI_API_KEY if it's not an OpenRouter key (which would have a base URL set)\n    if (process.env.OPENAI_API_KEY && !process.env.OPENAI_BASE_URL) {\n      return {\n        provider: 'openai',\n        model: DEFAULT_VISION_CONFIG.defaultModel,\n        apiKey: process.env.OPENAI_API_KEY,\n      };\n    }\n\n    if (process.env.ANTHROPIC_VISION_API_KEY || process.env.ANTHROPIC_API_KEY) {\n      return {\n        provider: 'claude',\n        model: 'claude-3-5-sonnet-20241022',\n        apiKey: process.env.ANTHROPIC_VISION_API_KEY || process.env.ANTHROPIC_API_KEY,\n      };\n    }\n\n    if (process.env.GEMINI_VISION_API_KEY || process.env.GEMINI_API_KEY) {\n      return {\n        provider: 'gemini',\n        model: 'gemini-1.5-pro',\n        apiKey: process.env.GEMINI_VISION_API_KEY || process.env.GEMINI_API_KEY,\n      };\n    }\n\n    // Default to Ollama (local)\n    return {\n      provider: 'ollama',\n      model: DEFAULT_VISION_CONFIG.fallbackModel,\n      baseURL: process.env.OLLAMA_BASE_URL || DEFAULT_VISION_CONFIG.ollamaBaseURL,\n    };\n  }\n\n  private getConfigFromEnv(): VisionConfig {\n    return this.autoDetectVisionConfig();\n  }\n\n  private getApiKeyForProvider(provider: string): string | undefined {\n    switch (provider) {\n      case 'openai':\n        return process.env.OPENAI_VISION_API_KEY || process.env.OPENAI_API_KEY;\n      case 'claude':\n        return process.env.ANTHROPIC_VISION_API_KEY || process.env.ANTHROPIC_API_KEY;\n      case 'gemini':\n        return process.env.GEMINI_VISION_API_KEY || process.env.GEMINI_API_KEY;\n      case 'ollama':\n        return undefined; // Ollama doesn't need API key\n      default:\n        return undefined;\n    }\n  }\n\n  private async getProviderForVision(): Promise<{\n    provider: {\n      name: string;\n      analyzeImage?: (\n        imagePath: string,\n        options?: VisionAnalysisOptions\n      ) => Promise<{ content: string }>;\n      analyzeImageFromBase64?: (\n        base64Data: string,\n        options?: VisionAnalysisOptions\n      ) => Promise<{ content: string }>;\n      getVisionModels: () => string[];\n    };\n    model: string;\n  }> {\n    const model = this.config.model;\n    const providerType = this.config.provider;\n\n    this.logger.debug('Getting provider for vision', {\n      configModel: model || 'undefined',\n      configProvider: providerType || 'undefined',\n      hasApiKey: !!this.config.apiKey,\n      hasBaseURL: !!this.config.baseURL,\n    });\n\n    if (providerType && model) {\n      // Use specified provider and model - NEVER use main base URL for vision\n      const mainProvider = await getLLMProvider(providerType, {\n        apiKey: this.config.apiKey,\n        baseUrl: this.config.baseURL || null, // Explicitly set to null to prevent fallback to main base URL\n        logger: this.logger,\n      });\n\n      // Use dedicated vision provider if available\n      const provider = mainProvider.getVisionProvider?.() || mainProvider;\n\n      // Check if provider supports vision\n      if (!provider.analyzeImage) {\n        throw new Error(`Provider ${providerType} does not support vision analysis`);\n      }\n\n      // Check if model is supported\n      const visionModels = mainProvider.getVisionModels();\n      if (!visionModels.includes(model)) {\n        this.logger.warn(\n          `Model ${model} is not in provider's vision models list. Proceeding anyway.`\n        );\n      }\n\n      return { provider, model };\n    }\n\n    // Auto-detect provider based on available API keys - NEVER use main base URL for vision\n    const config = this.autoDetectVisionConfig();\n\n    this.logger.debug('Auto-detected vision config', {\n      provider: config.provider || 'undefined',\n      model: config.model || 'undefined',\n      hasApiKey: !!config.apiKey,\n      hasBaseURL: !!config.baseURL,\n    });\n\n    if (!config.provider) {\n      throw new Error(\n        'Vision provider could not be auto-detected. Please configure a vision provider.'\n      );\n    }\n\n    const mainProvider = await getLLMProvider(config.provider, {\n      apiKey: config.apiKey,\n      baseUrl: config.baseURL || null, // Explicitly set to null to prevent fallback to main base URL\n      logger: this.logger,\n    });\n\n    // Use dedicated vision provider if available\n    const provider = mainProvider.getVisionProvider?.() || mainProvider;\n\n    if (!config.model) {\n      throw new Error('Vision model could not be determined. Please configure a vision model.');\n    }\n\n    return { provider, model: config.model };\n  }\n\n  async analyzeImage(imagePath: string, options: AnalysisOptions = {}): Promise<string> {\n    // Validate image path for security\n    validateImagePath(imagePath);\n\n    const fileName = path.basename(imagePath);\n\n    // User-facing info log\n    this.logger.info(`Analyzing image: ${fileName}`);\n\n    this.logger.debug('Starting image analysis', {\n      imagePath,\n      fileName,\n      provider: this.config.provider || 'auto',\n      model: this.config.model || 'auto',\n      hasOptions: Object.keys(options).length > 0,\n      hasAgent: !!this.agent,\n      agentVisionModel: this.agent?.config?.visionModel || 'undefined',\n      agentId: this.agent?.id ?? 0,\n    });\n\n    try {\n      const { provider, model } = await this.getProviderForVision();\n      const visionOptions: VisionAnalysisOptions = {\n        prompt: options.prompt,\n        maxTokens: options.maxTokens,\n        detail: options.detail,\n        model: model, // Pass the agent's vision model to provider\n      };\n\n      if (!provider.analyzeImage) {\n        throw new Error('Vision provider does not support analyzeImage method');\n      }\n\n      const result = await provider.analyzeImage(imagePath, visionOptions);\n\n      // User-facing success message\n      this.logger.info(`Image analysis completed for ${fileName}`);\n\n      this.logger.debug('Image analysis completed', {\n        fileName,\n        model: model,\n        provider: 'unknown',\n        processingTime: 0,\n        resultLength: result.content.length,\n        resultPreview: result.content.slice(0, 100) + '...',\n      });\n\n      return result.content;\n    } catch (error) {\n      const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';\n      this.logger.error(`Image analysis failed for ${fileName}`);\n      this.logger.debug('Image analysis error', {\n        fileName,\n        error: errorMessage,\n        hasStack: error instanceof Error && !!error.stack,\n      });\n      throw error;\n    }\n  }\n\n  async analyzeImageFromBase64(\n    base64Image: string,\n    options: AnalysisOptions = {}\n  ): Promise<string> {\n    // User-facing info log\n    this.logger.info('Analyzing base64 image');\n\n    this.logger.debug('Starting base64 image analysis', {\n      provider: this.config.provider || 'auto',\n      model: this.config.model || 'auto',\n      base64Length: base64Image.length,\n      hasOptions: Object.keys(options).length > 0,\n    });\n\n    try {\n      const { provider, model } = await this.getProviderForVision();\n      const visionOptions: VisionAnalysisOptions = {\n        prompt: options.prompt,\n        maxTokens: options.maxTokens,\n        detail: options.detail,\n        model: model, // Pass the agent's vision model to provider\n      };\n\n      if (!provider.analyzeImageFromBase64) {\n        throw new Error('Vision provider does not support analyzeImageFromBase64 method');\n      }\n\n      const result = await provider.analyzeImageFromBase64(base64Image, visionOptions);\n\n      // User-facing success message\n      this.logger.info('Base64 image analysis completed');\n\n      this.logger.debug('Base64 image analysis completed', {\n        model: model,\n        provider: 'unknown',\n        processingTime: 0,\n        resultLength: result.content.length,\n        resultPreview: result.content.slice(0, 100) + '...',\n      });\n\n      return result.content;\n    } catch (error) {\n      const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';\n      this.logger.error('Base64 image analysis failed');\n      this.logger.debug('Base64 image analysis error', {\n        error: errorMessage,\n        hasStack: error instanceof Error && !!error.stack,\n      });\n      throw error;\n    }\n  }\n}\n\nexport { visionTools, createVisionTools } from './tools';\n","/**\n * Default configuration values for vision module\n */\nexport const DEFAULT_VISION_CONFIG = {\n  defaultModel: 'gpt-4o-mini',\n  fallbackModel: 'llava',\n  defaultDetail: 'auto',\n  defaultMaxTokens: 4096,\n  defaultProvider: 'ollama',\n  ollamaBaseURL: 'http://localhost:11434',\n} as const;\n\n/**\n * Get default value for a vision config property\n */\nexport function getVisionDefaultValue<K extends keyof typeof DEFAULT_VISION_CONFIG>(\n  key: K\n): (typeof DEFAULT_VISION_CONFIG)[K] {\n  return DEFAULT_VISION_CONFIG[key];\n}\n","/**\n * Sub-agent coordination and result management\n */\nimport { IAgent } from '../agent/types';\nimport {\n  SubAgentTask,\n  SubAgentResult,\n  SubAgentCoordinationResult,\n  ContextIsolationStrategy,\n} from './types';\nimport { ContextMessage } from '../context/types';\nimport { Logger } from '../logger/types';\nimport { SubAgentError } from '../errors';\nimport { randomUUID } from 'crypto';\n\n/**\n * Coordinates execution of sub-agent tasks and manages results\n */\nexport class SubAgentCoordinator {\n  private logger?: Logger;\n\n  /**\n   * Store context snapshots for isolation/merge strategies.\n   * Uses execution ID based isolation to prevent race conditions when\n   * multiple executeSubAgentTasks calls run concurrently.\n   * Key format: `${executionId}:${agentId}`\n   */\n  private contextSnapshots: Map<string, ContextMessage[]> = new Map();\n\n  constructor(logger?: Logger) {\n    this.logger = logger;\n  }\n\n  /**\n   * Execute sub-agent tasks with coordination\n   * @param tasks - Tasks to execute\n   * @param subAgents - Available sub-agents\n   * @param coordination - Coordination strategy (parallel/sequential)\n   * @param contextIsolation - Context isolation strategy (isolated/shared/merge)\n   * @param parentAgent - Optional parent agent for context merging\n   */\n  async executeSubAgentTasks(\n    tasks: SubAgentTask[],\n    subAgents: IAgent[],\n    coordination: 'parallel' | 'sequential' = 'parallel',\n    contextIsolation: ContextIsolationStrategy = 'isolated',\n    parentAgent?: IAgent\n  ): Promise<SubAgentCoordinationResult> {\n    const startTime = Date.now();\n    const results: SubAgentResult[] = [];\n    const errors: string[] = [];\n\n    // Generate unique execution ID to prevent race conditions when\n    // multiple executeSubAgentTasks calls run concurrently\n    const executionId = randomUUID();\n\n    this.logger?.debug(`Sub-agent context isolation strategy: ${contextIsolation}`, {\n      hasParentAgent: !!parentAgent,\n      subAgentCount: subAgents.length,\n      executionId,\n    });\n\n    try {\n      // Handle context isolation BEFORE execution\n      if (contextIsolation === 'isolated' || contextIsolation === 'merge') {\n        // Snapshot sub-agent contexts before execution for isolation\n        await this.snapshotContexts(subAgents, executionId);\n      }\n\n      if (coordination === 'parallel') {\n        await this.executeParallel(tasks, subAgents, results, errors);\n      } else {\n        await this.executeSequential(tasks, subAgents, results, errors);\n      }\n\n      // Handle context isolation AFTER execution\n      if (contextIsolation === 'isolated') {\n        // Restore sub-agent contexts to pre-execution state (full isolation)\n        await this.restoreContexts(subAgents, executionId);\n        this.logger?.debug('Sub-agent contexts restored (isolated mode)');\n      } else if (contextIsolation === 'merge' && parentAgent) {\n        // Merge sub-agent context changes back to parent\n        await this.mergeContextsToParent(subAgents, parentAgent, executionId);\n        // Then restore sub-agent contexts to original state\n        await this.restoreContexts(subAgents, executionId);\n        this.logger?.debug('Sub-agent contexts merged to parent and restored');\n      }\n      // 'shared' mode: contexts are not restored, changes persist\n\n      // Clear snapshots for this execution only\n      this.clearExecutionSnapshots(executionId, subAgents);\n\n      // Generate final result from all sub-agent results\n      const finalResult = this.aggregateResults(results);\n\n      const totalExecutionTime = Date.now() - startTime;\n\n      this.logger?.info(`Sub-agent coordination completed in ${totalExecutionTime}ms`, {\n        coordination,\n        contextIsolation,\n        tasksExecuted: tasks.length,\n        successfulResults: results.filter((r) => r.success).length,\n        errors: errors.length,\n        executionId,\n      });\n\n      return {\n        success: errors.length === 0,\n        results,\n        finalResult,\n        totalExecutionTime,\n        errors,\n      };\n    } catch (error) {\n      // Ensure contexts are restored even on error (for isolated/merge modes)\n      if (contextIsolation === 'isolated' || contextIsolation === 'merge') {\n        try {\n          await this.restoreContexts(subAgents, executionId);\n        } catch (restoreError) {\n          this.logger?.warn('Failed to restore contexts after error', {\n            error: restoreError instanceof Error ? restoreError.message : String(restoreError),\n          });\n        }\n      }\n      // Clear snapshots for this execution only\n      this.clearExecutionSnapshots(executionId, subAgents);\n\n      const errorMessage = error instanceof Error ? error.message : String(error);\n      this.logger?.error('Sub-agent coordination failed', error as Error);\n\n      return {\n        success: false,\n        results,\n        finalResult: '',\n        totalExecutionTime: Date.now() - startTime,\n        errors: [errorMessage, ...errors],\n      };\n    }\n  }\n\n  /**\n   * Clear snapshots for a specific execution only (prevents affecting concurrent executions)\n   */\n  private clearExecutionSnapshots(executionId: string, subAgents: IAgent[]): void {\n    for (const agent of subAgents) {\n      const key = `${executionId}:${agent.id}`;\n      this.contextSnapshots.delete(key);\n    }\n  }\n\n  /**\n   * Snapshot contexts for all sub-agents (for isolation/merge strategies)\n   * @param subAgents - Agents to snapshot\n   * @param executionId - Unique execution ID for isolation\n   */\n  private async snapshotContexts(subAgents: IAgent[], executionId: string): Promise<void> {\n    for (const agent of subAgents) {\n      try {\n        // Get current context messages from agent (safely handle optional method)\n        const context = typeof agent.getContext === 'function' ? agent.getContext() : [];\n        // Deep copy to prevent reference issues, keyed by execution ID for isolation\n        const key = `${executionId}:${agent.id}`;\n        this.contextSnapshots.set(key, JSON.parse(JSON.stringify(context)));\n        this.logger?.debug(`Snapshotted context for agent ${agent.name}`, {\n          messageCount: context.length,\n          executionId,\n        });\n      } catch (error) {\n        this.logger?.warn(`Failed to snapshot context for agent ${agent.name}`, {\n          error: error instanceof Error ? error.message : String(error),\n          executionId,\n        });\n      }\n    }\n  }\n\n  /**\n   * Restore contexts for all sub-agents from snapshots\n   * @param subAgents - Agents to restore\n   * @param executionId - Unique execution ID for isolation\n   */\n  private async restoreContexts(subAgents: IAgent[], executionId: string): Promise<void> {\n    for (const agent of subAgents) {\n      const key = `${executionId}:${agent.id}`;\n      const snapshot = this.contextSnapshots.get(key);\n      if (!snapshot) continue;\n\n      try {\n        // Type guard for optional context methods not in IAgent interface\n        const agentWithContext = agent as IAgent & {\n          clearContext?: () => Promise<void>;\n          importContext?: (data: string) => void;\n          exportContext?: () => string;\n        };\n\n        // Clear current context and restore snapshot\n        if (agentWithContext.clearContext) {\n          await agentWithContext.clearContext();\n        }\n\n        // Re-add snapshotted messages (if agent has addMemory method)\n        // Note: This is a simplified restore - in production you might want\n        // to use importContext if available\n        if (\n          agentWithContext.importContext &&\n          typeof agentWithContext.exportContext === 'function'\n        ) {\n          // Use import/export for cleaner restore\n          const exportData = {\n            version: '1.0',\n            timestamp: new Date().toISOString(),\n            messages: snapshot,\n            metadata: { restored: true },\n          };\n          agentWithContext.importContext(JSON.stringify(exportData));\n        }\n\n        this.logger?.debug(`Restored context for agent ${agent.name}`, {\n          messageCount: snapshot.length,\n          executionId,\n        });\n      } catch (error) {\n        this.logger?.warn(`Failed to restore context for agent ${agent.name}`, {\n          error: error instanceof Error ? error.message : String(error),\n          executionId,\n        });\n      }\n    }\n  }\n\n  /**\n   * Merge sub-agent context changes back to parent agent\n   * @param subAgents - Agents to merge from\n   * @param parentAgent - Parent agent to merge into\n   * @param executionId - Unique execution ID for isolation\n   */\n  private async mergeContextsToParent(\n    subAgents: IAgent[],\n    parentAgent: IAgent,\n    executionId: string\n  ): Promise<void> {\n    for (const agent of subAgents) {\n      const key = `${executionId}:${agent.id}`;\n      const originalSnapshot = this.contextSnapshots.get(key);\n      if (!originalSnapshot) continue;\n\n      try {\n        // Get current context (after execution) - safely handle optional method\n        const currentContext = typeof agent.getContext === 'function' ? agent.getContext() : [];\n\n        // Find new messages (messages added during execution)\n        const originalIds = new Set(originalSnapshot.map((m) => JSON.stringify(m)));\n        const newMessages = currentContext.filter((m) => !originalIds.has(JSON.stringify(m)));\n\n        // Add new messages to parent agent's context\n        if (newMessages.length > 0 && parentAgent.addMemory) {\n          for (const message of newMessages) {\n            try {\n              await parentAgent.addMemory(message.content, {\n                ...message.metadata,\n                mergedFrom: agent.name,\n                mergedFromAgentId: agent.id,\n                originalRole: message.role,\n              });\n            } catch (addError) {\n              this.logger?.warn(`Failed to merge message to parent from ${agent.name}`, {\n                error: addError instanceof Error ? addError.message : String(addError),\n                executionId,\n              });\n            }\n          }\n\n          this.logger?.debug(\n            `Merged ${newMessages.length} new messages from ${agent.name} to parent`,\n            {\n              executionId,\n            }\n          );\n        }\n      } catch (error) {\n        this.logger?.warn(`Failed to merge context from agent ${agent.name}`, {\n          error: error instanceof Error ? error.message : String(error),\n          executionId,\n        });\n      }\n    }\n  }\n\n  /**\n   * Execute tasks in parallel\n   */\n  private async executeParallel(\n    tasks: SubAgentTask[],\n    subAgents: IAgent[],\n    results: SubAgentResult[],\n    errors: string[]\n  ): Promise<void> {\n    this.logger?.debug('Executing sub-agent tasks in parallel', { taskCount: tasks.length });\n\n    // Execute all tasks concurrently\n    const taskPromises = tasks.map((task) => this.executeTask(task, subAgents));\n\n    const taskResults = await Promise.allSettled(taskPromises);\n\n    for (let i = 0; i < taskResults.length; i++) {\n      const taskResult = taskResults[i];\n      const task = tasks[i];\n\n      if (taskResult.status === 'fulfilled') {\n        results.push(taskResult.value);\n        // If the task itself reported an error but didn't throw, track it\n        if (!taskResult.value.success && taskResult.value.error) {\n          errors.push(taskResult.value.error);\n        }\n      } else {\n        // Create a proper SubAgentError for rejected promises\n        const originalError =\n          taskResult.reason instanceof Error\n            ? taskResult.reason\n            : new Error(String(taskResult.reason));\n\n        const subAgentError = new SubAgentError(\n          `Parallel task for agent '${task.agentId}' failed: ${originalError.message}`,\n          task.agentId,\n          originalError\n        );\n\n        errors.push(subAgentError.message);\n        this.logger?.error('Sub-agent task failed in parallel execution', subAgentError, {\n          agentId: task.agentId,\n          taskIndex: i,\n          errorType: originalError.name,\n        });\n      }\n    }\n  }\n\n  /**\n   * Execute tasks sequentially with dependency handling\n   */\n  private async executeSequential(\n    tasks: SubAgentTask[],\n    subAgents: IAgent[],\n    results: SubAgentResult[],\n    errors: string[]\n  ): Promise<void> {\n    this.logger?.debug('Executing sub-agent tasks sequentially', { taskCount: tasks.length });\n\n    // Sort tasks by priority and dependencies\n    const sortedTasks = this.sortTasksByDependencies(tasks);\n\n    // Track failed task IDs for dependency error propagation\n    const failedTaskIds = new Set<string>();\n\n    for (const task of sortedTasks) {\n      // Check if any dependency failed - propagate error to dependent tasks\n      if (task.dependencies && task.dependencies.length > 0) {\n        const failedDependencies = task.dependencies.filter(\n          (depId) =>\n            failedTaskIds.has(depId) ||\n            results.some((r) => (r.agentId === depId || task.taskId === depId) && !r.success)\n        );\n\n        if (failedDependencies.length > 0) {\n          const dependencyErrorMessage = `Task skipped: dependencies failed [${failedDependencies.join(', ')}]`;\n          errors.push(dependencyErrorMessage);\n\n          // Mark this task as failed too so its dependents also get skipped\n          if (task.taskId) {\n            failedTaskIds.add(task.taskId);\n          }\n          failedTaskIds.add(task.agentId);\n\n          // Add a failed result for this task\n          const agent = subAgents.find((a) => a.id === task.agentId);\n          results.push({\n            agentId: task.agentId,\n            agentName: agent?.name || 'Unknown',\n            task: task.task,\n            result: '',\n            success: false,\n            error: dependencyErrorMessage,\n            executionTime: 0,\n          });\n\n          this.logger?.warn(`Skipping task due to failed dependencies`, {\n            agentId: task.agentId,\n            taskId: task.taskId,\n            failedDependencies,\n          });\n          continue;\n        }\n      }\n\n      try {\n        // Build context from previous results\n        const enhancedTask = this.enhanceTaskWithContext(task, results);\n        const result = await this.executeTask(enhancedTask, subAgents);\n        results.push(result);\n\n        // Track failed tasks for dependency propagation\n        if (!result.success) {\n          if (task.taskId) {\n            failedTaskIds.add(task.taskId);\n          }\n          failedTaskIds.add(task.agentId);\n        }\n\n        this.logger?.debug(`Sub-agent task completed: ${result.agentName}`, {\n          agentId: result.agentId,\n          success: result.success,\n          executionTime: result.executionTime,\n        });\n      } catch (error) {\n        const errorMessage = error instanceof Error ? error.message : String(error);\n        errors.push(errorMessage);\n        this.logger?.error('Sub-agent task failed in sequential execution', error as Error);\n\n        // Mark this task as failed for dependency propagation\n        if (task.taskId) {\n          failedTaskIds.add(task.taskId);\n        }\n        failedTaskIds.add(task.agentId);\n\n        // Continue with remaining tasks even if one fails\n      }\n    }\n  }\n\n  /**\n   * Execute a single sub-agent task\n   */\n  private async executeTask(task: SubAgentTask, subAgents: IAgent[]): Promise<SubAgentResult> {\n    const startTime = Date.now();\n\n    const agent = subAgents.find((a) => a.id === task.agentId);\n    if (!agent) {\n      throw new SubAgentError(`Agent with ID ${task.agentId} not found`, task.agentId);\n    }\n\n    try {\n      this.logger?.debug(`Executing task for agent: ${agent.name}`, {\n        agentId: agent.id,\n        task: task.task.substring(0, 100) + '...',\n      });\n\n      const result = await agent.ask(task.task);\n      const executionTime = Date.now() - startTime;\n\n      return {\n        agentId: agent.id,\n        agentName: agent.name,\n        task: task.task,\n        result,\n        success: true,\n        executionTime,\n      };\n    } catch (error) {\n      const executionTime = Date.now() - startTime;\n      const originalError = error instanceof Error ? error : new Error(String(error));\n\n      // Create SubAgentError with context for proper error chain propagation\n      const subAgentError = new SubAgentError(\n        `Sub-agent '${agent.name}' failed: ${originalError.message}`,\n        agent.id,\n        originalError\n      );\n\n      // Log the error with full context\n      this.logger?.error(`Sub-agent execution failed: ${agent.name}`, subAgentError, {\n        agentId: agent.id,\n        agentName: agent.name,\n        executionTime,\n        errorType: originalError.name,\n      });\n\n      return {\n        agentId: agent.id,\n        agentName: agent.name,\n        task: task.task,\n        result: '',\n        success: false,\n        error: subAgentError.message,\n        executionTime,\n      };\n    }\n  }\n\n  /**\n   * Sort tasks by dependencies to ensure proper execution order\n   * Uses task index instead of agentId to support multiple tasks for the same agent\n   * @param tasks - Array of tasks to sort\n   * @param maxDepth - Maximum recursion depth to prevent stack overflow (default: 1000)\n   */\n  private sortTasksByDependencies(tasks: SubAgentTask[], maxDepth: number = 1000): SubAgentTask[] {\n    const visited = new Set<number>(); // task index\n    const visiting = new Set<number>(); // task index\n    const sorted: SubAgentTask[] = [];\n\n    const visit = (index: number, depth: number = 0) => {\n      // Prevent stack overflow with depth limit\n      if (depth > maxDepth) {\n        throw new Error(\n          `Max dependency depth exceeded: ${maxDepth}. Possible circular dependency or too deep nesting.`\n        );\n      }\n\n      const task = tasks[index];\n      if (visiting.has(index)) {\n        throw new Error(`Circular dependency detected for task ${index}`);\n      }\n      if (visited.has(index)) return;\n\n      visiting.add(index);\n      if (task.dependencies) {\n        for (const depTaskId of task.dependencies) {\n          /**\n           * Dependency Resolution Strategy:\n           * 1. First, try to find by taskId (unique task identifier)\n           * 2. Fallback to agentId (UUID) for flexibility\n           *\n           * Note: When multiple tasks exist for the same agent, use taskId\n           * to specify which specific task is the dependency. Using agentId\n           * will match the first task for that agent, which may not be intended.\n           *\n           * Example:\n           * - taskId: \"validate-input\" -> Matches specific task\n           * - agentId: \"uuid-xxx\" -> Matches first task for agent\n           */\n          const depIndex = tasks.findIndex(\n            (t) => t.taskId === depTaskId || t.agentId === depTaskId\n          );\n          if (depIndex !== -1) {\n            visit(depIndex, depth + 1);\n          } else {\n            this.logger?.warn(\n              `Dependency not found: ${depTaskId}. Ensure taskId or agentId matches a defined task.`\n            );\n          }\n        }\n      }\n      visiting.delete(index);\n      visited.add(index);\n      sorted.push(task);\n    };\n\n    // Sort by priority first (using nullish coalescing for falsy priority values like 0)\n    const prioritySorted = tasks\n      .map((task, index) => ({ task, index }))\n      .sort((a, b) => (b.task.priority ?? 0) - (a.task.priority ?? 0));\n\n    for (const { index } of prioritySorted) {\n      visit(index, 0);\n    }\n\n    return sorted;\n  }\n\n  /**\n   * Enhance task with context from previous results\n   */\n  private enhanceTaskWithContext(\n    task: SubAgentTask,\n    previousResults: SubAgentResult[]\n  ): SubAgentTask {\n    if (!task.dependencies || task.dependencies.length === 0) {\n      return task;\n    }\n\n    // Get results from dependency agents\n    const deps = task.dependencies ?? [];\n    const dependencyResults = previousResults.filter((r) => deps.includes(r.agentId) && r.success);\n\n    if (dependencyResults.length === 0) {\n      return task;\n    }\n\n    // Build context string from dependency results\n    const contextParts = dependencyResults.map((r) => `Result from ${r.agentName}: ${r.result}`);\n\n    const enhancedTask = `Previous context:\\n${contextParts.join('\\n\\n')}\\n\\nBased on the above context, ${task.task}`;\n\n    return {\n      ...task,\n      task: enhancedTask,\n    };\n  }\n\n  /**\n   * Aggregate results from all sub-agents into a final result\n   */\n  private aggregateResults(results: SubAgentResult[]): string {\n    if (results.length === 0) {\n      return 'No results from sub-agents';\n    }\n\n    if (results.length === 1) {\n      return results[0].result;\n    }\n\n    // For multiple results, create a comprehensive summary\n    const successfulResults = results.filter((r) => r.success);\n\n    if (successfulResults.length === 0) {\n      return 'All sub-agent tasks failed';\n    }\n\n    const resultSections = successfulResults.map((r) => `## ${r.agentName} Results\\n\\n${r.result}`);\n\n    return resultSections.join('\\n\\n---\\n\\n');\n  }\n}\n","/**\n * Default configuration values for sub-agent module\n */\nexport const DEFAULT_SUBAGENT_CONFIG = {\n  fallbackModel: 'gpt-4o-mini',\n  defaultDelegation: 'auto',\n  defaultCoordination: 'parallel',\n  defaultTimeout: 5 * 60 * 1000, // 5 minutes - single source of truth for timeout\n} as const;\n\n/**\n * Sub-agent timeout configuration\n * Splitting total timeout between delegation and execution phases\n *\n * Problem solved: When node timeout is 1 minute and we split 40/60,\n * delegation gets only 24 seconds which is often too short.\n *\n * Solution: Use minimum values to ensure each phase has adequate time.\n */\nexport const SUB_AGENT_TIMEOUT_CONFIG = {\n  /** Total timeout for sub-agent operations (5 minutes) */\n  total: DEFAULT_SUBAGENT_CONFIG.defaultTimeout,\n  /** Percentage of total timeout allocated to delegation phase */\n  delegationRatio: 0.4,\n  /** Percentage of total timeout allocated to execution phase */\n  executionRatio: 0.6,\n  /** Minimum timeout for delegation phase (30 seconds) */\n  minDelegationTimeout: 30 * 1000,\n  /** Minimum timeout for execution phase (30 seconds) */\n  minExecutionTimeout: 30 * 1000,\n} as const;\n\n/**\n * Calculate timeout values with minimum guarantees\n * @param totalTimeout - Total available timeout in milliseconds\n * @returns Object with delegateTimeout and executeTimeout\n */\nexport function calculateSubAgentTimeouts(totalTimeout: number): {\n  delegateTimeout: number;\n  executeTimeout: number;\n} {\n  const calculatedDelegation = Math.floor(totalTimeout * SUB_AGENT_TIMEOUT_CONFIG.delegationRatio);\n  const calculatedExecution = Math.floor(totalTimeout * SUB_AGENT_TIMEOUT_CONFIG.executionRatio);\n\n  // Apply minimum values\n  const delegateTimeout = Math.max(\n    calculatedDelegation,\n    SUB_AGENT_TIMEOUT_CONFIG.minDelegationTimeout\n  );\n  const executeTimeout = Math.max(\n    calculatedExecution,\n    SUB_AGENT_TIMEOUT_CONFIG.minExecutionTimeout\n  );\n\n  return { delegateTimeout, executeTimeout };\n}\n\n/**\n * Get default value for a sub-agent config property\n */\nexport function getSubAgentDefaultValue<K extends keyof typeof DEFAULT_SUBAGENT_CONFIG>(\n  key: K\n): (typeof DEFAULT_SUBAGENT_CONFIG)[K] {\n  return DEFAULT_SUBAGENT_CONFIG[key];\n}\n","/**\n * Task delegation strategies for sub-agents\n */\nimport { IAgent } from '../agent/types';\nimport { SubAgentTask, DelegationStrategy, SubAgentRunOptions } from './types';\nimport { getLLM } from '../llm';\nimport { DEFAULT_SUBAGENT_CONFIG } from './defaults';\nimport { Logger } from '../logger/types';\n\n/**\n * Auto delegation strategy - uses LLM to intelligently analyze task and assign to sub-agents\n */\nexport class AutoDelegationStrategy implements DelegationStrategy {\n  name = 'auto' as const;\n  private logger?: Logger;\n\n  constructor(logger?: Logger) {\n    this.logger = logger;\n  }\n\n  async delegate(\n    prompt: string,\n    subAgents?: IAgent[],\n    options?: SubAgentRunOptions,\n    model?: string\n  ): Promise<SubAgentTask[]> {\n    // Null/empty check with warning\n    if (!subAgents || subAgents.length === 0) {\n      this.logger?.warn('No sub-agents provided for delegation');\n      return [];\n    }\n\n    // Single agent case - assign full task\n    if (subAgents.length === 1) {\n      return [\n        {\n          agentId: subAgents[0].id,\n          task: prompt,\n          priority: 5,\n        },\n      ];\n    }\n\n    try {\n      // Use LLM to analyze task and create delegation plan\n      const delegationPlan = await this.createDelegationPlan(prompt, subAgents, model);\n      return delegationPlan;\n    } catch (error) {\n      this.logger?.warn('LLM-based delegation failed, using fallback', {\n        error: error instanceof Error ? error.message : String(error),\n      });\n\n      // Fallback: assign full task to all agents (parallel execution)\n      return subAgents.map((agent) => ({\n        agentId: agent.id,\n        task: prompt,\n        priority: 5,\n      }));\n    }\n  }\n\n  private async createDelegationPlan(\n    prompt: string,\n    subAgents: IAgent[],\n    model?: string\n  ): Promise<SubAgentTask[]> {\n    const llm = getLLM(this.logger);\n\n    // Build sub-agent information for the LLM\n    const agentDescriptions = subAgents\n      .map(\n        (agent) =>\n          `Agent ID: ${agent.id}, Name: \"${agent.name}\", Role: \"${agent.config.systemPrompt || 'General assistant'}\"`\n      )\n      .join('\\n');\n\n    const delegationPrompt = `You are a task coordinator. Analyze the following task and decide how to distribute it among available sub-agents.\n\nTASK TO DELEGATE:\n\"${prompt}\"\n\nAVAILABLE SUB-AGENTS:\n${agentDescriptions}\n\nINSTRUCTIONS:\n1. Analyze the task and determine if it can be broken down into subtasks\n2. Assign each subtask to the most appropriate sub-agent based on their role/expertise\n3. If the task cannot be meaningfully split, assign it to the most relevant single agent\n4. Provide priority levels (1-10, higher = more important/should execute first)\n\nRESPONSE FORMAT (JSON only, no explanation):\n{\n  \"tasks\": [\n    {\n      \"agentId\": number,\n      \"task\": \"specific task description\",\n      \"priority\": number,\n      \"reasoning\": \"brief explanation why this agent\"\n    }\n  ]\n}\n\nExample response:\n{\n  \"tasks\": [\n    {\n      \"agentId\": \"agent-uuid-1234\",\n      \"task\": \"Research current AI trends in healthcare\",\n      \"priority\": 8,\n      \"reasoning\": \"Researcher agent best suited for information gathering\"\n    },\n    {\n      \"agentId\": \"agent-uuid-5678\",\n      \"task\": \"Write a comprehensive report based on the research findings\",\n      \"priority\": 6,\n      \"reasoning\": \"Writer agent specialized in content creation\"\n    }\n  ]\n}`;\n\n    const response = await llm.generateResponse({\n      model: model || DEFAULT_SUBAGENT_CONFIG.fallbackModel, // Use provided model or fallback to fast model\n      messages: [{ role: 'user', content: delegationPrompt }],\n      temperature: 0.3, // Low temperature for consistent delegation\n      maxTokens: 1000,\n    });\n\n    this.logger?.debug('LLM delegation response', {\n      response: response.content.substring(0, 200) + '...',\n    });\n\n    try {\n      // Extract JSON from response\n      const jsonMatch = response.content.match(/\\{[\\s\\S]*\\}/);\n      if (!jsonMatch) {\n        throw new Error('No JSON found in LLM response');\n      }\n\n      const delegationResult = JSON.parse(jsonMatch[0]);\n\n      if (!delegationResult.tasks || !Array.isArray(delegationResult.tasks)) {\n        throw new Error('Invalid delegation result format');\n      }\n\n      // Convert to SubAgentTask format and validate\n      const tasks: SubAgentTask[] = delegationResult.tasks\n        .filter((task: { agentId: string; task: string; priority?: number }) => {\n          // Validate each task\n          const hasValidAgentId =\n            typeof task.agentId === 'string' &&\n            subAgents.some((agent) => agent.id === task.agentId);\n          const hasValidTask = typeof task.task === 'string' && task.task.trim().length > 0;\n\n          if (!hasValidAgentId) {\n            this.logger?.warn(`Invalid agent ID in delegation: ${task.agentId}`);\n          }\n          if (!hasValidTask) {\n            this.logger?.warn(`Invalid task in delegation: ${task.task}`);\n          }\n\n          return hasValidAgentId && hasValidTask;\n        })\n        .map((task: { agentId: string; task: string; priority?: number }) => ({\n          agentId: task.agentId,\n          task: task.task.trim(),\n          priority: typeof task.priority === 'number' ? task.priority : 5,\n        }));\n\n      if (tasks.length === 0) {\n        throw new Error('No valid tasks generated by LLM');\n      }\n\n      this.logger?.info(`LLM generated ${tasks.length} delegation tasks`, {\n        taskCount: tasks.length,\n        agentIds: tasks.map((t) => t.agentId),\n      });\n\n      return tasks;\n    } catch (parseError) {\n      this.logger?.error('Failed to parse LLM delegation response', parseError as Error);\n      throw new Error(\n        `Failed to parse delegation plan: ${parseError instanceof Error ? parseError.message : 'Unknown error'}`\n      );\n    }\n  }\n}\n\n/**\n * Manual delegation strategy - uses provided task assignments\n */\nexport class ManualDelegationStrategy implements DelegationStrategy {\n  name = 'manual' as const;\n\n  async delegate(\n    _prompt: string,\n    subAgents?: IAgent[],\n    options?: SubAgentRunOptions\n  ): Promise<SubAgentTask[]> {\n    const tasks: SubAgentTask[] = [];\n\n    // Null/empty check\n    if (!subAgents || subAgents.length === 0) {\n      return [];\n    }\n\n    if (!options?.taskAssignment) {\n      throw new Error('Manual delegation requires taskAssignment in options');\n    }\n\n    // Create tasks based on manual assignment\n    for (const [agentId, task] of Object.entries(options.taskAssignment)) {\n      // agentId is already a UUID string, no need to parse\n      const agent = subAgents.find((a) => a.id === agentId);\n\n      if (!agent) {\n        throw new Error(`Agent with ID ${agentId} not found in sub-agents`);\n      }\n\n      tasks.push({\n        agentId, // UUID string\n        task,\n        priority: 5, // Default priority for manual tasks\n      });\n    }\n\n    return tasks;\n  }\n}\n\n/**\n * Sequential delegation strategy - assigns tasks in order to available sub-agents\n */\nexport class SequentialDelegationStrategy implements DelegationStrategy {\n  name = 'sequential' as const;\n\n  async delegate(prompt: string, subAgents?: IAgent[]): Promise<SubAgentTask[]> {\n    const tasks: SubAgentTask[] = [];\n\n    // Null/empty check\n    if (!subAgents || subAgents.length === 0) {\n      return tasks;\n    }\n\n    // For sequential, we assign the full prompt to each agent in order\n    // Each agent builds on the previous agent's work\n    for (let i = 0; i < subAgents.length; i++) {\n      const agent = subAgents[i];\n\n      let task: string;\n      if (i === 0) {\n        // First agent gets the original task\n        task = prompt;\n      } else {\n        // Subsequent agents build on previous work\n        task = `Based on the previous agent's work, continue and enhance: ${prompt}`;\n      }\n\n      tasks.push({\n        agentId: agent.id,\n        task,\n        priority: 10 - i, // Decreasing priority for execution order\n        dependencies: i > 0 ? [subAgents[i - 1].id] : [], // Depend on previous agent\n      });\n    }\n\n    return tasks;\n  }\n}\n\n/**\n * Factory function to get delegation strategy\n */\nexport function getDelegationStrategy(\n  type: 'auto' | 'manual' | 'sequential',\n  logger?: Logger\n): DelegationStrategy {\n  switch (type) {\n    case 'auto':\n      return new AutoDelegationStrategy(logger);\n    case 'manual':\n      return new ManualDelegationStrategy();\n    case 'sequential':\n      return new SequentialDelegationStrategy();\n    default:\n      throw new Error(`Unknown delegation strategy: ${type}`);\n  }\n}\n","/**\n * SubAgent module - Manages sub-agent coordination and delegation\n */\nimport { IAgentModule, IAgent, AskOptions } from '../agent/types';\nimport { SubAgentCoordinator } from './coordination';\nimport { getDelegationStrategy } from './delegation';\nimport { SubAgentCoordinationResult } from './types';\nimport { Logger } from '../logger/types';\nimport { getLogger } from '../logger';\nimport { DEFAULT_SUBAGENT_CONFIG, calculateSubAgentTimeouts } from './defaults';\nimport { SubAgentError } from '../errors';\n\n// Use centralized timeout configuration from defaults\nconst DEFAULT_EXECUTION_TIMEOUT = DEFAULT_SUBAGENT_CONFIG.defaultTimeout;\n\n/**\n * Error thrown when sub-agent execution times out\n */\nexport class SubAgentTimeoutError extends Error {\n  constructor(timeoutMs: number, operation?: string) {\n    const message = operation\n      ? `Sub-agent ${operation} timed out after ${timeoutMs}ms`\n      : `Sub-agent execution timed out after ${timeoutMs}ms`;\n    super(message);\n    this.name = 'SubAgentTimeoutError';\n  }\n}\n\n/**\n * Result of wrapping a promise with timeout using AbortController\n */\ninterface TimeoutResult<T> {\n  promise: Promise<T>;\n  abort: () => void;\n}\n\n/**\n * Wraps a promise with a timeout and provides proper cancellation via AbortController.\n * This prevents resource leaks by allowing cleanup when timeout occurs.\n *\n * @param promiseFactory - Factory function that creates the promise, receives AbortSignal\n * @param timeoutMs - Timeout in milliseconds\n * @param operation - Operation name for error messages\n * @returns Promise that resolves with result or rejects with timeout error\n */\nfunction withTimeoutAbortable<T>(\n  promiseFactory: (signal: AbortSignal) => Promise<T>,\n  timeoutMs: number,\n  operation: string\n): TimeoutResult<T> {\n  const controller = new AbortController();\n  const { signal } = controller;\n\n  const promise = new Promise<T>((resolve, reject) => {\n    const timer = setTimeout(() => {\n      controller.abort();\n      reject(new SubAgentTimeoutError(timeoutMs, operation));\n    }, timeoutMs);\n\n    // Handle abort from external source\n    signal.addEventListener('abort', () => {\n      clearTimeout(timer);\n    });\n\n    promiseFactory(signal)\n      .then((result) => {\n        clearTimeout(timer);\n        if (!signal.aborted) {\n          resolve(result);\n        }\n      })\n      .catch((error) => {\n        clearTimeout(timer);\n        if (!signal.aborted) {\n          reject(error);\n        }\n      });\n  });\n\n  return {\n    promise,\n    abort: () => controller.abort(),\n  };\n}\n\nexport class SubAgent implements IAgentModule {\n  readonly name = 'subAgent';\n  private coordinator: SubAgentCoordinator;\n  private logger: Logger;\n\n  constructor(logger?: Logger) {\n    this.logger = logger ?? getLogger();\n    this.coordinator = new SubAgentCoordinator(this.logger);\n  }\n\n  async initialize(): Promise<void> {\n    this.logger.debug('SubAgent module initialized');\n  }\n\n  /**\n   * Execute task using sub-agents\n   * @param prompt - The prompt/task to execute\n   * @param subAgents - Array of sub-agents to use\n   * @param options - Execution options including contextIsolation strategy\n   * @param mainAgentModel - Optional model override for main agent\n   * @param parentAgent - Optional parent agent for context merging\n   */\n  async executeWithSubAgents(\n    prompt: string,\n    subAgents: IAgent[],\n    options: AskOptions = {},\n    mainAgentModel?: string,\n    parentAgent?: IAgent\n  ): Promise<string> {\n    if (!subAgents || subAgents.length === 0) {\n      throw new Error('No sub-agents provided');\n    }\n\n    if (!prompt || typeof prompt !== 'string' || prompt.trim().length === 0) {\n      throw new Error('Invalid prompt: prompt must be a non-empty string');\n    }\n\n    const timeoutMs = options.timeout ?? DEFAULT_EXECUTION_TIMEOUT;\n    const contextIsolation = options.contextIsolation || 'isolated';\n\n    this.logger.info(`Executing task with ${subAgents.length} sub-agents`, {\n      delegation: options.delegation || 'auto',\n      coordination: options.coordination || 'parallel',\n      contextIsolation,\n      timeout: timeoutMs,\n    });\n\n    try {\n      // Get delegation strategy\n      const delegationType = options.delegation || 'auto';\n      const strategy = getDelegationStrategy(delegationType, this.logger);\n\n      // Calculate timeout values with minimum guarantees\n      // This prevents issues when node timeout is too short (e.g., 1 minute = 24s delegation)\n      const { delegateTimeout, executeTimeout } = calculateSubAgentTimeouts(timeoutMs);\n\n      this.logger.debug(\n        `Sub-agent timeout allocation: delegation=${delegateTimeout}ms, execution=${executeTimeout}ms (total=${timeoutMs}ms)`\n      );\n\n      // Delegate tasks to sub-agents with proportional timeout\n      const { promise: delegatePromise } = withTimeoutAbortable(\n        () => strategy.delegate(prompt, subAgents, options, mainAgentModel),\n        delegateTimeout,\n        'task delegation'\n      );\n      const tasks = await delegatePromise;\n\n      this.logger.debug(`Generated ${tasks.length} tasks for sub-agents`, {\n        taskCount: tasks.length,\n        agentIds: tasks.map((t) => t.agentId),\n        priorities: tasks.map((t) => t.priority ?? 0),\n      });\n\n      if (tasks.length === 0) {\n        throw new Error('No tasks generated for sub-agents');\n      }\n\n      // Execute tasks with coordination, context isolation, and proportional timeout\n      const coordination = options.coordination || 'parallel';\n      const { promise: executePromise } = withTimeoutAbortable(\n        () =>\n          this.coordinator.executeSubAgentTasks(\n            tasks,\n            subAgents,\n            coordination,\n            contextIsolation,\n            parentAgent\n          ),\n        executeTimeout,\n        'sub-agent execution'\n      );\n      const result = await executePromise;\n\n      if (!result.success) {\n        this.logger.warn('Sub-agent execution completed with errors', {\n          errors: result.errors,\n          successfulResults: result.results.filter((r) => r.success).length,\n        });\n      }\n\n      return result.finalResult;\n    } catch (error) {\n      const originalError = error instanceof Error ? error : new Error(String(error));\n      if (error instanceof SubAgentTimeoutError) {\n        this.logger.error(`Sub-agent execution timed out after ${timeoutMs}ms`);\n        throw error;\n      }\n      this.logger.error('Sub-agent execution failed', originalError, {\n        errorMessage: originalError.message,\n      });\n      throw new SubAgentError(\n        `Sub-agent execution failed: ${originalError.message}`,\n        undefined,\n        originalError\n      );\n    }\n  }\n\n  /**\n   * Get detailed results from sub-agent execution\n   */\n  async executeWithSubAgentsDetailed(\n    prompt: string,\n    subAgents: IAgent[],\n    options: AskOptions = {},\n    mainAgentModel?: string\n  ): Promise<SubAgentCoordinationResult> {\n    if (!subAgents || subAgents.length === 0) {\n      throw new Error('No sub-agents provided');\n    }\n\n    if (!prompt || typeof prompt !== 'string' || prompt.trim().length === 0) {\n      throw new Error('Invalid prompt: prompt must be a non-empty string');\n    }\n\n    const timeoutMs = options.timeout ?? DEFAULT_EXECUTION_TIMEOUT;\n\n    this.logger.debug('Starting detailed sub-agent execution', {\n      subAgentCount: subAgents.length,\n      delegation: options.delegation || 'auto',\n      coordination: options.coordination || 'parallel',\n      timeout: timeoutMs,\n    });\n\n    try {\n      // Get delegation strategy\n      const delegationType = options.delegation || 'auto';\n      const strategy = getDelegationStrategy(delegationType, this.logger);\n\n      // Calculate timeout values with minimum guarantees\n      // This prevents issues when node timeout is too short (e.g., 1 minute = 24s delegation)\n      const { delegateTimeout, executeTimeout } = calculateSubAgentTimeouts(timeoutMs);\n\n      this.logger.debug(\n        `Sub-agent timeout allocation: delegation=${delegateTimeout}ms, execution=${executeTimeout}ms (total=${timeoutMs}ms)`\n      );\n\n      // Delegate tasks to sub-agents with proportional timeout\n      const { promise: delegatePromise } = withTimeoutAbortable(\n        () => strategy.delegate(prompt, subAgents, options, mainAgentModel),\n        delegateTimeout,\n        'task delegation'\n      );\n      const tasks = await delegatePromise;\n\n      if (tasks.length === 0) {\n        throw new Error('No tasks generated for sub-agents');\n      }\n\n      // Execute tasks with coordination and proportional timeout\n      const coordination = options.coordination || 'parallel';\n      const { promise: executePromise } = withTimeoutAbortable(\n        () => this.coordinator.executeSubAgentTasks(tasks, subAgents, coordination),\n        executeTimeout,\n        'sub-agent execution'\n      );\n      return await executePromise;\n    } catch (error) {\n      const originalError = error instanceof Error ? error : new Error(String(error));\n      if (error instanceof SubAgentTimeoutError) {\n        this.logger.error(`Detailed sub-agent execution timed out after ${timeoutMs}ms`);\n        throw error;\n      }\n      this.logger.error('Detailed sub-agent execution failed', originalError, {\n        errorMessage: originalError.message,\n      });\n      throw new SubAgentError(\n        `Detailed sub-agent execution failed: ${originalError.message}`,\n        undefined,\n        originalError\n      );\n    }\n  }\n\n  /**\n   * Check if an agent has sub-agents\n   */\n  hasSubAgents(agent: IAgent): boolean {\n    if (!agent || !agent.config) {\n      return false;\n    }\n    return Array.isArray(agent.config.subAgents) && agent.config.subAgents.length > 0;\n  }\n\n  /**\n   * Get sub-agents for an agent\n   */\n  getSubAgents(agent: IAgent): IAgent[] {\n    if (!agent || !agent.config || !Array.isArray(agent.config.subAgents)) {\n      return [];\n    }\n    return agent.config.subAgents;\n  }\n\n  /**\n   * Destroy SubAgent module and free resources.\n   * Call this when the module is no longer needed.\n   */\n  async destroy(): Promise<void> {\n    // Clear coordinator reference\n    // Note: SubAgentCoordinator doesn't hold persistent state (just logger reference)\n    // The coordinator doesn't have pending tasks since executeSubAgentTasks returns a promise\n    // and we await it before destroy is called\n\n    // Clear any internal references\n    // SubAgentCoordinator uses IAgent references which are passed in per-call,\n    // not stored permanently, so no cleanup needed there\n\n    this.logger.debug('SubAgent module destroyed');\n  }\n}\n\n// Export types and utilities\nexport * from './types';\nexport * from './delegation';\nexport * from './coordination';\n\n// Export timeout utilities for advanced usage\nexport { withTimeoutAbortable, TimeoutResult };\n","import { ContextCompressorOptions } from './types';\n\nexport const DEFAULT_CONTEXT_OPTIONS: ContextCompressorOptions = {\n  maxContextLength: 8000,\n  compressionRatio: 0.3,\n  preserveLastN: 3,\n  model: 'gpt-4o-mini',\n  compressionStrategy: 'hybrid',\n  enableSemanticCompression: true,\n  preserveImportantContext: true,\n};\n","import { CompressionStrategy, ContextMessage, ContextCompressorOptions } from './types';\nimport { DEFAULT_CONTEXT_OPTIONS } from './defaults';\nimport { getLLM } from '../llm';\nimport { getLogger } from '../logger';\n\nexport class SummarizationStrategy implements CompressionStrategy {\n  name = 'summarize';\n  private logger = getLogger();\n\n  async compress(\n    messages: ContextMessage[],\n    options: ContextCompressorOptions\n  ): Promise<ContextMessage[]> {\n    // Handle empty messages array\n    if (!messages || messages.length === 0) {\n      return [];\n    }\n\n    const preserveCount = Math.min(options.preserveLastN ?? 3, messages.length);\n\n    // Edge case: if preserveCount equals message length, nothing to compress\n    if (preserveCount >= messages.length) {\n      return [...messages];\n    }\n\n    const messagesToPreserve = messages.slice(-preserveCount);\n\n    // Filter out old summaries from messages to compress (we'll combine them into new summary)\n    const messagesToCompress = messages.slice(0, -preserveCount);\n    const oldSummaries = messagesToCompress.filter((msg) => msg.metadata?.type === 'summary');\n    const regularMessages = messagesToCompress.filter((msg) => msg.metadata?.type !== 'summary');\n\n    if (messagesToCompress.length === 0) {\n      return [...messages];\n    }\n\n    // Combine old summaries and regular messages for new summary\n    let conversationText = '';\n\n    // Include old summaries content\n    if (oldSummaries.length > 0) {\n      conversationText += 'Previous Summaries:\\n';\n      conversationText += oldSummaries.map((msg) => msg.content).join('\\n\\n');\n      conversationText += '\\n\\nNew Messages:\\n';\n    }\n\n    // Add regular messages\n    conversationText += regularMessages\n      .map((msg) => `${msg.role.toUpperCase()}: ${msg.content}`)\n      .join('\\n\\n');\n\n    const summaryPrompt = `Summarize the following conversation history concisely, preserving key context and important information:\n\n${conversationText}\n\nCreate a comprehensive summary that maintains essential context, key decisions, and important facts.`;\n\n    try {\n      const llm = getLLM(getLogger());\n      if (!llm) {\n        this.logger.warn('LLM not available for compression');\n        return [...messagesToCompress, ...messagesToPreserve]; // Fallback: preserve all messages\n      }\n\n      const response = await llm.generateResponse({\n        model: options.model ?? DEFAULT_CONTEXT_OPTIONS.model ?? 'gpt-4o-mini',\n        messages: [{ role: 'user' as const, content: summaryPrompt }],\n        temperature: 0.3,\n        maxTokens: 500,\n      });\n\n      // Validate response content\n      const responseContent = response?.content ?? '';\n\n      const totalOriginalCount = messagesToCompress.reduce((count, msg) => {\n        const msgCount = msg.metadata?.originalMessageCount;\n        return count + (typeof msgCount === 'number' ? msgCount : 1);\n      }, 0);\n\n      const summaryMessage: ContextMessage = {\n        role: 'system',\n        content: `[Context Compressed] Previous ${totalOriginalCount} messages summarized:\\n${responseContent}`,\n        metadata: {\n          type: 'summary',\n          originalMessageCount: totalOriginalCount,\n          compressionTimestamp: new Date(),\n          compressed: true,\n        },\n        timestamp: new Date(),\n        tokens: Math.floor(responseContent.length / 4), // Estimate tokens\n      };\n\n      // Return only ONE summary plus preserved messages\n      return [summaryMessage, ...messagesToPreserve];\n    } catch (error) {\n      // Fallback: if summarization fails, preserve ALL messages to prevent data loss\n      this.logger.error(\n        'Compression failed, preserving all messages',\n        error instanceof Error ? error : undefined\n      );\n      return [...messagesToCompress, ...messagesToPreserve]; // Don't lose any messages\n    }\n  }\n\n  estimateCompression(): number {\n    return 0.3;\n  }\n}\n\nexport class SelectiveStrategy implements CompressionStrategy {\n  name = 'selective';\n  private logger = getLogger();\n\n  async compress(\n    messages: ContextMessage[],\n    options: ContextCompressorOptions\n  ): Promise<ContextMessage[]> {\n    // Handle empty messages array\n    if (!messages || messages.length === 0) {\n      return [];\n    }\n\n    const preserveCount = Math.min(options.preserveLastN ?? 3, messages.length);\n\n    // Edge case: if preserveCount equals message length, nothing to compress\n    if (preserveCount >= messages.length) {\n      return [...messages];\n    }\n\n    const messagesToPreserve = messages.slice(-preserveCount);\n    const messagesToAnalyze = messages.slice(0, -preserveCount);\n\n    if (messagesToAnalyze.length === 0) {\n      return [...messages];\n    }\n\n    const importantMessages = await this.selectImportantMessages(messagesToAnalyze, options);\n\n    // If no important messages were selected, preserve some older messages as fallback\n    // to prevent complete data loss from the non-preserved portion\n    if (importantMessages.length === 0 && messagesToAnalyze.length > 0) {\n      // Fallback: keep at least 20% of older messages or minimum 1 message\n      const fallbackCount = Math.max(1, Math.ceil(messagesToAnalyze.length * 0.2));\n      const fallbackMessages = messagesToAnalyze.slice(-fallbackCount);\n      this.logger.debug('Using fallback selection due to empty LLM selection', {\n        originalCount: messagesToAnalyze.length,\n        fallbackCount,\n      });\n      return [...fallbackMessages, ...messagesToPreserve];\n    }\n\n    return [...importantMessages, ...messagesToPreserve];\n  }\n\n  private async selectImportantMessages(\n    messages: ContextMessage[],\n    options: ContextCompressorOptions\n  ): Promise<ContextMessage[]> {\n    // Handle empty messages\n    if (!messages || messages.length === 0) {\n      return [];\n    }\n\n    try {\n      const llm = getLLM(getLogger());\n      if (!llm) {\n        this.logger.warn('LLM not available for selective compression');\n        return []; // Fallback: let compress() use only messagesToPreserve\n      }\n\n      const conversationText = messages\n        .map((msg, idx) => `[${idx}] ${msg.role?.toUpperCase() ?? 'UNKNOWN'}: ${msg.content ?? ''}`)\n        .join('\\n\\n');\n\n      const selectionPrompt = `Analyze the following conversation and identify the most important messages that must be preserved for context:\n\n${conversationText}\n\nReturn the indices of important messages as a comma-separated list. Consider:\n- Key decisions or agreements\n- Important facts or data\n- Context-setting information\n- Unresolved questions or tasks\n\nImportant message indices:`;\n\n      const response = await llm.generateResponse({\n        model: options.model ?? DEFAULT_CONTEXT_OPTIONS.model ?? 'gpt-4o-mini',\n        messages: [{ role: 'user' as const, content: selectionPrompt }],\n        temperature: 0.1,\n        maxTokens: 100,\n      });\n\n      // Safely parse response content\n      const responseContent = response?.content ?? '';\n      const indices = responseContent\n        .split(',')\n        .map((s) => parseInt(s.trim()))\n        .filter((n) => !isNaN(n) && n >= 0 && n < messages.length);\n\n      const selected = indices.map((i) => messages[i]).filter(Boolean);\n\n      if (selected.length === 0) {\n        // Fallback: return empty to let compress() use only messagesToPreserve\n        // This matches SummarizationStrategy's fallback behavior\n        this.logger.debug('No important messages selected, using fallback');\n        return [];\n      }\n\n      return selected;\n    } catch (error) {\n      // Fallback: if LLM call fails, return empty to let compress() use only messagesToPreserve\n      // This matches SummarizationStrategy's fallback behavior for consistency\n      this.logger.warn(\n        'Selective compression failed, falling back to preserving recent messages only',\n        {\n          error: error instanceof Error ? error.message : String(error),\n        }\n      );\n      return [];\n    }\n  }\n\n  estimateCompression(): number {\n    return 0.4;\n  }\n}\n\nexport class HybridStrategy implements CompressionStrategy {\n  name = 'hybrid';\n  private logger: ReturnType<typeof getLogger>;\n  private summarizationStrategy: SummarizationStrategy;\n  private selectiveStrategy: SelectiveStrategy;\n\n  constructor(logger?: ReturnType<typeof getLogger>) {\n    // Cache sub-strategies in constructor to prevent memory leaks from repeated instantiation\n    this.logger = logger ?? getLogger();\n    this.summarizationStrategy = new SummarizationStrategy();\n    this.selectiveStrategy = new SelectiveStrategy();\n  }\n\n  async compress(\n    messages: ContextMessage[],\n    options: ContextCompressorOptions\n  ): Promise<ContextMessage[]> {\n    // Handle empty messages array\n    if (!messages || messages.length === 0) {\n      return [];\n    }\n\n    const preserveCount = Math.min(options.preserveLastN ?? 3, messages.length);\n\n    // Edge case: if preserveCount equals message length, nothing to compress\n    if (preserveCount >= messages.length) {\n      return [...messages];\n    }\n\n    const messagesToPreserve = messages.slice(-preserveCount);\n    const messagesToCompress = messages.slice(0, -preserveCount);\n\n    if (messagesToCompress.length === 0) {\n      return [...messages];\n    }\n\n    try {\n      // For very long conversations or if we already have summaries, use summarization\n      const hasSummaries = messagesToCompress.some((msg) => msg.metadata?.type === 'summary');\n      if (messagesToCompress.length > 20 || hasSummaries) {\n        return this.summarizationStrategy.compress(messages, options);\n      }\n\n      // For medium conversations, use selective preservation with mini-summaries\n      const sliceIndex = Math.floor(messagesToCompress.length * 0.6);\n      const importantMessages = await this.selectiveStrategy.compress(\n        messagesToCompress.slice(0, sliceIndex),\n        options\n      );\n\n      const recentToSummarize = messagesToCompress.slice(sliceIndex);\n\n      if (recentToSummarize.length > 0) {\n        const summarized = await this.summarizationStrategy.compress(recentToSummarize, {\n          ...options,\n          preserveLastN: 0,\n        });\n        return [...importantMessages, ...summarized, ...messagesToPreserve];\n      }\n\n      return [...importantMessages, ...messagesToPreserve];\n    } catch (error) {\n      // Fallback: if hybrid compression fails, preserve ALL messages to prevent data loss\n      this.logger.error(\n        'Hybrid compression failed, preserving all messages',\n        error instanceof Error ? error : undefined\n      );\n      return [...messagesToCompress, ...messagesToPreserve]; // Don't lose any messages\n    }\n  }\n\n  estimateCompression(): number {\n    return 0.3;\n  }\n}\n\n// Singleton cache for strategy instances to prevent memory leaks\n// Limited to known strategy types to prevent unbounded growth\nconst VALID_STRATEGIES = ['summarize', 'selective', 'hybrid'] as const;\ntype ValidStrategyName = (typeof VALID_STRATEGIES)[number];\n\nconst strategyCache = new Map<ValidStrategyName, CompressionStrategy>();\n\nfunction createStrategy(strategyName: ValidStrategyName): CompressionStrategy {\n  switch (strategyName) {\n    case 'summarize':\n      return new SummarizationStrategy();\n    case 'selective':\n      return new SelectiveStrategy();\n    case 'hybrid':\n    default:\n      return new HybridStrategy();\n  }\n}\n\nexport function getCompressionStrategy(\n  strategyName: 'summarize' | 'selective' | 'hybrid'\n): CompressionStrategy {\n  // Validate strategy name to prevent cache pollution\n  const validName: ValidStrategyName = VALID_STRATEGIES.includes(strategyName as ValidStrategyName)\n    ? (strategyName as ValidStrategyName)\n    : 'hybrid';\n\n  if (!strategyCache.has(validName)) {\n    strategyCache.set(validName, createStrategy(validName));\n  }\n  return strategyCache.get(validName)!;\n}\n\n/**\n * Clear the strategy cache (useful for testing and cleanup)\n * This prevents memory leaks by allowing garbage collection of strategy instances\n */\nexport function clearStrategyCache(): void {\n  strategyCache.clear();\n}\n\n/**\n * Get the current cache size (useful for monitoring)\n */\nexport function getStrategyCacheSize(): number {\n  return strategyCache.size;\n}\n","import {\n  CompressionResult,\n  ContextCompressorOptions,\n  ContextMessage,\n  ContextAnalysis,\n} from './types';\nimport { DEFAULT_CONTEXT_OPTIONS } from './defaults';\nimport { getCompressionStrategy } from './strategies';\nimport { Logger } from '../logger/types';\nimport { getLogger } from '../logger';\n\nexport class ContextCompressor {\n  private logger: Logger;\n  private options: ContextCompressorOptions;\n\n  constructor(options: ContextCompressorOptions = {}) {\n    this.logger = getLogger();\n    this.options = {\n      ...DEFAULT_CONTEXT_OPTIONS,\n      ...options,\n    };\n\n    this.logger.debug('ContextCompressor initialized');\n  }\n\n  /**\n   * Token estimation ratios for different content types.\n   * Based on empirical analysis of typical tokenization patterns.\n   *\n   * Reference values (characters per token):\n   * - English prose: ~4 chars/token\n   * - Code (mixed): ~3.5 chars/token (more special chars, shorter words)\n   * - JSON/structured data: ~3 chars/token (lots of punctuation)\n   * - Markdown: ~3.8 chars/token (formatting characters)\n   * - Technical text: ~3.7 chars/token (technical terms, numbers)\n   * - Non-English: ~2.5-3 chars/token (varies by language)\n   */\n  private static readonly TOKEN_RATIOS = {\n    prose: 4.0, // Standard English text\n    code: 3.5, // Programming code\n    json: 3.0, // JSON/structured data\n    markdown: 3.8, // Markdown formatted text\n    technical: 3.7, // Technical documentation\n    mixed: 3.5, // Mixed content (default for uncertain)\n  };\n\n  /**\n   * Estimate token count for a message using content-type aware estimation.\n   * More accurate than simple character division.\n   */\n  estimateTokens(content: string): number {\n    // Handle null/undefined/empty content\n    if (!content || typeof content !== 'string') {\n      return 0;\n    }\n\n    // Detect content type and use appropriate ratio\n    const contentType = this.detectContentType(content);\n    const ratio = ContextCompressor.TOKEN_RATIOS[contentType];\n\n    // Calculate base estimate\n    const baseEstimate = content.length / ratio;\n\n    // Add overhead for special characters and formatting\n    // Tokenizers often split on special characters, creating extra tokens\n    const specialCharCount = (content.match(/[^\\w\\s]/g) || []).length;\n    const specialCharOverhead = specialCharCount * 0.1; // ~10% overhead per special char cluster\n\n    // Add overhead for numbers (often tokenized separately)\n    const numberCount = (content.match(/\\d+/g) || []).length;\n    const numberOverhead = numberCount * 0.5;\n\n    // Add overhead for whitespace patterns (newlines, indentation)\n    const whitespacePatterns = (content.match(/\\n\\s+/g) || []).length;\n    const whitespaceOverhead = whitespacePatterns * 0.3;\n\n    const totalEstimate = baseEstimate + specialCharOverhead + numberOverhead + whitespaceOverhead;\n\n    return Math.ceil(totalEstimate);\n  }\n\n  // Consistent content length limit for all detection methods\n  private static readonly CONTENT_DETECTION_LIMIT = 10000;\n\n  /**\n   * Detect the content type for more accurate token estimation\n   */\n  private detectContentType(content: string): keyof typeof ContextCompressor.TOKEN_RATIOS {\n    // Limit content length for detection to avoid performance issues\n    const sampleContent =\n      content.length > ContextCompressor.CONTENT_DETECTION_LIMIT\n        ? content.substring(0, ContextCompressor.CONTENT_DETECTION_LIMIT)\n        : content;\n\n    // Check for JSON content\n    if (this.detectJsonContent(sampleContent)) {\n      return 'json';\n    }\n\n    // Check for code content (highest priority after JSON)\n    if (this.detectCodeContent(sampleContent)) {\n      return 'code';\n    }\n\n    // Check for markdown content\n    if (this.detectMarkdownContent(sampleContent)) {\n      return 'markdown';\n    }\n\n    // Check for technical content\n    if (this.detectTechnicalContent(sampleContent)) {\n      return 'technical';\n    }\n\n    // Default to prose for regular text\n    return 'prose';\n  }\n\n  /**\n   * Detect if content is JSON or structured data\n   */\n  private detectJsonContent(content: string): boolean {\n    const trimmed = content.trim();\n    // Check if content starts with JSON-like patterns\n    if (\n      (trimmed.startsWith('{') && trimmed.endsWith('}')) ||\n      (trimmed.startsWith('[') && trimmed.endsWith(']'))\n    ) {\n      return true;\n    }\n    // Check for high density of JSON-like patterns\n    const jsonPatterns = (content.match(/[\"']?\\w+[\"']?\\s*:\\s*[\"'[{]/g) || []).length;\n    const contentLines = content.split('\\n').length;\n    return jsonPatterns > contentLines * 0.3; // More than 30% lines have JSON patterns\n  }\n\n  /**\n   * Detect if content contains markdown formatting\n   */\n  private detectMarkdownContent(content: string): boolean {\n    const markdownIndicators = [\n      /^#{1,6}\\s+/m, // Headers\n      /^\\s*[-*+]\\s+/m, // Unordered lists\n      /^\\s*\\d+\\.\\s+/m, // Ordered lists\n      /\\*\\*[^*]+\\*\\*/, // Bold\n      /\\*[^*]+\\*/, // Italic\n      /\\[.+?\\]\\(.+?\\)/, // Links\n      /`[^`]+`/, // Inline code\n      /^\\s*>\\s+/m, // Blockquotes\n    ];\n    let matchCount = 0;\n    for (const pattern of markdownIndicators) {\n      if (pattern.test(content)) matchCount++;\n    }\n    return matchCount >= 2; // At least 2 markdown patterns\n  }\n\n  /**\n   * Detect if content is technical documentation\n   */\n  private detectTechnicalContent(content: string): boolean {\n    const technicalIndicators = [\n      /\\b(API|HTTP|URL|JSON|XML|SQL|REST|SDK)\\b/i,\n      /\\b(function|method|class|interface|type|parameter)\\b/i,\n      /\\b(error|exception|warning|debug|log)\\b/i,\n      /\\b(config|configuration|setting|option)\\b/i,\n      /\\b(v\\d+\\.\\d+|version\\s+\\d+)/i,\n      /\\b(npm|yarn|pip|cargo|maven|gradle)\\b/i,\n    ];\n    let matchCount = 0;\n    for (const pattern of technicalIndicators) {\n      if (pattern.test(content)) matchCount++;\n    }\n    return matchCount >= 3; // At least 3 technical patterns\n  }\n\n  /**\n   * Detect if content contains code\n   * Note: Content is already limited by detectContentType (CONTENT_DETECTION_LIMIT)\n   * Regex patterns are optimized to prevent ReDoS (catastrophic backtracking)\n   */\n  private detectCodeContent(content: string): boolean {\n    // Content is already limited by detectContentType, no need to limit again\n    // Keeping regex patterns safe with bounded quantifiers for extra safety\n    const codeIndicators = [\n      // Safe: uses negated character class instead of [\\s\\S]* which can cause catastrophic backtracking\n      /```[^`]{0,10000}```/,\n      /function\\s+\\w+/,\n      /class\\s+\\w+/,\n      /const\\s+\\w+\\s*=/,\n      // Safe: limited repetition instead of .*\n      /import\\s+[^\\n]{0,500}from/,\n      // Safe: uses negated character class with limit instead of [\\s\\S]*\n      /\\{[^{}]{0,1000}\\}/,\n    ];\n    return codeIndicators.some((pattern) => pattern.test(content));\n  }\n\n  /**\n   * Calculate total token count for messages\n   */\n  calculateTotalTokens(messages: ContextMessage[]): number {\n    // Handle null/undefined messages array\n    if (!messages || !Array.isArray(messages)) {\n      return 0;\n    }\n    return messages.reduce((total, msg) => {\n      if (!msg) return total;\n      const tokens = msg.tokens ?? this.estimateTokens(msg.content ?? '');\n      return total + tokens;\n    }, 0);\n  }\n\n  /**\n   * Analyze context for insights\n   */\n  analyzeContext(messages: ContextMessage[]): ContextAnalysis {\n    // Handle null/undefined messages array\n    const safeMessages = messages ?? [];\n    const totalTokens = this.calculateTotalTokens(safeMessages);\n    const messageCount = safeMessages.length;\n    const averageTokensPerMessage = messageCount > 0 ? totalTokens / messageCount : 0;\n    const maxLength = this.options.maxContextLength ?? 8000;\n    // Prevent division by zero\n    const contextUtilization = maxLength > 0 ? (totalTokens / maxLength) * 100 : 0;\n    const compressionNeeded = totalTokens > maxLength;\n\n    let suggestedCompressionRatio: number | undefined;\n    if (compressionNeeded && totalTokens > 0) {\n      const targetTokens = maxLength * 0.8;\n      suggestedCompressionRatio = 1 - targetTokens / totalTokens;\n    }\n\n    return {\n      totalTokens,\n      messageCount,\n      averageTokensPerMessage,\n      contextUtilization,\n      compressionNeeded,\n      suggestedCompressionRatio,\n    };\n  }\n\n  /**\n   * Compress conversation history\n   */\n  async compressConversation(messages: ContextMessage[]): Promise<CompressionResult> {\n    try {\n      const analysis = this.analyzeContext(messages);\n      const originalTokens = analysis.totalTokens;\n\n      this.logger.debug('Starting context compression', {\n        messageCount: messages.length,\n        totalTokens: originalTokens,\n        maxContextLength: this.options.maxContextLength ?? 8000,\n        strategy: this.options.compressionStrategy ?? 'hybrid',\n      });\n\n      // If we're under the limit, no compression needed\n      if (!analysis.compressionNeeded) {\n        this.logger.debug('Context within limits, no compression needed');\n        return {\n          success: true,\n          compressedMessages: messages,\n          tokensReduced: 0,\n          compressionRatio: 0,\n        };\n      }\n\n      // Get compression strategy\n      const strategy = getCompressionStrategy(this.options.compressionStrategy ?? 'hybrid');\n\n      // Apply compression\n      const compressedMessages = await strategy.compress(messages, this.options);\n\n      // Calculate results\n      const newTotalTokens = this.calculateTotalTokens(compressedMessages);\n      const tokensReduced = originalTokens - newTotalTokens;\n      // Prevent division by zero\n      const compressionRatio = originalTokens > 0 ? tokensReduced / originalTokens : 0;\n\n      this.logger.info('Context compression completed', {\n        originalMessages: messages.length,\n        compressedMessages: compressedMessages.length,\n        originalTokens,\n        newTokens: newTotalTokens,\n        tokensReduced,\n        compressionRatio: `${(compressionRatio * 100).toFixed(1)}%`,\n      });\n\n      return {\n        success: true,\n        compressedMessages,\n        tokensReduced,\n        compressionRatio,\n      };\n    } catch (error) {\n      const errorMessage = error instanceof Error ? error.message : String(error);\n      this.logger.error('Context compression failed', error instanceof Error ? error : undefined);\n\n      return {\n        success: false,\n        compressedMessages: messages,\n        tokensReduced: 0,\n        compressionRatio: 0,\n        error: errorMessage,\n      };\n    }\n  }\n\n  /**\n   * Check if compression is needed\n   */\n  shouldCompress(messages: ContextMessage[]): boolean {\n    const analysis = this.analyzeContext(messages);\n    return analysis.compressionNeeded;\n  }\n\n  /**\n   * Update compression options\n   */\n  updateOptions(options: Partial<ContextCompressorOptions>): void {\n    this.options = {\n      ...this.options,\n      ...options,\n    };\n\n    this.logger.debug('ContextCompressor options updated');\n  }\n\n  /**\n   * Get current options\n   */\n  getOptions(): ContextCompressorOptions {\n    return { ...this.options };\n  }\n}\n","/**\n * Context storage for persistent context management\n * Handles saving/loading context windows to/from database\n */\nimport { Knex } from 'knex';\nimport { Logger } from '../logger/types';\nimport { ContextMessage } from './types';\nimport { getEncryptionService } from '../database/encryption';\nimport { encryptSensitiveFields, decryptSensitiveFields } from '../database/utils';\n\n/**\n * Custom error class for context data corruption\n * Includes agentId for better debugging and error tracking\n */\nexport class ContextDataCorruptionError extends Error {\n  public readonly agentId: string;\n  public readonly cause?: Error;\n\n  constructor(message: string, agentId: string, cause?: Error) {\n    super(message);\n    this.name = 'ContextDataCorruptionError';\n    this.agentId = agentId;\n    this.cause = cause;\n\n    // Maintains proper stack trace for where our error was thrown (only available on V8)\n    if (Error.captureStackTrace) {\n      Error.captureStackTrace(this, ContextDataCorruptionError);\n    }\n  }\n}\n\nexport interface ContextStorageData {\n  id: string;\n  agentId: string;\n  contextData: ContextMessage[];\n  summary?: string;\n  tokensUsed: number;\n  compressionVersion?: string;\n  lastCompressed?: Date;\n  createdAt: Date;\n  updatedAt: Date;\n}\n\nexport interface ContextStorageOptions {\n  agentId: string; // UUID\n  graphId?: string; // Graph UUID context belongs to\n  sessionId?: string; // Conversation session ID\n  contextData?: ContextMessage[];\n  summary?: string;\n  tokensUsed?: number;\n  compressionVersion?: string;\n}\n\n// Database row interface\ninterface ContextDbRow {\n  id: string; // UUID\n  agentId: string; // UUID\n  contextData: string | null;\n  summary: string | null;\n  tokensUsed: number;\n  compressionVersion: string | null;\n  lastCompressed: string | null;\n  created_at: string;\n  updated_at: string;\n}\n\nexport class ContextStorage {\n  private knex: Knex;\n  private logger: Logger;\n  private _encryption?: ReturnType<typeof getEncryptionService>;\n\n  private get encryption() {\n    if (!this._encryption) {\n      this._encryption = getEncryptionService();\n    }\n    return this._encryption;\n  }\n\n  constructor(knex: Knex, logger: Logger) {\n    this.knex = knex;\n    this.logger = logger;\n  }\n\n  /**\n   * Save context data for an agent\n   */\n  async saveContext(options: ContextStorageOptions): Promise<ContextStorageData> {\n    this.logger.debug('Saving context to storage', {\n      agentId: options.agentId,\n      messagesCount: options.contextData?.length || 0,\n      tokensUsed: options.tokensUsed || 0,\n    });\n\n    // Prepare data for storage\n    const contextDataJson = options.contextData ? JSON.stringify(options.contextData) : null;\n\n    const insertData = {\n      id: crypto.randomUUID(), // Generate UUID for context\n      agentId: options.agentId,\n      graphId: options.graphId || null, // Graph relationship\n      sessionId: options.sessionId || null, // Session ID\n      contextData: contextDataJson,\n      summary: options.summary || null,\n      tokensUsed: options.tokensUsed || 0,\n      compressionVersion: options.compressionVersion || null,\n      lastCompressed: options.compressionVersion ? new Date().toISOString() : null,\n    };\n\n    // Encrypt sensitive fields using centralized system\n    const encryptedData = await encryptSensitiveFields(insertData, 'contexts');\n\n    // Retry mechanism for handling concurrent modifications\n    const MAX_RETRIES = 3;\n    let lastError: Error | null = null;\n\n    for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {\n      try {\n        // Use transaction with optimistic locking to prevent race conditions\n        const result = await this.knex.transaction(async (trx) => {\n          // Check if context already exists for this agent (within transaction)\n          const existingContext = await trx('contexts')\n            .where({ agentId: options.agentId })\n            .forUpdate() // Lock the row to prevent concurrent updates\n            .first();\n\n          let dbResult: ContextDbRow;\n\n          if (existingContext) {\n            // Update existing context - preserve the existing ID, don't regenerate UUID\n            const { id: _, ...updateData } = encryptedData;\n            void _; // Intentionally unused - we discard the new ID to keep existing\n\n            // Optimistic locking: check if row was modified since we read it\n            const [updated] = await trx('contexts')\n              .where({ agentId: options.agentId })\n              .where({ updated_at: existingContext.updated_at }) // Ensure row hasn't changed\n              .update({\n                ...updateData,\n                updated_at: trx.fn.now(),\n              })\n              .returning('*');\n\n            if (!updated) {\n              // Row was modified by another process, will retry\n              throw new Error(\n                `Concurrent modification detected for context ${options.agentId}. Retrying...`\n              );\n            }\n            dbResult = updated;\n          } else {\n            // Create new context\n            const [created] = await trx('contexts').insert(encryptedData).returning('*');\n            dbResult = created;\n          }\n\n          return dbResult;\n        });\n\n        // Decrypt for return using centralized system\n        const decryptedResult = await decryptSensitiveFields(\n          result as unknown as Record<string, string | number | boolean | null | undefined | Date>,\n          'contexts'\n        );\n        return this.formatContextData(decryptedResult as unknown as ContextDbRow);\n      } catch (error) {\n        lastError = error instanceof Error ? error : new Error(String(error));\n\n        // Log retry attempt\n        if (attempt < MAX_RETRIES - 1) {\n          this.logger.warn('Context save failed, retrying...', {\n            agentId: options.agentId,\n            attempt: attempt + 1,\n            maxRetries: MAX_RETRIES,\n            error: lastError.message,\n          });\n          // Exponential backoff: 100ms, 200ms, 300ms\n          await new Promise((r) => setTimeout(r, 100 * (attempt + 1)));\n        }\n      }\n    }\n\n    // All retries exhausted\n    this.logger.error('Context save failed after all retries', lastError ?? undefined, {\n      agentId: options.agentId,\n      maxRetries: MAX_RETRIES,\n    });\n    throw lastError ?? new Error('Context save failed after all retries');\n  }\n\n  /**\n   * Load context data for an agent\n   */\n  async loadContext(agentId: string): Promise<ContextStorageData | null> {\n    // UUID\n    this.logger.debug('Loading context from storage', { agentId });\n\n    const contextRow = await this.knex('contexts').where({ agentId }).first();\n\n    if (!contextRow) {\n      this.logger.debug('No context found in storage', { agentId });\n      return null;\n    }\n\n    // Decrypt sensitive fields using centralized system\n    const decryptedRow = await decryptSensitiveFields(\n      contextRow as unknown as Record<string, string | number | boolean | null | undefined | Date>,\n      'contexts'\n    );\n    const formattedData = this.formatContextData(decryptedRow as unknown as ContextDbRow);\n\n    this.logger.debug('Context loaded from storage', {\n      agentId,\n      messagesCount: formattedData.contextData.length,\n      tokensUsed: formattedData.tokensUsed,\n    });\n\n    return formattedData;\n  }\n\n  /**\n   * Delete context data for an agent\n   */\n  async deleteContext(agentId: string): Promise<boolean> {\n    this.logger.debug('Deleting context from storage', { agentId });\n\n    const deleted = await this.knex('contexts').where({ agentId }).delete();\n\n    const success = deleted > 0;\n    this.logger.debug('Context deletion result', { agentId, success });\n\n    return success;\n  }\n\n  /**\n   * Update context tokens and compression info\n   */\n  async updateContextMetadata(\n    agentId: string, // UUID\n    metadata: {\n      tokensUsed?: number;\n      compressionVersion?: string;\n      summary?: string;\n    }\n  ): Promise<void> {\n    this.logger.debug('Updating context metadata', { agentId, metadata });\n\n    const updateData: Record<string, string | number | null> = {};\n\n    if (metadata.tokensUsed !== undefined) {\n      updateData.tokensUsed = metadata.tokensUsed;\n    }\n\n    if (metadata.compressionVersion !== undefined) {\n      updateData.compressionVersion = metadata.compressionVersion;\n      updateData.lastCompressed = new Date().toISOString();\n    }\n\n    if (metadata.summary !== undefined) {\n      updateData.summary = metadata.summary;\n    }\n\n    if (Object.keys(updateData).length > 0) {\n      // Encrypt sensitive fields using centralized system\n      const encryptedData = await encryptSensitiveFields(updateData, 'contexts');\n\n      await this.knex('contexts')\n        .where({ agentId })\n        .update({\n          ...encryptedData,\n          updated_at: this.knex.fn.now(),\n        });\n    }\n  }\n\n  /**\n   * Format database row to ContextStorageData\n   */\n  private formatContextData(row: ContextDbRow): ContextStorageData {\n    let contextData: ContextMessage[] = [];\n\n    if (row.contextData) {\n      try {\n        // Handle both string and object (PostgreSQL returns JSON as object)\n        contextData =\n          typeof row.contextData === 'string' ? JSON.parse(row.contextData) : row.contextData;\n        // Validate parsed data is an array\n        if (!Array.isArray(contextData)) {\n          this.logger.error('Context data is not an array after parsing', undefined, {\n            agentId: row.agentId,\n            dataType: typeof contextData,\n          });\n          throw new ContextDataCorruptionError(\n            `Context data corruption: expected array but got ${typeof contextData}`,\n            row.agentId\n          );\n        }\n      } catch (error) {\n        // If it's already our custom error, just re-throw without double logging\n        if (error instanceof ContextDataCorruptionError) {\n          throw error;\n        }\n\n        // Log and re-throw to prevent silent data loss\n        // Preserve the original error stack trace using cause option\n        const errorMessage = error instanceof Error ? error.message : String(error);\n        this.logger.error(\n          'Failed to parse context data - DATA CORRUPTION',\n          error instanceof Error ? error : undefined,\n          {\n            agentId: row.agentId,\n            errorMessage,\n            dataPreview:\n              typeof row.contextData === 'string'\n                ? row.contextData.substring(0, 100)\n                : 'non-string',\n          }\n        );\n        throw new ContextDataCorruptionError(\n          `Context data parsing failed: ${errorMessage}`,\n          row.agentId,\n          error instanceof Error ? error : undefined\n        );\n      }\n    }\n\n    return {\n      id: row.id,\n      agentId: row.agentId,\n      contextData,\n      summary: row.summary || undefined,\n      tokensUsed: row.tokensUsed,\n      compressionVersion: row.compressionVersion || undefined,\n      lastCompressed: row.lastCompressed ? new Date(row.lastCompressed) : undefined,\n      createdAt: new Date(row.created_at),\n      updatedAt: new Date(row.updated_at),\n    };\n  }\n}\n","import {\n  ContextManager as IContextManager,\n  ContextMessage,\n  ContextWindow,\n  ContextAnalysis,\n  CompressionResult,\n  ContextCompressorOptions,\n  ContextSummary,\n} from './types';\nimport { MetadataObject } from '../types';\nimport { ContextCompressor } from './compressor';\nimport { ContextStorage } from './storage';\nimport { DEFAULT_CONTEXT_OPTIONS } from './defaults';\nimport { Logger } from '../logger/types';\nimport { getLogger } from '../logger';\nimport { getLLM } from '../llm';\nimport { getDatabase } from '../database';\n\n// Maximum number of messages to prevent unbounded growth\nconst MAX_MESSAGE_COUNT = 10000;\n\n/**\n * Callback type for compression events\n * This allows Memory module to be notified when context compression occurs\n */\nexport type CompressionCallback = (info: {\n  originalMessageCount: number;\n  compressedMessageCount: number;\n  messagesRemoved: number;\n  tokensReduced: number;\n  strategy: string;\n}) => void | Promise<void>;\n\n/**\n * Callback type for context clear events\n * This allows Memory module to be notified when context is cleared\n */\nexport type ContextClearCallback = () => void | Promise<void>;\n\nexport class ContextManager implements IContextManager {\n  private messages: ContextMessage[] = [];\n  private compressor: ContextCompressor;\n  private storage: ContextStorage | null = null;\n  private logger: Logger;\n  private maxTokens: number;\n  private autoCompress: boolean;\n  private model: string;\n  private agentId: string | null = null;\n  private isDirty: boolean = false; // Track if context needs saving\n  private isCompressing: boolean = false; // Mutex for compression operations\n  private pendingOperations: Promise<void> = Promise.resolve(); // Queue for serializing operations\n  private operationLock: boolean = false; // Mutex for message operations\n\n  // Callback for compression events (used by Agent to notify Memory)\n  private onCompressionCallback: CompressionCallback | null = null;\n\n  // Callback for context clear events (used by Agent to sync with Memory)\n  private onClearCallback: ContextClearCallback | null = null;\n\n  constructor(options: ContextCompressorOptions & { autoCompress?: boolean } = {}) {\n    this.logger = getLogger();\n    this.compressor = new ContextCompressor(options);\n    this.maxTokens = options.maxContextLength ?? DEFAULT_CONTEXT_OPTIONS.maxContextLength ?? 8000;\n    this.autoCompress = options.autoCompress ?? true;\n    // Use provided model or context compression model as fallback\n    this.model = options.model ?? DEFAULT_CONTEXT_OPTIONS.model ?? 'gpt-4o-mini';\n\n    this.logger.debug('ContextManager initialized', {\n      maxTokens: this.maxTokens,\n      autoCompress: this.autoCompress,\n      model: this.model,\n    });\n  }\n\n  /**\n   * Register a callback for compression events\n   * This allows the Agent to notify Memory when context compression occurs\n   */\n  onCompression(callback: CompressionCallback): void {\n    this.onCompressionCallback = callback;\n  }\n\n  /**\n   * Register a callback for context clear events\n   * This allows the Agent to sync Memory when context is cleared\n   */\n  onContextClear(callback: ContextClearCallback): void {\n    this.onClearCallback = callback;\n  }\n\n  /**\n   * Notify registered callback about compression events\n   */\n  private async notifyCompression(info: {\n    originalMessageCount: number;\n    compressedMessageCount: number;\n    messagesRemoved: number;\n    tokensReduced: number;\n    strategy: string;\n  }): Promise<void> {\n    if (this.onCompressionCallback) {\n      try {\n        await this.onCompressionCallback(info);\n      } catch (error) {\n        this.logger.warn('Compression callback failed', {\n          error: error instanceof Error ? error.message : String(error),\n        });\n      }\n    }\n  }\n\n  /**\n   * Initialize storage and load context for a specific agent\n   */\n  async initializeForAgent(agentId: string): Promise<void> {\n    this.agentId = agentId;\n\n    try {\n      const db = await getDatabase();\n      if (!db) {\n        throw new Error('Database not initialized');\n      }\n      this.storage = new ContextStorage(db.getKnex(), this.logger);\n\n      // Load existing context from storage\n      const storedContext = await this.storage.loadContext(agentId);\n      if (storedContext) {\n        this.messages = storedContext.contextData;\n        this.logger.info('Context loaded from storage', {\n          agentId,\n          messagesCount: this.messages.length,\n          tokensUsed: storedContext.tokensUsed,\n        });\n      } else {\n        this.logger.debug('No stored context found, starting fresh', { agentId });\n      }\n\n      this.isDirty = false;\n    } catch (error) {\n      this.logger.warn('Failed to initialize context storage', {\n        agentId,\n        error: error instanceof Error ? error.message : String(error),\n      });\n      // Continue without storage - fallback to in-memory only\n      this.storage = null;\n    }\n  }\n\n  /**\n   * Save current context to storage\n   */\n  async saveToStorage(): Promise<void> {\n    if (!this.storage || !this.agentId || !this.isDirty) {\n      return;\n    }\n\n    try {\n      const tokensUsed = this.compressor.calculateTotalTokens(this.messages);\n\n      // Check if any messages are compressed summaries\n      const hasCompressedMessages = this.messages.some(\n        (msg) => msg.metadata?.type === 'summary' || msg.metadata?.compressed === true\n      );\n\n      await this.storage.saveContext({\n        agentId: this.agentId,\n        contextData: this.messages,\n        tokensUsed,\n        compressionVersion: hasCompressedMessages ? 'hybrid' : undefined,\n      });\n\n      this.isDirty = false;\n      this.logger.debug('Context saved to storage', {\n        agentId: this.agentId,\n        messagesCount: this.messages.length,\n        tokensUsed,\n        hasCompression: hasCompressedMessages,\n      });\n    } catch (error) {\n      this.logger.warn('Failed to save context to storage', {\n        agentId: this.agentId,\n        error: error instanceof Error ? error.message : String(error),\n      });\n    }\n  }\n\n  // Queue for waiting lock requesters (proper mutex instead of spin-wait)\n  private lockQueue: Array<{ resolve: () => void; reject: (err: Error) => void }> = [];\n\n  /**\n   * Acquire operation lock with timeout (proper mutex, no spin-wait)\n   * Includes deadlock prevention via timeouts\n   */\n  private async acquireLock(timeoutMs: number = 5000): Promise<boolean> {\n    // Fast path: lock is free\n    if (!this.operationLock) {\n      this.operationLock = true;\n      return true;\n    }\n\n    // Wait in queue (proper promise-based waiting, not spin-wait)\n    return new Promise<boolean>((resolve, reject) => {\n      const timeoutId = setTimeout(() => {\n        const index = this.lockQueue.findIndex((item) => item.resolve === wrappedResolve);\n        if (index !== -1) {\n          this.lockQueue.splice(index, 1);\n        }\n        this.logger.warn(\n          'Failed to acquire operation lock - timeout reached (deadlock prevention)',\n          {\n            timeoutMs,\n            queueLength: this.lockQueue.length,\n          }\n        );\n        resolve(false);\n      }, timeoutMs);\n\n      const wrappedResolve = () => {\n        clearTimeout(timeoutId);\n        resolve(true);\n      };\n\n      this.lockQueue.push({\n        resolve: wrappedResolve,\n        reject: (err: Error) => {\n          clearTimeout(timeoutId);\n          reject(err);\n        },\n      });\n    });\n  }\n\n  /**\n   * Release operation lock and wake up next waiter\n   */\n  private releaseLock(): void {\n    const next = this.lockQueue.shift();\n    if (next) {\n      // Pass lock to next waiter\n      next.resolve();\n    } else {\n      // No waiters, unlock\n      this.operationLock = false;\n    }\n  }\n\n  /**\n   * Add a message to the context\n   */\n  async addMessage(message: ContextMessage): Promise<void> {\n    // Queue this operation to prevent race conditions\n    this.pendingOperations = this.pendingOperations\n      .then(async () => {\n        // Acquire mutex lock\n        const lockAcquired = await this.acquireLock();\n        if (!lockAcquired) {\n          this.logger.error('Failed to add message - could not acquire lock');\n          return;\n        }\n\n        try {\n          // Validate and normalize content\n          if (message.content === null || message.content === undefined) {\n            message.content = '';\n          }\n\n          // Add timestamp if not provided\n          if (!message.timestamp) {\n            message.timestamp = new Date();\n          }\n\n          // Estimate tokens if not provided\n          if (message.tokens === undefined || message.tokens === null) {\n            message.tokens = this.compressor.estimateTokens(message.content);\n          }\n\n          // Bounds check: prevent unbounded message array growth\n          if (this.messages.length >= MAX_MESSAGE_COUNT) {\n            this.logger.warn('Message limit reached, forcing compression', {\n              currentCount: this.messages.length,\n              maxCount: MAX_MESSAGE_COUNT,\n            });\n            // Force compression before adding new message\n            // Wait for any ongoing compression to complete before deciding\n            if (this.isCompressing) {\n              // Another compression is in progress, wait using promise-based waiting\n              this.logger.warn('Compression already in progress, waiting...');\n              // Use promise-based waiting instead of spin-wait\n              const compressionWaitResult = await this.waitForCompressionComplete(5000);\n              // If still compressing after timeout, log warning but don't delete messages\n              if (!compressionWaitResult) {\n                this.logger.warn(\n                  'Compression timeout reached, skipping message add to prevent data loss'\n                );\n                return;\n              }\n            } else {\n              try {\n                await this.compressContext();\n              } catch (error) {\n                this.logger.error(\n                  'Forced compression failed',\n                  error instanceof Error ? error : undefined\n                );\n                // Log detailed info about messages that would be removed (backup mechanism)\n                const removeCount = Math.floor(this.messages.length * 0.2);\n                const removedMessages = this.messages.slice(0, removeCount);\n                this.logger.warn('Removing messages due to compression failure', {\n                  removedCount: removeCount,\n                  removedMessagesSummary: removedMessages\n                    .map((m) => `[${m.role}] ${m.content.substring(0, 50)}...`)\n                    .join('; '),\n                });\n                this.messages = this.messages.slice(removeCount);\n              }\n            }\n          }\n\n          this.messages.push(message);\n          this.isDirty = true; // Mark context as dirty for saving\n\n          this.logger.debug('Message added to context', {\n            role: message.role,\n            tokens: message.tokens,\n            totalMessages: this.messages.length,\n          });\n\n          // Auto-compress if needed BEFORE saving (skip if already compressing)\n          if (this.autoCompress && !this.isCompressing && this.shouldCompress()) {\n            this.logger.debug('Auto-compression triggered', {\n              currentTokens: this.compressor.calculateTotalTokens(this.messages),\n              maxTokens: this.maxTokens,\n            });\n\n            try {\n              await this.compressContext();\n              this.logger.debug('Auto-compression completed successfully');\n            } catch (error) {\n              this.logger.error(\n                'Auto-compression failed',\n                error instanceof Error ? error : undefined\n              );\n            }\n          }\n\n          // Auto-save to storage after potential compression\n          try {\n            await this.saveToStorage();\n          } catch (error) {\n            this.logger.debug('Auto-save failed', {\n              error: error instanceof Error ? error.message : String(error),\n            });\n          }\n        } finally {\n          // Always release the lock\n          this.releaseLock();\n        }\n      })\n      .catch((error): void => {\n        // Log error but don't release lock here - it's handled by finally block in the try/catch above\n        // The Promise chain should continue to work, and lock is always released in the finally\n        this.logger.error(\n          'Message add operation failed in Promise chain',\n          error instanceof Error ? error : undefined\n        );\n        // Don't re-throw to maintain Promise chain stability\n        // The error has been logged and handled\n      });\n\n    return this.pendingOperations;\n  }\n\n  /**\n   * Get all messages\n   */\n  getMessages(): ContextMessage[] {\n    return [...this.messages];\n  }\n\n  /**\n   * Get context window information\n   */\n  getContextWindow(): ContextWindow {\n    const totalTokens = this.compressor.calculateTotalTokens(this.messages);\n    const utilizationPercentage = (totalTokens / this.maxTokens) * 100;\n\n    return {\n      messages: this.getMessages(),\n      totalTokens,\n      maxTokens: this.maxTokens,\n      utilizationPercentage,\n    };\n  }\n\n  /**\n   * Analyze the current context\n   */\n  analyzeContext(): ContextAnalysis {\n    return this.compressor.analyzeContext(this.messages);\n  }\n\n  /**\n   * Compress the context\n   */\n  async compressContext(): Promise<CompressionResult> {\n    // Prevent concurrent compression operations\n    if (this.isCompressing) {\n      this.logger.debug('Compression already in progress, skipping');\n      return {\n        success: false,\n        compressedMessages: this.messages,\n        tokensReduced: 0,\n        compressionRatio: 0,\n        error: 'Compression already in progress',\n      };\n    }\n\n    this.isCompressing = true;\n\n    try {\n      const originalMessageCount = this.messages.length;\n      const originalTokens = this.compressor.calculateTotalTokens(this.messages);\n\n      this.logger.debug('Starting context compression', {\n        originalMessageCount,\n        originalTokens,\n        maxTokens: this.maxTokens,\n      });\n\n      const result = await this.compressor.compressConversation(this.messages);\n\n      if (result.success) {\n        this.messages = result.compressedMessages;\n        this.isDirty = true; // Mark as dirty since messages changed\n\n        const newTokens = this.compressor.calculateTotalTokens(this.messages);\n\n        this.logger.info('Context compressed successfully', {\n          originalMessages: originalMessageCount,\n          compressedMessages: this.messages.length,\n          originalTokens,\n          newTokens,\n          tokensReduced: result.tokensReduced,\n          compressionRatio: `${(result.compressionRatio * 100).toFixed(1)}%`,\n        });\n\n        // IMPORTANT: Warn that Memory module may have stale data\n        // Context compression removes/summarizes messages but Memory keeps originals\n        this.logger.warn(\n          'Context compressed but Memory module retains original messages. ' +\n            'Consider implementing memory archiving or cleanup for long conversations. ' +\n            `Removed ${originalMessageCount - this.messages.length} messages from context.`,\n          {\n            originalMessageCount,\n            compressedMessageCount: this.messages.length,\n            messagesRemoved: originalMessageCount - this.messages.length,\n            agentId: this.agentId,\n          }\n        );\n\n        // Save compressed context with metadata\n        if (this.storage && this.agentId) {\n          try {\n            await this.storage.updateContextMetadata(this.agentId, {\n              tokensUsed: this.compressor.calculateTotalTokens(this.messages),\n              compressionVersion: result.strategy,\n            });\n\n            // Save the compressed messages\n            await this.saveToStorage();\n          } catch (error) {\n            this.logger.warn('Failed to save compressed context', {\n              error: error instanceof Error ? error.message : String(error),\n            });\n          }\n        }\n\n        // Notify listeners about compression (for Memory module to handle archiving)\n        await this.notifyCompression({\n          originalMessageCount,\n          compressedMessageCount: this.messages.length,\n          messagesRemoved: originalMessageCount - this.messages.length,\n          tokensReduced: result.tokensReduced,\n          strategy: result.strategy || 'unknown',\n        });\n      }\n\n      return result;\n    } finally {\n      this.isCompressing = false;\n      // Wake up any waiters for compression completion\n      this.notifyCompressionWaiters();\n    }\n  }\n\n  // Queue for waiting on compression completion (replaces spin-wait)\n  private compressionWaiters: Array<() => void> = [];\n\n  /**\n   * Wait for ongoing compression to complete (promise-based, no spin-wait)\n   * @param timeoutMs - Maximum time to wait\n   * @returns true if compression completed, false if timed out\n   */\n  private async waitForCompressionComplete(timeoutMs: number): Promise<boolean> {\n    if (!this.isCompressing) {\n      return true;\n    }\n\n    return new Promise<boolean>((resolve) => {\n      const timeoutId = setTimeout(() => {\n        const index = this.compressionWaiters.findIndex((w) => w === wrappedResolve);\n        if (index !== -1) {\n          this.compressionWaiters.splice(index, 1);\n        }\n        resolve(false);\n      }, timeoutMs);\n\n      const wrappedResolve = () => {\n        clearTimeout(timeoutId);\n        resolve(true);\n      };\n\n      this.compressionWaiters.push(wrappedResolve);\n    });\n  }\n\n  /**\n   * Notify all compression waiters that compression is complete\n   */\n  private notifyCompressionWaiters(): void {\n    for (const waiter of this.compressionWaiters) {\n      waiter();\n    }\n    this.compressionWaiters = [];\n  }\n\n  /**\n   * Clear all context\n   * @param options - Optional settings for clearing context\n   * @param options.syncWithMemory - If true (default), notifies Memory to also clear. Set to false to clear only Context.\n   */\n  async clearContext(options?: { syncWithMemory?: boolean }): Promise<void> {\n    // Wait for any pending operations to complete before clearing\n    await this.pendingOperations;\n\n    const previousCount = this.messages.length;\n    this.messages = [];\n    this.isDirty = true;\n\n    // Reset pending operations to prevent memory leak from old Promise chain\n    this.pendingOperations = Promise.resolve();\n\n    this.logger.info('Context cleared', {\n      messagesRemoved: previousCount,\n      syncWithMemory: options?.syncWithMemory !== false,\n    });\n\n    // Save cleared state to storage immediately\n    try {\n      await this.saveToStorage();\n    } catch (error) {\n      this.logger.debug('Failed to save cleared context', {\n        error: error instanceof Error ? error.message : String(error),\n      });\n    }\n\n    // Notify Memory module to also clear if syncWithMemory is enabled (default: true)\n    if (previousCount > 0 && options?.syncWithMemory !== false && this.onClearCallback) {\n      try {\n        await this.onClearCallback();\n      } catch (error) {\n        this.logger.warn('Context clear callback failed', {\n          error: error instanceof Error ? error.message : String(error),\n        });\n      }\n    }\n  }\n\n  /**\n   * Cleanup resources and reset pending operations\n   * Call this when the context manager is no longer needed\n   */\n  async dispose(): Promise<void> {\n    // Wait for any pending operations to complete\n    await this.pendingOperations;\n\n    // Reset pending operations to allow garbage collection\n    this.pendingOperations = Promise.resolve();\n\n    // Clear waiting queues to prevent memory leaks\n    this.lockQueue = [];\n    this.compressionWaiters = [];\n\n    this.logger.debug('ContextManager disposed');\n  }\n\n  /**\n   * Check if compression is needed\n   */\n  shouldCompress(): boolean {\n    return this.compressor.shouldCompress(this.messages);\n  }\n\n  /**\n   * Export context as JSON string\n   */\n  exportContext(): string {\n    const exportData = {\n      version: '1.0',\n      timestamp: new Date().toISOString(),\n      messages: this.messages,\n      metadata: {\n        totalMessages: this.messages.length,\n        totalTokens: this.compressor.calculateTotalTokens(this.messages),\n      },\n    };\n    return JSON.stringify(exportData, null, 2);\n  }\n\n  /**\n   * Import context from JSON string\n   */\n  importContext(data: string): void {\n    try {\n      const parsed = JSON.parse(data);\n\n      if (!parsed.messages || !Array.isArray(parsed.messages)) {\n        throw new Error('Invalid context data: missing messages array');\n      }\n\n      // Validate and restore messages\n      const validRoles = ['user', 'assistant', 'system'] as const;\n      type ValidRole = (typeof validRoles)[number];\n\n      let invalidRoleCount = 0;\n      this.messages = parsed.messages.map(\n        (\n          msg: {\n            role?: string;\n            content?: string;\n            timestamp?: string;\n            metadata?: MetadataObject;\n            tokens?: number;\n          },\n          index: number\n        ) => {\n          // Type guard: validate role is one of the valid roles\n          const isValidRole = validRoles.includes(msg.role as ValidRole);\n          if (!isValidRole) {\n            invalidRoleCount++;\n            this.logger.warn('Invalid message role during import, defaulting to user', {\n              messageIndex: index,\n              originalRole: msg.role ?? 'undefined',\n              expected: 'user, assistant, or system',\n              contentPreview: (msg.content || '').substring(0, 50),\n            });\n          }\n          const role: ValidRole = isValidRole ? (msg.role as ValidRole) : 'user';\n\n          return {\n            role,\n            content: msg.content || '',\n            timestamp: msg.timestamp ? new Date(msg.timestamp) : new Date(),\n            metadata: msg.metadata || {},\n            tokens: msg.tokens,\n          };\n        }\n      );\n\n      // Summary warning if multiple invalid roles were found\n      if (invalidRoleCount > 0) {\n        this.logger.warn(\n          `Import completed with ${invalidRoleCount} invalid role(s) converted to \"user\"`,\n          {\n            totalMessages: this.messages.length,\n            invalidRoleCount,\n          }\n        );\n      }\n\n      this.isDirty = true;\n      this.logger.info('Context imported successfully', {\n        messagesImported: this.messages.length,\n      });\n    } catch (error) {\n      const errorMessage = error instanceof Error ? error.message : String(error);\n      this.logger.error('Failed to import context', error instanceof Error ? error : undefined);\n      throw new Error(`Failed to import context: ${errorMessage}`);\n    }\n  }\n\n  /**\n   * Generate a summary of the current context\n   */\n  async generateSummary(): Promise<ContextSummary> {\n    if (this.messages.length === 0) {\n      return {\n        mainTopics: [],\n        keyEntities: [],\n        conversationFlow: 'No conversation yet',\n        importantFacts: [],\n        actionItems: [],\n      };\n    }\n\n    const conversationText = this.messages\n      .map((msg) => `${msg.role.toUpperCase()}: ${msg.content}`)\n      .join('\\n\\n');\n\n    const summaryPrompt = `Analyze the following conversation and provide a structured summary:\n\n${conversationText}\n\nProvide a JSON summary with:\n1. mainTopics: Array of main topics discussed\n2. keyEntities: Array of important entities mentioned (people, places, concepts)\n3. conversationFlow: Brief description of how the conversation progressed\n4. importantFacts: Array of key facts or decisions\n5. actionItems: Array of any action items or tasks mentioned\n\nReturn only valid JSON.`;\n\n    try {\n      const llm = getLLM(getLogger());\n      if (!llm) {\n        this.logger.warn('LLM not available for summary generation');\n        return {\n          mainTopics: [],\n          keyEntities: [],\n          conversationFlow: 'LLM not available',\n          importantFacts: [],\n          actionItems: [],\n        };\n      }\n      const response = await llm.generateResponse({\n        model: this.model,\n        messages: [{ role: 'user' as const, content: summaryPrompt }],\n        temperature: 0.3,\n        maxTokens: 500,\n      });\n\n      // Safely parse JSON response with error handling\n      let summary: Record<string, unknown>;\n      try {\n        // Try to extract JSON from response (LLM might include extra text)\n        const jsonMatch = response.content.match(/\\{[\\s\\S]*\\}/);\n        if (!jsonMatch) {\n          throw new Error('No JSON object found in response');\n        }\n        summary = JSON.parse(jsonMatch[0]);\n      } catch (parseError) {\n        this.logger.warn('Failed to parse JSON from summary response', {\n          error: parseError instanceof Error ? parseError.message : String(parseError),\n          responsePreview: response.content.substring(0, 200),\n        });\n        return {\n          mainTopics: [],\n          keyEntities: [],\n          conversationFlow: 'Failed to parse summary response',\n          importantFacts: [],\n          actionItems: [],\n        };\n      }\n\n      return {\n        mainTopics: Array.isArray(summary.mainTopics) ? summary.mainTopics : [],\n        keyEntities: Array.isArray(summary.keyEntities) ? summary.keyEntities : [],\n        conversationFlow:\n          typeof summary.conversationFlow === 'string' ? summary.conversationFlow : '',\n        importantFacts: Array.isArray(summary.importantFacts) ? summary.importantFacts : [],\n        actionItems: Array.isArray(summary.actionItems) ? summary.actionItems : [],\n      };\n    } catch (error) {\n      this.logger.error('Failed to generate summary', error instanceof Error ? error : undefined);\n      return {\n        mainTopics: [],\n        keyEntities: [],\n        conversationFlow: 'Failed to generate summary',\n        importantFacts: [],\n        actionItems: [],\n      };\n    }\n  }\n\n  /**\n   * Get recent messages\n   */\n  getRecentMessages(count: number): ContextMessage[] {\n    // Bounds check: ensure count is valid\n    const safeCount = Math.max(0, Math.min(count, this.messages.length));\n    return this.messages.slice(-safeCount);\n  }\n\n  /**\n   * Find messages by role\n   */\n  getMessagesByRole(role: 'user' | 'assistant' | 'system'): ContextMessage[] {\n    return this.messages.filter((msg) => msg.role === role);\n  }\n\n  /**\n   * Update a message in context by memory ID\n   * Used for synchronizing with Memory module updates\n   */\n  updateMessageByMemoryId(\n    memoryId: string,\n    updates: { content?: string; metadata?: MetadataObject }\n  ): boolean {\n    const messageIndex = this.messages.findIndex((msg) => msg.metadata?.memory_id === memoryId);\n\n    if (messageIndex === -1) {\n      this.logger.debug('Message not found in context for memory update', { memoryId });\n      return false;\n    }\n\n    const message = this.messages[messageIndex];\n\n    if (updates.content !== undefined) {\n      message.content = updates.content;\n      message.tokens = this.compressor.estimateTokens(updates.content);\n    }\n\n    if (updates.metadata !== undefined) {\n      message.metadata = {\n        ...message.metadata,\n        ...updates.metadata,\n      };\n    }\n\n    this.isDirty = true;\n    this.logger.debug('Context message updated', { memoryId, messageIndex });\n    return true;\n  }\n\n  /**\n   * Remove a message from context by memory ID\n   * Used for synchronizing with Memory module deletions\n   */\n  removeMessageByMemoryId(memoryId: string): boolean {\n    const messageIndex = this.messages.findIndex((msg) => msg.metadata?.memory_id === memoryId);\n\n    if (messageIndex === -1) {\n      this.logger.debug('Message not found in context for removal', { memoryId });\n      return false;\n    }\n\n    this.messages.splice(messageIndex, 1);\n    this.isDirty = true;\n    this.logger.debug('Context message removed', { memoryId, messageIndex });\n    return true;\n  }\n\n  /**\n   * Search context messages\n   * Provides filtering by graphId, taskId, sessionId and text content\n   */\n  searchContext(options: {\n    query?: string;\n    graphId?: string;\n    taskId?: string;\n    sessionId?: string;\n    role?: 'user' | 'assistant' | 'system';\n    limit?: number;\n  }): ContextMessage[] {\n    let results = [...this.messages];\n\n    // Filter by graphId\n    if (options.graphId !== undefined) {\n      results = results.filter((msg) => msg.metadata?.graphId === options.graphId);\n    }\n\n    // Filter by taskId\n    if (options.taskId !== undefined) {\n      results = results.filter((msg) => msg.metadata?.taskId === options.taskId);\n    }\n\n    // Filter by sessionId\n    if (options.sessionId !== undefined) {\n      results = results.filter((msg) => msg.metadata?.sessionId === options.sessionId);\n    }\n\n    // Filter by role\n    if (options.role !== undefined) {\n      results = results.filter((msg) => msg.role === options.role);\n    }\n\n    // Filter by text content (case-insensitive)\n    if (options.query !== undefined && options.query.trim() !== '') {\n      const queryLower = options.query.toLowerCase();\n      results = results.filter((msg) => msg.content.toLowerCase().includes(queryLower));\n    }\n\n    // Apply limit\n    if (options.limit !== undefined && options.limit > 0) {\n      results = results.slice(0, options.limit);\n    }\n\n    this.logger.debug('Context search completed', {\n      query: options.query,\n      graphId: options.graphId,\n      taskId: options.taskId,\n      resultsCount: results.length,\n    });\n\n    return results;\n  }\n\n  /**\n   * Update the model used for context operations\n   */\n  updateModel(model: string): void {\n    this.model = model;\n    this.compressor.updateOptions({ model });\n    this.logger.debug('Context model updated', { model });\n  }\n\n  /**\n   * Load conversation history from memory module\n   * @returns true if loading was successful, false otherwise\n   */\n  async loadFromMemory(\n    memoryModule: {\n      listMemories: (options: { limit: number; orderBy: string; order: string }) => Promise<\n        Array<{\n          id: string; // UUID\n          content: string;\n          created_at: string;\n          graphId?: string; // UUID - Graph relationship\n          taskId?: string; // UUID - Task relationship\n          sessionId?: string; // Session ID\n          metadata?: MetadataObject;\n        }>\n      >;\n    },\n    limit: number = 20\n  ): Promise<boolean> {\n    try {\n      // Get the latest conversation messages from Memory\n      const recentMemories = await memoryModule.listMemories({\n        limit,\n        orderBy: 'created_at',\n        order: 'desc',\n      });\n\n      // Clear the old context\n      this.messages = [];\n\n      // Load messages from Memory to context (old to new order)\n      // Use direct push instead of addMessage to avoid triggering save for each message\n      const sortedMemories = recentMemories.reverse();\n      for (const memory of sortedMemories) {\n        // Preserve graphId and other metadata from the original memory\n        const baseMetadata = {\n          source: 'memory',\n          memory_id: memory.id,\n          ...(memory.graphId && { graphId: memory.graphId }),\n          ...(memory.taskId && { taskId: memory.taskId }),\n          ...(memory.sessionId && { sessionId: memory.sessionId }),\n        };\n\n        const content = memory.content || '';\n        const timestamp = new Date(memory.created_at);\n        const tokens = this.compressor.estimateTokens(content);\n\n        if (memory.metadata?.type === 'user_message') {\n          this.messages.push({\n            role: 'user',\n            content,\n            timestamp,\n            tokens,\n            metadata: baseMetadata,\n          });\n        } else if (memory.metadata?.type === 'assistant_response') {\n          this.messages.push({\n            role: 'assistant',\n            content,\n            timestamp,\n            tokens,\n            metadata: baseMetadata,\n          });\n        }\n      }\n\n      this.isDirty = true; // Mark as dirty after batch loading\n\n      this.logger.info('Context loaded from memory', {\n        messagesLoaded: this.messages.length,\n        memoryLimit: limit,\n      });\n\n      // Apply compression if needed after loading from Memory\n      if (this.autoCompress && this.shouldCompress()) {\n        await this.compressContext();\n      }\n\n      // Save once after all messages loaded\n      await this.saveToStorage();\n      return true;\n    } catch (error) {\n      this.logger.error(\n        'Failed to load context from memory',\n        error instanceof Error ? error : undefined\n      );\n      return false;\n    }\n  }\n\n  /**\n   * Save current context messages to memory\n   * @returns true if saving was successful, false otherwise\n   */\n  async saveToMemory(memoryModule: {\n    addMemory: (\n      content: string,\n      metadata?: MetadataObject,\n      context?: { graphId?: string; taskId?: string; sessionId?: string }\n    ) => Promise<{ id: string; content: string }>; // UUID\n  }): Promise<boolean> {\n    try {\n      // Save only new messages that are not already loaded from memory\n      // Skip messages that have source='memory' (already in database)\n      const newMessages = this.messages.filter((msg) => msg.metadata?.source !== 'memory');\n\n      for (const message of newMessages) {\n        // Extract graphId/taskId/sessionId for the context parameter (database columns)\n        const context: { graphId?: string; taskId?: string; sessionId?: string } = {};\n        if (message.metadata?.graphId) {\n          context.graphId = String(message.metadata.graphId);\n        }\n        if (message.metadata?.taskId) {\n          context.taskId = String(message.metadata.taskId);\n        }\n        if (message.metadata?.sessionId) {\n          context.sessionId = String(message.metadata.sessionId);\n        }\n\n        // Base metadata for the metadata JSON field\n        const baseMetadata = {\n          ...(message.timestamp && { timestamp: message.timestamp.toISOString() }),\n        };\n\n        if (message.role === 'user') {\n          await memoryModule.addMemory(\n            message.content,\n            {\n              type: 'user_message',\n              role: 'user',\n              ...baseMetadata,\n            },\n            Object.keys(context).length > 0 ? context : undefined\n          );\n        } else if (message.role === 'assistant') {\n          await memoryModule.addMemory(\n            message.content,\n            {\n              type: 'assistant_response',\n              role: 'assistant',\n              ...baseMetadata,\n            },\n            Object.keys(context).length > 0 ? context : undefined\n          );\n        }\n      }\n\n      this.logger.debug('Context saved to memory', {\n        messagesSaved: newMessages.length,\n      });\n      return true;\n    } catch (error) {\n      this.logger.error(\n        'Failed to save context to memory',\n        error instanceof Error ? error : undefined\n      );\n      return false;\n    }\n  }\n\n  /**\n   * Update compressor options\n   */\n  updateCompressorOptions(options: Partial<ContextCompressorOptions>): void {\n    this.compressor.updateOptions(options);\n    if (options.maxContextLength !== undefined) {\n      this.maxTokens = options.maxContextLength;\n    }\n    if (options.model !== undefined) {\n      this.model = options.model;\n    }\n  }\n}\n","import {\n  AgentConfig,\n  AgentConfigInput,\n  IAgent,\n  IAgentWithModules,\n  RunOptions,\n  AskOptions,\n} from './types';\nimport { DEFAULT_AGENT_CONFIG } from './defaults';\nimport { Task as TaskType, TaskRequest, TaskSearchOptions, TaskResponse } from '../task/types';\nimport { Memory as MemoryType, MemorySearchOptions } from '../memory/types';\nimport { MCPServerDefinition, MCPValue, MCPTool } from '../mcp/types';\nimport { AnalysisOptions } from '../vision/index';\nimport { MetadataObject } from '../types';\nimport {\n  ToolDefinition,\n  Plugin as IPlugin,\n  ToolParameterValue,\n  PluginConfig,\n  ToolCallResult,\n} from '../plugin/types';\nimport { convertToolParametersToJsonSchema, cleanupPlugin } from '../plugin';\nimport { ToolError } from '../errors';\n\nimport { Task } from '../task';\nimport { Memory } from '../memory';\nimport { Graph } from '../graph';\nimport { Plugin } from '../plugin';\nimport { MCP } from '../mcp';\nimport { Knowledge } from '../knowledge';\nimport { Vision } from '../vision';\nimport { cleanupVision } from '../vision/tools';\nimport { SubAgent } from '../sub-agent';\nimport { ContextManager } from '../context';\nimport {\n  ContextMessage,\n  ContextWindow,\n  ContextAnalysis,\n  ContextSummary,\n  CompressionResult,\n} from '../context/types';\nimport { getDatabase } from '../database';\nimport { getProviderForModel } from '../llm/models';\nimport { getLLM } from '../llm';\nimport { LLMRequestOptions, Tool, ToolCall } from '../llm/types';\nimport { Logger, getLogger } from '../logger';\nimport * as fs from 'fs/promises';\nimport path from 'path';\nimport { randomUUID } from 'crypto';\n\n// Maximum file size for attachments (10MB)\nconst MAX_FILE_SIZE = 10 * 1024 * 1024;\n\n// Cached base directory for path safety checks - computed once at module load\n// This prevents TOCTOU issues where cwd could change between checks\nconst SAFE_BASE_DIR = path.resolve(process.cwd());\n\n/**\n * Validate that a file path is safe and doesn't traverse outside allowed directories.\n * Prevents path traversal attacks (e.g., ../../etc/passwd).\n * @param filePath - The file path to validate\n * @param allowedBase - Optional base directory to restrict paths to (defaults to cached cwd)\n * @returns true if path is safe, false otherwise\n */\nfunction isPathSafe(filePath: string, allowedBase?: string): boolean {\n  // Validate input\n  if (!filePath || typeof filePath !== 'string') {\n    return false;\n  }\n\n  // Reject paths with null bytes (common attack vector)\n  if (filePath.includes('\\0')) {\n    return false;\n  }\n\n  // Normalize and resolve the path\n  const normalizedPath = path.normalize(filePath);\n  const resolved = path.resolve(normalizedPath);\n\n  // Use provided base or cached base directory (not live cwd)\n  const base = allowedBase ? path.resolve(allowedBase) : SAFE_BASE_DIR;\n  const normalizedBase = path.normalize(base);\n\n  // Check if resolved path starts with base directory\n  // Use normalizedBase + path.sep to prevent prefix attacks (e.g., /base-other matching /base)\n  const isWithinBase =\n    resolved === normalizedBase || resolved.startsWith(normalizedBase + path.sep);\n\n  // Additional check: reject symbolic link attempts in path components\n  // (actual symlink following would require async fs.realpath which is beyond this sync check)\n  const pathParts = normalizedPath.split(path.sep);\n  const hasTraversal = pathParts.some((part) => part === '..' || part === '.');\n\n  // If there are explicit traversal components, verify the final path is still safe\n  if (hasTraversal && !isWithinBase) {\n    return false;\n  }\n\n  return isWithinBase;\n}\n\n/**\n * Type guard for validating role values.\n * Ensures type safety when casting unknown values to role types.\n */\nfunction isValidRole(role: unknown): role is 'user' | 'assistant' | 'system' {\n  return role === 'user' || role === 'assistant' || role === 'system';\n}\n\n// Maximum session messages to prevent unbounded memory growth\nconst MAX_SESSION_MESSAGES = 1000;\n\n/**\n * Abstract base class for all agents\n * Provides core functionality and database operations\n */\nexport abstract class BaseAgent implements IAgent {\n  public data: AgentConfig;\n  public logger: Logger;\n  protected sessionMessages: ContextMessage[] = []; // Session-only messages when memory is disabled\n\n  constructor(data: AgentConfig) {\n    this.data = data;\n\n    // Create isolated logger instance for this agent (not shared)\n    const debugMode = data.debug === true;\n    this.logger = new Logger({\n      level: debugMode ? 'debug' : 'info',\n      debug: debugMode,\n      enableConsole: true,\n      enableFile: false,\n      agentName: data.name,\n    });\n  }\n\n  /**\n   * Abstract method that must be implemented by concrete agent classes\n   */\n  abstract run(prompt: string, options?: RunOptions): Promise<string>;\n\n  /**\n   * Abstract method that must be implemented by concrete agent classes\n   */\n  abstract ask(prompt: string, options?: AskOptions): Promise<string>;\n\n  /**\n   * Abstract context methods that must be implemented by concrete agent classes\n   */\n  abstract getContext(): ContextMessage[];\n  abstract clearContext(options?: { syncWithMemory?: boolean }): Promise<void>;\n  abstract exportContext(): string;\n  abstract importContext(data: string): void;\n\n  // Getters for IAgent interface\n  get id(): string {\n    if (this.data.id === undefined || this.data.id === null) {\n      throw new Error(\n        `Agent ${this.data.name || 'unknown'} has no ID - agent may not be saved to database`\n      );\n    }\n    return this.data.id;\n  }\n\n  get name(): string {\n    if (!this.data.name) {\n      throw new Error('Agent name is required but not provided');\n    }\n    return this.data.name;\n  }\n\n  get config(): AgentConfig {\n    return this.data;\n  }\n\n  // Feature checks\n  canUseTools(): boolean {\n    return this.config.useTools !== false;\n  }\n\n  hasMemory(): boolean {\n    return this.config.memory === true;\n  }\n\n  hasKnowledge(): boolean {\n    return this.config.knowledge === true;\n  }\n\n  hasVision(): boolean {\n    return this.config.vision === true;\n  }\n\n  // Instance methods\n  async update(updates: Partial<AgentConfig>): Promise<void> {\n    if (!this.data.id) {\n      throw new Error('Cannot update agent: agent has no ID');\n    }\n\n    const db = await getDatabase();\n    const updatedData = await db.updateAgent(this.data.id, updates);\n    if (!updatedData) {\n      throw new Error(`Failed to update agent ${this.data.name}: database returned null`);\n    }\n\n    this.data = updatedData;\n\n    // Update logger debug mode if changed\n    if (updates.debug !== undefined) {\n      // Dispose old logger if exists (Logger class has dispose method)\n      const loggerWithDispose = this.logger as Logger & { dispose?: () => void };\n      if (loggerWithDispose.dispose) {\n        loggerWithDispose.dispose();\n      }\n      const debugMode = updates.debug === true;\n      const agentName = this.data.name || 'unknown';\n      this.logger = new Logger({\n        level: debugMode ? 'debug' : 'info',\n        debug: debugMode,\n        enableConsole: true,\n        enableFile: false,\n        agentName,\n      });\n    }\n  }\n\n  async delete(): Promise<boolean> {\n    if (!this.data.id) {\n      throw new Error('Cannot delete agent: agent has no ID');\n    }\n\n    const db = await getDatabase();\n    return db.deleteAgent(this.data.id);\n  }\n\n  // Utility methods from original\n  getId(): string {\n    if (!this.data.id) {\n      throw new Error('Agent has no ID');\n    }\n    return this.data.id;\n  }\n\n  getName(): string {\n    return this.data.name;\n  }\n\n  getDescription(): string | null {\n    return this.data.description || null;\n  }\n\n  getModel(): string {\n    return this.config.model || DEFAULT_AGENT_CONFIG.model;\n  }\n\n  getTemperature(): number {\n    return this.config.temperature ?? DEFAULT_AGENT_CONFIG.temperature ?? 0.7;\n  }\n\n  getMaxTokens(): number {\n    return this.config.maxTokens ?? DEFAULT_AGENT_CONFIG.maxTokens ?? 2000;\n  }\n\n  getSystemPrompt(): string | null {\n    return this.config.systemPrompt || null;\n  }\n\n  /**\n   * Protected helper for concrete implementations\n   */\n  protected async callLLM(prompt: string, options?: RunOptions): Promise<string> {\n    const llm = getLLM(this.logger);\n\n    const response = await llm.generateResponse({\n      model: options?.model ?? this.getModel(),\n      messages: [{ role: 'user', content: prompt }],\n      temperature: options?.temperature ?? this.getTemperature(),\n      maxTokens: options?.maxTokens ?? this.getMaxTokens(),\n      systemPrompt: this.getSystemPrompt() || undefined,\n      stream: options?.stream,\n    });\n\n    return response.content;\n  }\n}\n\n/**\n * Main Agent class with module system\n */\nexport class Agent extends BaseAgent implements IAgentWithModules {\n  // Static lock map to prevent race conditions during agent creation\n  private static creationLock = new Map<string, Promise<Agent>>();\n\n  // Instance-level operation lock to prevent concurrent chat/run operations\n  // This prevents state corruption when multiple calls happen simultaneously\n  private operationLock: Promise<void> | null = null;\n  private operationQueue: Array<{\n    resolve: () => void;\n    reject: (error: Error) => void;\n  }> = [];\n\n  private modules: {\n    task: Task;\n    memory?: Memory;\n    graph?: Graph;\n    plugin?: Plugin;\n    mcp?: MCP;\n    knowledge?: Knowledge;\n    vision?: Vision;\n    subAgent?: SubAgent;\n    context?: ContextManager;\n  };\n\n  constructor(data: AgentConfig) {\n    super(data);\n\n    // Initialize modules\n    this.modules = {\n      task: new Task(this),\n    };\n\n    if (data.memory) {\n      this.modules.memory = new Memory(this);\n    }\n\n    if (data.useTools !== false) {\n      this.modules.plugin = new Plugin(this);\n      this.modules.mcp = new MCP(this);\n    }\n\n    if (data.knowledge) {\n      this.modules.knowledge = new Knowledge(this);\n    }\n\n    if (data.vision) {\n      this.modules.vision = new Vision(this);\n    }\n\n    // Always initialize SubAgent module for potential sub-agent usage\n    this.modules.subAgent = new SubAgent(this.logger);\n\n    // Always initialize context manager (core component)\n    // Use nullish coalescing (??) to properly handle 0 values for numeric fields\n    this.modules.context = new ContextManager({\n      maxContextLength: data.maxContextLength ?? data.maxTokens ?? 8000,\n      autoCompress: data.autoContextCompression ?? false,\n      model: this.getModel(), // Use agent's effective model\n      preserveLastN: data.preserveLastN,\n      compressionRatio: data.compressionRatio,\n      compressionStrategy: data.compressionStrategy,\n    });\n\n    // Module methods are now directly implemented in the class\n  }\n\n  // ===== TASK MODULE METHODS (always available) =====\n\n  async createTask(request: TaskRequest): Promise<TaskType> {\n    return this.modules.task.createTask(request);\n  }\n\n  async getTask(id: string): Promise<TaskType | null> {\n    return this.modules.task.getTask(id);\n  }\n\n  async listTasks(options?: TaskSearchOptions): Promise<TaskType[]> {\n    return this.modules.task.listTasks(options);\n  }\n\n  async updateTask(id: string, updates: Partial<TaskType>): Promise<TaskType | null> {\n    return this.modules.task.updateTask(id, updates);\n  }\n\n  async deleteTask(id: string): Promise<boolean> {\n    return this.modules.task.deleteTask(id);\n  }\n\n  async clearTasks(): Promise<number> {\n    return this.modules.task.clearTasks();\n  }\n\n  async executeTask(\n    taskId: string,\n    options?: { model?: string; stream?: boolean }\n  ): Promise<TaskResponse> {\n    return this.modules.task.executeTask(taskId, options);\n  }\n\n  // ===== MEMORY MODULE METHODS (when memory enabled) =====\n\n  async addMemory(content: string, metadata?: MetadataObject): Promise<MemoryType> {\n    if (this.modules.memory) {\n      // Extract context fields from metadata for proper DB storage\n      const context: { graphId?: string; taskId?: string; sessionId?: string } = {};\n      if (metadata?.graphId) {\n        context.graphId = String(metadata.graphId);\n      }\n      if (metadata?.taskId) {\n        context.taskId = String(metadata.taskId);\n      }\n      if (metadata?.sessionId) {\n        context.sessionId = String(metadata.sessionId);\n      }\n\n      // Memory enabled: Save to database with context\n      const memory = await this.modules.memory.addMemory(\n        content,\n        metadata,\n        Object.keys(context).length > 0 ? context : undefined\n      );\n\n      // Also add to context manager (for non-memory-fed scenarios)\n      // Mark as 'memory' source so saveContextToMemory won't re-save it\n      if (this.modules.context) {\n        const contextMessage: ContextMessage = {\n          role: isValidRole(metadata?.role) ? metadata.role : 'user',\n          content,\n          timestamp: new Date(),\n          metadata: {\n            ...metadata,\n            source: 'memory', // Mark as already saved to memory to prevent duplicate saves\n            memory_id: memory.id,\n          },\n        };\n        await this.modules.context.addMessage(contextMessage);\n      }\n\n      return memory;\n    } else {\n      // Memory disabled: Add to session-only messages\n      const contextMessage: ContextMessage = {\n        role: isValidRole(metadata?.role) ? metadata.role : 'user',\n        content,\n        timestamp: new Date(),\n        metadata,\n      };\n\n      // Enforce session messages size limit to prevent unbounded memory growth\n      if (this.sessionMessages.length >= MAX_SESSION_MESSAGES) {\n        // Remove oldest messages from the beginning (not from the middle)\n        const removeCount = Math.floor(MAX_SESSION_MESSAGES / 2);\n        this.sessionMessages = this.sessionMessages.slice(removeCount);\n        this.logger.debug('Truncated session messages', {\n          removed: removeCount,\n          remaining: this.sessionMessages.length,\n        });\n      }\n      this.sessionMessages.push(contextMessage);\n\n      // Return mock memory object with proper UUID\n      return {\n        id: randomUUID(),\n        agentId: this.id,\n        content,\n        metadata: metadata || {},\n        createdAt: new Date(),\n        updatedAt: new Date(),\n      };\n    }\n  }\n\n  async getMemory(id: string): Promise<MemoryType | null> {\n    if (!this.modules.memory) throw new Error('Memory module not enabled');\n    return this.modules.memory.getMemory(id);\n  }\n\n  async searchMemories(query: string, options?: MemorySearchOptions): Promise<MemoryType[]> {\n    if (!this.modules.memory) throw new Error('Memory module not enabled');\n    return this.modules.memory.searchMemories(query, options);\n  }\n\n  async listMemories(options?: MemorySearchOptions): Promise<MemoryType[]> {\n    if (!this.modules.memory) throw new Error('Memory module not enabled');\n    return this.modules.memory.listMemories(options);\n  }\n\n  async updateMemory(\n    id: string,\n    updates: { content?: string; metadata?: MetadataObject }\n  ): Promise<MemoryType | null> {\n    if (!this.modules.memory) throw new Error('Memory module not enabled');\n    return this.modules.memory.updateMemory(id, updates);\n  }\n\n  async deleteMemory(id: string): Promise<boolean> {\n    if (!this.modules.memory) throw new Error('Memory module not enabled');\n    return this.modules.memory.deleteMemory(id);\n  }\n\n  async clearMemories(): Promise<number> {\n    if (!this.modules.memory) throw new Error('Memory module not enabled');\n    return this.modules.memory.clearMemories();\n  }\n\n  /**\n   * Clear all data: both memory and context\n   * This ensures Memory and Context are always synchronized\n   */\n  async clearAll(): Promise<{ memoriesCleared: number; contextCleared: boolean }> {\n    let memoriesCleared = 0;\n    let contextCleared = false;\n\n    // Clear memory if enabled\n    if (this.modules.memory) {\n      memoriesCleared = await this.modules.memory.clearMemories();\n      // Note: Memory callback will automatically clear context\n    }\n\n    // Clear context (in case memory is not enabled or callback didn't fire)\n    if (this.modules.context) {\n      await this.modules.context.clearContext();\n      contextCleared = true;\n    }\n\n    // Clear session messages\n    this.sessionMessages = [];\n\n    this.logger.info(\n      `Cleared all data: ${memoriesCleared} memories, context cleared: ${contextCleared}`\n    );\n\n    return { memoriesCleared, contextCleared };\n  }\n\n  /**\n   * Clear session messages to free memory.\n   * Call this when conversation context is no longer needed.\n   */\n  clearSessionMessages(): void {\n    this.sessionMessages = [];\n  }\n\n  /**\n   * Destroy agent resources and free memory.\n   * Call this when the agent is no longer needed.\n   * All cleanup operations are performed even if some fail.\n   */\n  async destroy(): Promise<void> {\n    const cleanupErrors: Array<{ module: string; error: string }> = [];\n\n    // Clear session messages\n    this.sessionMessages = [];\n\n    // Clear operation queue - reject pending operations\n    while (this.operationQueue.length > 0) {\n      const pending = this.operationQueue.shift();\n      if (pending) {\n        pending.reject(new Error('Agent destroyed while operation was pending'));\n      }\n    }\n\n    // Clear operation lock\n    this.operationLock = null;\n\n    // Clear context if available\n    if (this.modules.context) {\n      try {\n        await this.clearContext();\n      } catch (error) {\n        cleanupErrors.push({\n          module: 'context',\n          error: error instanceof Error ? error.message : String(error),\n        });\n      }\n      // Always delete reference even if cleanup fails\n      delete this.modules.context;\n    }\n\n    // Memory module cleanup\n    if (this.modules.memory) {\n      try {\n        // Call Memory.destroy() for proper cleanup\n        this.modules.memory.destroy();\n      } catch (error) {\n        cleanupErrors.push({\n          module: 'memory',\n          error: error instanceof Error ? error.message : String(error),\n        });\n      }\n      delete this.modules.memory;\n    }\n\n    // Knowledge module cleanup\n    if (this.modules.knowledge) {\n      try {\n        // Knowledge module cleanup - clear internal references\n        const knowledgeModule = this.modules.knowledge as Knowledge & {\n          knex?: unknown;\n          vectorStore?: unknown;\n        };\n        knowledgeModule.knex = null;\n        knowledgeModule.vectorStore = null;\n      } catch (error) {\n        cleanupErrors.push({\n          module: 'knowledge',\n          error: error instanceof Error ? error.message : String(error),\n        });\n      }\n      delete this.modules.knowledge;\n    }\n\n    // Vision module cleanup\n    if (this.modules.vision) {\n      try {\n        // Vision module cleanup - call cleanupVision to remove from instance cache\n        cleanupVision(this.data.id);\n      } catch (error) {\n        cleanupErrors.push({\n          module: 'vision',\n          error: error instanceof Error ? error.message : String(error),\n        });\n      }\n      delete this.modules.vision;\n    }\n\n    // SubAgent module cleanup\n    if (this.modules.subAgent) {\n      try {\n        // SubAgent has async destroy method\n        await this.modules.subAgent.destroy();\n      } catch (error) {\n        cleanupErrors.push({\n          module: 'subAgent',\n          error: error instanceof Error ? error.message : String(error),\n        });\n      }\n      delete this.modules.subAgent;\n    }\n\n    // Task module cleanup\n    if (this.modules.task) {\n      try {\n        // Task module cleanup - clear agent reference\n        // Use type-safe approach with unknown cast to avoid intersection type issues\n        const taskModule = this.modules.task as unknown as {\n          agent?: unknown;\n          knex?: unknown;\n        };\n        taskModule.agent = null;\n        taskModule.knex = null;\n        // Note: We don't delete task module as it's required by interface\n      } catch (error) {\n        cleanupErrors.push({\n          module: 'task',\n          error: error instanceof Error ? error.message : String(error),\n        });\n      }\n    }\n\n    // MCP cleanup\n    if (this.modules.mcp) {\n      try {\n        // MCP module cleanup - remove all servers and wait for processes to exit\n        await this.modules.mcp.cleanup();\n      } catch (error) {\n        cleanupErrors.push({\n          module: 'mcp',\n          error: error instanceof Error ? error.message : String(error),\n        });\n      }\n      delete this.modules.mcp;\n    }\n\n    // Plugin cleanup\n    if (this.modules.plugin) {\n      try {\n        if (this.data.id) {\n          await cleanupPlugin(this.data.id);\n        }\n      } catch (error) {\n        cleanupErrors.push({\n          module: 'plugin',\n          error: error instanceof Error ? error.message : String(error),\n        });\n      }\n      delete this.modules.plugin;\n    }\n\n    // Graph module cleanup (if exists)\n    if (this.modules.graph) {\n      try {\n        await this.modules.graph.destroy();\n      } catch (error) {\n        cleanupErrors.push({\n          module: 'graph',\n          error: error instanceof Error ? error.message : String(error),\n        });\n      }\n      delete this.modules.graph;\n    }\n\n    // Log cleanup errors if any occurred\n    if (cleanupErrors.length > 0) {\n      this.logger.warn('Agent destroy completed with errors', {\n        agentName: this.data.name,\n        errorCount: cleanupErrors.length,\n        // Serialize errors array to string for LogData compatibility\n        errors: JSON.stringify(cleanupErrors),\n      });\n    }\n\n    this.logger.info(`Agent ${this.data.name} destroyed`);\n\n    // Logger dispose - must be last to allow logging above\n    try {\n      this.logger.dispose();\n    } catch (error) {\n      // Can't log here since logger is being disposed\n      console.warn(\n        'Logger dispose failed:',\n        error instanceof Error ? error.message : String(error)\n      );\n    }\n  }\n\n  async rememberConversation(\n    content: string,\n    role: 'user' | 'assistant' = 'user'\n  ): Promise<MemoryType> {\n    if (!this.modules.memory) throw new Error('Memory module not enabled');\n    return this.modules.memory.rememberConversation(content, role);\n  }\n\n  async searchMemoriesBySimilarity(\n    query: string,\n    options?: MemorySearchOptions\n  ): Promise<MemoryType[]> {\n    if (!this.modules.memory) throw new Error('Memory module not enabled');\n    return this.modules.memory.searchMemoriesBySimilarity(query, options);\n  }\n\n  async generateEmbeddingForMemory(\n    memoryId: string\n  ): Promise<{ success: boolean; message: string; embedding?: number[] }> {\n    if (!this.modules.memory) throw new Error('Memory module not enabled');\n    return this.modules.memory.generateEmbeddingForMemory(memoryId);\n  }\n\n  // ===== KNOWLEDGE MODULE METHODS (when knowledge enabled) =====\n\n  async addKnowledge(content: string, title?: string, metadata?: MetadataObject): Promise<string> {\n    // Returns UUID\n    if (!this.modules.knowledge) throw new Error('Knowledge module not enabled');\n    return this.modules.knowledge.addKnowledge(content, title, metadata);\n  }\n\n  async searchKnowledge(\n    query: string,\n    limit?: number,\n    threshold?: number\n  ): Promise<Array<{ content: string; metadata: MetadataObject; similarity: number }>> {\n    if (!this.modules.knowledge) throw new Error('Knowledge module not enabled');\n    return this.modules.knowledge.searchKnowledge(query, limit, threshold);\n  }\n\n  async getKnowledgeContext(query: string, limit?: number): Promise<string> {\n    if (!this.modules.knowledge) throw new Error('Knowledge module not enabled');\n    return this.modules.knowledge.getKnowledgeContext(query, limit);\n  }\n\n  async getKnowledgeDocuments(): Promise<Array<{ id: string; title: string; created_at: string }>> {\n    if (!this.modules.knowledge) throw new Error('Knowledge module not enabled');\n    return this.modules.knowledge.getKnowledgeDocuments();\n  }\n\n  async deleteKnowledgeDocument(documentId: string): Promise<boolean> {\n    if (!this.modules.knowledge) throw new Error('Knowledge module not enabled');\n    return this.modules.knowledge.deleteKnowledgeDocument(documentId);\n  }\n\n  async deleteKnowledgeChunk(chunkId: string): Promise<boolean> {\n    if (!this.modules.knowledge) throw new Error('Knowledge module not enabled');\n    return this.modules.knowledge.deleteKnowledgeChunk(chunkId);\n  }\n\n  async clearKnowledge(): Promise<void> {\n    if (!this.modules.knowledge) throw new Error('Knowledge module not enabled');\n    return this.modules.knowledge.clearKnowledge();\n  }\n\n  async addKnowledgeFromFile(filePath: string, metadata?: MetadataObject): Promise<void> {\n    if (!this.modules.knowledge) throw new Error('Knowledge module not enabled');\n    // Security: Validate file path to prevent path traversal attacks\n    if (!isPathSafe(filePath)) {\n      this.logger.error('Invalid file path: path traversal detected', undefined, { filePath });\n      throw new Error('Invalid file path: path traversal detected');\n    }\n    return this.modules.knowledge.addKnowledgeFromFile(filePath, metadata);\n  }\n\n  async addKnowledgeFromDirectory(dirPath: string, metadata?: MetadataObject): Promise<void> {\n    if (!this.modules.knowledge) throw new Error('Knowledge module not enabled');\n    // Security: Validate directory path to prevent path traversal attacks\n    if (!isPathSafe(dirPath)) {\n      this.logger.error('Invalid directory path: path traversal detected', undefined, { dirPath });\n      throw new Error('Invalid directory path: path traversal detected');\n    }\n    return this.modules.knowledge.addKnowledgeFromDirectory(dirPath, metadata);\n  }\n\n  async expandKnowledgeContext(\n    documentId: string,\n    chunkIndex: number,\n    expandBefore?: number,\n    expandAfter?: number\n  ): Promise<string[]> {\n    if (!this.modules.knowledge) throw new Error('Knowledge module not enabled');\n    return this.modules.knowledge.expandKnowledgeContext(\n      documentId,\n      chunkIndex,\n      expandBefore,\n      expandAfter\n    );\n  }\n\n  // ===== PLUGIN MODULE METHODS (when useTools enabled) =====\n\n  async registerPlugin(plugin: IPlugin, config?: PluginConfig): Promise<void> {\n    if (!this.modules.plugin) throw new Error('Plugin module not enabled');\n    return this.modules.plugin.registerPlugin(plugin, config);\n  }\n\n  async unregisterPlugin(name: string): Promise<void> {\n    if (!this.modules.plugin) throw new Error('Plugin module not enabled');\n    return this.modules.plugin.unregisterPlugin(name);\n  }\n\n  listPlugins(): IPlugin[] {\n    if (!this.modules.plugin) throw new Error('Plugin module not enabled');\n    return this.modules.plugin.listPlugins();\n  }\n\n  getTools(): ToolDefinition[] {\n    if (!this.modules.plugin) throw new Error('Plugin module not enabled');\n    return this.modules.plugin.getTools();\n  }\n\n  async executeTool(toolCall: import('../plugin/types').ToolCall): Promise<ToolCallResult> {\n    if (!this.modules.plugin) throw new Error('Plugin module not enabled');\n    return this.modules.plugin.executeTool(toolCall, { agentId: this.id, agent: this });\n  }\n\n  // ===== MCP MODULE METHODS (when useTools enabled) =====\n\n  async addMCPServer(serverDef: MCPServerDefinition): Promise<void> {\n    if (!this.modules.mcp) throw new Error('MCP module not enabled');\n    return this.modules.mcp.addMCPServer(serverDef);\n  }\n\n  async addMCPServers(servers: MCPServerDefinition[]): Promise<void> {\n    if (!this.modules.mcp) throw new Error('MCP module not enabled');\n    return this.modules.mcp.addMCPServers(servers);\n  }\n\n  removeMCPServer(name: string): void {\n    if (!this.modules.mcp) throw new Error('MCP module not enabled');\n    return this.modules.mcp.removeMCPServer(name);\n  }\n\n  async callMCPTool(\n    toolName: string,\n    args: Record<string, MCPValue>\n  ): Promise<{ content: Array<{ type: string; text?: string }>; isError?: boolean }> {\n    if (!this.modules.mcp) throw new Error('MCP module not enabled');\n    return this.modules.mcp.callMCPTool(toolName, args);\n  }\n\n  getMCPTools(): MCPTool[] {\n    if (!this.modules.mcp) throw new Error('MCP module not enabled');\n    return this.modules.mcp.getMCPTools();\n  }\n\n  // ===== VISION MODULE METHODS (when vision enabled) =====\n\n  async analyzeImage(imagePath: string, options?: AnalysisOptions): Promise<string> {\n    if (!this.modules.vision) throw new Error('Vision module not enabled');\n    return this.modules.vision.analyzeImage(imagePath, options);\n  }\n\n  async describeImage(imagePath: string): Promise<string> {\n    if (!this.modules.vision) throw new Error('Vision module not enabled');\n    return this.modules.vision.analyzeImage(imagePath, { prompt: 'Describe this image in detail' });\n  }\n\n  async extractTextFromImage(imagePath: string): Promise<string> {\n    if (!this.modules.vision) throw new Error('Vision module not enabled');\n    return this.modules.vision.analyzeImage(imagePath, {\n      prompt: 'Extract all text from this image',\n    });\n  }\n\n  // ===== SUB-AGENT MODULE METHODS (always available) =====\n\n  async executeWithSubAgents(\n    prompt: string,\n    subAgents: IAgent[],\n    options?: Record<string, string | number | boolean | object | null>,\n    mainModel?: string\n  ): Promise<string> {\n    if (!this.modules.subAgent) throw new Error('SubAgent module not available');\n    return this.modules.subAgent.executeWithSubAgents(prompt, subAgents, options, mainModel);\n  }\n\n  async delegateTask(\n    taskPrompt: string,\n    targetAgent: IAgent,\n    options?: Record<string, string | number | boolean | object | null>\n  ): Promise<string> {\n    if (!this.modules.subAgent) throw new Error('SubAgent module not available');\n    return this.modules.subAgent.executeWithSubAgents(taskPrompt, [targetAgent], options);\n  }\n\n  async coordinateAgents(\n    tasks: Array<{ agent: IAgent; prompt: string }>,\n    coordination: 'parallel' | 'sequential' = 'sequential'\n  ): Promise<Array<{ task: { agent: IAgent; prompt: string }; result: string }>> {\n    if (!this.modules.subAgent) {\n      throw new Error('SubAgent module not initialized');\n    }\n\n    // Capture reference to avoid repeated null checks in callbacks\n    const subAgentModule = this.modules.subAgent;\n\n    if (coordination === 'parallel') {\n      // Use Promise.allSettled to handle partial failures gracefully\n      // This ensures successful tasks are not lost when some tasks fail\n      const settledResults = await Promise.allSettled(\n        tasks.map(async (task) => {\n          if (task.agent && task.prompt) {\n            const result = await subAgentModule.executeWithSubAgents(task.prompt, [task.agent], {});\n            return { task, result };\n          }\n          return null;\n        })\n      );\n\n      const results: Array<{ task: { agent: IAgent; prompt: string }; result: string }> = [];\n      for (const settled of settledResults) {\n        if (settled.status === 'fulfilled' && settled.value !== null) {\n          results.push(settled.value);\n        } else if (settled.status === 'rejected') {\n          // Log failed tasks but don't throw - allow other tasks to complete\n          this.logger.warn('Parallel task execution failed', {\n            error:\n              settled.reason instanceof Error ? settled.reason.message : String(settled.reason),\n          });\n        }\n      }\n      return results;\n    }\n\n    // Sequential mode - use the captured reference for consistency\n    const results: Array<{ task: { agent: IAgent; prompt: string }; result: string }> = [];\n    for (const task of tasks) {\n      if (task.agent && task.prompt) {\n        const result = await subAgentModule.executeWithSubAgents(task.prompt, [task.agent], {\n          coordination,\n        });\n        results.push({ task, result });\n      }\n    }\n    return results;\n  }\n\n  // ===== CONTEXT MODULE METHODS (always available) =====\n\n  private getContextModule(): ContextManager {\n    if (!this.modules.context) {\n      throw new Error('Context module not initialized');\n    }\n    return this.modules.context;\n  }\n\n  getContextMessages(): ContextMessage[] {\n    return this.getContextModule().getMessages();\n  }\n\n  getContextWindow(): ContextWindow {\n    return this.getContextModule().getContextWindow();\n  }\n\n  analyzeContext(): ContextAnalysis {\n    return this.getContextModule().analyzeContext();\n  }\n\n  async compressContext(): Promise<CompressionResult> {\n    return this.getContextModule().compressContext();\n  }\n\n  async clearContext(options?: { syncWithMemory?: boolean }): Promise<void> {\n    await this.getContextModule().clearContext(options);\n  }\n\n  exportContext(): string {\n    return this.getContextModule().exportContext();\n  }\n\n  importContext(data: string): void {\n    this.getContextModule().importContext(data);\n  }\n\n  async generateContextSummary(): Promise<ContextSummary> {\n    return this.getContextModule().generateSummary();\n  }\n\n  updateContextModel(model: string): void {\n    this.getContextModule().updateModel(model);\n  }\n\n  /**\n   * Search context messages with filtering support\n   * Supports graphId, taskId, sessionId, role, and text query filters\n   */\n  searchContext(options: {\n    query?: string;\n    graphId?: string;\n    taskId?: string;\n    sessionId?: string;\n    role?: 'user' | 'assistant' | 'system';\n    limit?: number;\n  }): ContextMessage[] {\n    return this.getContextModule().searchContext(options);\n  }\n\n  /**\n   * Get conversation context messages based on memory configuration\n   * This is the central method that all modules use to get conversation history\n   */\n  getContext(): ContextMessage[] {\n    if (this.hasMemory() && this.modules.memory) {\n      // Memory enabled: Get from context manager (fed by memory)\n      return this.getContextModule().getMessages();\n    } else {\n      // Memory disabled: Return session-only messages\n      return [...this.sessionMessages];\n    }\n  }\n\n  /**\n   * Save current context to memory\n   */\n  private async saveContextToMemory(): Promise<void> {\n    if (!this.hasMemory() || !this.modules.memory) {\n      return;\n    }\n\n    if (!this.modules.context) {\n      this.logger.warn('Context module not available for saving to memory');\n      return;\n    }\n\n    try {\n      await this.modules.context.saveToMemory(this.modules.memory);\n    } catch (error) {\n      this.logger.warn('Failed to save context to memory', {\n        error: error instanceof Error ? error.message : String(error),\n      });\n    }\n  }\n\n  /**\n   * Update agent's model and propagate to context manager\n   */\n  updateModel(model: string): void {\n    this.data.model = model;\n\n    // Update context manager's model\n    if (this.modules.context) {\n      this.modules.context.updateModel(model);\n    }\n\n    this.logger.info(`Agent model updated to: ${model}`);\n  }\n\n  /**\n   * Load conversation history from memory for a specific graph\n   * @param graphId - The graph ID to load context for\n   * @param limit - Maximum number of messages to load\n   * @param isolated - If true, only load graph-specific memories (default: false)\n   *                   If false, load both general agent memories + graph-specific memories\n   */\n  async loadGraphContext(\n    graphId: string,\n    limit: number = 100,\n    isolated: boolean = false\n  ): Promise<void> {\n    if (!this.hasMemory() || !this.modules.memory || !this.modules.context) {\n      this.logger.debug('Memory or context module not available, skipping graph context load');\n      return;\n    }\n\n    try {\n      // Clear existing context\n      await this.clearContext();\n\n      let allMemories: MemoryType[] = [];\n\n      if (isolated) {\n        // ISOLATED MODE: Only load graph-specific memories\n        allMemories = await this.listMemories({\n          graphId,\n          orderBy: 'createdAt',\n          order: 'asc',\n          limit,\n        });\n\n        this.logger.debug(\n          `Loaded ${allMemories.length} isolated graph-specific memories for graph ${graphId}`\n        );\n      } else {\n        // HYBRID MODE: Load both general + graph-specific memories\n        // 1. Load agent's general memories (not tied to any graph)\n        const generalMemories = await this.modules.memory.listMemories({\n          orderBy: 'createdAt',\n          order: 'asc',\n          limit: Math.floor(limit / 2), // Use half of limit for general memories\n        });\n\n        // Filter only memories without graphId (general agent memories)\n        const generalConversations = generalMemories.filter(\n          (m) =>\n            !m.graphId &&\n            (m.metadata?.type === 'user_message' || m.metadata?.type === 'assistant_response')\n        );\n\n        // 2. Load graph-specific memories\n        const graphMemories = await this.listMemories({\n          graphId,\n          orderBy: 'createdAt',\n          order: 'asc',\n          limit: Math.floor(limit / 2), // Use half of limit for graph memories\n        });\n\n        // Combine, deduplicate by memory ID, and sort by timestamp\n        const seenIds = new Set<string>();\n        const combinedMemories = [...generalConversations, ...graphMemories];\n        allMemories = combinedMemories\n          .filter((m) => {\n            if (seenIds.has(m.id)) {\n              return false; // Skip duplicate\n            }\n            seenIds.add(m.id);\n            return true;\n          })\n          .sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime());\n\n        this.logger.debug(\n          `Loaded ${generalConversations.length} general + ${graphMemories.length} graph-specific memories for graph ${graphId}`\n        );\n      }\n\n      // Load all memories into context\n      for (const memory of allMemories) {\n        const role = isValidRole(memory.metadata?.role) ? memory.metadata.role : 'user';\n        const contextMessage: ContextMessage = {\n          role,\n          content: memory.content,\n          timestamp: memory.createdAt,\n          metadata: {\n            ...memory.metadata,\n            memory_id: memory.id,\n            source: memory.graphId ? 'graph' : 'general',\n          },\n        };\n        await this.modules.context.addMessage(contextMessage);\n      }\n    } catch (error) {\n      this.logger.warn('Failed to load graph context from memory', {\n        graphId,\n        error: error instanceof Error ? error.message : String(error),\n      });\n    }\n  }\n\n  /**\n   * Initialize all modules\n   */\n  async initializeModules(): Promise<void> {\n    // User-facing info log with agent details\n    this.logger.info(`Initializing agent: ${this.data.name}`);\n\n    // Get LLM provider information - handle empty string as well as undefined/null\n    const model =\n      this.data.model && this.data.model.trim() !== '' ? this.data.model : 'gpt-4o-mini';\n    const provider = getProviderForModel(model);\n\n    // Detailed debug log with all agent configuration\n    this.logger.debug('Agent initialization started', {\n      id: this.data.id || 0,\n      name: this.data.name,\n      model: model,\n      provider: provider || 'unknown',\n      temperature: this.data.temperature || 0.7,\n      maxTokens: this.data.maxTokens || 2000,\n      hasSystemPrompt: !!this.data.systemPrompt,\n      memory: !!this.data.memory,\n      knowledge: !!this.data.knowledge,\n      vision: !!this.data.vision,\n      useTools: this.data.useTools !== false,\n      autoContextCompression: !!this.data.autoContextCompression,\n      debug: !!this.data.debug,\n    });\n\n    await this.modules.task.initialize();\n\n    // Scheduler is now just utilities, no initialization needed\n\n    if (this.modules.memory) {\n      await this.modules.memory.initialize();\n\n      // Register callback for Memory-Context synchronization (Memory -> Context)\n      // Note: Callback is async and must await all async operations to prevent race conditions\n      this.modules.memory.onMemoryChange(async (event, data) => {\n        if (!this.modules.context) return;\n\n        try {\n          switch (event) {\n            case 'update':\n              if (data.memoryId) {\n                // updateMessageByMemoryId may be async - await it\n                await Promise.resolve(\n                  this.modules.context.updateMessageByMemoryId(data.memoryId, {\n                    content: data.content,\n                    metadata: data.metadata,\n                  })\n                );\n              }\n              break;\n            case 'delete':\n              if (data.memoryId) {\n                // removeMessageByMemoryId may be async - await it\n                await Promise.resolve(this.modules.context.removeMessageByMemoryId(data.memoryId));\n              }\n              break;\n            case 'clear':\n              // Memory cleared, also clear context (use syncWithMemory: false to prevent infinite loop)\n              await this.modules.context.clearContext({ syncWithMemory: false });\n              break;\n          }\n        } catch (error) {\n          this.logger.warn('Memory-Context synchronization failed', {\n            event,\n            memoryId: data.memoryId,\n            error: error instanceof Error ? error.message : String(error),\n          });\n        }\n      });\n    }\n\n    // Register callback for Context-Memory synchronization (Context -> Memory)\n    if (this.modules.context) {\n      // When context is cleared, optionally clear memory too\n      this.modules.context.onContextClear(async () => {\n        if (this.modules.memory) {\n          // Use syncWithContext: false to prevent infinite loop\n          await this.modules.memory.clearMemories({ syncWithContext: false });\n          this.logger.debug('Memory cleared due to context clear sync');\n        }\n      });\n\n      // When context is compressed, notify memory for potential archiving\n      this.modules.context.onCompression(async (info) => {\n        this.logger.info('Context compression completed', {\n          originalMessages: info.originalMessageCount,\n          compressedMessages: info.compressedMessageCount,\n          messagesRemoved: info.messagesRemoved,\n          tokensReduced: info.tokensReduced,\n          strategy: info.strategy,\n        });\n\n        // Note: Memory archiving could be implemented here if needed\n        // For now, we just log the compression event\n        // Future enhancement: Mark old memories as archived or move to cold storage\n      });\n    }\n\n    if (this.modules.plugin) {\n      await this.modules.plugin.initialize();\n    }\n\n    if (this.modules.mcp) {\n      await this.modules.mcp.initialize();\n    }\n\n    if (this.modules.knowledge) {\n      await this.modules.knowledge.initialize();\n    }\n\n    if (this.modules.vision) {\n      await this.modules.vision.initialize();\n    }\n\n    if (this.modules.subAgent) {\n      await this.modules.subAgent.initialize();\n    }\n\n    // Initialize context storage for this agent\n    if (this.data.id && this.modules.context) {\n      try {\n        await this.modules.context.initializeForAgent(this.data.id);\n      } catch (error) {\n        this.logger.warn('Failed to initialize context storage', {\n          error: error instanceof Error ? error.message : String(error),\n        });\n      }\n    }\n\n    // User-facing success message with capabilities summary\n    const capabilities = [];\n    if (this.data.memory) capabilities.push('Memory');\n    if (this.data.knowledge) capabilities.push('Knowledge');\n    if (this.data.vision) capabilities.push('Vision');\n    if (this.data.useTools !== false) capabilities.push('Tools');\n    if (this.data.autoContextCompression) capabilities.push('Auto Context Compression');\n\n    this.logger.info(\n      `Agent ready: ${this.data.name} (${model} via ${provider || 'unknown'}) - ${capabilities.join(', ')}`\n    );\n\n    this.logger.debug('Agent initialization completed', {\n      name: this.data.name,\n      model: model,\n      provider: provider || 'unknown',\n      enabledCapabilities: capabilities,\n      totalModules: Object.keys(this.modules).length,\n    });\n  }\n\n  /**\n   * Factory method to create a new agent or find existing one by name.\n   * Uses a lock mechanism to prevent race conditions when creating agents\n   * with the same name concurrently.\n   *\n   * Note: If the first creation attempt fails, subsequent callers will NOT\n   * receive the rejected promise - instead they will start a fresh creation attempt.\n   */\n  static async create(config: AgentConfigInput): Promise<Agent> {\n    const lockKey = config.name;\n\n    // Check if there's already a creation in progress for this name\n    const existingLock = Agent.creationLock.get(lockKey);\n    if (existingLock) {\n      try {\n        // Wait for the existing creation to complete and return that agent\n        return await existingLock;\n      } catch {\n        // The existing creation failed - check if it's still the same promise\n        // If so, we can try a fresh creation (the original caller would have cleaned up)\n        const currentLock = Agent.creationLock.get(lockKey);\n        if (currentLock === existingLock) {\n          // Same failed promise is still there - this shouldn't happen normally\n          // because the original caller's finally block should have cleaned it up\n          // But handle it defensively by continuing to try fresh creation\n          Agent.creationLock.delete(lockKey);\n        } else if (currentLock) {\n          // A new creation attempt is in progress, wait for it\n          return await currentLock;\n        }\n        // Fall through to start fresh creation\n      }\n    }\n\n    // Create the agent with lock protection\n    // Wrap in a new promise to handle errors and cleanup properly\n    const createPromise = Agent._doCreate(config).catch((error) => {\n      // On error, immediately clean up the lock so other callers can retry\n      // This must happen before the error propagates to prevent others from waiting on a failed promise\n      Agent.creationLock.delete(lockKey);\n      throw error;\n    });\n\n    Agent.creationLock.set(lockKey, createPromise);\n\n    try {\n      const agent = await createPromise;\n      return agent;\n    } finally {\n      // Clean up on success as well\n      // Use a check to avoid deleting a different promise (in case of rapid recreation)\n      if (Agent.creationLock.get(lockKey) === createPromise) {\n        Agent.creationLock.delete(lockKey);\n      }\n    }\n  }\n\n  /**\n   * Internal method that performs the actual agent creation.\n   * Should not be called directly - use create() instead.\n   */\n  private static async _doCreate(config: AgentConfigInput): Promise<Agent> {\n    const db = await getDatabase();\n\n    // Apply defaults for required boolean fields\n    const fullConfig: AgentConfigInput = {\n      memory: false,\n      knowledge: false,\n      vision: false,\n      useTools: true,\n      autoContextCompression: false,\n      debug: false,\n      ...config,\n    };\n\n    // Check if agent with this name already exists\n    const existingAgent = await db.getAgentByName(fullConfig.name);\n\n    let agentData: AgentConfig;\n    if (existingAgent && existingAgent.id) {\n      // Agent exists, update it with new config\n      const updatedAgent = await db.updateAgent(existingAgent.id, fullConfig);\n      if (!updatedAgent) {\n        throw new Error(`Failed to update agent with ID ${existingAgent.id}`);\n      }\n      agentData = updatedAgent;\n    } else {\n      // Agent doesn't exist, create new one\n      agentData = await db.createAgent(fullConfig);\n    }\n\n    const agent = new Agent(agentData);\n\n    // Initialize all modules\n    await agent.initializeModules();\n\n    // Log agent creation/update\n    if (existingAgent) {\n      agent.logger.info(`Agent updated: ${agentData.name}`);\n    } else {\n      agent.logger.info(`Agent created: ${agentData.name}`);\n    }\n\n    agent.logger.debug('Agent initialized', {\n      agentId: agentData.id || 0,\n      name: agentData.name,\n      model: agentData.model || 'default',\n      memory: !!agentData.memory,\n      knowledge: !!agentData.knowledge,\n      vision: !!agentData.vision,\n      debug: !!agentData.debug,\n    });\n\n    return agent;\n  }\n\n  /**\n   * Find agent by ID\n   */\n  static async findById(id: string): Promise<Agent | null> {\n    const db = await getDatabase();\n    const agentData = await db.getAgent(id);\n    if (!agentData) return null;\n\n    const agent = new Agent(agentData);\n    await agent.initializeModules();\n    return agent;\n  }\n\n  /**\n   * Find agent by name\n   */\n  static async findByName(name: string): Promise<Agent | null> {\n    const db = await getDatabase();\n    const agentData = await db.getAgentByName(name);\n    if (!agentData) return null;\n\n    const agent = new Agent(agentData);\n    await agent.initializeModules();\n    return agent;\n  }\n\n  /**\n   * List all agents (returns only agent data without initializing modules).\n   * Use this for listing/browsing agents without full initialization.\n   * @param options - Optional settings\n   * @param options.initialize - If true, fully initialize all agents (default: false for performance)\n   * @param options.limit - Maximum number of agents to return (default: 100, max: 1000)\n   * @param options.offset - Number of agents to skip for pagination (default: 0)\n   */\n  static async list(options?: {\n    initialize?: boolean;\n    limit?: number;\n    offset?: number;\n  }): Promise<Agent[]> {\n    const db = await getDatabase();\n    const agentsData = await db.listAgents();\n\n    // Apply pagination with sensible defaults to prevent memory issues\n    const limit = Math.min(Math.max(options?.limit ?? 100, 1), 1000);\n    const offset = Math.max(options?.offset ?? 0, 0);\n    const paginatedData = agentsData.slice(offset, offset + limit);\n\n    // Lazy loading: Don't initialize modules unless explicitly requested\n    // This prevents memory issues when listing many agents\n    if (options?.initialize) {\n      // Use Promise.allSettled to handle partial failures gracefully\n      const settledResults = await Promise.allSettled(\n        paginatedData.map(async (data) => {\n          const agent = new Agent(data);\n          await agent.initializeModules();\n          return agent;\n        })\n      );\n\n      // Collect successful agents and log failures\n      const agents: Agent[] = [];\n      for (let i = 0; i < settledResults.length; i++) {\n        const result = settledResults[i];\n        if (result.status === 'fulfilled') {\n          agents.push(result.value);\n        } else {\n          // Log initialization failure but continue with other agents\n          const agentName = paginatedData[i]?.name ?? 'unknown';\n          const logger = getLogger();\n          logger.warn(`Failed to initialize agent '${agentName}'`, {\n            reason: result.reason instanceof Error ? result.reason.message : String(result.reason),\n          });\n        }\n      }\n      return agents;\n    }\n\n    // Return agents without full module initialization (lazy loading)\n    return paginatedData.map((data) => new Agent(data));\n  }\n\n  /**\n   * Acquire operation lock to prevent concurrent chat/run operations\n   * Operations are queued and executed sequentially to prevent state corruption\n   * Uses a proper async queue instead of busy-wait loop for efficiency\n   * @param timeout - Maximum time to wait for lock acquisition (default: 60000ms)\n   * @returns A release function to be called when operation completes\n   */\n  private async acquireOperationLock(timeout = 60000): Promise<() => void> {\n    // If there's an existing operation, queue this one\n    if (this.operationLock) {\n      // Create a promise that will resolve when it's our turn\n      const waitPromise = new Promise<void>((resolve, reject) => {\n        // Set up timeout\n        const timeoutId = setTimeout(() => {\n          // Remove ourselves from queue on timeout\n          const index = this.operationQueue.findIndex((item) => item.resolve === resolve);\n          if (index !== -1) {\n            this.operationQueue.splice(index, 1);\n          }\n          reject(new Error(`Operation lock acquisition timeout after ${timeout}ms`));\n        }, timeout);\n\n        // Add to queue with timeout cleanup\n        this.operationQueue.push({\n          resolve: () => {\n            clearTimeout(timeoutId);\n            resolve();\n          },\n          reject: (error: Error) => {\n            clearTimeout(timeoutId);\n            reject(error);\n          },\n        });\n      });\n\n      // Wait for our turn\n      await waitPromise;\n    }\n\n    // Create new lock - we now own the lock\n    let releaseFunction: (() => void) | null = null;\n    this.operationLock = new Promise<void>((resolve) => {\n      releaseFunction = () => {\n        // Release our lock first\n        this.operationLock = null;\n        resolve();\n\n        // Then notify next in queue (if any) that it's their turn\n        const next = this.operationQueue.shift();\n        if (next) {\n          // Use setImmediate/nextTick pattern to avoid stack overflow on long queues\n          Promise.resolve().then(() => next.resolve());\n        }\n      };\n    });\n\n    if (!releaseFunction) {\n      throw new Error('Failed to initialize operation lock release function');\n    }\n\n    return releaseFunction;\n  }\n\n  /**\n   * Main run method - protected by operation lock to prevent concurrent state corruption\n   */\n  async run(prompt: string, options?: RunOptions): Promise<string> {\n    const release = await this.acquireOperationLock();\n\n    try {\n      // Add context processing here if needed\n\n      // Check if we should use tools\n      const useTools = options?.useTools !== undefined ? options.useTools : this.canUseTools();\n\n      if (useTools) {\n        // Tool execution logic would go here\n        // For now, just use LLM\n      }\n\n      // Call LLM\n      return await this.callLLM(prompt, options);\n    } finally {\n      release();\n    }\n  }\n\n  /**\n   * Ask method - direct conversation with the agent (task-independent)\n   * Protected by operation lock to prevent concurrent state corruption\n   */\n  async ask(prompt: string, options?: AskOptions): Promise<string> {\n    const release = await this.acquireOperationLock();\n\n    try {\n      return await this._askInternal(prompt, options);\n    } finally {\n      release();\n    }\n  }\n\n  /**\n   * Internal ask implementation - do not call directly, use ask() instead\n   */\n  private async _askInternal(prompt: string, options?: AskOptions): Promise<string> {\n    // Check if sub-agents should be used\n    if (options?.useSubAgents && this.config.subAgents && this.config.subAgents.length > 0) {\n      if (!this.modules.subAgent) {\n        this.logger.warn('SubAgent module not available, falling back to main agent');\n      } else {\n        this.logger.info(`Using sub-agents for task delegation`, {\n          subAgentCount: this.config.subAgents.length,\n          delegation: options.delegation || 'auto',\n        });\n\n        try {\n          const result = await this.modules.subAgent.executeWithSubAgents(\n            prompt,\n            this.config.subAgents,\n            options,\n            this.getModel() // Pass main agent's model for delegation\n          );\n          return result;\n        } catch (error) {\n          this.logger.warn('Sub-agent execution failed, falling back to main agent', {\n            error: error instanceof Error ? error.message : String(error),\n          });\n          // Fall through to regular agent execution\n        }\n      }\n    }\n    let enhancedPrompt = prompt;\n    const messages: Array<{\n      role: 'user' | 'assistant' | 'system' | 'tool';\n      content: string;\n      tool_call_id?: string;\n      tool_calls?: ToolCall[];\n    }> = [];\n\n    // Add system prompt if available\n    const systemPrompt = this.getSystemPrompt();\n    if (systemPrompt) {\n      messages.push({ role: 'system', content: systemPrompt });\n    }\n\n    // Process attachments if provided\n    if (options?.attachments && options.attachments.length > 0) {\n      const attachmentDescriptions = await Promise.all(\n        options.attachments.map(async (attachment) => {\n          if (!attachment || !attachment.path || !attachment.type) {\n            return `[Invalid attachment: missing required fields]`;\n          }\n\n          try {\n            const displayName = attachment.name || attachment.path.split('/').pop() || 'unknown';\n            let description = `${attachment.type}: ${displayName} (${attachment.path})`;\n\n            if (attachment.language) {\n              description += ` [Language: ${attachment.language}]`;\n            }\n\n            // For image files, use vision if available\n            if (attachment.type === 'image' && this.hasVision() && this.modules?.vision) {\n              try {\n                // Security: Validate image path to prevent path traversal attacks\n                if (!isPathSafe(attachment.path)) {\n                  this.logger.error('Invalid image path: path traversal detected', undefined, {\n                    imagePath: attachment.path,\n                  });\n                  throw new Error('Invalid image path: path traversal detected');\n                }\n\n                const visionModule = this.modules.vision as Vision;\n                if (visionModule && typeof visionModule.analyzeImage === 'function') {\n                  const analysis = await visionModule.analyzeImage(attachment.path, {\n                    prompt: 'Describe this image',\n                    maxTokens: 500,\n                  });\n                  description += `\\nImage content: ${analysis}`;\n                }\n              } catch (error) {\n                description += ` [Vision analysis failed: ${error instanceof Error ? error.message : 'Unknown error'}]`;\n              }\n            }\n            // For text-based files, include content preview\n            else if (['text', 'markdown', 'code', 'json'].includes(attachment.type)) {\n              try {\n                // Security: Validate path to prevent path traversal attacks\n                if (!isPathSafe(attachment.path)) {\n                  throw new Error('Invalid file path: path traversal detected');\n                }\n\n                // Fix TOCTOU vulnerability: Read file first, then check size\n                // This prevents race conditions where file changes between stat and read\n                // Use a file handle for atomic operation\n                let fileHandle: import('fs/promises').FileHandle | null = null;\n                try {\n                  fileHandle = await fs.open(attachment.path, 'r');\n                  const stats = await fileHandle.stat();\n\n                  // Security: Check file size to prevent DoS attacks\n                  if (stats.size > MAX_FILE_SIZE) {\n                    throw new Error(`File too large: ${stats.size} bytes (max: ${MAX_FILE_SIZE})`);\n                  }\n\n                  // Read content using the same file handle to prevent TOCTOU\n                  const buffer = await fileHandle.readFile({ encoding: 'utf-8' });\n                  const content = buffer.toString();\n\n                  // Double-check the actual content size (in case file grew)\n                  if (content.length > MAX_FILE_SIZE) {\n                    throw new Error(\n                      `File content too large: ${content.length} chars (max: ${MAX_FILE_SIZE})`\n                    );\n                  }\n\n                  const preview = content.length > 500 ? content.slice(0, 500) + '...' : content;\n                  description += `\\nContent:\\n${preview}`;\n                } finally {\n                  // Always close the file handle\n                  if (fileHandle) {\n                    await fileHandle.close();\n                  }\n                }\n              } catch (error) {\n                description += ` [File read error: ${error instanceof Error ? error.message : 'Unknown error'}]`;\n              }\n            }\n\n            return description;\n          } catch (error) {\n            return `[Error processing attachment ${attachment.path}: ${error instanceof Error ? error.message : 'Unknown error'}]`;\n          }\n        })\n      );\n\n      enhancedPrompt = `${prompt}\\n\\nAttached files:\\n${attachmentDescriptions.join('\\n\\n')}`;\n    }\n\n    // Add conversation context (handles memory integration internally)\n    const contextMessages = this.getContext();\n    for (const contextMsg of contextMessages) {\n      messages.push({\n        role: contextMsg.role,\n        content: contextMsg.content,\n      });\n    }\n\n    // Track added servers and plugins for cleanup on error\n    const addedMcpServers: string[] = [];\n    const addedPlugins: string[] = [];\n\n    try {\n      // Add temporary MCP servers if provided\n      if (options?.mcpServers && Array.isArray(options.mcpServers) && this.modules?.mcp) {\n        const mcpModule = this.modules.mcp as MCP;\n        if (mcpModule && typeof mcpModule.addMCPServer === 'function') {\n          for (const server of options.mcpServers) {\n            if (server && server.name) {\n              try {\n                await mcpModule.addMCPServer(server);\n                addedMcpServers.push(server.name);\n              } catch (error) {\n                this.logger.warn(\n                  `Failed to add MCP server ${server.name}:`,\n                  error instanceof Error ? error.message : String(error)\n                );\n              }\n            }\n          }\n        }\n      }\n\n      // Add temporary plugins if provided\n      if (options?.plugins && Array.isArray(options.plugins) && this.modules?.plugin) {\n        const pluginModule = this.modules.plugin as Plugin;\n        if (pluginModule && typeof pluginModule.registerPlugin === 'function') {\n          for (const pluginDef of options.plugins) {\n            if (pluginDef && pluginDef.plugin) {\n              try {\n                // Create a temporary plugin instance\n                const tempPlugin: IPlugin = {\n                  name: pluginDef.plugin.name,\n                  version: pluginDef.plugin.version,\n                  description: pluginDef.plugin.description || '',\n                  tools: (pluginDef.plugin.tools || []) as ToolDefinition[],\n                };\n\n                await pluginModule.registerPlugin(tempPlugin, {\n                  name: pluginDef.plugin.name,\n                  enabled: true,\n                  config: pluginDef.config || {},\n                });\n                addedPlugins.push(pluginDef.plugin.name);\n              } catch (error) {\n                this.logger.warn(\n                  `Failed to register temporary plugin ${pluginDef.plugin.name}:`,\n                  error instanceof Error ? error.message : String(error)\n                );\n              }\n            }\n          }\n        }\n      }\n    } catch (error) {\n      // Cleanup on error: remove any successfully added servers and plugins\n      // Log cleanup errors for debugging instead of silently ignoring\n      for (const serverName of addedMcpServers) {\n        try {\n          (this.modules.mcp as MCP)?.removeMCPServer(serverName);\n        } catch (cleanupError) {\n          this.logger.debug('Failed to cleanup MCP server on error', {\n            serverName,\n            error: cleanupError instanceof Error ? cleanupError.message : String(cleanupError),\n          });\n        }\n      }\n      for (const pluginName of addedPlugins) {\n        try {\n          await (this.modules.plugin as Plugin)?.unregisterPlugin(pluginName);\n        } catch (cleanupError) {\n          this.logger.debug('Failed to cleanup plugin on error', {\n            pluginName,\n            error: cleanupError instanceof Error ? cleanupError.message : String(cleanupError),\n          });\n        }\n      }\n      throw error;\n    }\n\n    // Add current user prompt\n    messages.push({ role: 'user', content: enhancedPrompt });\n\n    // Add user message to conversation (memory/context)\n    await this.addMemory(enhancedPrompt, { role: 'user' });\n\n    // Check if we should use tools\n    const shouldUseTools =\n      options?.useTools !== undefined\n        ? options.useTools\n        : (options?.attachments && options.attachments.length > 0) || this.canUseTools();\n\n    // Get LLM instance\n    const llm = getLLM(this.logger);\n\n    // Collect all available tools\n    const tools: Tool[] = [];\n\n    if (shouldUseTools) {\n      // Add MCP tools\n      if (this.modules.mcp) {\n        const mcpTools = this.modules.mcp.getMCPTools();\n        for (const mcpTool of mcpTools) {\n          tools.push({\n            type: 'function',\n            function: {\n              name: `mcp_${mcpTool.name}`,\n              description: mcpTool.description,\n              parameters: mcpTool.inputSchema as Tool['function']['parameters'],\n            },\n          });\n        }\n      }\n\n      // Add plugin tools\n      if (this.modules.plugin) {\n        const pluginTools = this.modules.plugin.getTools();\n        for (const pluginTool of pluginTools) {\n          tools.push({\n            type: 'function',\n            function: {\n              name: `plugin_${pluginTool.name}`,\n              description: pluginTool.description,\n              parameters: convertToolParametersToJsonSchema(pluginTool.parameters),\n            },\n          });\n        }\n      }\n\n      this.logger.info(\n        `Prepared ${tools.length} tools for LLM: ${tools.map((t) => t.function.name).join(', ')}`\n      );\n      this.logger.debug('Tools prepared for LLM', {\n        toolCount: tools.length,\n        toolNames: tools.map((t) => t.function.name),\n      });\n    }\n\n    // Prepare LLM options\n    const llmOptions: LLMRequestOptions = {\n      model: options?.model ?? this.getModel(),\n      messages,\n      temperature: options?.temperature ?? this.getTemperature(),\n      maxTokens: options?.maxTokens ?? this.getMaxTokens(),\n      stream: options?.stream,\n      tools: tools.length > 0 ? tools : undefined,\n    };\n\n    // Handle streaming vs non-streaming\n    let response: string;\n\n    if (options?.stream) {\n      // Stream response\n      let fullContent = '';\n\n      for await (const chunk of llm.generateStreamResponse(llmOptions)) {\n        fullContent += chunk.content;\n        // If there's a callback for streaming, call it\n        if (options.onChunk) {\n          options.onChunk(chunk.content);\n        } else {\n          // If no callback, just output to console\n          process.stdout.write(chunk.content);\n        }\n      }\n\n      if (!options.onChunk) {\n        process.stdout.write('\\n'); // New line after streaming\n      }\n\n      response = fullContent;\n    } else {\n      // Single LLM call with tool handling\n      const llmResponse = await llm.generateResponse(llmOptions);\n\n      // Handle tool calls if present\n      if (llmResponse.toolCalls && llmResponse.toolCalls.length > 0) {\n        this.logger.debug('Processing tool calls', {\n          toolCallCount: llmResponse.toolCalls.length,\n          toolNames: llmResponse.toolCalls.map((tc) => tc.function.name),\n        });\n\n        // Add assistant message with tool calls\n        // IMPORTANT: OpenAI requires content to be a string (can be empty string or null) when tool_calls present\n        messages.push({\n          role: 'assistant',\n          content: llmResponse.content || '',\n          tool_calls: llmResponse.toolCalls,\n        });\n\n        // Execute each tool call\n        for (const toolCall of llmResponse.toolCalls) {\n          const toolName = toolCall.function?.name;\n          if (!toolName) {\n            this.logger.warn('Skipping tool call with missing function name', {\n              toolCallId: toolCall.id,\n            });\n            continue;\n          }\n\n          try {\n            let toolResult: string;\n\n            if (toolName.startsWith('mcp_')) {\n              // Handle MCP tool call\n              const mcpToolName = toolName.substring(4); // Remove 'mcp_' prefix\n\n              // Ensure arguments are properly formatted for MCP with type-safe parsing\n              let mcpArgs: Record<string, string | number | boolean | object | null>;\n              if (typeof toolCall.function.arguments === 'string') {\n                try {\n                  const parsed: unknown = JSON.parse(toolCall.function.arguments);\n                  // Validate parsed result is an object (not null, array, or primitive)\n                  if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {\n                    throw new Error('MCP tool arguments must be a JSON object');\n                  }\n                  mcpArgs = parsed as Record<string, string | number | boolean | object | null>;\n                } catch (parseError) {\n                  const parseErr =\n                    parseError instanceof Error ? parseError : new Error(String(parseError));\n                  this.logger.error('Failed to parse MCP tool arguments', parseErr);\n                  throw new Error(`Invalid JSON in MCP tool arguments: ${parseErr.message}`);\n                }\n              } else if (\n                toolCall.function.arguments &&\n                typeof toolCall.function.arguments === 'object'\n              ) {\n                mcpArgs = toolCall.function.arguments as Record<\n                  string,\n                  string | number | boolean | object | null\n                >;\n              } else {\n                // Default to empty object if no arguments provided\n                mcpArgs = {};\n              }\n\n              if (this.modules.mcp) {\n                const mcpResult = await this.modules.mcp.callMCPTool(\n                  mcpToolName,\n                  mcpArgs as Record<string, import('../mcp/types').MCPValue>\n                );\n                toolResult = mcpResult.content.map((c) => c.text || '').join('\\n');\n              } else {\n                toolResult = 'MCP module not available';\n              }\n            } else if (toolName.startsWith('plugin_')) {\n              // Handle plugin tool call\n              const pluginToolName = toolName.substring(7); // Remove 'plugin_' prefix\n\n              // Ensure arguments are properly formatted for plugin tools with type-safe parsing\n              let pluginArgs: Record<string, string | number | boolean | object | null>;\n              if (typeof toolCall.function.arguments === 'string') {\n                try {\n                  const parsed: unknown = JSON.parse(toolCall.function.arguments);\n                  // Validate parsed result is an object (not null, array, or primitive)\n                  if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {\n                    throw new Error('Plugin tool arguments must be a JSON object');\n                  }\n                  pluginArgs = parsed as Record<string, string | number | boolean | object | null>;\n                } catch (parseError) {\n                  const parseErr =\n                    parseError instanceof Error ? parseError : new Error(String(parseError));\n                  this.logger.error('Failed to parse plugin tool arguments', parseErr);\n                  throw new Error(`Invalid JSON in plugin tool arguments: ${parseErr.message}`);\n                }\n              } else if (\n                toolCall.function.arguments &&\n                typeof toolCall.function.arguments === 'object'\n              ) {\n                pluginArgs = toolCall.function.arguments as Record<\n                  string,\n                  string | number | boolean | object | null\n                >;\n              } else {\n                // Default to empty object if no arguments provided\n                pluginArgs = {};\n              }\n\n              if (this.modules.plugin) {\n                const pluginResult = await this.modules.plugin.executeTool(\n                  {\n                    id: toolCall.id,\n                    name: pluginToolName,\n                    parameters: pluginArgs as Record<string, ToolParameterValue>,\n                  },\n                  { agentId: this.id, agent: this }\n                );\n\n                // Log metadata if present (for debugging and observability)\n                if (pluginResult.result.metadata) {\n                  this.logger.debug('Plugin tool returned metadata', {\n                    toolName: pluginToolName,\n                    toolCallId: toolCall.id,\n                    metadata: pluginResult.result.metadata,\n                  });\n                }\n\n                // Build tool result with optional metadata inclusion\n                if (pluginResult.result.success) {\n                  const resultData =\n                    typeof pluginResult.result.data === 'string'\n                      ? pluginResult.result.data\n                      : JSON.stringify(pluginResult.result.data);\n\n                  // Include metadata in response if present (allows LLM to see relevant context)\n                  if (\n                    pluginResult.result.metadata &&\n                    Object.keys(pluginResult.result.metadata).length > 0\n                  ) {\n                    toolResult = JSON.stringify({\n                      result: resultData,\n                      metadata: pluginResult.result.metadata,\n                    });\n                  } else {\n                    toolResult = resultData;\n                  }\n                } else {\n                  toolResult = `Error: ${pluginResult.result.error || 'Unknown error'}`;\n                }\n              } else {\n                toolResult = `Plugin module not available`;\n              }\n            } else {\n              // Handle other tool types (future implementations)\n              toolResult = `Tool ${toolName} not implemented yet`;\n            }\n\n            // CRITICAL: Tool result content cannot be empty for OpenAI API\n            if (!toolResult || toolResult.trim() === '') {\n              this.logger.warn('Empty tool result detected', {\n                toolName,\n                toolCallId: toolCall.id,\n                resultType: typeof toolResult,\n                resultValue: toolResult,\n              });\n              toolResult = 'Tool execution completed but returned no data.';\n            }\n\n            this.logger.debug('Tool result received', {\n              toolName,\n              toolCallId: toolCall.id,\n              resultLength: toolResult.length,\n              resultPreview: toolResult.slice(0, 200),\n            });\n\n            // Add tool result to messages\n            messages.push({\n              role: 'tool',\n              content: toolResult,\n              tool_call_id: toolCall.id,\n            });\n\n            this.logger.debug('Tool call executed', {\n              toolName,\n              toolCallId: toolCall.id,\n              resultLength: toolResult.length,\n            });\n          } catch (error) {\n            // Normalize tool error using ToolError class\n            const originalError = error instanceof Error ? error : new Error(String(error));\n            const toolType = toolName.startsWith('mcp_')\n              ? 'mcp'\n              : toolName.startsWith('plugin_')\n                ? 'plugin'\n                : 'unknown';\n            const actualToolName =\n              toolType === 'mcp'\n                ? toolName.substring(4)\n                : toolType === 'plugin'\n                  ? toolName.substring(7)\n                  : toolName;\n\n            // Determine error type based on error message\n            let errorType: 'not_found' | 'validation' | 'execution' | 'timeout' | 'unknown' =\n              'execution';\n            if (\n              originalError.message.includes('not found') ||\n              originalError.message.includes('not available')\n            ) {\n              errorType = 'not_found';\n            } else if (\n              originalError.message.includes('Invalid') ||\n              originalError.message.includes('validation')\n            ) {\n              errorType = 'validation';\n            } else if (\n              originalError.message.includes('timeout') ||\n              originalError.message.includes('timed out')\n            ) {\n              errorType = 'timeout';\n            }\n\n            // Determine if error is recoverable (LLM can try alternative approach)\n            const recoverable = errorType !== 'not_found';\n\n            const toolError = new ToolError(\n              `Tool '${actualToolName}' (${toolType}) failed: ${originalError.message}`,\n              actualToolName,\n              toolType,\n              errorType,\n              recoverable,\n              originalError\n            );\n\n            this.logger.error(`Tool call failed: ${toolName}`, toolError, {\n              toolType,\n              errorType,\n              recoverable,\n              toolCallId: toolCall.id,\n            });\n\n            // Add normalized error result to messages (LLM can use this to decide next action)\n            const errorResult = toolError.toToolResult();\n            messages.push({\n              role: 'tool',\n              content: JSON.stringify(errorResult),\n              tool_call_id: toolCall.id,\n            });\n          }\n        }\n\n        // Get final response from LLM with tool results\n        const toolMessages = messages.filter((m) => m.role === 'tool');\n        if (toolMessages.length > 0) {\n          const lastToolContent = toolMessages[toolMessages.length - 1]?.content || '';\n          this.logger.info(\n            `Sending tool results to LLM (${lastToolContent.length} chars, ${toolMessages.length} tool results)`\n          );\n          this.logger.debug('Tool result content preview', {\n            preview: lastToolContent.slice(0, 500),\n            totalLength: lastToolContent.length,\n            toolCount: toolMessages.length,\n          });\n        }\n        // Log full message structure for debugging OpenAI 400 errors\n        const messageStructure = messages.map((m) => ({\n          role: m.role,\n          contentPreview: typeof m.content === 'string' ? m.content.slice(0, 100) : 'non-string',\n          contentLength: typeof m.content === 'string' ? m.content.length : 0,\n          hasToolCalls: 'tool_calls' in m,\n          toolCallId: 'tool_call_id' in m ? m.tool_call_id : undefined,\n          toolCallsCount:\n            'tool_calls' in m && Array.isArray(m.tool_calls) ? m.tool_calls.length : 0,\n        }));\n\n        this.logger.debug('Sending tool results to LLM for final response', {\n          messageCount: messages.length,\n          toolMessageCount: toolMessages.length,\n          lastToolContentLength: toolMessages[toolMessages.length - 1]?.content.length || 0,\n          lastToolPreview: toolMessages[toolMessages.length - 1]?.content.slice(0, 100) || '',\n          messageStructure: JSON.stringify(messageStructure, null, 2),\n        });\n\n        const finalLlmOptions: LLMRequestOptions = {\n          ...llmOptions,\n          messages,\n          tools: undefined, // Don't include tools in follow-up call\n        };\n\n        try {\n          const finalResponse = await llm.generateResponse(finalLlmOptions);\n          response = finalResponse.content;\n\n          this.logger.debug('Final response generated after tool calls', {\n            responseLength: response.length,\n          });\n        } catch (finalResponseError) {\n          // Log the detailed error but return a friendly message to the user\n          this.logger.error(\n            'Failed to generate final response after tool execution',\n            finalResponseError instanceof Error\n              ? finalResponseError\n              : new Error(String(finalResponseError))\n          );\n          this.logger.debug('Tool execution was successful, but LLM response failed', {\n            errorMessage:\n              finalResponseError instanceof Error\n                ? finalResponseError.message\n                : String(finalResponseError),\n            toolResultsCount: toolMessages.length,\n            messageCount: messages.length,\n          });\n\n          // Create a user-friendly response based on tool results\n          const toolResultsSummary = toolMessages\n            .map((m, i) => {\n              try {\n                const result = JSON.parse(m.content);\n                if (result.success === true) {\n                  return `✓ Tool ${i + 1} completed successfully`;\n                }\n              } catch {\n                // Not JSON, treat as plain text\n              }\n              return null;\n            })\n            .filter(Boolean)\n            .join('\\n');\n\n          response = toolResultsSummary\n            ? `I've completed the requested operations:\\n\\n${toolResultsSummary}\\n\\nHowever, I encountered a temporary issue generating a detailed response. The operations were successful though!`\n            : `I've processed your request and the operations completed successfully. However, I encountered a temporary issue generating a detailed response. Please try asking me to explain the results.`;\n        }\n      } else {\n        response = llmResponse.content;\n      }\n    }\n\n    // Add response to conversation (memory/context)\n    await this.addMemory(response, { role: 'assistant' });\n\n    // Save context to memory if enabled - propagate errors for visibility\n    try {\n      await this.saveContextToMemory();\n    } catch (saveError) {\n      // Log but don't throw - response is already generated, we don't want to lose it\n      this.logger.error(\n        'Failed to save context to memory',\n        saveError instanceof Error ? saveError : new Error(String(saveError)),\n        {\n          responseLength: response.length,\n        }\n      );\n    }\n\n    // Clean up temporary MCP servers and plugins in finally-like block\n    // This ensures cleanup happens even if saveContextToMemory fails\n    const cleanupMcpServers = async () => {\n      if (options?.mcpServers && this.modules.mcp) {\n        for (const server of options.mcpServers) {\n          try {\n            (this.modules.mcp as MCP).removeMCPServer(server.name);\n          } catch (error) {\n            this.logger.warn('Failed to remove temporary MCP server', {\n              serverName: server.name,\n              error: error instanceof Error ? error.message : String(error),\n            });\n          }\n        }\n      }\n    };\n\n    const cleanupPlugins = async () => {\n      if (options?.plugins && Array.isArray(options.plugins) && this.modules?.plugin) {\n        for (const pluginDef of options.plugins) {\n          if (pluginDef && pluginDef.plugin) {\n            try {\n              await (this.modules.plugin as Plugin).unregisterPlugin(pluginDef.plugin.name);\n            } catch (error) {\n              this.logger.warn('Failed to unregister temporary plugin', {\n                pluginName: pluginDef.plugin.name,\n                error: error instanceof Error ? error.message : String(error),\n              });\n            }\n          }\n        }\n      }\n    };\n\n    // Execute cleanup - errors are logged but don't prevent response return\n    await Promise.all([cleanupMcpServers(), cleanupPlugins()]);\n\n    return response;\n  }\n\n  /**\n   * Update agent configuration\n   * Ensures module state consistency even if initialization or cleanup fails\n   */\n  async update(updates: Partial<AgentConfig>): Promise<void> {\n    const wasMemoryEnabled = this.hasMemory();\n    const wasKnowledgeEnabled = this.hasKnowledge();\n    const wasVisionEnabled = this.hasVision();\n    const wasToolsEnabled = this.canUseTools();\n\n    await super.update(updates);\n\n    const moduleErrors: Array<{ module: string; operation: string; error: string }> = [];\n\n    // Handle module changes - properly cleanup before disabling\n    // Memory module\n    if (this.hasMemory() && !wasMemoryEnabled) {\n      const newMemory = new Memory(this);\n      try {\n        await newMemory.initialize();\n        this.modules.memory = newMemory;\n      } catch (error) {\n        moduleErrors.push({\n          module: 'memory',\n          operation: 'initialize',\n          error: error instanceof Error ? error.message : String(error),\n        });\n        // Don't assign the failed module\n      }\n    } else if (!this.hasMemory() && wasMemoryEnabled && this.modules.memory) {\n      // Memory module cleanup - call destroy() for proper cleanup\n      this.logger.debug('Cleaning up Memory module on disable');\n      try {\n        this.modules.memory.destroy();\n      } catch (error) {\n        moduleErrors.push({\n          module: 'memory',\n          operation: 'cleanup',\n          error: error instanceof Error ? error.message : String(error),\n        });\n      }\n      // Always delete reference even if cleanup fails\n      delete this.modules.memory;\n    }\n\n    // Knowledge module\n    if (this.hasKnowledge() && !wasKnowledgeEnabled) {\n      const newKnowledge = new Knowledge(this);\n      try {\n        await newKnowledge.initialize();\n        this.modules.knowledge = newKnowledge;\n      } catch (error) {\n        moduleErrors.push({\n          module: 'knowledge',\n          operation: 'initialize',\n          error: error instanceof Error ? error.message : String(error),\n        });\n      }\n    } else if (!this.hasKnowledge() && wasKnowledgeEnabled && this.modules.knowledge) {\n      // Knowledge module cleanup - clear internal references before deleting\n      this.logger.debug('Cleaning up Knowledge module on disable');\n      try {\n        const knowledgeModule = this.modules.knowledge as Knowledge & {\n          knex?: unknown;\n          vectorStore?: unknown;\n        };\n        knowledgeModule.knex = null;\n        knowledgeModule.vectorStore = null;\n      } catch (error) {\n        moduleErrors.push({\n          module: 'knowledge',\n          operation: 'cleanup',\n          error: error instanceof Error ? error.message : String(error),\n        });\n      }\n      delete this.modules.knowledge;\n    }\n\n    // Vision module\n    if (this.hasVision() && !wasVisionEnabled) {\n      const newVision = new Vision(this);\n      try {\n        await newVision.initialize();\n        this.modules.vision = newVision;\n      } catch (error) {\n        moduleErrors.push({\n          module: 'vision',\n          operation: 'initialize',\n          error: error instanceof Error ? error.message : String(error),\n        });\n      }\n    } else if (!this.hasVision() && wasVisionEnabled && this.modules.vision) {\n      // Vision module cleanup - call cleanupVision to remove from instance cache\n      this.logger.debug('Cleaning up Vision module on disable');\n      try {\n        cleanupVision(this.data.id);\n      } catch (error) {\n        moduleErrors.push({\n          module: 'vision',\n          operation: 'cleanup',\n          error: error instanceof Error ? error.message : String(error),\n        });\n      }\n      delete this.modules.vision;\n    }\n\n    // Handle useTools toggle - properly cleanup MCP and Plugin modules\n    const nowToolsEnabled =\n      updates.useTools !== undefined ? updates.useTools !== false : wasToolsEnabled;\n    if (!nowToolsEnabled && wasToolsEnabled) {\n      // Tools disabled - cleanup MCP and Plugin modules\n      this.logger.debug('Cleaning up tool modules on disable');\n\n      if (this.modules.mcp) {\n        try {\n          await this.modules.mcp.cleanup();\n        } catch (error) {\n          moduleErrors.push({\n            module: 'mcp',\n            operation: 'cleanup',\n            error: error instanceof Error ? error.message : String(error),\n          });\n        }\n        delete this.modules.mcp;\n      }\n\n      if (this.modules.plugin) {\n        try {\n          if (this.data.id) {\n            await cleanupPlugin(this.data.id);\n          }\n        } catch (error) {\n          moduleErrors.push({\n            module: 'plugin',\n            operation: 'cleanup',\n            error: error instanceof Error ? error.message : String(error),\n          });\n        }\n        delete this.modules.plugin;\n      }\n    } else if (nowToolsEnabled && !wasToolsEnabled) {\n      // Tools enabled - initialize MCP and Plugin modules\n      // Initialize plugin first, then MCP - maintain order for proper dependency\n      const newPlugin = new Plugin(this);\n      const newMcp = new MCP(this);\n\n      try {\n        await newPlugin.initialize();\n        this.modules.plugin = newPlugin;\n      } catch (error) {\n        moduleErrors.push({\n          module: 'plugin',\n          operation: 'initialize',\n          error: error instanceof Error ? error.message : String(error),\n        });\n      }\n\n      try {\n        await newMcp.initialize();\n        this.modules.mcp = newMcp;\n      } catch (error) {\n        moduleErrors.push({\n          module: 'mcp',\n          operation: 'initialize',\n          error: error instanceof Error ? error.message : String(error),\n        });\n      }\n    }\n\n    // Log any module errors\n    if (moduleErrors.length > 0) {\n      this.logger.warn('Agent update completed with module errors', {\n        errorCount: moduleErrors.length,\n        moduleErrorDetails: JSON.stringify(moduleErrors),\n      });\n    }\n\n    // Module methods are directly implemented and don't need re-binding\n  }\n}\n\nexport type { AgentConfig } from './types';\nexport default Agent;\n","import { Knex } from 'knex';\nimport crypto from 'crypto';\nimport { getDatabase, Database } from '../database/index';\nimport { Graph, GraphNode, GraphEdge } from './types';\nimport { encryptSensitiveFields, decryptSensitiveFields } from '../database/utils';\nimport { Logger } from '../logger/types';\nimport { getLogger } from '../logger';\nimport { MetadataObject } from '../types';\n\nexport class GraphStorage {\n  private knex: Knex | null = null;\n  private db: Database | null = null;\n  private logger: Logger;\n  private initialized: boolean = false;\n\n  constructor() {\n    // Note: knex and db will be initialized in initialize() method\n    this.logger = getLogger();\n  }\n\n  /**\n   * Ensure database is initialized and return knex instance\n   * @throws Error if database is not initialized\n   */\n  private getKnex(): Knex {\n    if (!this.knex) {\n      throw new Error('Database not initialized. Call initialize() first.');\n    }\n    return this.knex;\n  }\n\n  /**\n   * Ensure database is initialized and return db instance\n   * @throws Error if database is not initialized\n   */\n  private getDb(): Database {\n    if (!this.db) {\n      throw new Error('Database not initialized. Call initialize() first.');\n    }\n    return this.db;\n  }\n\n  private async initialize(): Promise<void> {\n    if (this.initialized) return;\n    this.db = await getDatabase();\n    this.knex = this.db.getKnex();\n    await this.createTables();\n    this.initialized = true;\n  }\n\n  async initializeTables(): Promise<void> {\n    await this.initialize();\n  }\n\n  private async createTables(): Promise<void> {\n    const knex = this.getKnex();\n    const db = this.getDb();\n\n    // Enable UUID extension for PostgreSQL\n    if (db.isPostgres()) {\n      await knex.raw('CREATE EXTENSION IF NOT EXISTS \"uuid-ossp\"');\n    }\n\n    // Create graphs table\n    const hasGraphsTable = await knex.schema.hasTable('graphs');\n    if (!hasGraphsTable) {\n      await knex.schema.createTable('graphs', (table) => {\n        table.string('id', 36).primary(); // UUID generated in application layer\n        table.string('name').notNullable();\n        table.text('description').nullable();\n        table.string('defaultAgentId', 36).nullable();\n        table.integer('maxConcurrency').defaultTo(1);\n        table.integer('timeout').nullable();\n        table.integer('retryAttempts').defaultTo(0);\n        table.boolean('autoLink').defaultTo(false);\n        table.json('metadata').nullable();\n        table.enu('status', ['idle', 'running', 'completed', 'failed', 'paused']).defaultTo('idle');\n        table.timestamp('startedAt').nullable();\n        table.timestamp('completedAt').nullable();\n        table.timestamps(true, true);\n        table.index(['defaultAgentId']);\n        table.index(['status']);\n      });\n    }\n\n    // Create graph_nodes table\n    const hasNodesTable = await knex.schema.hasTable('graph_nodes');\n    if (!hasNodesTable) {\n      await knex.schema.createTable('graph_nodes', (table) => {\n        table.string('id', 36).primary(); // UUID generated in application layer\n        table\n          .string('graphId', 36)\n          .notNullable()\n          .references('id')\n          .inTable('graphs')\n          .onDelete('CASCADE');\n        table.string('nodeId').notNullable(); // Internal node ID string (e.g., \"node_1_abc\")\n        table.enu('type', ['agent', 'task']).notNullable();\n        table.string('name').notNullable();\n        table.text('description').nullable();\n        table.string('agentId', 36).nullable();\n        table.text('prompt').nullable();\n        table.string('model').nullable();\n        table.boolean('stream').defaultTo(false);\n        table.string('taskId', 36).nullable(); // Task ID created during execution\n        table\n          .enu('status', ['pending', 'running', 'completed', 'failed', 'skipped', 'scheduled'])\n          .defaultTo('pending');\n        table.integer('priority').defaultTo(0);\n        table.json('dependencies').nullable();\n        table.text('result').nullable(); // TEXT - stores encrypted string\n        table.text('error').nullable();\n        table.json('metadata').nullable(); // JSONB - stores actual JSON data\n        table.timestamps(true, true);\n        table.index(['graphId']);\n        table.index(['nodeId']);\n        table.index(['taskId']);\n        table.index(['type']);\n        table.index(['status']);\n        table.index(['graphId', 'status']); // Composite index for graph execution tracking\n        table.index(['graphId', 'priority']); // Composite index for priority queue\n      });\n    } else {\n      // Check and add task relationship column\n      const hasTaskId = await knex.schema.hasColumn('graph_nodes', 'taskId');\n\n      if (!hasTaskId) {\n        await knex.schema.alterTable('graph_nodes', (table) => {\n          table.string('taskId', 36).nullable();\n        });\n\n        // Add indexes\n        await knex.schema.alterTable('graph_nodes', (table) => {\n          table.index('taskId');\n          table.index(['graphId', 'status']); // Composite index for graph execution tracking\n          table.index(['graphId', 'priority']); // Composite index for priority queue\n        });\n      }\n\n      // Fix result column type (from JSONB to TEXT for encrypted data)\n      // Only run this migration for PostgreSQL - SQLite doesn't have JSONB type\n      if (db.isPostgres()) {\n        await knex.raw(`\n          DO $$\n          BEGIN\n            IF EXISTS (\n              SELECT 1 FROM information_schema.columns\n              WHERE table_name = 'graph_nodes'\n              AND column_name = 'result'\n              AND data_type = 'jsonb'\n            ) THEN\n              ALTER TABLE graph_nodes ALTER COLUMN result TYPE TEXT USING result::TEXT;\n            END IF;\n          END $$;\n        `);\n      }\n    }\n\n    // Create graph_edges table\n    const hasEdgesTable = await knex.schema.hasTable('graph_edges');\n    if (!hasEdgesTable) {\n      await knex.schema.createTable('graph_edges', (table) => {\n        table.string('id', 36).primary(); // UUID generated in application layer\n        table\n          .string('graphId', 36)\n          .notNullable()\n          .references('id')\n          .inTable('graphs')\n          .onDelete('CASCADE');\n        table.string('edgeId').notNullable(); // Internal edge ID string (e.g., \"edge_1_abc\")\n        table.string('fromNodeId').notNullable(); // Internal node ID\n        table.string('toNodeId').notNullable(); // Internal node ID\n        table.string('condition').nullable();\n        table.json('metadata').nullable();\n        table.timestamps(true, true);\n        table.index(['graphId']);\n        table.index(['edgeId']);\n      });\n    }\n  }\n\n  async saveGraph(graph: Graph): Promise<string> {\n    await this.initialize();\n    const knex = this.getKnex();\n\n    const graphId = crypto.randomUUID();\n\n    // Use transaction to ensure atomicity - all or nothing\n    await knex.transaction(async (trx) => {\n      // Prepare and encrypt graph data\n      const graphData = {\n        id: graphId,\n        name: graph.config.name,\n        description: graph.config.description,\n        defaultAgentId: graph.defaultAgentId || null, // Save default agent ID\n        maxConcurrency: graph.config.maxConcurrency,\n        timeout: graph.config.timeout,\n        retryAttempts: graph.config.retryAttempts,\n        autoLink: graph.config.autoLink || false,\n        metadata: graph.config.metadata ? JSON.stringify(graph.config.metadata) : null,\n        status: graph.status,\n        startedAt: graph.startedAt,\n        completedAt: graph.completedAt,\n      };\n\n      const encryptedGraphData = await encryptSensitiveFields(\n        graphData as Record<string, string | number | boolean | null | undefined | Date>,\n        'graphs'\n      );\n\n      // Insert graph\n      await trx('graphs').insert(encryptedGraphData);\n\n      // Prepare and encrypt all nodes\n      if (graph.nodes.length > 0) {\n        const nodeDataList = await Promise.all(\n          graph.nodes.map(async (node) => {\n            const nodeData = {\n              id: crypto.randomUUID(),\n              graphId,\n              nodeId: node.id,\n              type: node.type,\n              name: node.name,\n              description: node.description,\n              agentId: node.agentId,\n              prompt: node.prompt,\n              model: node.model,\n              stream: node.stream,\n              taskId: node.taskId, // Task ID created during execution\n              status: node.status,\n              priority: node.priority,\n              dependencies: JSON.stringify(node.dependencies),\n              result: node.result || null, // TEXT field - store as-is, no JSON.stringify\n              error: node.error,\n              metadata: node.metadata ? JSON.stringify(node.metadata) : null,\n            };\n\n            return encryptSensitiveFields(\n              nodeData as Record<string, string | number | boolean | null | undefined | Date>,\n              'graph_nodes'\n            );\n          })\n        );\n\n        // Batch insert all nodes\n        await trx('graph_nodes').insert(nodeDataList);\n      }\n\n      // Prepare and encrypt all edges\n      if (graph.edges.length > 0) {\n        const edgeDataList = await Promise.all(\n          graph.edges.map(async (edge) => {\n            const edgeData = {\n              id: crypto.randomUUID(),\n              graphId,\n              edgeId: edge.id,\n              fromNodeId: edge.fromNodeId,\n              toNodeId: edge.toNodeId,\n              condition: edge.condition,\n              metadata: edge.metadata ? JSON.stringify(edge.metadata) : null,\n            };\n\n            return encryptSensitiveFields(\n              edgeData as Record<string, string | number | boolean | null | undefined | Date>,\n              'graph_edges'\n            );\n          })\n        );\n\n        // Batch insert all edges\n        await trx('graph_edges').insert(edgeDataList);\n      }\n    });\n\n    return graphId;\n  }\n\n  async loadGraph(graphId: string): Promise<Graph | null> {\n    await this.initialize();\n    const knex = this.getKnex();\n\n    // Load graph config\n    const graphData = await knex('graphs').where({ id: graphId }).first();\n\n    if (!graphData) {\n      return null;\n    }\n\n    // Decrypt graph data\n    const decryptedGraphData = await decryptSensitiveFields(graphData, 'graphs');\n\n    // Load nodes\n    const nodesData = await knex('graph_nodes').where({ graphId }).orderBy('id');\n\n    // Load edges\n    const edgesData = await knex('graph_edges').where({ graphId }).orderBy('id');\n\n    // Decrypt and map nodes\n    const nodes: GraphNode[] = await Promise.all(\n      nodesData.map(async (node) => {\n        const decryptedNode = await decryptSensitiveFields(node, 'graph_nodes');\n        return {\n          id: decryptedNode.nodeId as string,\n          type: decryptedNode.type as 'agent' | 'task',\n          name: decryptedNode.name as string,\n          description: decryptedNode.description as string | undefined,\n          agentId: decryptedNode.agentId as string | undefined,\n          prompt: decryptedNode.prompt as string | undefined,\n          model: decryptedNode.model as string | undefined,\n          stream: decryptedNode.stream as boolean | undefined,\n          taskId: decryptedNode.taskId as string | undefined, // Task ID from execution\n          status: decryptedNode.status as GraphNode['status'],\n          priority: decryptedNode.priority as number,\n          dependencies: (() => {\n            if (!decryptedNode.dependencies) return [];\n            // If already parsed by DB driver (PostgreSQL/Knex behavior)\n            if (typeof decryptedNode.dependencies === 'object') {\n              return decryptedNode.dependencies;\n            }\n            // If string, parse it\n            if (\n              typeof decryptedNode.dependencies === 'string' &&\n              decryptedNode.dependencies !== ''\n            ) {\n              return JSON.parse(decryptedNode.dependencies);\n            }\n            return [];\n          })(),\n          result: decryptedNode.result as string | undefined, // TEXT field - no JSON parse needed\n          error: decryptedNode.error as string | undefined,\n          metadata: (decryptedNode.metadata as unknown as MetadataObject) || undefined, // Already parsed by decryptSensitiveFields\n          createdAt: new Date(node.created_at),\n          updatedAt: new Date(node.updated_at),\n        };\n      })\n    );\n\n    // Decrypt and map edges\n    const edges: GraphEdge[] = await Promise.all(\n      edgesData.map(async (edge) => {\n        const decryptedEdge = await decryptSensitiveFields(edge, 'graph_edges');\n        return {\n          id: decryptedEdge.edgeId as string,\n          fromNodeId: decryptedEdge.fromNodeId as string,\n          toNodeId: decryptedEdge.toNodeId as string,\n          condition: decryptedEdge.condition as string | undefined,\n          metadata: (decryptedEdge.metadata as unknown as MetadataObject) || undefined, // Already parsed by decryptSensitiveFields\n          createdAt: new Date(),\n          updatedAt: new Date(),\n        };\n      })\n    );\n\n    const graph: Graph = {\n      id: graphId,\n      defaultAgentId: decryptedGraphData.defaultAgentId as string | undefined, // Load default agent ID\n      config: {\n        id: graphId,\n        name: decryptedGraphData.name as string,\n        description: decryptedGraphData.description as string | undefined,\n        maxConcurrency: decryptedGraphData.maxConcurrency as number | undefined,\n        timeout: decryptedGraphData.timeout as number | undefined,\n        retryAttempts: decryptedGraphData.retryAttempts as number | undefined,\n        autoLink: decryptedGraphData.autoLink as boolean | undefined,\n        metadata: (decryptedGraphData.metadata as unknown as MetadataObject) || undefined, // Already parsed by decryptSensitiveFields\n      },\n      nodes,\n      edges,\n      status: decryptedGraphData.status as Graph['status'],\n      startedAt: decryptedGraphData.startedAt\n        ? new Date(decryptedGraphData.startedAt as string)\n        : undefined,\n      completedAt: decryptedGraphData.completedAt\n        ? new Date(decryptedGraphData.completedAt as string)\n        : undefined,\n      executionLog: [], // Execution log is runtime only\n      createdAt: new Date(graphData.created_at),\n      updatedAt: new Date(graphData.updated_at),\n    };\n\n    return graph;\n  }\n\n  async updateGraph(graphId: string, graph: Graph): Promise<void> {\n    await this.initialize();\n    const knex = this.getKnex();\n\n    this.logger.debug(\n      `Updating graph ${graphId} with ${graph.nodes.length} nodes and ${graph.edges.length} edges`\n    );\n\n    // Use transaction for atomicity and batch queries to prevent N+1\n    await knex.transaction(async (trx) => {\n      // Prepare and encrypt graph update data\n      const graphUpdateData = {\n        status: graph.status,\n        startedAt: graph.startedAt,\n        completedAt: graph.completedAt,\n      };\n\n      const encryptedGraphUpdate = await encryptSensitiveFields(\n        graphUpdateData as Record<string, string | number | boolean | null | undefined | Date>,\n        'graphs'\n      );\n      await trx('graphs').where({ id: graphId }).update(encryptedGraphUpdate);\n\n      // Batch query: Get all existing nodes in one query (prevents N+1)\n      const existingNodes = await trx('graph_nodes')\n        .where({ graphId })\n        .whereIn(\n          'nodeId',\n          graph.nodes.map((n) => n.id)\n        )\n        .select('nodeId');\n\n      const existingNodeIds = new Set(existingNodes.map((n) => n.nodeId));\n\n      // Separate nodes into update and insert batches\n      const nodesToUpdate = graph.nodes.filter((n) => existingNodeIds.has(n.id));\n      const nodesToInsert = graph.nodes.filter((n) => !existingNodeIds.has(n.id));\n\n      // Batch update existing nodes\n      for (const node of nodesToUpdate) {\n        const nodeUpdateData = {\n          status: node.status,\n          taskId: node.taskId,\n          result: node.result || null,\n          error: node.error,\n        };\n\n        const encryptedNodeUpdate = await encryptSensitiveFields(\n          nodeUpdateData as Record<string, string | number | boolean | null | undefined | Date>,\n          'graph_nodes'\n        );\n        await trx('graph_nodes').where({ graphId, nodeId: node.id }).update(encryptedNodeUpdate);\n      }\n\n      // Batch insert new nodes\n      if (nodesToInsert.length > 0) {\n        this.logger.debug(\n          `Batch inserting ${nodesToInsert.length} new nodes into graph ${graphId}`\n        );\n        const nodeDataList = await Promise.all(\n          nodesToInsert.map(async (node) => {\n            const nodeData = {\n              id: crypto.randomUUID(),\n              graphId,\n              nodeId: node.id,\n              type: node.type,\n              name: node.name,\n              description: node.description,\n              agentId: node.agentId,\n              prompt: node.prompt,\n              model: node.model,\n              stream: node.stream,\n              taskId: node.taskId,\n              status: node.status,\n              priority: node.priority,\n              dependencies: JSON.stringify(node.dependencies),\n              result: node.result || null,\n              error: node.error,\n              metadata: node.metadata ? JSON.stringify(node.metadata) : null,\n            };\n\n            return encryptSensitiveFields(\n              nodeData as Record<string, string | number | boolean | null | undefined | Date>,\n              'graph_nodes'\n            );\n          })\n        );\n\n        await trx('graph_nodes').insert(nodeDataList);\n      }\n\n      // Batch query: Get all existing edges in one query (prevents N+1)\n      const existingEdges = await trx('graph_edges')\n        .where({ graphId })\n        .whereIn(\n          'edgeId',\n          graph.edges.map((e) => e.id)\n        )\n        .select('edgeId');\n\n      const existingEdgeIds = new Set(existingEdges.map((e) => e.edgeId));\n\n      // Filter edges to insert (only new ones)\n      const edgesToInsert = graph.edges.filter((e) => !existingEdgeIds.has(e.id));\n\n      // Batch insert new edges\n      if (edgesToInsert.length > 0) {\n        this.logger.debug(\n          `Batch inserting ${edgesToInsert.length} new edges into graph ${graphId}`\n        );\n        const edgeDataList = await Promise.all(\n          edgesToInsert.map(async (edge) => {\n            const edgeData = {\n              id: crypto.randomUUID(),\n              graphId,\n              edgeId: edge.id,\n              fromNodeId: edge.fromNodeId,\n              toNodeId: edge.toNodeId,\n              condition: edge.condition,\n              metadata: edge.metadata ? JSON.stringify(edge.metadata) : null,\n            };\n\n            return encryptSensitiveFields(\n              edgeData as Record<string, string | number | boolean | null | undefined | Date>,\n              'graph_edges'\n            );\n          })\n        );\n\n        await trx('graph_edges').insert(edgeDataList);\n      }\n    });\n\n    this.logger.debug(`Graph ${graphId} update completed`);\n  }\n\n  async deleteGraph(graphId: string): Promise<boolean> {\n    await this.initialize();\n    const knex = this.getKnex();\n\n    const deleted = await knex('graphs').where({ id: graphId }).delete();\n\n    return deleted > 0;\n  }\n\n  async listGraphs(): Promise<{ id: string; name: string; status: string; createdAt: Date }[]> {\n    await this.initialize();\n    const knex = this.getKnex();\n\n    const graphs = await knex('graphs')\n      .select('id', 'name', 'status', 'created_at')\n      .orderBy('created_at', 'desc');\n\n    return graphs.map((g) => ({\n      id: g.id,\n      name: g.name,\n      status: g.status,\n      createdAt: new Date(g.created_at),\n    }));\n  }\n}\n\n// Singleton pattern with proper async mutex for race condition prevention\n\n/**\n * Simple async mutex for protecting initialization.\n * Replaces spin-wait anti-pattern with proper promise-based waiting.\n */\nclass AsyncMutex {\n  private locked = false;\n  private queue: Array<() => void> = [];\n\n  async acquire(): Promise<void> {\n    if (!this.locked) {\n      this.locked = true;\n      return;\n    }\n    return new Promise<void>((resolve) => {\n      this.queue.push(resolve);\n    });\n  }\n\n  release(): void {\n    const next = this.queue.shift();\n    if (next) {\n      next();\n    } else {\n      this.locked = false;\n    }\n  }\n}\n\nlet storage: GraphStorage | null = null;\nlet initPromise: Promise<GraphStorage> | null = null;\nconst initMutex = new AsyncMutex();\n\nexport function getGraphStorage(): GraphStorage {\n  if (!storage) {\n    storage = new GraphStorage();\n  }\n  return storage;\n}\n\n/**\n * Get or create singleton GraphStorage instance with proper initialization\n * This prevents race conditions when multiple callers request the instance simultaneously\n */\nexport async function getGraphStorageAsync(): Promise<GraphStorage> {\n  // Fast path: already initialized\n  if (storage) return storage;\n\n  // If already initializing, wait for the promise\n  // Keep reference to avoid race condition where initPromise becomes null\n  const existingPromise = initPromise;\n  if (existingPromise) {\n    return existingPromise;\n  }\n\n  // Use proper async mutex instead of spin-wait\n  await initMutex.acquire();\n  try {\n    // Double-check after acquiring lock\n    if (storage) return storage;\n\n    // Check again if initialization started while waiting for lock\n    const currentPromise = initPromise;\n    if (currentPromise) {\n      // Release mutex early since we'll wait on the promise\n      initMutex.release();\n      return currentPromise;\n    }\n\n    // Create and store the initialization promise\n    // Keep the promise alive until storage is fully initialized\n    initPromise = (async () => {\n      try {\n        const newStorage = new GraphStorage();\n        await newStorage.initializeTables();\n        storage = newStorage;\n        return newStorage;\n      } catch (error) {\n        // On error, clear promise so next caller can retry\n        initPromise = null;\n        throw error;\n      }\n    })();\n\n    // Wait for initialization to complete before releasing mutex\n    const result = await initPromise;\n    // Clear promise only after successful initialization\n    // This prevents race condition where initPromise is null but storage is set\n    initPromise = null;\n    return result;\n  } finally {\n    initMutex.release();\n  }\n}\n\nexport async function initializeGraphStorage(): Promise<void> {\n  const storage = getGraphStorage();\n  await storage.initializeTables();\n}\n","import { IAgentModule, IAgent } from '../agent/types';\nimport { Agent } from '../agent';\nimport { getDatabase } from '../database';\nimport { Task } from '../task';\nimport { Memory } from '../memory';\nimport { getGraphStorage } from './storage';\nimport { Logger, LogData } from '../logger/types';\nimport { GraphNodeError } from '../errors';\nimport {\n  Graph as GraphType,\n  GraphConfig,\n  GraphNode,\n  GraphEdge,\n  GraphExecutionResult,\n  GraphExecutionLogEntry,\n  AddAgentNodeOptions,\n  AddTaskNodeOptions,\n  GraphExecutionStatus,\n  GraphSchedulingOptions,\n  GraphUsage,\n  NodeUsage,\n  GraphStateChangeEvent,\n  GraphStateChangeCallback,\n} from './types';\nimport { Memory as MemoryType } from '../memory/types';\nimport { Knex } from 'knex';\n\ninterface TaskExecutionResult {\n  type: 'task';\n  taskId: string; // UUID\n  response: string;\n  model?: string;\n  usage?: {\n    promptTokens: number;\n    completionTokens: number;\n    totalTokens: number;\n    cost?: number;\n  };\n  // Sub-agent execution metadata\n  subAgentUsed?: boolean;\n  delegationStrategy?: 'auto' | 'manual' | 'sequential';\n  coordinationPattern?: 'parallel' | 'sequential';\n}\n\ninterface AgentExecutionResult {\n  type: 'agent';\n  agentId?: string; // UUID\n}\n\ntype NodeExecutionResult = TaskExecutionResult | AgentExecutionResult;\n\nexport class Graph implements IAgentModule {\n  readonly name = 'graph';\n  private knex: Knex | null = null;\n  private graph: GraphType;\n  private initialized: boolean = false;\n  private agent?: IAgent;\n  private logger?: Logger;\n  public lastNodeId: string | null = null; // Track last added node for auto-linking\n\n  // Bounds limits for graph collections\n  private static readonly MAX_NODES = 1000;\n  private static readonly MAX_EDGES = 5000;\n\n  // Promise-based mutex for preventing concurrent execution\n  private executionLock: Promise<void> | null = null;\n  private releaseLock: (() => void) | null = null;\n\n  // State change callback for Agent state synchronization\n  private stateChangeCallback: GraphStateChangeCallback | null = null;\n\n  // Current execution state for tracking\n  private executionState: Map<string, { status: string; result?: unknown; error?: string }> =\n    new Map();\n\n  // Track active timeouts for cleanup\n  private activeNodeTimeouts: Map<string, NodeJS.Timeout> = new Map();\n  private overallTimeoutId: NodeJS.Timeout | null = null;\n\n  constructor(config: GraphConfig, agent?: IAgent) {\n    // Note: knex will be initialized in initialize() method\n    this.agent = agent;\n    this.logger = agent?.logger;\n\n    // Log warning if no agent provided - note: logger may not be available yet\n    // This is intentionally left as a silent case since logger depends on agent\n\n    this.graph = {\n      config,\n      defaultAgentId: agent?.id, // Store default agent ID\n      nodes: [],\n      edges: [],\n      status: 'idle',\n      executionLog: [],\n      createdAt: new Date(),\n      updatedAt: new Date(),\n    };\n\n    // User-facing info log\n    if (this.logger) {\n      this.logger.info('Graph module initialized', undefined, this.agent?.name);\n    }\n  }\n\n  async initialize(): Promise<void> {\n    if (this.initialized) return;\n    const db = await getDatabase();\n    this.knex = db.getKnex();\n    this.initialized = true;\n\n    // User-facing info log\n    if (this.logger) {\n      this.logger.info('Graph module ready', undefined, this.agent?.name);\n    }\n  }\n\n  /**\n   * Register a callback for graph state change events\n   * This allows Agent to track state changes during graph execution\n   */\n  onStateChange(callback: GraphStateChangeCallback): void {\n    this.stateChangeCallback = callback;\n  }\n\n  /**\n   * Notify registered callback about state changes\n   */\n  private async notifyStateChange(event: GraphStateChangeEvent): Promise<void> {\n    // Update internal execution state\n    if (event.nodeId) {\n      this.executionState.set(event.nodeId, {\n        status: event.status,\n        result: event.result,\n        error: event.error,\n      });\n    }\n\n    if (this.stateChangeCallback) {\n      try {\n        await this.stateChangeCallback(event);\n      } catch (error) {\n        this.log(\n          'warn',\n          `State change callback failed: ${error instanceof Error ? error.message : String(error)}`\n        );\n      }\n    }\n  }\n\n  /**\n   * Get the current execution state of all nodes\n   * Useful for Agent to sync its state with graph execution\n   */\n  getExecutionState(): Map<string, { status: string; result?: unknown; error?: string }> {\n    return new Map(this.executionState);\n  }\n\n  /**\n   * Get the current state of a specific node\n   */\n  getNodeExecutionState(\n    nodeId: string\n  ): { status: string; result?: unknown; error?: string } | undefined {\n    return this.executionState.get(nodeId);\n  }\n\n  /**\n   * Clear execution state (useful after graph reset)\n   */\n  clearExecutionState(): void {\n    this.executionState.clear();\n  }\n\n  // Node management\n  addAgentNode(options: AddAgentNodeOptions): string {\n    // Validate agentId is provided\n    if (!options.agentId) {\n      throw new Error('agentId is required for agent nodes');\n    }\n\n    const nodeId = this.generateNodeId();\n\n    const dependencies: string[] = [...(options.dependencies ?? [])];\n    const explicitDependencies: string[] = [];\n\n    // Validate dependencies exist before adding\n    for (const depId of dependencies) {\n      const depNode = this.graph.nodes.find((n) => n.id === depId);\n      if (!depNode) {\n        throw new Error(`Dependency node not found: ${depId}`);\n      }\n    }\n\n    // Auto-link: Link to previous node if autoLink is enabled\n    if (this.graph.config.autoLink && this.lastNodeId && !dependencies.length) {\n      dependencies.push(this.lastNodeId);\n      explicitDependencies.push(this.lastNodeId);\n      this.log('debug', `Auto-linked node to previous: ${this.lastNodeId}`, nodeId);\n    } else if (dependencies.length > 0) {\n      explicitDependencies.push(...dependencies);\n    }\n\n    const node: GraphNode = {\n      id: nodeId,\n      type: 'agent',\n      name: `Agent-${options.agentId}`,\n      agentId: options.agentId,\n      status: 'pending',\n      priority: options.priority ?? 0,\n      dependencies,\n      metadata: options.metadata,\n      createdAt: new Date(),\n      updatedAt: new Date(),\n    };\n\n    // Bounds check: prevent unbounded growth of nodes\n    if (this.graph.nodes.length >= Graph.MAX_NODES) {\n      throw new Error(`Maximum number of nodes (${Graph.MAX_NODES}) exceeded`);\n    }\n\n    this.graph.nodes.push(node);\n    this.graph.updatedAt = new Date();\n\n    // Auto-create edges for dependencies\n    for (const depId of explicitDependencies) {\n      this.addEdge(depId, nodeId);\n    }\n\n    // Track this node as last added for auto-linking\n    this.lastNodeId = nodeId;\n\n    this.log('debug', `Added agent node: ${node.name} (agentId: ${options.agentId})`, nodeId);\n\n    return nodeId;\n  }\n\n  addTaskNode(options: AddTaskNodeOptions): string {\n    // Validate prompt is provided\n    if (!options.prompt || options.prompt.trim() === '') {\n      throw new Error('prompt is required for task nodes');\n    }\n\n    const nodeId = this.generateNodeId();\n\n    // Handle dependsOn (node names) vs dependencies (node IDs)\n    let dependencies: string[] = options.dependencies ?? [];\n    const explicitDependencies: string[] = [];\n\n    // Validate dependencies exist before adding\n    for (const depId of dependencies) {\n      const depNode = this.graph.nodes.find((n) => n.id === depId);\n      if (!depNode) {\n        throw new Error(`Dependency node not found: ${depId}`);\n      }\n    }\n\n    if (options.dependsOn && options.dependsOn.length > 0) {\n      // Convert node names to node IDs\n      const dependencyIds = options.dependsOn\n        .map((nodeName) => {\n          const depNode = this.graph.nodes.find(\n            (n) => n.metadata?.name === nodeName || n.name === nodeName\n          );\n          if (!depNode) {\n            this.log('warn', `Dependency node not found: ${nodeName}`, nodeId);\n            return null;\n          }\n          return depNode.id;\n        })\n        .filter((id): id is string => id !== null);\n\n      dependencies = [...dependencies, ...dependencyIds];\n      explicitDependencies.push(...dependencyIds);\n    }\n\n    // Auto-link: Link to previous node if autoLink is enabled\n    if (this.graph.config.autoLink && this.lastNodeId && !explicitDependencies.length) {\n      if (!dependencies.includes(this.lastNodeId)) {\n        dependencies.push(this.lastNodeId);\n        explicitDependencies.push(this.lastNodeId);\n        this.log('debug', `Auto-linked node to previous: ${this.lastNodeId}`, nodeId);\n      }\n    }\n\n    // Check if schedule is provided (no validation needed - just store the string)\n    if (options.schedule) {\n      this.log('debug', `Schedule provided: ${options.schedule}`, nodeId);\n    }\n\n    // Validate agentId - task nodes require an agent\n    const agentId = options.agentId || this.agent?.id;\n    if (!agentId) {\n      throw new Error(\n        'Agent ID required for task node - either provide agentId in options or attach an agent to the graph'\n      );\n    }\n\n    const node: GraphNode = {\n      id: nodeId,\n      type: 'task',\n      name: options.name || `Task-${nodeId.split('_')[1]}-${nodeId.split('_')[2]}`,\n      prompt: options.prompt,\n      model: options.model,\n      stream: options.stream,\n      agentId,\n      // Sub-agent delegation options\n      useSubAgents: options.useSubAgents,\n      subAgentDelegation: options.subAgentDelegation,\n      subAgentCoordination: options.subAgentCoordination,\n      status: 'pending',\n      priority: options.priority ?? 0,\n      dependencies,\n      schedule: options.schedule,\n      metadata: {\n        ...options.metadata,\n        ...(options.name ? { name: options.name } : {}),\n      },\n      createdAt: new Date(),\n      updatedAt: new Date(),\n    };\n\n    // Bounds check: prevent unbounded growth of nodes\n    if (this.graph.nodes.length >= Graph.MAX_NODES) {\n      throw new Error(`Maximum number of nodes (${Graph.MAX_NODES}) exceeded`);\n    }\n\n    this.graph.nodes.push(node);\n    this.graph.updatedAt = new Date();\n\n    // Auto-create edges for explicit dependencies (dependsOn or autoLink)\n    for (const depId of explicitDependencies) {\n      this.addEdge(depId, nodeId);\n    }\n\n    // Track this node as last added for auto-linking\n    this.lastNodeId = nodeId;\n\n    const scheduleInfo = options.schedule ? ` (scheduled: ${options.schedule})` : '';\n    this.log(\n      'debug',\n      `Added task node: ${node.name} (prompt: \"${options.prompt.slice(0, 50)}...\")${scheduleInfo}`,\n      nodeId\n    );\n\n    return nodeId;\n  }\n\n  addEdge(fromNodeId: string, toNodeId: string, condition?: string): string {\n    // Bounds check: prevent unbounded growth of edges\n    if (this.graph.edges.length >= Graph.MAX_EDGES) {\n      throw new Error(`Maximum number of edges (${Graph.MAX_EDGES}) exceeded`);\n    }\n\n    // Validate that both nodes exist\n    const fromNode = this.graph.nodes.find((n) => n.id === fromNodeId);\n    if (!fromNode) {\n      throw new Error(`Source node not found: ${fromNodeId}`);\n    }\n\n    const toNode = this.graph.nodes.find((n) => n.id === toNodeId);\n    if (!toNode) {\n      throw new Error(`Target node not found: ${toNodeId}`);\n    }\n\n    // Prevent self-referencing edges\n    if (fromNodeId === toNodeId) {\n      throw new Error(`Cannot create self-referencing edge: ${fromNodeId}`);\n    }\n\n    // Check for duplicate edges\n    const existingEdge = this.graph.edges.find(\n      (e) => e.fromNodeId === fromNodeId && e.toNodeId === toNodeId\n    );\n    if (existingEdge) {\n      this.log('warn', `Duplicate edge ignored: ${fromNodeId} -> ${toNodeId}`);\n      return existingEdge.id;\n    }\n\n    const edgeId = this.generateEdgeId();\n\n    const edge: GraphEdge = {\n      id: edgeId,\n      fromNodeId,\n      toNodeId,\n      condition,\n      createdAt: new Date(),\n      updatedAt: new Date(),\n    };\n\n    this.graph.edges.push(edge);\n\n    // Add dependency to target node\n    if (!toNode.dependencies.includes(fromNodeId)) {\n      toNode.dependencies.push(fromNodeId);\n    }\n\n    this.graph.updatedAt = new Date();\n\n    return edgeId;\n  }\n\n  /**\n   * Acquire the execution lock, waiting if another execution is in progress\n   * Returns a release function to be called when execution is complete\n   * @param timeout - Maximum time to wait for lock acquisition (default: 30000ms)\n   * @throws Error if lock acquisition times out\n   */\n  private async acquireLock(timeout = 30000): Promise<() => void> {\n    const startTime = Date.now();\n\n    // Wait for any existing execution to complete with timeout\n    while (this.executionLock) {\n      if (Date.now() - startTime > timeout) {\n        throw new Error(`Lock acquisition timeout after ${timeout}ms - possible deadlock detected`);\n      }\n\n      // Create timeout promise with proper cleanup\n      let timeoutId: NodeJS.Timeout | null = null;\n      const remainingTime = Math.max(100, Math.min(1000, timeout - (Date.now() - startTime)));\n      const timeoutPromise = new Promise<void>((resolve) => {\n        timeoutId = setTimeout(() => {\n          resolve(); // Resolve instead of reject to avoid unhandled rejection\n        }, remainingTime);\n      });\n\n      try {\n        // Wait for either lock release or timeout\n        await Promise.race([\n          this.executionLock.then(() => {\n            if (timeoutId) clearTimeout(timeoutId);\n          }),\n          timeoutPromise,\n        ]);\n      } finally {\n        // Ensure timeout is cleared even if promise race throws\n        if (timeoutId) clearTimeout(timeoutId);\n      }\n    }\n\n    // Create a new lock with proper initialization\n    let releaseFunction: (() => void) | null = null;\n    this.executionLock = new Promise<void>((resolve) => {\n      releaseFunction = () => {\n        this.executionLock = null;\n        this.releaseLock = null;\n        resolve();\n      };\n    });\n\n    // At this point, releaseFunction is guaranteed to be set by the Promise executor\n    // which runs synchronously\n    if (!releaseFunction) {\n      throw new Error('Failed to initialize lock release function');\n    }\n\n    this.releaseLock = releaseFunction;\n    return releaseFunction;\n  }\n\n  // Execution\n  async run(\n    options?: {\n      stream?: boolean;\n      onChunk?: (chunk: string) => void;\n      onToolCall?: (\n        toolName: string,\n        args: Record<string, unknown>,\n        status: 'start' | 'end',\n        result?: string\n      ) => void;\n      timeout?: number;\n      nodeTimeout?: number;\n    } & GraphSchedulingOptions\n  ): Promise<GraphExecutionResult> {\n    // Acquire Promise-based lock - prevents concurrent execution race conditions\n    const release = await this.acquireLock();\n\n    try {\n      return await this.executeGraph(options);\n    } finally {\n      release();\n    }\n  }\n\n  private async executeGraph(\n    options?: {\n      stream?: boolean;\n      onChunk?: (chunk: string) => void;\n      onToolCall?: (\n        toolName: string,\n        args: Record<string, unknown>,\n        status: 'start' | 'end',\n        result?: string\n      ) => void;\n      timeout?: number;\n      nodeTimeout?: number;\n    } & GraphSchedulingOptions\n  ): Promise<GraphExecutionResult> {\n    await this.initialize();\n\n    // Clear previous execution state\n    this.clearExecutionState();\n\n    // Set status to running before save\n    this.graph.status = 'running';\n    this.graph.startedAt = new Date();\n\n    // Notify state change: graph started\n    await this.notifyStateChange({\n      type: 'graph_started',\n      graphId: this.graph.id,\n      status: 'running',\n      timestamp: new Date(),\n    });\n\n    // Auto-save if not already saved\n    if (!this.graph.id) {\n      this.log('info', 'Auto-saving graph before execution');\n      await this.save();\n    }\n\n    // Detect scheduled nodes\n    const hasScheduledNodes = this.graph.nodes.some((node) => node.schedule);\n    if (hasScheduledNodes) {\n      this.log('info', 'Detected scheduled nodes in graph');\n    }\n\n    this.log('info', 'Starting graph execution with scheduling support');\n\n    const results: Record<string, NodeExecutionResult> = {};\n    const errors: Record<string, string> = {};\n    let completedNodes = 0;\n    let failedNodes = 0;\n\n    // Default scheduling options with timeout support\n    // SubAgent nodes need longer timeout (5 minutes) vs regular nodes (1 minute)\n    const defaultNodeTimeout = 60000; // 1 minute per node default\n    const subAgentNodeTimeout = this.graph.config.subAgentNodeTimeout || 300000; // 5 minutes for sub-agent nodes\n\n    const schedulingOptions = {\n      respectSchedules: true,\n      waitForScheduled: true,\n      schedulingCheckInterval: 1000,\n      timeout: options?.timeout || 300000, // 5 minutes default\n      nodeTimeout: options?.nodeTimeout || defaultNodeTimeout,\n      subAgentNodeTimeout: subAgentNodeTimeout,\n      ...options,\n    };\n\n    // Set up overall graph timeout with Promise-based rejection\n    // Store reject function with proper cleanup to prevent memory leak\n    let timeoutReject: ((error: Error) => void) | null = null;\n    let timeoutResolved = false;\n    const timeoutPromise = new Promise<never>((_, reject) => {\n      timeoutReject = (error: Error) => {\n        if (!timeoutResolved) {\n          timeoutResolved = true;\n          reject(error);\n        }\n      };\n    });\n    this.overallTimeoutId = setTimeout(() => {\n      this.graph.status = 'failed';\n      this.log('error', `Graph execution timed out after ${schedulingOptions.timeout}ms`);\n      if (timeoutReject && !timeoutResolved) {\n        timeoutReject(new Error(`Graph execution timed out after ${schedulingOptions.timeout}ms`));\n      }\n    }, schedulingOptions.timeout);\n\n    // Cleanup function to mark timeout as resolved and prevent memory leak\n    const markTimeoutResolved = () => {\n      timeoutResolved = true;\n    };\n\n    // Clear any existing node timeouts from previous runs\n    this.activeNodeTimeouts.clear();\n\n    try {\n      // Ultra-simplified scheduler - no complex schedule calculation needed\n\n      const sortedNodes = this.topologicalSort();\n      this.log(\n        'debug',\n        `Execution plan: ${sortedNodes.length} nodes, max concurrency: ${this.graph.config.maxConcurrency || 1}, scheduling enabled: ${schedulingOptions.respectSchedules}`\n      );\n\n      const maxConcurrency = this.graph.config.maxConcurrency ?? 1;\n      const executing = new Set<string>();\n      let currentIndex = 0;\n\n      // Find the last PENDING node for streaming (skip already completed nodes)\n      const pendingNodes = sortedNodes.filter((n) => n.status !== 'completed');\n      const lastNode = pendingNodes[pendingNodes.length - 1];\n      const shouldStreamLastNode = options?.stream && lastNode?.type === 'task';\n\n      // Wrap execution loop in a Promise that can race with timeout\n      const executionPromise = (async () => {\n        // Prevent infinite loops with max iterations guard\n        const MAX_ITERATIONS = sortedNodes.length * 2 + 100; // Allow extra iterations for async processing\n        let iterations = 0;\n\n        while (\n          (currentIndex < sortedNodes.length || executing.size > 0) &&\n          iterations < MAX_ITERATIONS\n        ) {\n          iterations++;\n          // Start new nodes if we have capacity\n          while (executing.size < maxConcurrency && currentIndex < sortedNodes.length) {\n            const node = sortedNodes[currentIndex];\n\n            // Skip already completed nodes\n            if (node.status === 'completed') {\n              currentIndex++;\n              continue;\n            }\n\n            // Check if node is ready to execute (dependencies only in ultra-simplified mode)\n            if (this.areDependenciesCompleted(node)) {\n              this.log(\n                'debug',\n                `Node ${node.name} ready to execute - all dependencies completed`,\n                node.id\n              );\n              executing.add(node.id);\n\n              // Determine timeout based on whether node uses sub-agents\n              // SubAgent nodes need longer timeout to accommodate delegation + execution phases\n              const usesSubAgents = this.shouldUseSubAgents(node);\n              const effectiveNodeTimeout = usesSubAgents\n                ? schedulingOptions.subAgentNodeTimeout\n                : schedulingOptions.nodeTimeout;\n\n              // Set up node timeout with proper state change notification\n              const nodeTimeoutId = setTimeout(async () => {\n                if (executing.has(node.id)) {\n                  errors[node.id] = `Node execution timed out after ${effectiveNodeTimeout}ms`;\n                  node.status = 'failed';\n                  node.error = `Node execution timed out after ${effectiveNodeTimeout}ms`;\n                  failedNodes++;\n                  executing.delete(node.id);\n                  this.activeNodeTimeouts.delete(node.id);\n                  this.log(\n                    'error',\n                    `Node ${node.name} timed out after ${effectiveNodeTimeout}ms${usesSubAgents ? ' (sub-agent node)' : ''}`,\n                    node.id\n                  );\n\n                  // Notify state change: node timed out (wrapped to prevent unhandled rejection)\n                  try {\n                    await this.notifyStateChange({\n                      type: 'node_failed',\n                      nodeId: node.id,\n                      nodeName: node.name,\n                      graphId: this.graph.id,\n                      status: 'failed',\n                      error: `Node execution timed out after ${effectiveNodeTimeout}ms`,\n                      timestamp: new Date(),\n                    });\n                  } catch (notifyError) {\n                    this.log(\n                      'warn',\n                      `Failed to notify state change for timed out node ${node.name}: ${notifyError instanceof Error ? notifyError.message : 'Unknown error'}`,\n                      node.id\n                    );\n                  }\n                }\n              }, effectiveNodeTimeout);\n              this.activeNodeTimeouts.set(node.id, nodeTimeoutId);\n\n              // Special handling for last node with streaming\n              if (shouldStreamLastNode && node.id === lastNode.id) {\n                this.executeNode(node, true, options?.onChunk, options?.onToolCall) // Pass stream=true and onChunk for last node\n                  .then(async (result) => {\n                    const timeoutId = this.activeNodeTimeouts.get(node.id);\n                    if (timeoutId) {\n                      clearTimeout(timeoutId);\n                      this.activeNodeTimeouts.delete(node.id);\n                    }\n                    results[node.id] = result;\n                    node.status = 'completed';\n                    node.result = JSON.stringify(result);\n\n                    // Track usage for task nodes\n                    if (result.type === 'task' && result.usage) {\n                      node.usage = {\n                        promptTokens: result.usage.promptTokens,\n                        completionTokens: result.usage.completionTokens,\n                        totalTokens: result.usage.totalTokens,\n                        cost: result.usage.cost,\n                        model: result.model,\n                      };\n                    }\n\n                    completedNodes++;\n                    executing.delete(node.id);\n                    this.log('info', `Node ${node.name} completed (streamed)`, node.id);\n\n                    // Notify state change: node completed\n                    await this.notifyStateChange({\n                      type: 'node_completed',\n                      nodeId: node.id,\n                      nodeName: node.name,\n                      graphId: this.graph.id,\n                      status: 'completed',\n                      result: node.result,\n                      usage: node.usage,\n                      timestamp: new Date(),\n                    });\n\n                    // Save assistant response to memory (wrapped to prevent unhandled rejection)\n                    try {\n                      await this.saveResponseToMemory(node, result);\n                    } catch (memoryError) {\n                      this.log(\n                        'warn',\n                        `Failed to save response to memory for node ${node.name}: ${memoryError instanceof Error ? memoryError.message : 'Unknown error'}`,\n                        node.id\n                      );\n                    }\n                  })\n                  .catch(async (error) => {\n                    const timeoutId = this.activeNodeTimeouts.get(node.id);\n                    if (timeoutId) {\n                      clearTimeout(timeoutId);\n                      this.activeNodeTimeouts.delete(node.id);\n                    }\n                    const errorMessage = error instanceof Error ? error.message : String(error);\n                    errors[node.id] = errorMessage;\n                    node.status = 'failed';\n                    node.error = errorMessage;\n                    failedNodes++;\n                    executing.delete(node.id);\n                    this.log('error', `Node ${node.name} failed: ${errorMessage}`, node.id);\n\n                    // Notify state change: node failed (wrapped to prevent unhandled rejection)\n                    try {\n                      await this.notifyStateChange({\n                        type: 'node_failed',\n                        nodeId: node.id,\n                        nodeName: node.name,\n                        graphId: this.graph.id,\n                        status: 'failed',\n                        error: errorMessage,\n                        timestamp: new Date(),\n                      });\n                    } catch (notifyError) {\n                      this.log(\n                        'warn',\n                        `Failed to notify state change for failed node ${node.name}: ${notifyError instanceof Error ? notifyError.message : 'Unknown error'}`,\n                        node.id\n                      );\n                    }\n                  });\n              } else {\n                this.executeNode(node, false, options?.onChunk, options?.onToolCall)\n                  .then(async (result) => {\n                    const timeoutId = this.activeNodeTimeouts.get(node.id);\n                    if (timeoutId) {\n                      clearTimeout(timeoutId);\n                      this.activeNodeTimeouts.delete(node.id);\n                    }\n                    results[node.id] = result;\n                    node.status = 'completed';\n                    node.result = JSON.stringify(result);\n\n                    // Track usage for task nodes\n                    if (result.type === 'task' && result.usage) {\n                      node.usage = {\n                        promptTokens: result.usage.promptTokens,\n                        completionTokens: result.usage.completionTokens,\n                        totalTokens: result.usage.totalTokens,\n                        cost: result.usage.cost,\n                        model: result.model,\n                      };\n                    }\n\n                    completedNodes++;\n                    executing.delete(node.id);\n                    this.log('info', `Node ${node.name} completed`, node.id);\n\n                    // Notify state change: node completed\n                    await this.notifyStateChange({\n                      type: 'node_completed',\n                      nodeId: node.id,\n                      nodeName: node.name,\n                      graphId: this.graph.id,\n                      status: 'completed',\n                      result: node.result,\n                      usage: node.usage,\n                      timestamp: new Date(),\n                    });\n\n                    // Save assistant response to memory (wrapped to prevent unhandled rejection)\n                    try {\n                      await this.saveResponseToMemory(node, result);\n                    } catch (memoryError) {\n                      this.log(\n                        'warn',\n                        `Failed to save response to memory for node ${node.name}: ${memoryError instanceof Error ? memoryError.message : 'Unknown error'}`,\n                        node.id\n                      );\n                    }\n                  })\n                  .catch(async (error) => {\n                    const timeoutId = this.activeNodeTimeouts.get(node.id);\n                    if (timeoutId) {\n                      clearTimeout(timeoutId);\n                      this.activeNodeTimeouts.delete(node.id);\n                    }\n                    const errorMessage = error instanceof Error ? error.message : String(error);\n                    errors[node.id] = errorMessage;\n                    node.status = 'failed';\n                    node.error = errorMessage;\n                    failedNodes++;\n                    executing.delete(node.id);\n                    this.log('error', `Node ${node.name} failed: ${errorMessage}`, node.id);\n\n                    // Notify state change: node failed (wrapped to prevent unhandled rejection)\n                    try {\n                      await this.notifyStateChange({\n                        type: 'node_failed',\n                        nodeId: node.id,\n                        nodeName: node.name,\n                        graphId: this.graph.id,\n                        status: 'failed',\n                        error: errorMessage,\n                        timestamp: new Date(),\n                      });\n                    } catch (notifyError) {\n                      this.log(\n                        'warn',\n                        `Failed to notify state change for failed node ${node.name}: ${notifyError instanceof Error ? notifyError.message : 'Unknown error'}`,\n                        node.id\n                      );\n                    }\n                  });\n              }\n              currentIndex++;\n            } else {\n              // Node not ready (dependencies not completed)\n              break;\n            }\n          }\n\n          // Wait a bit before checking again\n          if (executing.size > 0) {\n            await new Promise((resolve) => setTimeout(resolve, 100));\n          }\n\n          // Skip nodes that have failed dependencies (not running/pending ones)\n          while (\n            currentIndex < sortedNodes.length &&\n            this.hasFailedDependencies(sortedNodes[currentIndex])\n          ) {\n            const node = sortedNodes[currentIndex];\n            node.status = 'skipped';\n\n            // Debug: show which dependencies failed\n            const failedDeps = node.dependencies.filter((depId) => {\n              const depNode = this.graph.nodes.find((n) => n.id === depId);\n              return depNode?.status === 'failed';\n            });\n\n            this.log(\n              'warn',\n              `Node ${node.name} skipped due to failed dependencies: ${failedDeps\n                .map((id) => {\n                  const depNode = this.graph.nodes.find((n) => n.id === id);\n                  return `${depNode?.name || id}(${depNode?.status || 'unknown'})`;\n                })\n                .join(', ')}`,\n              node.id\n            );\n            currentIndex++;\n          }\n        }\n\n        // Check if we hit the max iterations limit\n        if (iterations >= MAX_ITERATIONS) {\n          throw new Error(\n            'Graph execution exceeded max iterations - possible infinite loop detected'\n          );\n        }\n      })();\n\n      // Race execution against timeout\n      await Promise.race([executionPromise, timeoutPromise]);\n\n      // Mark timeout as resolved to prevent memory leak from pending promise\n      markTimeoutResolved();\n\n      this.graph.status = failedNodes > 0 ? 'failed' : 'completed';\n    } catch (error) {\n      // Mark timeout as resolved even on error to prevent memory leak\n      markTimeoutResolved();\n      this.graph.status = 'failed';\n      this.log(\n        'error',\n        `Graph execution failed: ${error instanceof Error ? error.message : 'Unknown error'}`\n      );\n    } finally {\n      // Clean up all timeouts\n      if (this.overallTimeoutId) {\n        clearTimeout(this.overallTimeoutId);\n        this.overallTimeoutId = null;\n      }\n      for (const [nodeId, timeoutId] of this.activeNodeTimeouts.entries()) {\n        clearTimeout(timeoutId);\n        this.log('debug', `Cleaned up timeout for node ${nodeId}`);\n      }\n      this.activeNodeTimeouts.clear();\n    }\n\n    this.graph.completedAt = new Date();\n    const duration = this.graph.startedAt\n      ? this.graph.completedAt.getTime() - this.graph.startedAt.getTime()\n      : 0;\n\n    // Aggregate usage statistics\n    const usage = this.aggregateUsage();\n    this.graph.usage = usage;\n\n    this.log(\n      'info',\n      `Graph execution ${this.graph.status}. Completed: ${completedNodes}, Failed: ${failedNodes}, Tokens: ${usage.totalTokens} (${duration}ms)`\n    );\n\n    // Persist updated graph state (node statuses) to database\n    await this.update();\n\n    // Notify state change: graph completed or failed\n    await this.notifyStateChange({\n      type: this.graph.status === 'completed' ? 'graph_completed' : 'graph_failed',\n      graphId: this.graph.id,\n      status: this.graph.status,\n      timestamp: new Date(),\n    });\n\n    return {\n      graph: this.graph,\n      success: this.graph.status === 'completed',\n      completedNodes,\n      failedNodes,\n      duration,\n      results: Object.fromEntries(Object.entries(results).map(([k, v]) => [k, JSON.stringify(v)])),\n      errors,\n      usage,\n    };\n  }\n\n  /**\n   * Aggregate usage statistics from all completed nodes\n   */\n  private aggregateUsage(): GraphUsage {\n    const nodeUsages: Record<string, NodeUsage> = {};\n    let totalPromptTokens = 0;\n    let totalCompletionTokens = 0;\n    let totalTokens = 0;\n    let totalContextTokens = 0;\n    let totalCost = 0;\n    const modelsUsed = new Set<string>();\n\n    for (const node of this.graph.nodes) {\n      if (node.usage) {\n        nodeUsages[node.id] = node.usage;\n        totalPromptTokens += node.usage.promptTokens;\n        totalCompletionTokens += node.usage.completionTokens;\n        totalTokens += node.usage.totalTokens;\n        totalContextTokens += node.usage.contextTokens ?? 0;\n        totalCost += node.usage.cost ?? 0;\n        if (node.usage.model) {\n          modelsUsed.add(node.usage.model);\n        }\n      }\n    }\n\n    return {\n      totalPromptTokens,\n      totalCompletionTokens,\n      totalTokens,\n      totalContextTokens,\n      totalCost,\n      nodeUsages,\n      modelsUsed: Array.from(modelsUsed),\n    };\n  }\n\n  /**\n   * Check context size and warn if approaching limits\n   */\n  private checkContextSize(node: GraphNode): void {\n    if (!this.agent) return;\n\n    try {\n      // Get context window info from agent\n      const contextWindow = (this.agent as Agent).getContextWindow?.();\n      if (!contextWindow) return;\n\n      const { totalTokens, maxTokens } = contextWindow;\n\n      // Check against graph config limits if set\n      const maxContextTokens = this.graph.config.maxContextTokens || maxTokens;\n      const warningThreshold = this.graph.config.contextWarningThreshold || 0.8;\n\n      const utilization = totalTokens / maxContextTokens;\n\n      if (utilization >= 1.0) {\n        this.log(\n          'error',\n          `Context limit exceeded! Using ${totalTokens}/${maxContextTokens} tokens (${(utilization * 100).toFixed(1)}%)`,\n          node.id\n        );\n      } else if (utilization >= warningThreshold) {\n        this.log(\n          'warn',\n          `Context approaching limit: ${totalTokens}/${maxContextTokens} tokens (${(utilization * 100).toFixed(1)}%)`,\n          node.id\n        );\n      } else {\n        this.log(\n          'debug',\n          `Context usage: ${totalTokens}/${maxContextTokens} tokens (${(utilization * 100).toFixed(1)}%)`,\n          node.id\n        );\n      }\n\n      // Track context tokens in node usage\n      if (node.usage) {\n        node.usage.contextTokens = totalTokens;\n      }\n    } catch (error) {\n      this.log(\n        'debug',\n        `Failed to check context size: ${error instanceof Error ? error.message : String(error)}`,\n        node.id\n      );\n    }\n  }\n\n  private async executeNode(\n    node: GraphNode,\n    forceStream?: boolean,\n    onChunk?: (chunk: string) => void,\n    onToolCall?: (\n      toolName: string,\n      args: Record<string, unknown>,\n      status: 'start' | 'end',\n      result?: string\n    ) => void\n  ): Promise<NodeExecutionResult> {\n    this.log('info', `Executing node ${node.name}`, node.id);\n    node.status = 'running';\n    node.updatedAt = new Date();\n\n    // Notify state change: node started\n    await this.notifyStateChange({\n      type: 'node_started',\n      nodeId: node.id,\n      nodeName: node.name,\n      graphId: this.graph.id,\n      status: 'running',\n      timestamp: new Date(),\n    });\n\n    // Find parent node ID for error chain tracking\n    const parentNodeId = node.dependencies.length > 0 ? node.dependencies[0] : undefined;\n\n    if (node.type === 'agent') {\n      // For agent nodes, we just mark them as completed\n      // The actual agent work would be defined by connected task nodes\n      return { type: 'agent', agentId: node.agentId };\n    } else if (node.type === 'task') {\n      if (!node.agentId) {\n        throw new GraphNodeError(\n          `Task node ${node.name} has no assigned agent`,\n          node.id,\n          node.name,\n          'initialization',\n          this.graph.id,\n          parentNodeId\n        );\n      }\n\n      if (!node.prompt) {\n        throw new GraphNodeError(\n          `Task node ${node.name} has no prompt`,\n          node.id,\n          node.name,\n          'initialization',\n          this.graph.id,\n          parentNodeId\n        );\n      }\n\n      // Load conversation history from Memory if agent has memory enabled\n      if (this.graph.id && this.agent && this.agent.loadGraphContext) {\n        try {\n          // Use isolated=true for graph-only memories (no general agent memories)\n          await this.agent.loadGraphContext(this.graph.id, 100, true);\n          this.log(\n            'debug',\n            `Loaded isolated conversation history for graph ${this.graph.id}`,\n            node.id\n          );\n\n          // Monitor context size and warn if approaching limits\n          this.checkContextSize(node);\n        } catch (error) {\n          this.log(\n            'warn',\n            `Failed to load conversation history: ${error instanceof Error ? error.message : String(error)}`,\n            node.id\n          );\n        }\n      }\n\n      // Save user prompt to memory before execution (this also adds to context)\n      if (this.graph.id && node.prompt && this.agent && this.agent.addMemory) {\n        try {\n          const metadata: Record<string, string | boolean | number> = {\n            type: 'user_message',\n            role: 'user',\n            graphId: this.graph.id,\n            graphNodeId: node.id,\n          };\n          if (node.taskId) {\n            metadata.taskId = node.taskId;\n          }\n          await this.agent.addMemory(node.prompt, metadata);\n          this.log('debug', `Saved user prompt to memory`, node.id);\n        } catch (error) {\n          this.log(\n            'warn',\n            `Failed to save user prompt: ${error instanceof Error ? error.message : String(error)}`,\n            node.id\n          );\n        }\n      }\n\n      // Use the original prompt (context is already loaded in ContextManager)\n      const enhancedPrompt = node.prompt;\n\n      // Execute task using the assigned agent\n      if (!this.agent) {\n        throw new GraphNodeError(\n          `No agent available for task node ${node.name}`,\n          node.id,\n          node.name,\n          'initialization',\n          this.graph.id,\n          parentNodeId\n        );\n      }\n\n      // Determine if sub-agents should be used\n      const shouldUseSubAgents = this.shouldUseSubAgents(node);\n\n      // Always use Task module for proper tool support and consistency\n      if (shouldUseSubAgents) {\n        this.log('info', `Using sub-agent delegation for task node ${node.name}`, node.id);\n\n        // Enhanced context for sub-agent coordination\n        let contextualPrompt = enhancedPrompt;\n\n        // Add graph context for sub-agents\n        if (this.graph.nodes.length > 1) {\n          const graphContext = this.buildGraphContext(node);\n          if (graphContext) {\n            contextualPrompt = `Graph Context: ${graphContext}\\n\\n${enhancedPrompt}`;\n            this.log('debug', `Enhanced prompt with graph context for sub-agents`, node.id);\n          }\n        }\n\n        // Use Task module with sub-agent delegation\n        const taskModule = new Task(this.agent);\n        await taskModule.initialize();\n\n        const createdTask = await taskModule.createTask({\n          prompt: contextualPrompt,\n          metadata: {\n            ...node.metadata,\n            useSubAgents: true,\n            subAgentDelegation:\n              node.subAgentDelegation ||\n              (this.graph.config.subAgentCoordination === 'adaptive'\n                ? 'auto'\n                : this.graph.config.subAgentCoordination) ||\n              'auto',\n            subAgentCoordination:\n              node.subAgentCoordination ||\n              (this.graph.config.subAgentCoordination === 'adaptive'\n                ? 'sequential'\n                : this.graph.config.subAgentCoordination) ||\n              'sequential',\n          },\n        });\n\n        if (!createdTask.id) {\n          throw new GraphNodeError(\n            `Task creation failed for node ${node.name}: no task ID returned`,\n            node.id,\n            node.name,\n            'execution',\n            this.graph.id,\n            parentNodeId\n          );\n        }\n\n        try {\n          const taskResponse = await taskModule.executeTask(createdTask.id, {\n            model: node.model,\n            stream: forceStream || node.stream,\n            onChunk,\n            onToolCall,\n          });\n\n          return {\n            type: 'task',\n            taskId: createdTask.id,\n            response: taskResponse.response,\n            model: taskResponse.model,\n            usage: taskResponse.usage,\n            subAgentUsed: true,\n            delegationStrategy: node.subAgentDelegation ?? 'auto',\n            coordinationPattern: node.subAgentCoordination ?? 'sequential',\n          };\n        } catch (execError) {\n          throw new GraphNodeError(\n            `Task execution failed for node ${node.name}: ${execError instanceof Error ? execError.message : String(execError)}`,\n            node.id,\n            node.name,\n            'execution',\n            this.graph.id,\n            parentNodeId,\n            execError instanceof Error ? execError : undefined\n          );\n        }\n      } else {\n        // Use traditional Task module execution\n        const taskModule = new Task(this.agent);\n        await taskModule.initialize();\n\n        const createdTask = await taskModule.createTask({\n          prompt: enhancedPrompt,\n          graphId: this.graph.id, // Link task to graph (UUID)\n          graphNodeId: node.id, // Node ID (string)\n          metadata: node.metadata,\n        });\n\n        if (!createdTask.id) {\n          throw new GraphNodeError(\n            `Task creation failed for node ${node.name}: no task ID returned`,\n            node.id,\n            node.name,\n            'execution',\n            this.graph.id,\n            parentNodeId\n          );\n        }\n\n        // Update node with task ID\n        node.taskId = createdTask.id;\n\n        try {\n          const taskResponse = await taskModule.executeTask(createdTask.id, {\n            model: node.model,\n            stream: forceStream || node.stream,\n            onChunk,\n            onToolCall,\n          });\n\n          return {\n            type: 'task',\n            taskId: createdTask.id,\n            response: taskResponse.response,\n            model: taskResponse.model,\n            usage: taskResponse.usage,\n          };\n        } catch (execError) {\n          throw new GraphNodeError(\n            `Task execution failed for node ${node.name}: ${execError instanceof Error ? execError.message : String(execError)}`,\n            node.id,\n            node.name,\n            'execution',\n            this.graph.id,\n            parentNodeId,\n            execError instanceof Error ? execError : undefined\n          );\n        }\n      }\n    }\n\n    throw new GraphNodeError(\n      `Unknown node type: ${node.type}`,\n      node.id,\n      node.name,\n      'initialization',\n      this.graph.id,\n      parentNodeId\n    );\n  }\n\n  /**\n   * Save task response to memory with graph context\n   */\n  private async saveResponseToMemory(node: GraphNode, result: NodeExecutionResult): Promise<void> {\n    if (!this.agent || !this.agent.addMemory || !this.graph.id || result.type !== 'task') {\n      return;\n    }\n\n    try {\n      const metadata: Record<string, string | boolean | number> = {\n        type: 'assistant_response',\n        role: 'assistant',\n        graphId: this.graph.id,\n        graphNodeId: node.id,\n        taskId: result.taskId,\n      };\n      if (result.model) {\n        metadata.model = result.model;\n      }\n      if (result.usage) {\n        metadata.promptTokens = result.usage.promptTokens;\n        metadata.completionTokens = result.usage.completionTokens;\n        metadata.totalTokens = result.usage.totalTokens;\n      }\n      await this.agent.addMemory(result.response, metadata);\n      this.log('debug', `Saved assistant response to memory`, node.id);\n    } catch (error) {\n      this.log(\n        'warn',\n        `Failed to save response to memory: ${error instanceof Error ? error.message : String(error)}`,\n        node.id\n      );\n    }\n  }\n\n  private areDependenciesCompleted(node: GraphNode): boolean {\n    return node.dependencies.every((depId) => {\n      const depNode = this.graph.nodes.find((n) => n.id === depId);\n      if (!depNode) {\n        this.log('warn', `Dependency node not found: ${depId}`, node.id);\n        return false;\n      }\n      return depNode.status === 'completed';\n    });\n  }\n\n  private hasFailedDependencies(node: GraphNode): boolean {\n    return node.dependencies.some((depId) => {\n      const depNode = this.graph.nodes.find((n) => n.id === depId);\n      return depNode?.status === 'failed';\n    });\n  }\n\n  /**\n   * Build contextual information about the graph for sub-agent coordination\n   */\n  private buildGraphContext(currentNode: GraphNode): string | null {\n    const completedNodes = this.graph.nodes.filter(\n      (n) => n.status === 'completed' && n.id !== currentNode.id\n    );\n\n    if (completedNodes.length === 0) {\n      return null;\n    }\n\n    const contextParts: string[] = [];\n\n    // Add graph structure overview\n    contextParts.push(\n      `This task is part of a ${this.graph.nodes.length}-node workflow: \"${this.graph.config.name || 'Unnamed Graph'}\"`\n    );\n\n    // Add completed node summaries\n    const completedSummaries = completedNodes.map((node) => {\n      let summary = `- ${node.name}: ${node.status}`;\n      if (node.result) {\n        try {\n          const result = JSON.parse(String(node.result));\n          if (result.response) {\n            const truncatedResponse =\n              result.response.length > 150\n                ? result.response.substring(0, 150) + '...'\n                : result.response;\n            summary += ` (Result: ${truncatedResponse})`;\n          }\n        } catch {\n          // If parsing fails, skip result summary\n        }\n      }\n      return summary;\n    });\n\n    if (completedSummaries.length > 0) {\n      contextParts.push(`Previous workflow steps:\\n${completedSummaries.join('\\n')}`);\n    }\n\n    // Add remaining workflow steps\n    const pendingNodes = this.graph.nodes.filter(\n      (n) => n.status === 'pending' && n.id !== currentNode.id\n    );\n\n    if (pendingNodes.length > 0) {\n      const pendingSummaries = pendingNodes.map((node) => `- ${node.name}: pending`);\n      contextParts.push(`Upcoming workflow steps:\\n${pendingSummaries.join('\\n')}`);\n    }\n\n    return contextParts.join('\\n\\n');\n  }\n\n  /**\n   * Determine if a node should use sub-agents for execution\n   */\n  private shouldUseSubAgents(node: GraphNode): boolean {\n    // If node explicitly specifies useSubAgents, respect that\n    if (node.useSubAgents !== undefined) {\n      return node.useSubAgents;\n    }\n\n    // If graph is sub-agent aware and agent has sub-agents, use them\n    if (this.graph.config.subAgentAware && this.agent?.config.subAgents?.length) {\n      return true;\n    }\n\n    // If optimization is enabled and agent has sub-agents, use them for complex tasks\n    if (this.graph.config.optimizeSubAgentUsage && this.agent?.config.subAgents?.length) {\n      // Simple heuristic: use sub-agents for longer prompts (more complex tasks)\n      const promptLength = node.prompt?.length ?? 0;\n      return promptLength > 100; // Threshold for \"complex\" tasks\n    }\n\n    return false;\n  }\n\n  /**\n   * Iterative topological sort to prevent stack overflow on large graphs\n   * Uses Kahn's algorithm with in-degree tracking\n   */\n  private topologicalSort(): GraphNode[] {\n    const nodeMap = new Map<string, GraphNode>();\n    const inDegree = new Map<string, number>();\n    const adjacency = new Map<string, string[]>();\n\n    // Initialize data structures\n    for (const node of this.graph.nodes) {\n      nodeMap.set(node.id, node);\n      inDegree.set(node.id, 0);\n      adjacency.set(node.id, []);\n    }\n\n    // Build adjacency list and calculate in-degrees\n    for (const node of this.graph.nodes) {\n      for (const depId of node.dependencies) {\n        if (!nodeMap.has(depId)) {\n          throw new Error(`Dependency node not found: ${depId}`);\n        }\n        // depId -> node.id (dependency points to dependent)\n        const adj = adjacency.get(depId);\n        if (adj) {\n          adj.push(node.id);\n        }\n        inDegree.set(node.id, (inDegree.get(node.id) || 0) + 1);\n      }\n    }\n\n    // Sort nodes by priority for deterministic ordering (higher priority first)\n    const nodesByPriority = [...this.graph.nodes].sort((a, b) => b.priority - a.priority);\n\n    // Initialize queue with nodes that have no dependencies (in-degree = 0)\n    const queue: string[] = [];\n    for (const node of nodesByPriority) {\n      if ((inDegree.get(node.id) || 0) === 0) {\n        queue.push(node.id);\n      }\n    }\n\n    const result: GraphNode[] = [];\n    let processedCount = 0;\n\n    // Process nodes iteratively\n    while (queue.length > 0) {\n      // Sort queue by priority to maintain priority ordering\n      queue.sort((a, b) => {\n        const nodeA = nodeMap.get(a);\n        const nodeB = nodeMap.get(b);\n        return (nodeB?.priority || 0) - (nodeA?.priority || 0);\n      });\n\n      const nodeId = queue.shift();\n      // This should never happen due to while condition, but check for safety\n      if (!nodeId) {\n        throw new Error('Queue unexpectedly empty during topological sort');\n      }\n      const node = nodeMap.get(nodeId);\n      if (!node) {\n        throw new Error(`Node ${nodeId} not found during topological sort`);\n      }\n\n      result.push(node);\n      processedCount++;\n\n      // Reduce in-degree for all dependent nodes\n      const dependents = adjacency.get(nodeId) || [];\n      for (const depId of dependents) {\n        const newDegree = (inDegree.get(depId) || 1) - 1;\n        inDegree.set(depId, newDegree);\n\n        // If in-degree becomes 0, add to queue\n        if (newDegree === 0) {\n          queue.push(depId);\n        }\n      }\n    }\n\n    // Check for circular dependency\n    if (processedCount !== this.graph.nodes.length) {\n      // Find nodes involved in cycle for better error message\n      const unprocessedNodes = this.graph.nodes\n        .filter((n) => !result.find((r) => r.id === n.id))\n        .map((n) => n.name || n.id);\n      throw new Error(\n        `Circular dependency detected involving nodes: ${unprocessedNodes.join(', ')}`\n      );\n    }\n\n    return result;\n  }\n\n  private static readonly MAX_EXECUTION_LOG_SIZE = 10000;\n\n  private log(level: 'info' | 'warn' | 'error' | 'debug', message: string, nodeId?: string) {\n    const entry: GraphExecutionLogEntry = {\n      timestamp: new Date(),\n      level,\n      message,\n      nodeId,\n    };\n\n    // Bounds check: prevent unbounded growth of execution log\n    if (this.graph.executionLog.length >= Graph.MAX_EXECUTION_LOG_SIZE) {\n      // Remove oldest entries (keep last 80%)\n      const keepCount = Math.floor(Graph.MAX_EXECUTION_LOG_SIZE * 0.8);\n      this.graph.executionLog = this.graph.executionLog.slice(-keepCount);\n    }\n\n    this.graph.executionLog.push(entry);\n\n    // Also log to agent's logger if available\n    if (this.logger) {\n      const nodeContext = nodeId ? ` [Node: ${nodeId}]` : '';\n      const fullMessage = message + nodeContext;\n\n      // Use the logger's log method with 'Graph' as module name\n      // Check if logger has the public log method (it should based on implementation)\n      if ('log' in this.logger && typeof this.logger.log === 'function') {\n        (\n          this.logger as {\n            log: (\n              level: string,\n              message: string,\n              module?: string,\n              data?: LogData,\n              error?: Error,\n              agentName?: string\n            ) => void;\n          }\n        ).log(\n          level,\n          fullMessage,\n          'Graph',\n          undefined,\n          level === 'error' ? new Error(fullMessage) : undefined,\n          this.agent?.name\n        );\n      } else {\n        // Fallback to standard methods if log method is not available\n        switch (level) {\n          case 'info':\n            this.logger.info(fullMessage, undefined, this.agent?.name);\n            break;\n          case 'warn':\n            this.logger.warn(fullMessage, undefined, this.agent?.name);\n            break;\n          case 'error':\n            this.logger.error(fullMessage, undefined, undefined, this.agent?.name);\n            break;\n          case 'debug':\n            this.logger.debug(fullMessage, undefined, this.agent?.name);\n            break;\n        }\n      }\n    }\n  }\n\n  private generateNodeId(): string {\n    return `node_${crypto.randomUUID()}`;\n  }\n\n  private generateEdgeId(): string {\n    return `edge_${crypto.randomUUID()}`;\n  }\n\n  // Getters\n  getGraph(): GraphType {\n    return this.graph;\n  }\n\n  getNodes(): GraphNode[] {\n    return this.graph.nodes;\n  }\n\n  getEdges(): GraphEdge[] {\n    return this.graph.edges;\n  }\n\n  getStatus(): GraphExecutionStatus {\n    return this.graph.status;\n  }\n\n  setStatus(status: GraphExecutionStatus): void {\n    this.graph.status = status;\n    this.graph.updatedAt = new Date();\n  }\n\n  getExecutionLog(): GraphExecutionLogEntry[] {\n    return this.graph.executionLog;\n  }\n\n  // Utility methods\n  getNode(id: string): GraphNode | undefined {\n    return this.graph.nodes.find((n) => n.id === id);\n  }\n\n  getNodesByType(type: 'agent' | 'task'): GraphNode[] {\n    return this.graph.nodes.filter((n) => n.type === type);\n  }\n\n  getNodesByStatus(status: GraphNode['status']): GraphNode[] {\n    return this.graph.nodes.filter((n) => n.status === status);\n  }\n\n  // Memory methods for graph\n  // Note: Extended version with graphId filtering is at the end of the class\n\n  async searchMemories(query: string, limit?: number): Promise<MemoryType[]> {\n    if (!this.agent) {\n      throw new Error('No agent available for this graph');\n    }\n\n    if (!this.agent.hasMemory()) {\n      return [];\n    }\n\n    // Check if agent has searchMemories method (dynamically bound)\n    if (\n      'searchMemories' in this.agent &&\n      typeof (\n        this.agent as Agent & {\n          searchMemories?: (query: string, limit?: number) => Promise<MemoryType[]>;\n        }\n      ).searchMemories === 'function'\n    ) {\n      try {\n        const agentWithMemory = this.agent as Agent & {\n          searchMemories: (query: string, limit?: number) => Promise<MemoryType[]>;\n        };\n        return await agentWithMemory.searchMemories(query, limit);\n      } catch (error) {\n        this.log(\n          'error',\n          `Failed to search memories: ${error instanceof Error ? error.message : String(error)}`\n        );\n        return [];\n      }\n    }\n    return [];\n  }\n\n  // Persistence methods\n  async save(): Promise<string> {\n    await this.initialize();\n    try {\n      const storage = getGraphStorage();\n      const graphId = await storage.saveGraph(this.graph);\n\n      this.graph.id = graphId;\n      this.graph.config.id = graphId;\n      return graphId;\n    } catch (error) {\n      this.log(\n        'error',\n        `Failed to save graph: ${error instanceof Error ? error.message : String(error)}`\n      );\n      throw error;\n    }\n  }\n\n  async update(): Promise<void> {\n    await this.initialize();\n    if (!this.graph.id) {\n      throw new Error('Graph must be saved before updating');\n    }\n    try {\n      const storage = getGraphStorage();\n      await storage.updateGraph(this.graph.id, this.graph);\n    } catch (error) {\n      this.log(\n        'error',\n        `Failed to update graph: ${error instanceof Error ? error.message : String(error)}`\n      );\n      throw error;\n    }\n  }\n\n  async delete(): Promise<boolean> {\n    await this.initialize();\n    if (!this.graph.id) {\n      throw new Error('Graph must be saved before deleting');\n    }\n    try {\n      const storage = getGraphStorage();\n      return await storage.deleteGraph(this.graph.id);\n    } catch (error) {\n      this.log(\n        'error',\n        `Failed to delete graph: ${error instanceof Error ? error.message : String(error)}`\n      );\n      throw error;\n    }\n  }\n\n  // Ultra-simplified scheduler - complex scheduling methods removed\n  // Schedule detection happens at runtime with simple string parsing\n\n  // Ultra-simplified scheduler - these methods not needed\n  // Use simple schedule strings in addTaskNode() instead\n\n  // Static methods\n  static async findById(graphId: string, agent?: IAgent): Promise<Graph | null> {\n    const storage = getGraphStorage();\n    const graphData = await storage.loadGraph(graphId);\n\n    if (!graphData) {\n      return null;\n    }\n\n    const graph = new Graph(graphData.config, agent);\n    graph.graph = graphData;\n\n    // Restore lastNodeId for autoLink to work on loaded graphs\n    if (graphData.nodes.length > 0) {\n      // Find the most recently created node\n      const sortedNodes = [...graphData.nodes].sort((a, b) => {\n        const timeA = a.createdAt ? new Date(a.createdAt).getTime() : 0;\n        const timeB = b.createdAt ? new Date(b.createdAt).getTime() : 0;\n        return timeB - timeA;\n      });\n      graph.lastNodeId = sortedNodes[0].id;\n    }\n\n    return graph;\n  }\n\n  static async list(): Promise<{ id: string; name: string; status: string; createdAt: Date }[]> {\n    // UUID\n    const storage = getGraphStorage();\n    return await storage.listGraphs();\n  }\n\n  static async create(config: GraphConfig, agent?: IAgent): Promise<Graph> {\n    const graph = new Graph(config, agent);\n    await graph.save();\n    return graph;\n  }\n\n  // Sub-agent coordination utilities\n\n  /**\n   * Enable sub-agent awareness for all task nodes in the graph\n   */\n  enableSubAgentAwareness(): void {\n    this.graph.config.subAgentAware = true;\n    this.graph.updatedAt = new Date();\n    this.log('info', 'Sub-agent awareness enabled for graph');\n  }\n\n  /**\n   * Configure sub-agent delegation for specific nodes\n   */\n  configureSubAgentDelegation(\n    nodeIds: string[],\n    delegation: 'auto' | 'manual' | 'sequential'\n  ): void {\n    let configuredCount = 0;\n\n    nodeIds.forEach((nodeId) => {\n      const node = this.graph.nodes.find((n) => n.id === nodeId);\n      if (node && node.type === 'task') {\n        node.subAgentDelegation = delegation;\n        node.updatedAt = new Date();\n        configuredCount++;\n      }\n    });\n\n    this.graph.updatedAt = new Date();\n    this.log(\n      'info',\n      `Configured sub-agent delegation (${delegation}) for ${configuredCount} nodes`\n    );\n  }\n\n  /**\n   * Configure sub-agent coordination for specific nodes\n   */\n  configureSubAgentCoordination(nodeIds: string[], coordination: 'parallel' | 'sequential'): void {\n    let configuredCount = 0;\n\n    nodeIds.forEach((nodeId) => {\n      const node = this.graph.nodes.find((n) => n.id === nodeId);\n      if (node && node.type === 'task') {\n        node.subAgentCoordination = coordination;\n        node.updatedAt = new Date();\n        configuredCount++;\n      }\n    });\n\n    this.graph.updatedAt = new Date();\n    this.log(\n      'info',\n      `Configured sub-agent coordination (${coordination}) for ${configuredCount} nodes`\n    );\n  }\n\n  /**\n   * Get nodes that are currently using sub-agents\n   */\n  getSubAgentEnabledNodes(): GraphNode[] {\n    return this.graph.nodes.filter(\n      (node) =>\n        node.type === 'task' &&\n        (node.useSubAgents === true ||\n          (this.graph.config.subAgentAware && this.agent?.config.subAgents?.length))\n    );\n  }\n\n  /**\n   * Get sub-agent usage statistics for the graph\n   */\n  getSubAgentStats(): {\n    totalNodes: number;\n    subAgentEnabledNodes: number;\n    delegationStrategies: Record<string, number>;\n    coordinationPatterns: Record<string, number>;\n  } {\n    const taskNodes = this.graph.nodes.filter((n) => n.type === 'task');\n    const subAgentNodes = this.getSubAgentEnabledNodes();\n\n    const delegationStats: Record<string, number> = {};\n    const coordinationStats: Record<string, number> = {};\n\n    subAgentNodes.forEach((node) => {\n      const delegation =\n        node.subAgentDelegation ?? this.graph.config.subAgentCoordination ?? 'auto';\n      const coordination =\n        node.subAgentCoordination ?? this.graph.config.subAgentCoordination ?? 'sequential';\n\n      delegationStats[delegation] = (delegationStats[delegation] ?? 0) + 1;\n      coordinationStats[coordination] = (coordinationStats[coordination] ?? 0) + 1;\n    });\n\n    return {\n      totalNodes: taskNodes.length,\n      subAgentEnabledNodes: subAgentNodes.length,\n      delegationStrategies: delegationStats,\n      coordinationPatterns: coordinationStats,\n    };\n  }\n\n  /**\n   * Optimize sub-agent usage across the graph based on task complexity\n   */\n  optimizeSubAgentUsage(): void {\n    if (!this.agent?.config.subAgents?.length) {\n      this.log('warn', 'No sub-agents available for optimization');\n      return;\n    }\n\n    this.graph.config.optimizeSubAgentUsage = true;\n\n    // Enable sub-agent awareness\n    this.graph.config.subAgentAware = true;\n\n    // Analyze task complexity and configure coordination\n    this.graph.nodes.forEach((node) => {\n      if (node.type === 'task' && node.prompt) {\n        const promptLength = node.prompt.length;\n        const hasDependencies = node.dependencies.length > 0;\n\n        // Complex tasks: long prompts or nodes with dependencies\n        if (promptLength > 200 || hasDependencies) {\n          node.useSubAgents = true;\n          node.subAgentDelegation = 'auto';\n          node.subAgentCoordination = hasDependencies ? 'sequential' : 'parallel';\n        }\n        // Simple tasks: short prompts, no dependencies\n        else if (promptLength <= 100) {\n          node.useSubAgents = false; // Use single agent for efficiency\n        }\n        // Medium tasks: use default graph settings\n\n        node.updatedAt = new Date();\n      }\n    });\n\n    this.graph.updatedAt = new Date();\n    this.log('info', 'Optimized sub-agent usage across graph nodes');\n  }\n\n  /**\n   * Monitor and analyze sub-agent performance during execution\n   */\n  getSubAgentPerformanceMetrics(): {\n    nodePerformance: Array<{\n      nodeId: string;\n      nodeName: string;\n      usedSubAgents: boolean;\n      delegationStrategy?: string;\n      coordinationPattern?: string;\n      executionTime?: number;\n      status: string;\n    }>;\n    overallMetrics: {\n      totalNodes: number;\n      subAgentNodes: number;\n      averageExecutionTime: number;\n      successRate: number;\n      subAgentEfficiency: number;\n    };\n  } {\n    const nodeMetrics = this.graph.nodes.map((node) => {\n      const nodeMetric: {\n        nodeId: string;\n        nodeName: string;\n        usedSubAgents: boolean;\n        status: string;\n        delegationStrategy?: string;\n        coordinationPattern?: string;\n        executionTime?: number;\n      } = {\n        nodeId: node.id,\n        nodeName: node.name,\n        usedSubAgents: this.shouldUseSubAgents(node),\n        status: node.status,\n      };\n\n      if (this.shouldUseSubAgents(node)) {\n        nodeMetric.delegationStrategy =\n          node.subAgentDelegation || this.graph.config.subAgentCoordination || 'auto';\n        nodeMetric.coordinationPattern =\n          node.subAgentCoordination || this.graph.config.subAgentCoordination || 'sequential';\n      }\n\n      // Calculate execution time if available\n      if (node.status === 'completed' && this.graph.startedAt && this.graph.completedAt) {\n        // Estimate based on graph timing (simplified)\n        nodeMetric.executionTime =\n          this.graph.completedAt.getTime() - this.graph.startedAt.getTime();\n      }\n\n      return nodeMetric;\n    });\n\n    const subAgentNodes = nodeMetrics.filter((n) => n.usedSubAgents);\n    const completedNodes = nodeMetrics.filter((n) => n.status === 'completed');\n    const totalExecutionTime = nodeMetrics.reduce((sum, n) => sum + (n.executionTime ?? 0), 0);\n\n    return {\n      nodePerformance: nodeMetrics,\n      overallMetrics: {\n        totalNodes: this.graph.nodes.length,\n        subAgentNodes: subAgentNodes.length,\n        averageExecutionTime: totalExecutionTime / Math.max(completedNodes.length, 1),\n        successRate: completedNodes.length / this.graph.nodes.length,\n        subAgentEfficiency:\n          subAgentNodes.filter((n) => n.status === 'completed').length /\n          Math.max(subAgentNodes.length, 1),\n      },\n    };\n  }\n\n  /**\n   * Benchmark different sub-agent coordination strategies\n   */\n  async benchmarkSubAgentStrategies(\n    testPrompt: string = 'Analyze market trends and provide recommendations'\n  ): Promise<{\n    strategies: Record<\n      string,\n      {\n        duration: number;\n        success: boolean;\n        nodeResults: number;\n      }\n    >;\n    recommendation: string;\n  }> {\n    if (!this.agent?.config.subAgents?.length) {\n      throw new Error('No sub-agents available for benchmarking');\n    }\n\n    const strategies = ['parallel', 'sequential'] as const;\n    const results: Record<\n      string,\n      {\n        duration: number;\n        success: boolean;\n        nodeResults: number;\n      }\n    > = {};\n\n    for (const strategy of strategies) {\n      // Create test node\n      const testNodeId = this.addTaskNode({\n        name: `Benchmark Test - ${strategy}`,\n        prompt: testPrompt,\n        useSubAgents: true,\n        subAgentDelegation: 'auto',\n        subAgentCoordination: strategy,\n      });\n\n      const startTime = Date.now();\n\n      try {\n        // Execute just this node\n        const testNode = this.graph.nodes.find((n) => n.id === testNodeId);\n        if (!testNode) {\n          throw new Error(`Test node ${testNodeId} not found`);\n        }\n        await this.executeNode(testNode, false, undefined);\n\n        const duration = Date.now() - startTime;\n        results[strategy] = {\n          duration,\n          success: true,\n          nodeResults: 1,\n        };\n\n        this.log('info', `Benchmark ${strategy}: ${duration}ms`);\n      } catch (error) {\n        const duration = Date.now() - startTime;\n        results[strategy] = {\n          duration,\n          success: false,\n          nodeResults: 0,\n        };\n\n        this.log(\n          'error',\n          `Benchmark ${strategy} failed: ${error instanceof Error ? error.message : 'Unknown error'}`\n        );\n      }\n\n      // Remove test node and any associated edges\n      this.graph.nodes = this.graph.nodes.filter((n) => n.id !== testNodeId);\n      this.graph.edges = this.graph.edges.filter(\n        (e) => e.fromNodeId !== testNodeId && e.toNodeId !== testNodeId\n      );\n\n      // Reset lastNodeId if it was the test node to prevent stale references\n      if (this.lastNodeId === testNodeId) {\n        const remainingNodes = this.graph.nodes;\n        if (remainingNodes.length > 0) {\n          // Restore to the most recently created remaining node\n          const sortedNodes = [...remainingNodes].sort((a, b) => {\n            const timeA = a.createdAt ? new Date(a.createdAt).getTime() : 0;\n            const timeB = b.createdAt ? new Date(b.createdAt).getTime() : 0;\n            return timeB - timeA;\n          });\n          this.lastNodeId = sortedNodes[0].id;\n        } else {\n          this.lastNodeId = null;\n        }\n      }\n    }\n\n    // Determine best strategy\n    const successfulStrategies = Object.entries(results).filter(([, result]) => result.success);\n    const recommendation =\n      successfulStrategies.length > 0\n        ? successfulStrategies.reduce((best, current) =>\n            current[1].duration < best[1].duration ? current : best\n          )[0]\n        : 'sequential'; // Default fallback\n\n    return {\n      strategies: results,\n      recommendation: `Based on performance testing, '${recommendation}' strategy is recommended for similar tasks.`,\n    };\n  }\n\n  /**\n   * Dynamically adjust sub-agent coordination based on current performance\n   */\n  autoOptimizeSubAgentCoordination(): void {\n    if (!this.agent?.config.subAgents?.length) {\n      this.log('warn', 'No sub-agents available for auto-optimization');\n      return;\n    }\n\n    const metrics = this.getSubAgentPerformanceMetrics();\n\n    // Analyze current performance\n    const subAgentEfficiency = metrics.overallMetrics.subAgentEfficiency;\n\n    this.graph.nodes.forEach((node) => {\n      if (node.type === 'task' && node.status === 'pending') {\n        const promptComplexity = node.prompt?.length ?? 0;\n        const hasDependencies = node.dependencies.length > 0;\n\n        // Optimize based on current performance and task characteristics\n        if (subAgentEfficiency > 0.8) {\n          // High efficiency - can use more aggressive parallelization\n          if (promptComplexity > 300 && !hasDependencies) {\n            node.subAgentCoordination = 'parallel';\n            node.useSubAgents = true;\n          }\n        } else if (subAgentEfficiency < 0.6) {\n          // Lower efficiency - use more conservative sequential approach\n          if (promptComplexity > 150) {\n            node.subAgentCoordination = 'sequential';\n            node.useSubAgents = true;\n          } else {\n            node.useSubAgents = false; // Use single agent for simple tasks\n          }\n        }\n\n        // Always use sequential for dependent tasks\n        if (hasDependencies) {\n          node.subAgentCoordination = 'sequential';\n        }\n\n        node.updatedAt = new Date();\n      }\n    });\n\n    this.graph.updatedAt = new Date();\n    this.log(\n      'info',\n      `Auto-optimized sub-agent coordination based on efficiency: ${subAgentEfficiency.toFixed(2)}`\n    );\n  }\n\n  /**\n   * Generate performance report for sub-agent usage\n   */\n  generateSubAgentPerformanceReport(): string {\n    const stats = this.getSubAgentStats();\n    const metrics = this.getSubAgentPerformanceMetrics();\n\n    const report = [\n      '=== Sub-Agent Performance Report ===',\n      '',\n      `Graph: ${this.graph.config.name || 'Unnamed'}`,\n      `Total Nodes: ${stats.totalNodes}`,\n      `Sub-Agent Enabled: ${stats.subAgentEnabledNodes}`,\n      `Success Rate: ${(metrics.overallMetrics.successRate * 100).toFixed(1)}%`,\n      `Sub-Agent Efficiency: ${(metrics.overallMetrics.subAgentEfficiency * 100).toFixed(1)}%`,\n      '',\n      '--- Delegation Strategies ---',\n      ...Object.entries(stats.delegationStrategies).map(\n        ([strategy, count]) => `${strategy}: ${count} nodes`\n      ),\n      '',\n      '--- Coordination Patterns ---',\n      ...Object.entries(stats.coordinationPatterns).map(\n        ([pattern, count]) => `${pattern}: ${count} nodes`\n      ),\n      '',\n      '--- Node Performance ---',\n      ...metrics.nodePerformance.map(\n        (node) =>\n          `${node.nodeName}: ${node.status} ${node.usedSubAgents ? `(${node.delegationStrategy}/${node.coordinationPattern})` : '(single agent)'}`\n      ),\n      '',\n      '--- Recommendations ---',\n    ];\n\n    // Add recommendations based on analysis\n    if (metrics.overallMetrics.subAgentEfficiency < 0.7) {\n      report.push('• Consider optimizing sub-agent delegation strategies');\n      report.push('• Review task complexity vs coordination patterns');\n    }\n\n    if (stats.subAgentEnabledNodes < stats.totalNodes * 0.3) {\n      report.push('• Consider enabling sub-agents for more complex tasks');\n    }\n\n    if (metrics.overallMetrics.successRate < 0.9) {\n      report.push('• Review failed nodes and optimize task dependencies');\n    }\n\n    return report.join('\\n');\n  }\n\n  /**\n   * Get all tasks created by this graph\n   */\n  async getTasks(options?: {\n    limit?: number;\n    offset?: number;\n    status?: string;\n  }): Promise<unknown[]> {\n    if (!this.graph.id) {\n      throw new Error('Graph must be saved before querying tasks');\n    }\n\n    if (!this.agent) {\n      throw new Error('No agent available for this graph');\n    }\n\n    const taskModule = new Task(this.agent);\n    await taskModule.initialize();\n\n    return taskModule.listTasks({\n      graphId: this.graph.id,\n      limit: options?.limit,\n      offset: options?.offset,\n      status: options?.status as 'pending' | 'in_progress' | 'completed' | 'failed' | undefined,\n    });\n  }\n\n  /**\n   * Get task for a specific node\n   */\n  async getTaskByNode(nodeId: string): Promise<unknown | null> {\n    const node = this.getNode(nodeId);\n    if (!node || node.type !== 'task' || !node.taskId) {\n      return null;\n    }\n\n    if (!this.agent) {\n      throw new Error('No agent available for this graph');\n    }\n\n    const taskModule = new Task(this.agent);\n    await taskModule.initialize();\n\n    return taskModule.getTask(node.taskId);\n  }\n\n  /**\n   * Get aggregated usage statistics for the graph\n   */\n  getUsage(): GraphUsage | undefined {\n    return this.graph.usage || this.aggregateUsage();\n  }\n\n  /**\n   * Get usage statistics for a specific node\n   */\n  getNodeUsage(nodeId: string): NodeUsage | undefined {\n    const node = this.graph.nodes.find((n) => n.id === nodeId);\n    return node?.usage;\n  }\n\n  /**\n   * Get total token count across all nodes\n   */\n  getTotalTokens(): number {\n    const usage = this.getUsage();\n    return usage?.totalTokens ?? 0;\n  }\n\n  /**\n   * Get total cost across all nodes\n   */\n  getTotalCost(): number {\n    const usage = this.getUsage();\n    return usage?.totalCost ?? 0;\n  }\n\n  /**\n   * Get context size information\n   */\n  getContextInfo(): {\n    currentTokens: number;\n    maxTokens: number;\n    utilization: number;\n    isWarning: boolean;\n    isExceeded: boolean;\n  } | null {\n    if (!this.agent) return null;\n\n    try {\n      const contextWindow = (this.agent as Agent).getContextWindow?.();\n      if (!contextWindow) return null;\n\n      const { totalTokens, maxTokens } = contextWindow;\n      const maxContextTokens = this.graph.config.maxContextTokens || maxTokens;\n      const warningThreshold = this.graph.config.contextWarningThreshold || 0.8;\n      const utilization = totalTokens / maxContextTokens;\n\n      return {\n        currentTokens: totalTokens,\n        maxTokens: maxContextTokens,\n        utilization,\n        isWarning: utilization >= warningThreshold,\n        isExceeded: utilization >= 1.0,\n      };\n    } catch {\n      return null;\n    }\n  }\n\n  /**\n   * Get usage summary as formatted string\n   */\n  getUsageSummary(): string {\n    const usage = this.getUsage();\n    if (!usage) return 'No usage data available';\n\n    const lines = [\n      `Total Tokens: ${usage.totalTokens.toLocaleString()}`,\n      `  - Prompt: ${usage.totalPromptTokens.toLocaleString()}`,\n      `  - Completion: ${usage.totalCompletionTokens.toLocaleString()}`,\n      `  - Context: ${usage.totalContextTokens.toLocaleString()}`,\n    ];\n\n    if (usage.totalCost > 0) {\n      lines.push(`Total Cost: $${usage.totalCost.toFixed(4)}`);\n    }\n\n    if (usage.modelsUsed.length > 0) {\n      lines.push(`Models Used: ${usage.modelsUsed.join(', ')}`);\n    }\n\n    lines.push(`Nodes: ${Object.keys(usage.nodeUsages).length}`);\n\n    return lines.join('\\n');\n  }\n\n  /**\n   * Get all memories created during this graph execution\n   */\n  async getMemories(options?: { limit?: number; sessionId?: string }): Promise<unknown[]> {\n    if (!this.graph.id) {\n      throw new Error('Graph must be saved before querying memories');\n    }\n\n    if (!this.agent) {\n      throw new Error('No agent available for this graph');\n    }\n\n    const memoryModule = new Memory(this.agent);\n    await memoryModule.initialize();\n\n    return memoryModule.listMemories({\n      graphId: this.graph.id,\n      limit: options?.limit,\n      sessionId: options?.sessionId,\n    });\n  }\n\n  /**\n   * Destroy graph resources and free memory.\n   * Call this when the graph is no longer needed.\n   */\n  async destroy(): Promise<void> {\n    // Clear active timeouts to prevent memory leaks\n    if (this.overallTimeoutId) {\n      clearTimeout(this.overallTimeoutId);\n      this.overallTimeoutId = null;\n    }\n\n    // Clear all node timeouts\n    for (const [, timeoutId] of this.activeNodeTimeouts.entries()) {\n      clearTimeout(timeoutId);\n    }\n    this.activeNodeTimeouts.clear();\n\n    // Release execution lock if held\n    if (this.releaseLock) {\n      try {\n        this.releaseLock();\n      } catch {\n        // Ignore errors during lock release\n      }\n    }\n\n    // Clear lock references\n    this.executionLock = null;\n    this.releaseLock = null;\n\n    // Clear graph data\n    this.graph.nodes = [];\n    this.graph.edges = [];\n    this.graph.executionLog = [];\n    this.lastNodeId = null;\n\n    // Clear knex reference (shared database, don't close)\n    this.knex = null;\n\n    // Clear agent reference\n    this.agent = undefined;\n    this.logger = undefined;\n\n    // Reset initialization state\n    this.initialized = false;\n  }\n}\n\nexport * from './types';\n","import { Schedule, RecurrencePattern } from './types';\n\nexport interface ParsedSchedule {\n  schedule: Schedule;\n  isValid: boolean;\n  error?: string;\n}\n\n/**\n * Parses simple schedule strings into full Schedule objects\n *\n * Supported formats:\n * - 'daily@07:00' → daily at 7 AM\n * - 'weekly@monday@09:00' → weekly on Monday at 9 AM\n * - 'monthly@1@10:00' → monthly on 1st day at 10 AM\n * - 'hourly' → every hour\n * - '@15:30' → once today at 3:30 PM\n * - 'once@2024-12-25@10:00' → once on specific date\n * - 'after:5s' → run after 5 seconds delay\n * - 'after:30m' → run after 30 minutes delay\n * - 'after:2h' → run after 2 hours delay\n */\nexport function parseScheduleString(scheduleStr: string, timezone: string = 'UTC'): ParsedSchedule {\n  try {\n    // Check for empty or whitespace-only input first\n    if (!scheduleStr || scheduleStr.trim() === '') {\n      return {\n        schedule: {} as Schedule,\n        isValid: false,\n        error: 'Empty schedule string',\n      };\n    }\n\n    const trimmed = scheduleStr.trim().toLowerCase();\n\n    // Handle 'after:Xs/m/h' format for delayed execution\n    if (trimmed.startsWith('after:')) {\n      return parseAfterDelay(trimmed, timezone);\n    }\n\n    const parts = trimmed.split('@');\n\n    if (parts.length === 0) {\n      return {\n        schedule: {} as Schedule,\n        isValid: false,\n        error: 'Empty schedule string',\n      };\n    }\n\n    const pattern = parts[0];\n\n    // Handle different patterns\n    switch (pattern) {\n      case 'hourly':\n        return parseHourly(timezone);\n\n      case 'daily':\n        if (parts.length < 2) {\n          return {\n            schedule: {} as Schedule,\n            isValid: false,\n            error: 'Daily schedule requires time (e.g., daily@07:00)',\n          };\n        }\n        return parseDaily(parts[1], timezone);\n\n      case 'weekly':\n        if (parts.length < 3) {\n          return {\n            schedule: {} as Schedule,\n            isValid: false,\n            error: 'Weekly schedule requires day and time (e.g., weekly@monday@09:00)',\n          };\n        }\n        return parseWeekly(parts[1], parts[2], timezone);\n\n      case 'monthly':\n        if (parts.length < 3) {\n          return {\n            schedule: {} as Schedule,\n            isValid: false,\n            error: 'Monthly schedule requires day and time (e.g., monthly@1@10:00)',\n          };\n        }\n        return parseMonthly(parts[1], parts[2], timezone);\n\n      case 'once':\n        if (parts.length < 3) {\n          return {\n            schedule: {} as Schedule,\n            isValid: false,\n            error: 'Once schedule requires date and time (e.g., once@2024-12-25@10:00)',\n          };\n        }\n        return parseOnce(parts[1], parts[2], timezone);\n\n      case '':\n        // Handle '@15:30' format (once today)\n        if (parts.length >= 2) {\n          const isoString = new Date().toISOString();\n          const dateParts = isoString.split('T');\n          const today = dateParts[0] ?? isoString.slice(0, 10); // Fallback to slice if split fails\n          return parseOnce(today, parts[1], timezone);\n        }\n        return {\n          schedule: {} as Schedule,\n          isValid: false,\n          error: 'Invalid schedule format',\n        };\n\n      default:\n        return {\n          schedule: {} as Schedule,\n          isValid: false,\n          error: `Unknown schedule pattern: ${pattern}`,\n        };\n    }\n  } catch (error) {\n    return {\n      schedule: {} as Schedule,\n      isValid: false,\n      error: `Parse error: ${error instanceof Error ? error.message : 'Unknown error'}`,\n    };\n  }\n}\n\nfunction parseHourly(timezone: string): ParsedSchedule {\n  const now = new Date();\n  const nextHour = new Date(now);\n  nextHour.setHours(now.getHours() + 1, 0, 0, 0);\n\n  return {\n    schedule: {\n      type: 'recurring',\n      executeAt: nextHour,\n      recurrence: {\n        pattern: 'custom' as RecurrencePattern,\n        interval: 1,\n        customCron: '0 * * * *', // Every hour\n      },\n      timezone,\n    },\n    isValid: true,\n  };\n}\n\nfunction parseDaily(timeStr: string, timezone: string): ParsedSchedule {\n  const executeAt = parseTime(timeStr, timezone);\n  if (!executeAt.isValid || !executeAt.time) {\n    return {\n      schedule: {} as Schedule,\n      isValid: false,\n      error: executeAt.error ?? 'Failed to parse time',\n    };\n  }\n\n  return {\n    schedule: {\n      type: 'recurring',\n      executeAt: executeAt.time,\n      recurrence: {\n        pattern: 'daily' as RecurrencePattern,\n        interval: 1,\n      },\n      timezone,\n    },\n    isValid: true,\n  };\n}\n\nfunction parseWeekly(dayStr: string, timeStr: string, timezone: string): ParsedSchedule {\n  const dayOfWeek = parseDayOfWeek(dayStr);\n  if (dayOfWeek === -1) {\n    return {\n      schedule: {} as Schedule,\n      isValid: false,\n      error: `Invalid day of week: ${dayStr}`,\n    };\n  }\n\n  const executeAt = parseTime(timeStr, timezone);\n  if (!executeAt.isValid || !executeAt.time) {\n    return {\n      schedule: {} as Schedule,\n      isValid: false,\n      error: executeAt.error ?? 'Failed to parse time',\n    };\n  }\n\n  // Find next occurrence of this day\n  const nextDate = getNextWeekday(dayOfWeek, executeAt.time);\n\n  return {\n    schedule: {\n      type: 'recurring',\n      executeAt: nextDate,\n      recurrence: {\n        pattern: 'weekly' as RecurrencePattern,\n        interval: 1,\n        daysOfWeek: [dayOfWeek],\n      },\n      timezone,\n    },\n    isValid: true,\n  };\n}\n\nfunction parseMonthly(dayStr: string, timeStr: string, timezone: string): ParsedSchedule {\n  const dayOfMonth = parseInt(dayStr);\n  if (isNaN(dayOfMonth) || dayOfMonth < 1 || dayOfMonth > 31) {\n    return {\n      schedule: {} as Schedule,\n      isValid: false,\n      error: `Invalid day of month: ${dayStr}`,\n    };\n  }\n\n  const executeAt = parseTime(timeStr, timezone);\n  if (!executeAt.isValid || !executeAt.time) {\n    return {\n      schedule: {} as Schedule,\n      isValid: false,\n      error: executeAt.error ?? 'Failed to parse time',\n    };\n  }\n\n  // Find next occurrence of this day of month\n  const nextDate = getNextMonthDay(dayOfMonth, executeAt.time);\n\n  return {\n    schedule: {\n      type: 'recurring',\n      executeAt: nextDate,\n      recurrence: {\n        pattern: 'monthly' as RecurrencePattern,\n        interval: 1,\n        dayOfMonth,\n      },\n      timezone,\n    },\n    isValid: true,\n  };\n}\n\nfunction parseOnce(dateStr: string, timeStr: string, timezone: string): ParsedSchedule {\n  const date = new Date(dateStr);\n  if (isNaN(date.getTime())) {\n    return {\n      schedule: {} as Schedule,\n      isValid: false,\n      error: `Invalid date: ${dateStr}`,\n    };\n  }\n\n  const executeAt = parseTime(timeStr, timezone);\n  if (!executeAt.isValid || !executeAt.time) {\n    return {\n      schedule: {} as Schedule,\n      isValid: false,\n      error: executeAt.error ?? 'Failed to parse time',\n    };\n  }\n\n  // Combine date and time\n  const finalDate = new Date(date);\n  finalDate.setHours(executeAt.time.getHours(), executeAt.time.getMinutes(), 0, 0);\n\n  return {\n    schedule: {\n      type: 'once',\n      executeAt: finalDate,\n      timezone,\n    },\n    isValid: true,\n  };\n}\n\ninterface ParsedTime {\n  isValid: boolean;\n  time?: Date;\n  error?: string;\n}\n\nfunction parseTime(timeStr: string, timezone?: string): ParsedTime {\n  const timeMatch = timeStr.match(/^(\\d{1,2}):(\\d{2})$/);\n  if (!timeMatch) {\n    return {\n      isValid: false,\n      error: `Invalid time format: ${timeStr}. Use HH:MM format.`,\n    };\n  }\n\n  const hours = parseInt(timeMatch[1]);\n  const minutes = parseInt(timeMatch[2]);\n\n  if (hours < 0 || hours > 23 || minutes < 0 || minutes > 59) {\n    return {\n      isValid: false,\n      error: `Invalid time: ${timeStr}. Hours must be 0-23, minutes 0-59.`,\n    };\n  }\n\n  // Use timezone parameter for proper timezone-aware date creation\n  const now = timezone\n    ? new Date(new Date().toLocaleString('en-US', { timeZone: timezone }))\n    : new Date();\n  now.setHours(hours, minutes, 0, 0);\n\n  return { isValid: true, time: now };\n}\n\nfunction parseDayOfWeek(dayStr: string): number {\n  const days: Record<string, number> = {\n    sunday: 0,\n    sun: 0,\n    monday: 1,\n    mon: 1,\n    tuesday: 2,\n    tue: 2,\n    tues: 2,\n    wednesday: 3,\n    wed: 3,\n    thursday: 4,\n    thu: 4,\n    thurs: 4,\n    friday: 5,\n    fri: 5,\n    saturday: 6,\n    sat: 6,\n  };\n\n  return days[dayStr.toLowerCase()] ?? -1;\n}\n\nfunction getNextWeekday(targetDay: number, time: Date): Date {\n  const now = new Date();\n  const currentDay = now.getDay();\n\n  // Check if the target time has already passed today\n  const todayTargetTime = new Date(now);\n  todayTargetTime.setHours(time.getHours(), time.getMinutes(), 0, 0);\n  const hasTimePassed = now >= todayTargetTime;\n\n  let daysUntilTarget = targetDay - currentDay;\n  if (daysUntilTarget < 0 || (daysUntilTarget === 0 && hasTimePassed)) {\n    daysUntilTarget += 7; // Next week\n  }\n\n  const nextDate = new Date(now);\n  nextDate.setDate(now.getDate() + daysUntilTarget);\n  nextDate.setHours(time.getHours(), time.getMinutes(), 0, 0);\n\n  return nextDate;\n}\n\n/**\n * Get the last day of a given month\n */\nfunction getLastDayOfMonth(year: number, month: number): number {\n  // Create a date for the first day of the next month, then go back one day\n  return new Date(year, month + 1, 0).getDate();\n}\n\n/**\n * Clamp the target day to the last valid day of the month\n * This handles cases like scheduling for day 31 in months with fewer days\n */\nfunction clampDayToMonth(targetDay: number, year: number, month: number): number {\n  const lastDay = getLastDayOfMonth(year, month);\n  return Math.min(targetDay, lastDay);\n}\n\nfunction getNextMonthDay(targetDay: number, time: Date): Date {\n  const now = new Date();\n  const currentDay = now.getDate();\n\n  // Check if the target time has already passed today\n  const todayTargetTime = new Date(now);\n  todayTargetTime.setHours(time.getHours(), time.getMinutes(), 0, 0);\n  const hasTimePassed = now >= todayTargetTime;\n\n  const nextDate = new Date(now);\n\n  // Clamp target day to valid day for current month\n  const clampedTargetDayThisMonth = clampDayToMonth(targetDay, now.getFullYear(), now.getMonth());\n\n  if (clampedTargetDayThisMonth > currentDay) {\n    // Target day is later this month (clamped to valid day)\n    nextDate.setDate(clampedTargetDayThisMonth);\n  } else if (clampedTargetDayThisMonth === currentDay && !hasTimePassed) {\n    // Today is the target day and time hasn't passed yet\n    nextDate.setDate(clampedTargetDayThisMonth);\n  } else {\n    // Target day has passed this month, go to next month\n    const nextMonth = now.getMonth() + 1;\n    const nextYear = nextMonth > 11 ? now.getFullYear() + 1 : now.getFullYear();\n    const normalizedMonth = nextMonth % 12;\n\n    // Clamp target day to valid day for next month\n    const clampedTargetDayNextMonth = clampDayToMonth(targetDay, nextYear, normalizedMonth);\n\n    nextDate.setFullYear(nextYear);\n    nextDate.setMonth(normalizedMonth);\n    nextDate.setDate(clampedTargetDayNextMonth);\n  }\n\n  nextDate.setHours(time.getHours(), time.getMinutes(), 0, 0);\n\n  return nextDate;\n}\n\n/**\n * Parse 'after:Xs/m/h' format for delayed execution\n * Examples:\n * - 'after:5s' → run after 5 seconds\n * - 'after:30m' → run after 30 minutes\n * - 'after:2h' → run after 2 hours\n */\nfunction parseAfterDelay(delayStr: string, timezone: string): ParsedSchedule {\n  // Remove 'after:' prefix\n  const delayPart = delayStr.slice(6);\n\n  // Parse number and unit\n  const match = delayPart.match(/^(\\d+)(s|m|h)$/);\n  if (!match) {\n    return {\n      schedule: {} as Schedule,\n      isValid: false,\n      error: `Invalid delay format: ${delayStr}. Use after:Xs, after:Xm, or after:Xh (e.g., after:5s, after:30m, after:2h)`,\n    };\n  }\n\n  const value = parseInt(match[1]);\n  const unit = match[2];\n\n  if (value <= 0) {\n    return {\n      schedule: {} as Schedule,\n      isValid: false,\n      error: `Delay value must be positive: ${delayStr}`,\n    };\n  }\n\n  // Calculate delay in milliseconds\n  let delayMs: number;\n  switch (unit) {\n    case 's':\n      delayMs = value * 1000;\n      break;\n    case 'm':\n      delayMs = value * 60 * 1000;\n      break;\n    case 'h':\n      delayMs = value * 60 * 60 * 1000;\n      break;\n    default:\n      return {\n        schedule: {} as Schedule,\n        isValid: false,\n        error: `Unknown time unit: ${unit}`,\n      };\n  }\n\n  // Calculate execution time\n  const executeAt = new Date(Date.now() + delayMs);\n\n  return {\n    schedule: {\n      type: 'once',\n      executeAt,\n      timezone,\n      delayMs, // Store delay for reference\n    } as Schedule,\n    isValid: true,\n  };\n}\n"],"mappings":"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","names":["import_crypto","import_crypto","pino","module","resolve","currentConfig","crypto","knex","_AsyncMutex","resolve","AsyncMutex","fs","OpenAI","fs","path","withRetry","Anthropic","fs","path","withRetry","fs","path","resolve","RequestPriority","resolve","resolve","_AsyncMutex","AsyncMutex","result","fs","path","_AsyncMutex","resolve","AsyncMutex","crypto","import_crypto","fs","resolve","fs","path","stat","fs","path","path","fs","mainProvider","provider","import_crypto","resolve","knex","resolve","isValidRole","fs","import_crypto","path","results","resolve","import_crypto","knex","crypto","_AsyncMutex","resolve","AsyncMutex","initMutex","AsyncMutex","resolve","storage"]}