@voltagent/libsql 1.0.0-next.0 → 1.0.0-next.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/migrations/add-suspended-status.ts","../src/migrations/workflow-tables.ts","../src/workflow-extension.ts"],"sourcesContent":["import { existsSync, mkdirSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport type { Client, Row } from \"@libsql/client\";\nimport { createClient } from \"@libsql/client\";\nimport type { BaseMessage, NewTimelineEvent } from \"@voltagent/core\";\nimport { safeJsonParse } from \"@voltagent/core\";\nimport type {\n Conversation,\n ConversationQueryOptions,\n CreateConversationInput,\n Memory,\n MemoryMessage,\n MemoryOptions,\n MessageFilterOptions,\n} from \"@voltagent/core\";\nimport { safeStringify } from \"@voltagent/internal/utils\";\nimport { type Logger, createPinoLogger } from \"@voltagent/logger\";\nimport { addSuspendedStatusMigration } from \"./migrations/add-suspended-status\";\nimport { createWorkflowTables } from \"./migrations/workflow-tables\";\nimport { LibSQLWorkflowExtension } from \"./workflow-extension\";\n\n/**\n * LibSQL Storage for VoltAgent\n *\n * This implementation provides:\n * - Conversation management with user support\n * - Automatic migration from old schema to new schema\n * - Query builder pattern for flexible data retrieval\n * - Pagination support\n *\n * @see {@link https://voltagent.dev/docs/agents/memory/libsql | LibSQL Storage Documentation}\n * Function to add a delay between 0-0 seconds for debugging\n */\nasync function debugDelay(): Promise<void> {\n const min = 0; // 0 seconds\n const max = 0; // 0 seconds\n const delay = Math.floor(Math.random() * (max - min + 1)) + min;\n return new Promise((resolve) => setTimeout(resolve, delay));\n}\n\n/**\n * Options for configuring the LibSQLStorage\n */\nexport interface LibSQLStorageOptions extends MemoryOptions {\n /**\n * LibSQL connection URL\n * Can be either a remote Turso URL or a local file path\n * @default \"file:./.voltagent/memory.db\"\n * @example \"libsql://your-database.turso.io\" for remote Turso\n * @example \"file:memory.db\" for local SQLite in current directory\n * @example \"file:.voltagent/memory.db\" for local SQLite in .voltagent folder\n */\n url?: string;\n\n /**\n * Auth token for LibSQL/Turso\n * Not needed for local SQLite\n */\n authToken?: string;\n\n /**\n * Prefix for table names\n * @default \"voltagent_memory\"\n */\n tablePrefix?: string;\n\n /**\n * Whether to enable debug logging\n * @default false\n */\n debug?: boolean;\n\n /**\n * Storage limit for the LibSQLStorage\n * @default 100\n */\n storageLimit?: number;\n\n /**\n * Number of retry attempts for database operations when encountering busy/locked errors\n * @default 3\n */\n retryAttempts?: number;\n\n /**\n * Base delay in milliseconds before retrying a failed operation\n * Uses a jittered exponential backoff strategy for better load distribution\n * @default 50\n */\n baseDelayMs?: number;\n\n /**\n * Optional logger instance\n */\n logger?: Logger;\n}\n\n/**\n * A LibSQL storage implementation of the Memory and WorkflowMemory interfaces\n * Uses libsql/Turso to store and retrieve conversation history and workflow data\n *\n * This implementation automatically handles both:\n * - Remote Turso databases (with libsql:// URLs)\n * - Local SQLite databases (with file: URLs)\n */\ntype InternalLibSQLStorageOptions = {\n url: string;\n authToken?: string;\n tablePrefix: string;\n debug: boolean;\n storageLimit: number;\n retryAttempts: number;\n baseDelayMs: number;\n};\n\nexport class LibSQLStorage implements Memory {\n private client: Client;\n private options: InternalLibSQLStorageOptions;\n private initialized: Promise<void>;\n private workflowExtension: LibSQLWorkflowExtension;\n private logger: Logger;\n private retryAttempts: number;\n private baseDelayMs: number;\n\n /**\n * Create a new LibSQL storage\n * @param options Configuration options\n */\n constructor(options: LibSQLStorageOptions) {\n // Initialize the logger\n this.logger = options.logger || createPinoLogger({ name: \"libsql-storage\" });\n this.retryAttempts = options.retryAttempts ?? 3;\n this.baseDelayMs = options.baseDelayMs ?? 50;\n\n this.options = {\n storageLimit: options.storageLimit || 100,\n tablePrefix: options.tablePrefix || \"voltagent_memory\",\n debug: options.debug || false,\n url: options.url || \"file:./.voltagent/memory.db\",\n authToken: options.authToken,\n retryAttempts: this.retryAttempts,\n baseDelayMs: this.baseDelayMs,\n };\n\n // Ensure parent directory exists for file-based databases\n if (this.options.url.startsWith(\"file:\") && !this.options.url.includes(\":memory:\")) {\n const filePath = this.options.url.substring(5); // Remove 'file:' prefix\n const dir = dirname(filePath);\n if (dir && dir !== \".\" && !existsSync(dir)) {\n try {\n mkdirSync(dir, { recursive: true });\n this.debug(\"Created directory for database\", { dir });\n } catch (error) {\n this.logger.warn(\"Failed to create directory for database\", { dir, error });\n }\n }\n }\n\n // Initialize the LibSQL client\n this.client = createClient({\n url: this.options.url,\n authToken: this.options.authToken,\n });\n\n this.debug(\"LibSQL storage provider initialized with options\", this.options);\n\n // Initialize workflow extension\n this.workflowExtension = new LibSQLWorkflowExtension(\n this.client,\n this.options.tablePrefix,\n this.logger,\n );\n\n // Initialize the database tables\n this.initialized = this.initializeDatabase();\n }\n\n /**\n * Log a debug message if debug is enabled\n * @param message Message to log\n * @param data Additional data to log\n */\n private debug(message: string, data?: unknown): void {\n if (this.options?.debug) {\n this.logger.debug(`${message}`, data || \"\");\n }\n }\n\n /**\n * Calculate delay with jitter for better load distribution\n * @param attempt Current retry attempt number\n * @returns Delay in milliseconds\n */\n private calculateRetryDelay(attempt: number): number {\n // Exponential backoff: baseDelay * 2^(attempt-1)\n const exponentialDelay = this.baseDelayMs * 2 ** (attempt - 1);\n\n // Add 20-40% jitter to prevent thundering herd\n const jitterFactor = 0.2 + Math.random() * 0.2;\n const delayWithJitter = exponentialDelay * (1 + jitterFactor);\n\n // Cap at 2 seconds max\n return Math.min(delayWithJitter, 2000);\n }\n\n /**\n * Execute a database operation with retry strategy\n * Implements jittered exponential backoff\n * @param operationFn The operation function to execute\n * @param operationName Operation name for logging\n * @returns The result of the operation\n */\n private async executeWithRetryStrategy<T>(\n operationFn: () => Promise<T>,\n operationName: string,\n ): Promise<T> {\n let attempt = 0;\n\n while (attempt < this.retryAttempts) {\n attempt++;\n\n try {\n return await operationFn();\n } catch (error: any) {\n const isBusyError =\n error.message &&\n (error.message.includes(\"SQLITE_BUSY\") ||\n error.message.includes(\"database is locked\") ||\n error.code === \"SQLITE_BUSY\");\n\n if (!isBusyError || attempt >= this.retryAttempts) {\n this.debug(`Operation failed: ${operationName}`, {\n attempt,\n error: error.message,\n });\n throw error;\n }\n\n // Calculate delay with jitter\n const delay = this.calculateRetryDelay(attempt);\n\n this.debug(`Retrying ${operationName}`, {\n attempt,\n remainingAttempts: this.retryAttempts - attempt,\n delay,\n });\n\n // Wait before retry\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n }\n\n // Should never reach here\n throw new Error(`Max retry attempts (${this.retryAttempts}) exceeded for ${operationName}`);\n }\n\n /**\n * Initialize workflow tables\n */\n private async initializeWorkflowTables(): Promise<void> {\n try {\n await createWorkflowTables(this.client, this.options.tablePrefix);\n this.debug(\"Workflow tables initialized successfully\");\n\n // Run migrations\n await addSuspendedStatusMigration(this.client, this.options.tablePrefix);\n this.debug(\"Workflow migrations applied successfully\");\n } catch (error) {\n this.debug(\"Error initializing workflow tables:\", error);\n // Don't throw error to avoid breaking existing functionality\n }\n }\n\n /**\n * Initialize the database tables\n * @returns Promise that resolves when initialization is complete\n */\n private async initializeDatabase(): Promise<void> {\n // Set PRAGMA settings for better concurrency, especially for file-based databases\n if (this.options.url.startsWith(\"file:\") || this.options.url.includes(\":memory:\")) {\n try {\n await this.client.execute(\"PRAGMA journal_mode=WAL;\");\n this.debug(\"PRAGMA journal_mode=WAL set.\");\n } catch (err) {\n this.debug(\"Failed to set PRAGMA journal_mode=WAL.\", err);\n }\n\n try {\n await this.client.execute(\"PRAGMA busy_timeout = 5000;\"); // 5 seconds\n this.debug(\"PRAGMA busy_timeout=5000 set.\");\n } catch (err) {\n this.debug(\"Failed to set PRAGMA busy_timeout.\", err);\n }\n }\n\n // Create conversations table if it doesn't exist\n const conversationsTableName = `${this.options.tablePrefix}_conversations`;\n\n await this.client.execute(`\n CREATE TABLE IF NOT EXISTS ${conversationsTableName} (\n id TEXT PRIMARY KEY,\n resource_id TEXT NOT NULL,\n user_id TEXT NOT NULL,\n title TEXT NOT NULL,\n metadata TEXT NOT NULL,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL\n )\n `);\n\n // Create messages table if it doesn't exist\n const messagesTableName = `${this.options.tablePrefix}_messages`;\n\n await this.client.execute(`\n CREATE TABLE IF NOT EXISTS ${messagesTableName} (\n conversation_id TEXT NOT NULL,\n message_id TEXT NOT NULL,\n role TEXT NOT NULL,\n content TEXT NOT NULL,\n type TEXT NOT NULL,\n created_at TEXT NOT NULL,\n PRIMARY KEY (conversation_id, message_id)\n )\n `);\n\n // Create agent_history table\n const historyTableName = `${this.options.tablePrefix}_agent_history`;\n await this.client.execute(`\n CREATE TABLE IF NOT EXISTS ${historyTableName} (\n id TEXT PRIMARY KEY,\n agent_id TEXT NOT NULL,\n timestamp TEXT NOT NULL,\n status TEXT,\n input TEXT,\n output TEXT,\n usage TEXT,\n metadata TEXT,\n userId TEXT,\n conversationId TEXT\n )\n `);\n\n // Create agent_history_steps table\n const historyStepsTableName = `${this.options.tablePrefix}_agent_history_steps`;\n await this.client.execute(`\n CREATE TABLE IF NOT EXISTS ${historyStepsTableName} (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL,\n history_id TEXT NOT NULL,\n agent_id TEXT\n )\n `);\n\n // Create timeline events table\n const timelineEventsTableName = `${this.options.tablePrefix}_agent_history_timeline_events`;\n await this.client.execute(`\n CREATE TABLE IF NOT EXISTS ${timelineEventsTableName} (\n id TEXT PRIMARY KEY,\n history_id TEXT NOT NULL,\n agent_id TEXT,\n event_type TEXT NOT NULL,\n event_name TEXT NOT NULL,\n start_time TEXT NOT NULL,\n end_time TEXT,\n status TEXT,\n status_message TEXT,\n level TEXT,\n version TEXT,\n parent_event_id TEXT,\n tags TEXT,\n input TEXT,\n output TEXT,\n error TEXT,\n metadata TEXT\n )\n `);\n\n // Create index for faster queries\n await this.client.execute(`\n CREATE INDEX IF NOT EXISTS idx_${messagesTableName}_lookup\n ON ${messagesTableName}(conversation_id, created_at)\n `);\n\n // Create index for conversations\n await this.client.execute(`\n CREATE INDEX IF NOT EXISTS idx_${conversationsTableName}_resource\n ON ${conversationsTableName}(resource_id)\n `);\n\n // Create index for conversations by user_id (only if user_id column exists)\n try {\n const tableInfo = await this.client.execute(`PRAGMA table_info(${conversationsTableName})`);\n\n const hasUserIdColumn = tableInfo.rows.some((row) => row.name === \"user_id\");\n\n if (hasUserIdColumn) {\n await this.client.execute(`\n CREATE INDEX IF NOT EXISTS idx_${conversationsTableName}_user\n ON ${conversationsTableName}(user_id)\n `);\n }\n } catch (error) {\n this.debug(\"Error creating user_id index, will be created after migration:\", error);\n }\n\n // Create indexes for history tables\n\n await this.client.execute(`\n CREATE INDEX IF NOT EXISTS idx_${historyStepsTableName}_history_id \n ON ${historyStepsTableName}(history_id)\n `);\n\n // Initialize workflow tables\n await this.initializeWorkflowTables();\n\n // Create indexes for agent_id for more efficient querying\n await this.client.execute(`\n CREATE INDEX IF NOT EXISTS idx_${historyTableName}_agent_id \n ON ${historyTableName}(agent_id)\n `);\n\n await this.client.execute(`\n CREATE INDEX IF NOT EXISTS idx_${historyStepsTableName}_agent_id \n ON ${historyStepsTableName}(agent_id)\n `);\n\n // Create indexes for timeline events table\n await this.client.execute(`\n CREATE INDEX IF NOT EXISTS idx_${timelineEventsTableName}_history_id \n ON ${timelineEventsTableName}(history_id)\n `);\n\n await this.client.execute(`\n CREATE INDEX IF NOT EXISTS idx_${timelineEventsTableName}_agent_id \n ON ${timelineEventsTableName}(agent_id)\n `);\n\n await this.client.execute(`\n CREATE INDEX IF NOT EXISTS idx_${timelineEventsTableName}_event_type \n ON ${timelineEventsTableName}(event_type)\n `);\n\n await this.client.execute(`\n CREATE INDEX IF NOT EXISTS idx_${timelineEventsTableName}_event_name \n ON ${timelineEventsTableName}(event_name)\n `);\n\n await this.client.execute(`\n CREATE INDEX IF NOT EXISTS idx_${timelineEventsTableName}_parent_event_id \n ON ${timelineEventsTableName}(parent_event_id)\n `);\n\n await this.client.execute(`\n CREATE INDEX IF NOT EXISTS idx_${timelineEventsTableName}_status \n ON ${timelineEventsTableName}(status)\n `);\n\n this.debug(\"Database initialized successfully\");\n\n // Run conversation schema migration first\n try {\n const migrationResult = await this.migrateConversationSchema({\n createBackup: true,\n deleteBackupAfterSuccess: true,\n });\n\n if (migrationResult.success) {\n if ((migrationResult.migratedCount || 0) > 0) {\n this.logger.info(\n `${migrationResult.migratedCount} conversation records successfully migrated`,\n );\n }\n } else {\n this.logger.error(\"Conversation migration error:\", migrationResult.error);\n }\n } catch (error) {\n this.debug(\"Error migrating conversation schema:\", error);\n }\n\n // Run agent history schema migration\n try {\n const migrationResult = await this.migrateAgentHistorySchema();\n\n if (!migrationResult.success) {\n this.logger.error(\"Agent history schema migration error:\", migrationResult.error);\n }\n } catch (error) {\n this.debug(\"Error migrating agent history schema:\", error);\n }\n\n try {\n const result = await this.migrateAgentHistoryData({\n restoreFromBackup: false,\n });\n\n if (result.success) {\n if ((result.migratedCount || 0) > 0) {\n this.logger.info(`${result.migratedCount} records successfully migrated`);\n }\n } else {\n this.logger.error(\"Migration error:\", result.error);\n\n // Restore from backup in case of error\n const restoreResult = await this.migrateAgentHistoryData({});\n\n if (restoreResult.success) {\n this.logger.info(\"Successfully restored from backup\");\n }\n }\n } catch (error) {\n this.debug(\"Error initializing database:\", error);\n //throw new Error(\"Failed to initialize LibSQL database\");\n }\n }\n\n /**\n * Generate a unique ID for a message\n * @returns Unique ID\n */\n private generateId(): string {\n return (\n Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15)\n );\n }\n\n /**\n * Get messages with filtering options\n * @param options Filtering options\n * @returns Filtered messages\n */\n async getMessages(options: MessageFilterOptions = {}): Promise<MemoryMessage[]> {\n // Wait for database initialization\n await this.initialized;\n\n // Add delay for debugging\n await debugDelay();\n\n const {\n userId = \"default\",\n conversationId = \"default\",\n limit,\n before,\n after,\n role,\n types,\n } = options;\n\n const messagesTableName = `${this.options.tablePrefix}_messages`;\n const conversationsTableName = `${this.options.tablePrefix}_conversations`;\n\n try {\n let sql = `\n SELECT m.message_id, m.role, m.content, m.type, m.created_at, m.conversation_id\n FROM ${messagesTableName} m\n `;\n const args: any[] = [];\n const conditions: string[] = [];\n\n // If userId is specified, we need to join with conversations table\n if (userId !== \"default\") {\n sql += ` INNER JOIN ${conversationsTableName} c ON m.conversation_id = c.id`;\n conditions.push(\"c.user_id = ?\");\n args.push(userId);\n }\n\n // Add conversation_id filter\n if (conversationId !== \"default\") {\n conditions.push(\"m.conversation_id = ?\");\n args.push(conversationId);\n }\n\n // Add time-based filters\n if (before) {\n conditions.push(\"m.created_at < ?\");\n args.push(new Date(before).toISOString());\n }\n\n if (after) {\n conditions.push(\"m.created_at > ?\");\n args.push(new Date(after).toISOString());\n }\n\n // Add role filter\n if (role) {\n conditions.push(\"m.role = ?\");\n args.push(role);\n }\n\n // Add types filter\n if (types) {\n const placeholders = types.map(() => \"?\").join(\", \");\n conditions.push(`m.type IN (${placeholders})`);\n args.push(...types);\n }\n\n // Add WHERE clause if we have conditions\n if (conditions.length > 0) {\n sql += ` WHERE ${conditions.join(\" AND \")}`;\n }\n\n // Add ordering and limit\n // When limit is specified, we need to get the most recent messages\n if (limit && limit > 0) {\n sql += \" ORDER BY m.created_at DESC LIMIT ?\";\n args.push(limit);\n } else {\n sql += \" ORDER BY m.created_at ASC\";\n }\n\n const result = await this.client.execute({\n sql,\n args,\n });\n\n // Map the results\n const messages = result.rows.map((row) => {\n // Try to parse content if it's JSON, otherwise use as-is\n let content = row.content as string;\n const parsedContent = safeJsonParse(content);\n if (parsedContent !== null) {\n content = parsedContent;\n }\n\n return {\n id: row.message_id as string,\n role: row.role as BaseMessage[\"role\"],\n content,\n type: row.type as \"text\" | \"tool-call\" | \"tool-result\",\n createdAt: row.created_at as string,\n };\n });\n\n // If we used DESC order with limit, reverse to get chronological order\n if (limit && limit > 0) {\n return messages.reverse();\n }\n\n return messages;\n } catch (error) {\n this.debug(\"Error getting messages:\", error);\n throw new Error(\"Failed to get messages from LibSQL database\");\n }\n }\n\n /**\n * Add a message to the conversation history\n * @param message Message to add\n * @param userId User identifier (optional, defaults to \"default\")\n * @param conversationId Conversation identifier (optional, defaults to \"default\")\n */\n async addMessage(message: MemoryMessage, conversationId = \"default\"): Promise<void> {\n // Wait for database initialization\n await this.initialized;\n\n // Add delay for debugging\n await debugDelay();\n\n const tableName = `${this.options.tablePrefix}_messages`;\n const contentString = safeStringify(message.content);\n\n await this.executeWithRetryStrategy(async () => {\n await this.client.execute({\n sql: `INSERT INTO ${tableName} (conversation_id, message_id, role, content, type, created_at)\n VALUES (?, ?, ?, ?, ?, ?)`,\n args: [\n conversationId,\n message.id,\n message.role,\n contentString,\n message.type,\n message.createdAt,\n ],\n });\n\n this.debug(\"Message added successfully\", { conversationId, messageId: message.id });\n\n // Optionally, prune old messages to respect storage limit\n try {\n await this.pruneOldMessages(conversationId);\n } catch (pruneError) {\n this.debug(\"Error pruning old messages:\", pruneError);\n // Don't throw error for pruning failure\n }\n }, `addMessage[${message.id}]`);\n }\n\n /**\n * Prune old messages to respect storage limit\n * @param conversationId Conversation ID to prune messages for\n */\n private async pruneOldMessages(conversationId: string): Promise<void> {\n const limit = this.options.storageLimit || 100;\n const tableName = `${this.options.tablePrefix}_messages`;\n\n try {\n // Get the count of messages for this conversation\n const countResult = await this.client.execute({\n sql: `SELECT COUNT(*) as count FROM ${tableName} WHERE conversation_id = ?`,\n args: [conversationId],\n });\n\n const messageCount = countResult.rows[0]?.count as number;\n\n if (messageCount > limit) {\n // Delete the oldest messages beyond the limit\n const deleteCount = messageCount - limit;\n\n await this.client.execute({\n sql: `DELETE FROM ${tableName} \n WHERE conversation_id = ? \n AND message_id IN (\n SELECT message_id FROM ${tableName} \n WHERE conversation_id = ? \n ORDER BY created_at ASC \n LIMIT ?\n )`,\n args: [conversationId, conversationId, deleteCount],\n });\n\n this.debug(`Pruned ${deleteCount} old messages for conversation ${conversationId}`);\n }\n } catch (error) {\n this.debug(\"Error pruning old messages:\", error);\n throw error;\n }\n }\n\n /**\n * Clear messages from memory\n */\n async clearMessages(options: { userId: string; conversationId?: string }): Promise<void> {\n // Wait for database initialization\n await this.initialized;\n\n // Add delay for debugging\n await debugDelay();\n\n const { userId, conversationId } = options;\n const messagesTableName = `${this.options.tablePrefix}_messages`;\n const conversationsTableName = `${this.options.tablePrefix}_conversations`;\n\n try {\n if (conversationId) {\n // Clear messages for a specific conversation (with user validation)\n await this.client.execute({\n sql: `DELETE FROM ${messagesTableName} \n WHERE conversation_id = ? \n AND conversation_id IN (\n SELECT id FROM ${conversationsTableName} WHERE user_id = ?\n )`,\n args: [conversationId, userId],\n });\n this.debug(`Cleared messages for conversation ${conversationId} for user ${userId}`);\n } else {\n // Clear all messages for the user across all their conversations\n await this.client.execute({\n sql: `DELETE FROM ${messagesTableName} \n WHERE conversation_id IN (\n SELECT id FROM ${conversationsTableName} WHERE user_id = ?\n )`,\n args: [userId],\n });\n this.debug(`Cleared all messages for user ${userId}`);\n }\n } catch (error) {\n this.debug(\"Error clearing messages:\", error);\n throw new Error(\"Failed to clear messages from LibSQL database\");\n }\n }\n\n /**\n * Close the database connection\n */\n async close(): Promise<void> {\n try {\n // Wait for initialization to complete before closing\n await this.initialized;\n } catch {\n // Ignore initialization errors when closing\n }\n\n this.client.close();\n }\n\n /**\n * Add or update a history entry\n * @param key Entry ID\n * @param value Entry data\n * @param agentId Agent ID for filtering\n */\n async addHistoryEntry(key: string, value: any, agentId: string): Promise<void> {\n await this.initialized;\n\n try {\n const tableName = `${this.options.tablePrefix}_agent_history`;\n\n // Normalize the data for storage\n const inputJSON = value.input ? safeStringify(value.input) : null;\n const outputJSON = value.output ? safeStringify(value.output) : null;\n const usageJSON = value.usage ? safeStringify(value.usage) : null;\n const metadataJSON = value.metadata ? safeStringify(value.metadata) : null;\n\n // Insert or replace with the structured format including userId and conversationId\n await this.client.execute({\n sql: `INSERT OR REPLACE INTO ${tableName} \n\t\t\t\t\t(id, agent_id, timestamp, status, input, output, usage, metadata, userId, conversationId) \n\t\t\t\t\tVALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n args: [\n key, // id\n agentId, // agent_id\n value.timestamp ? value.timestamp.toISOString() : new Date().toISOString(), // timestamp\n value.status || null, // status\n inputJSON, // input\n outputJSON, // output\n usageJSON, // usage\n metadataJSON, // metadata\n value.userId || null, // userId\n value.conversationId || null, // conversationId\n ],\n });\n\n this.debug(`Set agent_history entry with ID ${key} for agent ${agentId}`);\n } catch (error) {\n this.debug(\"Error setting agent_history entry:\", error);\n throw new Error(\"Failed to set value in agent_history\");\n }\n }\n\n /**\n * Update an existing history entry\n * @param key Entry ID\n * @param value Updated entry data\n * @param agentId Agent ID for filtering\n */\n async updateHistoryEntry(key: string, value: any, agentId: string): Promise<void> {\n // Same implementation as addHistoryEntry since it uses INSERT OR REPLACE\n return this.addHistoryEntry(key, value, agentId);\n }\n\n /**\n * Add a history step\n * @param key Step ID\n * @param value Step data\n * @param historyId Related history entry ID\n * @param agentId Agent ID for filtering\n */\n async addHistoryStep(key: string, value: any, historyId: string, agentId: string): Promise<void> {\n await this.initialized;\n\n try {\n const tableName = `${this.options.tablePrefix}_agent_history_steps`;\n\n // Serialize value to JSON\n const serializedValue = safeStringify(value);\n\n // Insert or replace with history_id and agent_id columns\n await this.client.execute({\n sql: `INSERT OR REPLACE INTO ${tableName} (key, value, history_id, agent_id) VALUES (?, ?, ?, ?)`,\n args: [key, serializedValue, historyId, agentId],\n });\n\n this.debug(`Set agent_history_steps:${key} for history ${historyId} and agent ${agentId}`);\n } catch (error) {\n this.debug(`Error setting agent_history_steps:${key}`, error);\n throw new Error(\"Failed to set value in agent_history_steps\");\n }\n }\n\n /**\n * Update a history step\n * @param key Step ID\n * @param value Updated step data\n * @param historyId Related history entry ID\n * @param agentId Agent ID for filtering\n */\n async updateHistoryStep(\n key: string,\n value: any,\n historyId: string,\n agentId: string,\n ): Promise<void> {\n // Just call addHistoryStep as the behavior is the same\n return this.addHistoryStep(key, value, historyId, agentId);\n }\n\n /**\n * Add a timeline event\n * @param key Event ID (UUID)\n * @param value Timeline event data\n * @param historyId Related history entry ID\n * @param agentId Agent ID for filtering\n */\n async addTimelineEvent(\n key: string,\n value: NewTimelineEvent,\n historyId: string,\n agentId: string,\n ): Promise<void> {\n await this.initialized;\n\n try {\n const tableName = `${this.options.tablePrefix}_agent_history_timeline_events`;\n\n // Serialize JSON fields\n const inputJSON = value.input ? safeStringify(value.input) : null;\n const outputJSON = value.output ? safeStringify(value.output) : null;\n const statusMessageJSON = value.statusMessage ? safeStringify(value.statusMessage) : null;\n const metadataJSON = value.metadata ? safeStringify(value.metadata) : null;\n const tagsJSON = value.tags ? safeStringify(value.tags) : null;\n\n // Insert with all the indexed fields\n await this.client.execute({\n sql: `INSERT OR REPLACE INTO ${tableName} \n (id, history_id, agent_id, event_type, event_name, \n start_time, end_time, status, status_message, level, \n version, parent_event_id, tags,\n input, output, error, metadata) \n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n args: [\n key,\n historyId,\n agentId,\n value.type,\n value.name,\n value.startTime,\n value.endTime || null,\n value.status || null,\n statusMessageJSON || null,\n value.level || \"INFO\",\n value.version || null,\n value.parentEventId || null,\n tagsJSON,\n inputJSON,\n outputJSON,\n statusMessageJSON,\n metadataJSON,\n ],\n });\n\n this.debug(`Added timeline event ${key} for history ${historyId}`);\n } catch (error) {\n this.debug(\"Error adding timeline event:\", error);\n throw new Error(\"Failed to add timeline event\");\n }\n }\n\n /**\n * Get a history entry by ID\n * @param key Entry ID\n * @returns The history entry or undefined if not found\n */\n async getHistoryEntry(key: string): Promise<any | undefined> {\n await this.initialized;\n\n try {\n const tableName = `${this.options.tablePrefix}_agent_history`;\n\n // Get the entry from the database including userId and conversationId\n const result = await this.client.execute({\n sql: `SELECT id, agent_id, timestamp, status, input, output, usage, metadata, userId, conversationId \n\t\t\t\tFROM ${tableName} WHERE id = ?`,\n args: [key],\n });\n\n if (result.rows.length === 0) {\n this.debug(`History entry with ID ${key} not found`);\n return undefined;\n }\n\n const row = result.rows[0];\n\n // Construct the entry object\n const entry = {\n id: row.id as string,\n _agentId: row.agent_id as string, // Keep _agentId for compatibility\n timestamp: new Date(row.timestamp as string),\n status: row.status as string,\n input: row.input ? safeJsonParse(row.input as string) : null,\n output: row.output ? safeJsonParse(row.output as string) : null,\n usage: row.usage ? safeJsonParse(row.usage as string) : null,\n metadata: row.metadata ? safeJsonParse(row.metadata as string) : null,\n userId: row.userId as string | null,\n conversationId: row.conversationId as string | null,\n };\n\n this.debug(`Got history entry with ID ${key}`);\n\n // Now also get related steps\n const stepsTableName = `${this.options.tablePrefix}_agent_history_steps`;\n const stepsResult = await this.client.execute({\n sql: `SELECT value FROM ${stepsTableName} WHERE history_id = ? AND agent_id = ?`,\n args: [key, entry._agentId],\n });\n\n // Parse and transform steps\n const steps = stepsResult.rows.map((row) => {\n const step = safeJsonParse(row.value as string);\n return {\n type: step.type,\n name: step.name,\n content: step.content,\n arguments: step.arguments,\n };\n });\n\n // Get timeline events\n const timelineEventsTableName = `${this.options.tablePrefix}_agent_history_timeline_events`;\n const timelineEventsResult = await this.client.execute({\n sql: `SELECT id, event_type, event_name, start_time, end_time, \n\t\t\t\t\tstatus, status_message, level, version, \n\t\t\t\t\tparent_event_id, tags, input, output, error, metadata \n\t\t\t\t\tFROM ${timelineEventsTableName} \n\t\t\t\t\tWHERE history_id = ? AND agent_id = ?`,\n args: [key, entry._agentId],\n });\n\n // Parse timeline events and construct NewTimelineEvent objects\n const events = timelineEventsResult.rows.map((row) => {\n // Parse JSON fields\n const input = row.input ? safeJsonParse(row.input as string) : undefined;\n const output = row.output ? safeJsonParse(row.output as string) : undefined;\n const error = row.error ? safeJsonParse(row.error as string) : undefined;\n const statusMessage = row.status_message\n ? safeJsonParse(row.status_message as string)\n : undefined;\n const metadata = row.metadata ? safeJsonParse(row.metadata as string) : undefined;\n const tags = row.tags ? safeJsonParse(row.tags as string) : undefined;\n\n // Construct NewTimelineEvent object\n return {\n id: row.id as string,\n type: row.event_type as string,\n name: row.event_name as string,\n startTime: row.start_time as string,\n endTime: row.end_time as string,\n status: row.status as string,\n statusMessage: statusMessage,\n level: row.level as string,\n version: row.version as string,\n parentEventId: row.parent_event_id as string,\n tags,\n input,\n output,\n error: statusMessage ? statusMessage : error,\n metadata,\n };\n });\n\n // @ts-ignoreç\n entry.steps = steps;\n // @ts-ignore\n entry.events = events;\n\n return entry;\n } catch (error) {\n this.debug(`Error getting history entry with ID ${key}`, error);\n return undefined;\n }\n }\n\n /**\n * Get a history step by ID\n * @param key Step ID\n * @returns The history step or undefined if not found\n */\n async getHistoryStep(key: string): Promise<any | undefined> {\n await this.initialized;\n\n try {\n const tableName = `${this.options.tablePrefix}_agent_history_steps`;\n\n // Get the value\n const result = await this.client.execute({\n sql: `SELECT value FROM ${tableName} WHERE key = ?`,\n args: [key],\n });\n\n if (result.rows.length === 0) {\n this.debug(`History step with ID ${key} not found`);\n return undefined;\n }\n\n // Parse the JSON value\n const value = safeJsonParse(result.rows[0].value as string);\n this.debug(`Got history step with ID ${key}`);\n return value;\n } catch (error) {\n this.debug(`Error getting history step with ID ${key}`, error);\n return undefined;\n }\n }\n\n async createConversation(conversation: CreateConversationInput): Promise<Conversation> {\n await this.initialized;\n\n // Add delay for debugging\n await debugDelay();\n\n const now = new Date().toISOString();\n const metadataString = safeStringify(conversation.metadata);\n\n const tableName = `${this.options.tablePrefix}_conversations`;\n\n return await this.executeWithRetryStrategy(async () => {\n await this.client.execute({\n sql: `INSERT INTO ${tableName} (id, resource_id, user_id, title, metadata, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?)`,\n args: [\n conversation.id,\n conversation.resourceId,\n conversation.userId,\n conversation.title,\n metadataString,\n now,\n now,\n ],\n });\n\n return {\n id: conversation.id,\n resourceId: conversation.resourceId,\n userId: conversation.userId,\n title: conversation.title,\n metadata: conversation.metadata,\n createdAt: now,\n updatedAt: now,\n };\n }, `createConversation[${conversation.id}]`);\n }\n\n async getConversation(id: string): Promise<Conversation | null> {\n await this.initialized;\n\n // Add delay for debugging\n await debugDelay();\n\n const tableName = `${this.options.tablePrefix}_conversations`;\n\n try {\n const result = await this.client.execute({\n sql: `SELECT * FROM ${tableName} WHERE id = ?`,\n args: [id],\n });\n\n if (result.rows.length === 0) {\n return null;\n }\n\n const row = result.rows[0];\n return {\n id: row.id as string,\n resourceId: row.resource_id as string,\n userId: row.user_id as string,\n title: row.title as string,\n metadata: row.metadata ? safeJsonParse(row.metadata as string) : {},\n createdAt: row.created_at as string,\n updatedAt: row.updated_at as string,\n };\n } catch (error) {\n this.debug(\"Error getting conversation:\", error);\n throw new Error(\"Failed to get conversation from LibSQL database\");\n }\n }\n\n async getConversations(resourceId: string): Promise<Conversation[]> {\n await this.initialized;\n\n // Add delay for debugging\n await debugDelay();\n\n const tableName = `${this.options.tablePrefix}_conversations`;\n\n try {\n const result = await this.client.execute({\n sql: `SELECT * FROM ${tableName} WHERE resource_id = ? ORDER BY updated_at DESC`,\n args: [resourceId],\n });\n\n return result.rows.map((row) => ({\n id: row.id as string,\n resourceId: row.resource_id as string,\n userId: row.user_id as string,\n title: row.title as string,\n metadata: safeJsonParse(row.metadata as string),\n createdAt: row.created_at as string,\n updatedAt: row.updated_at as string,\n }));\n } catch (error) {\n this.debug(\"Error getting conversations:\", error);\n throw new Error(\"Failed to get conversations from LibSQL database\");\n }\n }\n\n public async getConversationsByUserId(\n userId: string,\n options: Omit<ConversationQueryOptions, \"userId\"> = {},\n ): Promise<Conversation[]> {\n await this.initialized;\n\n // Add delay for debugging\n await debugDelay();\n\n const {\n resourceId,\n limit = 50,\n offset = 0,\n orderBy = \"updated_at\",\n orderDirection = \"DESC\",\n } = options;\n\n const tableName = `${this.options.tablePrefix}_conversations`;\n\n try {\n let sql = `SELECT * FROM ${tableName} WHERE user_id = ?`;\n const args: any[] = [userId];\n\n if (resourceId) {\n sql += \" AND resource_id = ?\";\n args.push(resourceId);\n }\n\n sql += ` ORDER BY ${orderBy} ${orderDirection}`;\n\n if (limit > 0) {\n sql += \" LIMIT ? OFFSET ?\";\n args.push(limit, offset);\n }\n\n const result = await this.client.execute({\n sql,\n args,\n });\n\n return result.rows.map((row) => ({\n id: row.id as string,\n resourceId: row.resource_id as string,\n userId: row.user_id as string,\n title: row.title as string,\n metadata: safeJsonParse(row.metadata as string),\n createdAt: row.created_at as string,\n updatedAt: row.updated_at as string,\n }));\n } catch (error) {\n this.debug(\"Error getting conversations by user ID:\", error);\n throw new Error(\"Failed to get conversations by user ID from LibSQL database\");\n }\n }\n\n /**\n * Query conversations with filtering and pagination options\n *\n * @param options Query options for filtering and pagination\n * @returns Promise that resolves to an array of conversations matching the criteria\n * @see {@link https://voltagent.dev/docs/agents/memory/libsql#querying-conversations | Querying Conversations}\n */\n public async queryConversations(options: ConversationQueryOptions): Promise<Conversation[]> {\n await this.initialized;\n\n // Add delay for debugging\n await debugDelay();\n\n const {\n userId,\n resourceId,\n limit = 50,\n offset = 0,\n orderBy = \"updated_at\",\n orderDirection = \"DESC\",\n } = options;\n\n const tableName = `${this.options.tablePrefix}_conversations`;\n\n try {\n let sql = `SELECT * FROM ${tableName}`;\n const args: any[] = [];\n const conditions: string[] = [];\n\n if (userId) {\n conditions.push(\"user_id = ?\");\n args.push(userId);\n }\n\n if (resourceId) {\n conditions.push(\"resource_id = ?\");\n args.push(resourceId);\n }\n\n if (conditions.length > 0) {\n sql += ` WHERE ${conditions.join(\" AND \")}`;\n }\n\n sql += ` ORDER BY ${orderBy} ${orderDirection}`;\n\n if (limit > 0) {\n sql += \" LIMIT ? OFFSET ?\";\n args.push(limit, offset);\n }\n\n const result = await this.client.execute({\n sql,\n args,\n });\n\n return result.rows.map((row) => ({\n id: row.id as string,\n resourceId: row.resource_id as string,\n userId: row.user_id as string,\n title: row.title as string,\n metadata: safeJsonParse(row.metadata as string),\n createdAt: row.created_at as string,\n updatedAt: row.updated_at as string,\n }));\n } catch (error) {\n this.debug(\"Error querying conversations:\", error);\n throw new Error(\"Failed to query conversations from LibSQL database\");\n }\n }\n\n /**\n * Get messages for a specific conversation with pagination support\n *\n * @param conversationId The unique identifier of the conversation to retrieve messages from\n * @param options Optional pagination and filtering options\n * @returns Promise that resolves to an array of messages in chronological order (oldest first)\n * @see {@link https://voltagent.dev/docs/agents/memory/libsql#conversation-messages | Getting Conversation Messages}\n */\n public async getConversationMessages(\n conversationId: string,\n options: { limit?: number; offset?: number } = {},\n ): Promise<MemoryMessage[]> {\n await this.initialized;\n\n // Add delay for debugging\n await debugDelay();\n\n const { limit = 100, offset = 0 } = options;\n const tableName = `${this.options.tablePrefix}_messages`;\n\n try {\n let sql = `SELECT * FROM ${tableName} WHERE conversation_id = ? ORDER BY created_at ASC`;\n const args: any[] = [conversationId];\n\n if (limit > 0) {\n sql += \" LIMIT ? OFFSET ?\";\n args.push(limit, offset);\n }\n\n const result = await this.client.execute({\n sql,\n args,\n });\n\n return result.rows.map((row) => {\n // Try to parse content if it's JSON, otherwise use as-is\n let content = row.content as string;\n const parsedContent = safeJsonParse(content);\n if (parsedContent !== null) {\n content = parsedContent;\n }\n\n return {\n id: row.message_id as string,\n role: row.role as BaseMessage[\"role\"],\n content,\n type: row.type as \"text\" | \"tool-call\" | \"tool-result\",\n createdAt: row.created_at as string,\n };\n });\n } catch (error) {\n this.debug(\"Error getting conversation messages:\", error);\n throw new Error(\"Failed to get conversation messages from LibSQL database\");\n }\n }\n\n async updateConversation(\n id: string,\n updates: Partial<Omit<Conversation, \"id\" | \"createdAt\" | \"updatedAt\">>,\n ): Promise<Conversation> {\n await this.initialized;\n\n // Add delay for debugging\n await debugDelay();\n\n const tableName = `${this.options.tablePrefix}_conversations`;\n const now = new Date().toISOString();\n\n try {\n const updatesList: string[] = [];\n const args: any[] = [];\n\n if (updates.resourceId !== undefined) {\n updatesList.push(\"resource_id = ?\");\n args.push(updates.resourceId);\n }\n\n if (updates.userId !== undefined) {\n updatesList.push(\"user_id = ?\");\n args.push(updates.userId);\n }\n\n if (updates.title !== undefined) {\n updatesList.push(\"title = ?\");\n args.push(updates.title);\n }\n\n if (updates.metadata !== undefined) {\n updatesList.push(\"metadata = ?\");\n args.push(safeStringify(updates.metadata));\n }\n\n updatesList.push(\"updated_at = ?\");\n args.push(now);\n args.push(id);\n\n await this.client.execute({\n sql: `UPDATE ${tableName} SET ${updatesList.join(\", \")} WHERE id = ?`,\n args,\n });\n\n const updated = await this.getConversation(id);\n if (!updated) {\n throw new Error(\"Conversation not found after update\");\n }\n\n return updated;\n } catch (error) {\n this.debug(\"Error updating conversation:\", error);\n throw new Error(\"Failed to update conversation in LibSQL database\");\n }\n }\n\n async deleteConversation(id: string): Promise<void> {\n await this.initialized;\n\n // Add delay for debugging\n await debugDelay();\n\n const conversationsTableName = `${this.options.tablePrefix}_conversations`;\n const messagesTableName = `${this.options.tablePrefix}_messages`;\n\n try {\n // Delete all messages in the conversation\n await this.client.execute({\n sql: `DELETE FROM ${messagesTableName} WHERE conversation_id = ?`,\n args: [id],\n });\n\n // Delete the conversation\n await this.client.execute({\n sql: `DELETE FROM ${conversationsTableName} WHERE id = ?`,\n args: [id],\n });\n } catch (error) {\n this.debug(\"Error deleting conversation:\", error);\n throw new Error(\"Failed to delete conversation from LibSQL database\");\n }\n }\n\n /**\n * Get all history entries for an agent with pagination\n * @param agentId Agent ID\n * @param page Page number (0-based)\n * @param limit Number of entries per page\n * @returns Object with entries array and total count\n */\n async getAllHistoryEntriesByAgent(\n agentId: string,\n page: number,\n limit: number,\n ): Promise<{\n entries: any[];\n total: number;\n }> {\n await this.initialized;\n\n try {\n const tableName = `${this.options.tablePrefix}_agent_history`;\n const offset = page * limit;\n\n // Get total count\n const countResult = await this.client.execute({\n sql: `SELECT COUNT(*) as total FROM ${tableName} WHERE agent_id = ?`,\n args: [agentId],\n });\n\n const total = Number(countResult.rows[0].total);\n\n // Get paginated entries for the specified agent ID using the new schema\n const result = await this.client.execute({\n sql: `SELECT id, agent_id, timestamp, status, input, output, usage, metadata, userId, conversationId \n\t\t\t\t\tFROM ${tableName} WHERE agent_id = ?\n\t\t\t\t\tORDER BY timestamp DESC\n\t\t\t\t\tLIMIT ? OFFSET ?`,\n args: [agentId, limit, offset],\n });\n\n // Construct entry objects from rows\n const entries = result.rows.map((row) => ({\n id: row.id as string,\n _agentId: row.agent_id as string, // Keep _agentId for compatibility\n timestamp: new Date(row.timestamp as string),\n status: row.status as string,\n input: row.input ? safeJsonParse(row.input as string) : null,\n output: row.output ? safeJsonParse(row.output as string) : null,\n usage: row.usage ? safeJsonParse(row.usage as string) : null,\n metadata: row.metadata ? safeJsonParse(row.metadata as string) : null,\n userId: row.userId as string | null,\n conversationId: row.conversationId as string | null,\n }));\n\n this.debug(`Got all history entries for agent ${agentId} (${entries.length} items)`);\n\n // Now fetch events and steps for each entry\n const completeEntries = await Promise.all(\n entries.map(async (entry) => {\n // Get steps for this entry\n const stepsTableName = `${this.options.tablePrefix}_agent_history_steps`;\n const stepsResult = await this.client.execute({\n sql: `SELECT value FROM ${stepsTableName} WHERE history_id = ? AND agent_id = ?`,\n args: [entry.id, agentId],\n });\n\n // Parse and transform steps\n const steps = stepsResult.rows.map((row) => {\n const step = safeJsonParse(row.value as string);\n return {\n type: step.type,\n name: step.name,\n content: step.content,\n arguments: step.arguments,\n };\n });\n\n // Get timeline events for this entry\n const timelineEventsTableName = `${this.options.tablePrefix}_agent_history_timeline_events`;\n const timelineEventsResult = await this.client.execute({\n sql: `SELECT id, event_type, event_name, start_time, end_time, \n\t\t\t\t\t\t\tstatus, status_message, level, version, \n\t\t\t\t\t\t\tparent_event_id, tags, input, output, error, metadata \n\t\t\t\t\t\t\tFROM ${timelineEventsTableName} \n\t\t\t\t\t\t\tWHERE history_id = ? AND agent_id = ?`,\n args: [entry.id, agentId],\n });\n\n // Parse timeline events and construct NewTimelineEvent objects\n const events = timelineEventsResult.rows.map((row) => {\n // Parse JSON fields\n const input = row.input ? safeJsonParse(row.input as string) : undefined;\n const output = row.output ? safeJsonParse(row.output as string) : undefined;\n const error = row.error ? safeJsonParse(row.error as string) : undefined;\n const statusMessage = row.status_message\n ? safeJsonParse(row.status_message as string)\n : undefined;\n const metadata = row.metadata ? safeJsonParse(row.metadata as string) : undefined;\n const tags = row.tags ? safeJsonParse(row.tags as string) : undefined;\n\n // Construct NewTimelineEvent object\n return {\n id: row.id as string,\n type: row.event_type as string,\n name: row.event_name as string,\n startTime: row.start_time as string,\n endTime: row.end_time as string,\n status: row.status as string,\n statusMessage: statusMessage,\n level: row.level as string,\n version: row.version as string,\n parentEventId: row.parent_event_id as string,\n tags,\n input,\n output,\n error: statusMessage ? statusMessage : error,\n metadata,\n };\n });\n\n // @ts-ignoreç\n entry.steps = steps;\n // @ts-ignore\n entry.events = events;\n\n return entry;\n }),\n );\n\n // Return completed entries with total\n return {\n entries: completeEntries,\n total,\n };\n } catch (error) {\n this.debug(`Error getting history entries for agent ${agentId}`, error);\n return {\n entries: [],\n total: 0,\n };\n }\n }\n\n /**\n * Migrates agent history data from old structure to new structure.\n * If migration fails, it can be rolled back using the backup mechanism.\n *\n * Old database structure:\n * CREATE TABLE voltagent_memory_agent_history (\n * key TEXT PRIMARY KEY,\n * value TEXT NOT NULL,\n * agent_id TEXT\n * );\n */\n async migrateAgentHistoryData(\n options: {\n createBackup?: boolean;\n restoreFromBackup?: boolean;\n deleteBackupAfterSuccess?: boolean;\n } = {},\n ): Promise<{\n success: boolean;\n migratedCount?: number;\n error?: Error;\n backupCreated?: boolean;\n }> {\n //await this.initialized;\n\n const {\n createBackup = true,\n restoreFromBackup = false,\n deleteBackupAfterSuccess = false,\n } = options;\n\n // Eski tablo ismi\n const oldTableName = `${this.options.tablePrefix}_agent_history`;\n // Eski tablo yedeği\n const oldTableBackup = `${oldTableName}_backup`;\n // Yeni tablo isimleri\n const timelineEventsTableName = `${this.options.tablePrefix}_agent_history_timeline_events`;\n\n try {\n this.debug(\"Starting agent history migration...\");\n\n // Check if migration has already been completed by looking for a migration flag\n const flagCheck = await this.checkMigrationFlag(\"agent_history_data_migration\");\n if (flagCheck.alreadyCompleted) {\n return { success: true, migratedCount: 0 };\n }\n\n // If restoreFromBackup option is active, restore from backup\n if (restoreFromBackup) {\n this.debug(\"Starting restoration from backup...\");\n\n // Check if backup table exists\n const backupCheck = await this.client.execute({\n sql: \"SELECT name FROM sqlite_master WHERE type='table' AND name=?\",\n args: [oldTableBackup],\n });\n\n if (backupCheck.rows.length === 0) {\n throw new Error(\"No backup found to restore\");\n }\n\n // Start transaction\n await this.client.execute(\"BEGIN TRANSACTION;\");\n\n // Delete current table\n await this.client.execute(`DROP TABLE IF EXISTS ${oldTableName};`);\n\n // Restore from backup\n await this.client.execute(`ALTER TABLE ${oldTableBackup} RENAME TO ${oldTableName};`);\n\n // Complete transaction\n await this.client.execute(\"COMMIT;\");\n\n this.debug(\"Restoration from backup completed successfully\");\n\n return {\n success: true,\n backupCreated: false,\n };\n }\n\n // First check the structure of the old table\n const tableInfoQuery = await this.client.execute(`PRAGMA table_info(${oldTableName})`);\n\n // If the table is empty or doesn't exist, migration is not needed\n if (tableInfoQuery.rows.length === 0) {\n this.debug(`${oldTableName} table not found, migration not needed`);\n return {\n success: true,\n migratedCount: 0,\n };\n }\n\n // Check if it's an old format table or new format table\n // Old format: key, value, agent_id\n // New format: id, agent_id, timestamp, status, input, output, usage, metadata\n const hasValueColumn = tableInfoQuery.rows.some((row) => row.name === \"value\");\n\n if (!hasValueColumn) {\n this.debug(\"Table is already in new format, migration not needed\");\n return {\n success: true,\n migratedCount: 0,\n };\n }\n\n // Create backup\n if (createBackup) {\n this.debug(\"Creating backup...\");\n\n // Check previous backup and delete if exists\n const backupCheck = await this.client.execute({\n sql: \"SELECT name FROM sqlite_master WHERE type='table' AND name=?\",\n args: [oldTableBackup],\n });\n\n if (backupCheck.rows.length > 0) {\n await this.client.execute(`DROP TABLE IF EXISTS ${oldTableBackup};`);\n }\n\n // Create backup\n await this.client.execute(\n `CREATE TABLE ${oldTableBackup} AS SELECT * FROM ${oldTableName};`,\n );\n\n this.debug(\"Backup created successfully\");\n }\n\n // Get all data in old format\n const oldFormatData = await this.client.execute({\n sql: `SELECT key, value, agent_id FROM ${oldTableName}`,\n });\n\n if (oldFormatData.rows.length === 0) {\n this.debug(\"No data found to migrate\");\n return {\n success: true,\n migratedCount: 0,\n backupCreated: createBackup,\n };\n }\n\n // Create temporary table\n const tempTableName = `${oldTableName}_temp`;\n\n await this.client.execute(`\n CREATE TABLE ${tempTableName} (\n id TEXT PRIMARY KEY,\n agent_id TEXT NOT NULL,\n timestamp TEXT NOT NULL,\n status TEXT,\n input TEXT,\n output TEXT,\n usage TEXT,\n metadata TEXT\n )\n `);\n\n // Start transaction\n await this.client.execute(\"BEGIN TRANSACTION;\");\n\n let migratedCount = 0;\n const migratedIds = new Set<string>();\n\n for (const row of oldFormatData.rows) {\n const key = row.key as string;\n const agentId = row.agent_id as string;\n const valueStr = row.value as string;\n\n try {\n // JSON verisini parse et\n const valueObj = safeJsonParse(valueStr);\n\n // ID check\n const id = valueObj.id || key;\n\n // Skip if this ID has already been migrated\n if (migratedIds.has(id)) {\n continue;\n }\n\n migratedIds.add(id);\n migratedCount++;\n\n // Add main history record\n const inputJSON = valueObj.input ? safeStringify(valueObj.input) : null;\n const outputJSON = valueObj.output ? safeStringify(valueObj.output) : null;\n const usageJSON = valueObj.usage ? safeStringify(valueObj.usage) : null;\n\n await this.client.execute({\n sql: `INSERT INTO ${tempTableName} \n (id, agent_id, timestamp, status, input, output, usage, metadata) \n VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,\n args: [\n id,\n valueObj._agentId || agentId,\n valueObj.timestamp || new Date().toISOString(),\n valueObj.status || null,\n inputJSON,\n outputJSON,\n usageJSON,\n null,\n ],\n });\n let input = \"\";\n\n // Transfer events to timeline_events table\n if (Array.isArray(valueObj.events)) {\n for (const event of valueObj.events) {\n try {\n // Skip events with affectedNodeId starting with message_\n // @ts-ignore\n if (event.affectedNodeId?.startsWith(\"message_\")) {\n input = event.data.input;\n continue;\n }\n\n // Convert to new timeline event format\n const eventId = event.id || this.generateId();\n const eventType = event.type || \"unknown\";\n let eventName = event.name || \"unknown\";\n const startTime = event.timestamp || event.startTime || new Date().toISOString();\n const endTime = event.updatedAt || event.endTime || startTime;\n let status = event.status || event.data?.status || null;\n let inputData = null;\n\n // Set input data correctly\n if (event.input) {\n inputData = safeStringify({ input: event.input });\n } else if (event.data?.input) {\n inputData = safeStringify({ input: event.data.input });\n } else if (input) {\n inputData = safeStringify({ input: input });\n }\n\n input = \"\";\n\n // Set metadata\n let metadata = null;\n if (event.metadata) {\n metadata = safeStringify(event.metadata);\n } else if (event.data) {\n metadata = safeStringify({\n id: event.affectedNodeId?.split(\"_\").pop(),\n agentId: event.data?.metadata?.sourceAgentId,\n ...event.data,\n });\n }\n\n // Special event transformations\n if (eventType === \"agent\") {\n if (eventName === \"start\") {\n eventName = \"agent:start\";\n // @ts-ignore\n status = \"running\";\n } else if (eventName === \"finished\") {\n if (event.data.status === \"error\") {\n eventName = \"agent:error\";\n } else {\n eventName = \"agent:success\";\n }\n }\n\n // Add to timeline events table\n await this.client.execute({\n sql: `INSERT OR REPLACE INTO ${timelineEventsTableName}\n (id, history_id, agent_id, event_type, event_name, start_time, end_time, \n status, status_message, level, version, parent_event_id, \n tags, input, output, error, metadata)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n args: [\n eventId,\n id,\n valueObj._agentId || agentId,\n eventType,\n eventName,\n startTime,\n endTime,\n // @ts-ignore\n status,\n eventName === \"agent:error\" ? event.data.error.message : null,\n event.level || \"INFO\",\n event.version || null,\n event.parentEventId || null,\n null, // tags\n inputData,\n event.data.output ? safeStringify(event.data.output) : null,\n eventName === \"agent:error\" ? safeStringify(event.data.error) : null,\n metadata,\n ],\n });\n } else if (eventType === \"memory\") {\n // memory:saveMessage -> memory:write_start and memory:write_success\n if (eventName === \"memory:saveMessage\") {\n // First event: memory:write_start\n await this.client.execute({\n sql: `INSERT OR REPLACE INTO ${timelineEventsTableName}\n (id, history_id, agent_id, event_type, event_name, start_time, end_time, \n status, status_message, level, version, parent_event_id, \n tags, input, output, error, metadata)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n args: [\n eventId,\n id,\n valueObj._agentId || agentId,\n eventType,\n \"memory:write_start\",\n startTime,\n null, // no endTime\n \"running\",\n event.statusMessage || null,\n event.level || \"INFO\",\n event.version || null,\n event.parentEventId || null,\n null, // tags\n inputData,\n null, // no output\n null, // no error\n safeStringify({\n id: \"memory\",\n agentId: event.affectedNodeId?.split(\"_\").pop(),\n }),\n ],\n });\n\n // Second event: tool:success\n await this.client.execute({\n sql: `INSERT OR REPLACE INTO ${timelineEventsTableName}\n (id, history_id, agent_id, event_type, event_name, start_time, end_time, \n status, status_message, level, version, parent_event_id, \n tags, input, output, error, metadata)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n args: [\n this.generateId(), // New ID\n id,\n valueObj._agentId || agentId,\n eventType,\n \"memory:write_success\",\n endTime, // End time\n endTime,\n \"completed\",\n event.statusMessage || null,\n event.level || \"INFO\",\n event.version || null,\n eventId, // Parent event ID\n null, // tags\n inputData,\n event.data.output ? safeStringify(event.data.output) : null,\n event.error ? safeStringify(event.error) : null,\n safeStringify({\n id: \"memory\",\n agentId: event.affectedNodeId?.split(\"_\").pop(),\n }),\n ],\n });\n }\n // memory:getMessages -> memory:read_start and memory:read_success\n else if (eventName === \"memory:getMessages\") {\n // First event: memory:read_start\n await this.client.execute({\n sql: `INSERT OR REPLACE INTO ${timelineEventsTableName}\n (id, history_id, agent_id, event_type, event_name, start_time, end_time, \n status, status_message, level, version, parent_event_id, \n tags, input, output, error, metadata)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n args: [\n eventId,\n id,\n valueObj._agentId || agentId,\n eventType,\n \"memory:read_start\",\n startTime,\n null, // no endTime\n \"running\",\n event.statusMessage || null,\n event.level || \"INFO\",\n event.version || null,\n event.parentEventId || null,\n null, // tags\n inputData,\n null, // no output\n null, // no error\n safeStringify({\n id: \"memory\",\n agentId: event.affectedNodeId?.split(\"_\").pop(),\n }),\n ],\n });\n\n // Second event: memory:read_success\n await this.client.execute({\n sql: `INSERT OR REPLACE INTO ${timelineEventsTableName}\n (id, history_id, agent_id, event_type, event_name, start_time, end_time, \n status, status_message, level, version, parent_event_id, \n tags, input, output, error, metadata)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n args: [\n this.generateId(), // New ID\n id,\n valueObj._agentId || agentId,\n eventType,\n \"memory:read_success\",\n endTime, // End time\n endTime,\n status,\n event.statusMessage || null,\n event.level || \"INFO\",\n event.version || null,\n eventId, // Parent event ID\n null, // tags\n inputData,\n event.data.output ? safeStringify(event.data.output) : null,\n event.error ? safeStringify(event.error) : null,\n safeStringify({\n id: \"memory\",\n agentId: event.affectedNodeId?.split(\"_\").pop(),\n }),\n ],\n });\n } else {\n // Normal addition for other memory events\n await this.client.execute({\n sql: `INSERT OR REPLACE INTO ${timelineEventsTableName}\n (id, history_id, agent_id, event_type, event_name, start_time, end_time, \n status, status_message, level, version, parent_event_id, \n tags, input, output, error, metadata)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n args: [\n eventId,\n id,\n valueObj._agentId || agentId,\n eventType,\n eventName,\n startTime,\n endTime,\n status,\n event.statusMessage || null,\n event.level || \"INFO\",\n event.version || null,\n event.parentEventId || null,\n null, // tags\n inputData,\n event.output ? safeStringify(event.output) : null,\n event.error ? safeStringify(event.error) : null,\n metadata,\n ],\n });\n }\n } else if (eventType === \"tool\") {\n if (eventName === \"tool_working\") {\n // First event: tool:start\n await this.client.execute({\n sql: `INSERT OR REPLACE INTO ${timelineEventsTableName}\n\t\t\t\t\t\t\t\t(id, history_id, agent_id, event_type, event_name, start_time, end_time, \n\t\t\t\t\t\t\t\tstatus, status_message, level, version, parent_event_id, \n\t\t\t\t\t\t\t\ttags, input, output, error, metadata)\n\t\t\t\t\t\t\t\tVALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n args: [\n eventId,\n id,\n valueObj._agentId || agentId,\n eventType,\n \"tool:start\",\n startTime,\n null, // no endTime\n \"running\",\n event.statusMessage || null,\n event.level || \"INFO\",\n event.version || null,\n event.parentEventId || null,\n null, // tags\n inputData,\n null, // no output\n null, // no error\n safeStringify({\n id: event.affectedNodeId?.split(\"_\").pop(),\n agentId: event.data?.metadata?.sourceAgentId,\n displayName: event.data.metadata.toolName,\n }),\n ],\n });\n\n // Second event: tool:success\n await this.client.execute({\n sql: `INSERT OR REPLACE INTO ${timelineEventsTableName}\n\t\t\t\t\t\t\t\t(id, history_id, agent_id, event_type, event_name, start_time, end_time, \n\t\t\t\t\t\t\t\tstatus, status_message, level, version, parent_event_id, \n\t\t\t\t\t\t\t\ttags, input, output, error, metadata)\n\t\t\t\t\t\t\t\tVALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n args: [\n this.generateId(), // New ID\n id,\n valueObj._agentId || agentId,\n eventType,\n \"tool:success\",\n endTime, // End time\n endTime,\n \"completed\",\n event.statusMessage || null,\n event.level || \"INFO\",\n event.version || null,\n eventId, // Parent event ID\n null, // tags\n inputData,\n event.data.output ? safeStringify(event.data.output) : null,\n event.error ? safeStringify(event.error) : null,\n safeStringify({\n id: event.affectedNodeId?.split(\"_\").pop(),\n agentId: event.data?.metadata?.sourceAgentId,\n displayName: event.data.metadata.toolName,\n }),\n ],\n });\n }\n } else {\n // Normal addition for other event types\n await this.client.execute({\n sql: `INSERT OR REPLACE INTO ${timelineEventsTableName}\n (id, history_id, agent_id, event_type, event_name, start_time, end_time, \n status, status_message, level, version, parent_event_id, \n tags, input, output, error, metadata)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n args: [\n eventId,\n id,\n valueObj._agentId || agentId,\n eventType,\n eventName,\n startTime,\n endTime,\n status,\n event.statusMessage || null,\n event.level || \"INFO\",\n event.version || null,\n event.parentEventId || null,\n null, // tags\n inputData,\n event.output ? safeStringify(event.output) : null,\n event.error ? safeStringify(event.error) : null,\n safeStringify({\n id: eventType === \"retriever\" ? \"retriever\" : event.type,\n agentId: event.affectedNodeId?.split(\"_\").pop(),\n }),\n ],\n });\n }\n } catch (error) {\n this.debug(\"Error processing event:\", error);\n // Skip problematic event but continue migration\n }\n }\n }\n\n // Note: steps field is removed so it won't be processed here\n } catch (error) {\n this.debug(`Error processing record with ID ${key}:`, error);\n // Skip problematic records and continue\n }\n }\n\n // Delete original table and rename temp table as original table\n await this.client.execute(`DROP TABLE ${oldTableName};`);\n await this.client.execute(`ALTER TABLE ${tempTableName} RENAME TO ${oldTableName};`);\n\n // Recreate indexes\n await this.client.execute(`\n CREATE INDEX IF NOT EXISTS idx_${oldTableName}_agent_id \n ON ${oldTableName}(agent_id)\n `);\n\n // Complete transaction\n await this.client.execute(\"COMMIT;\");\n\n this.debug(`Total ${migratedCount} records successfully migrated`);\n\n // Should we delete the backup after success?\n if (createBackup && deleteBackupAfterSuccess) {\n await this.client.execute(`DROP TABLE IF EXISTS ${oldTableBackup};`);\n this.debug(\"Unnecessary backup deleted\");\n }\n\n // Set migration flag to prevent future runs\n await this.setMigrationFlag(\"agent_history_data_migration\", migratedCount);\n\n return {\n success: true,\n migratedCount,\n backupCreated: createBackup && !deleteBackupAfterSuccess,\n };\n } catch (error) {\n // Rollback in case of error\n await this.client.execute(\"ROLLBACK;\");\n\n this.debug(\"Error occurred while migrating agent history data:\", error);\n\n return {\n success: false,\n error: error instanceof Error ? error : new Error(String(error)),\n backupCreated: options.createBackup,\n };\n }\n }\n\n /**\n * Migrate conversation schema to add user_id and update messages table\n *\n * ⚠️ **CRITICAL WARNING: DESTRUCTIVE OPERATION** ⚠️\n *\n * This method performs a DESTRUCTIVE schema migration that:\n * - DROPS and recreates existing tables\n * - Creates temporary tables during migration\n * - Modifies the primary key structure of the messages table\n * - Can cause DATA LOSS if interrupted or if errors occur\n *\n * **IMPORTANT SAFETY REQUIREMENTS:**\n * - 🛑 STOP all application instances before running this migration\n * - 🛑 Ensure NO concurrent database operations are running\n * - 🛑 Take a full database backup before running (independent of built-in backup)\n * - 🛑 Test the migration on a copy of production data first\n * - 🛑 Plan for downtime during migration execution\n *\n * **What this migration does:**\n * 1. Creates backup tables (if createBackup=true)\n * 2. Creates temporary tables with new schema\n * 3. Migrates data from old tables to new schema\n * 4. DROPS original tables\n * 5. Renames temporary tables to original names\n * 6. All operations are wrapped in a transaction for atomicity\n *\n * @param options Migration configuration options\n * @param options.createBackup Whether to create backup tables before migration (default: true, HIGHLY RECOMMENDED)\n * @param options.restoreFromBackup Whether to restore from existing backup instead of migrating (default: false)\n * @param options.deleteBackupAfterSuccess Whether to delete backup tables after successful migration (default: false)\n *\n * @returns Promise resolving to migration result with success status, migrated count, and backup info\n *\n * @example\n * ```typescript\n * // RECOMMENDED: Run with backup creation (default)\n * const result = await storage.migrateConversationSchema({\n * createBackup: true,\n * deleteBackupAfterSuccess: false // Keep backup for safety\n * });\n *\n * if (result.success) {\n * console.log(`Migrated ${result.migratedCount} conversations successfully`);\n * } else {\n * console.error('Migration failed:', result.error);\n * // Consider restoring from backup\n * }\n *\n * // If migration fails, restore from backup:\n * const restoreResult = await storage.migrateConversationSchema({\n * restoreFromBackup: true\n * });\n * ```\n *\n * @throws {Error} If migration fails and transaction is rolled back\n *\n * @since This migration is typically only needed when upgrading from older schema versions\n */\n private async migrateConversationSchema(\n options: {\n createBackup?: boolean;\n restoreFromBackup?: boolean;\n deleteBackupAfterSuccess?: boolean;\n } = {},\n ): Promise<{\n success: boolean;\n migratedCount?: number;\n error?: Error;\n backupCreated?: boolean;\n }> {\n const {\n createBackup = true,\n restoreFromBackup = false,\n deleteBackupAfterSuccess = false,\n } = options;\n\n const conversationsTableName = `${this.options.tablePrefix}_conversations`;\n const messagesTableName = `${this.options.tablePrefix}_messages`;\n const conversationsBackupName = `${conversationsTableName}_backup`;\n const messagesBackupName = `${messagesTableName}_backup`;\n\n try {\n this.debug(\"Starting conversation schema migration...\");\n\n // Check if migration has already been completed by looking for a migration flag\n const flagCheck = await this.checkMigrationFlag(\"conversation_schema_migration\");\n if (flagCheck.alreadyCompleted) {\n return { success: true, migratedCount: 0 };\n }\n\n // If restoreFromBackup option is active, restore from backup\n if (restoreFromBackup) {\n this.debug(\"Starting restoration from backup...\");\n\n // Check if backup tables exist\n const convBackupCheck = await this.client.execute({\n sql: \"SELECT name FROM sqlite_master WHERE type='table' AND name=?\",\n args: [conversationsBackupName],\n });\n\n const msgBackupCheck = await this.client.execute({\n sql: \"SELECT name FROM sqlite_master WHERE type='table' AND name=?\",\n args: [messagesBackupName],\n });\n\n if (convBackupCheck.rows.length === 0 || msgBackupCheck.rows.length === 0) {\n throw new Error(\"No backup found to restore\");\n }\n\n // Start transaction\n await this.client.execute(\"BEGIN TRANSACTION;\");\n\n // Restore tables from backup\n await this.client.execute(`DROP TABLE IF EXISTS ${conversationsTableName};`);\n await this.client.execute(`DROP TABLE IF EXISTS ${messagesTableName};`);\n await this.client.execute(\n `ALTER TABLE ${conversationsBackupName} RENAME TO ${conversationsTableName};`,\n );\n await this.client.execute(\n `ALTER TABLE ${messagesBackupName} RENAME TO ${messagesTableName};`,\n );\n\n // Complete transaction\n await this.client.execute(\"COMMIT;\");\n\n this.debug(\"Restoration from backup completed successfully\");\n return { success: true, backupCreated: false };\n }\n\n // Check current table structures\n const convTableInfo = await this.client.execute(\n `PRAGMA table_info(${conversationsTableName})`,\n );\n\n const msgTableInfo = await this.client.execute(`PRAGMA table_info(${messagesTableName})`);\n\n // Check if conversations table has user_id column\n const hasUserIdInConversations = convTableInfo.rows.some((row) => row.name === \"user_id\");\n\n // Check if messages table has user_id column\n const hasUserIdInMessages = msgTableInfo.rows.some((row) => row.name === \"user_id\");\n\n // If conversations already has user_id and messages doesn't have user_id, migration not needed\n if (hasUserIdInConversations && !hasUserIdInMessages) {\n this.debug(\"Tables are already in new format, migration not needed\");\n return { success: true, migratedCount: 0 };\n }\n\n // If neither table exists, no migration needed\n if (convTableInfo.rows.length === 0 && msgTableInfo.rows.length === 0) {\n this.debug(\"Tables don't exist, migration not needed\");\n return { success: true, migratedCount: 0 };\n }\n\n // Create backups if requested\n if (createBackup) {\n this.debug(\"Creating backups...\");\n\n // Remove existing backups\n await this.client.execute(`DROP TABLE IF EXISTS ${conversationsBackupName};`);\n await this.client.execute(`DROP TABLE IF EXISTS ${messagesBackupName};`);\n\n // Create backups\n if (convTableInfo.rows.length > 0) {\n await this.client.execute(\n `CREATE TABLE ${conversationsBackupName} AS SELECT * FROM ${conversationsTableName};`,\n );\n }\n\n if (msgTableInfo.rows.length > 0) {\n await this.client.execute(\n `CREATE TABLE ${messagesBackupName} AS SELECT * FROM ${messagesTableName};`,\n );\n }\n\n this.debug(\"Backups created successfully\");\n }\n\n // Get existing data\n let conversationData: Row[] = [];\n let messageData: Row[] = [];\n\n if (convTableInfo.rows.length > 0) {\n const convResult = await this.client.execute(`SELECT * FROM ${conversationsTableName}`);\n conversationData = convResult.rows;\n }\n\n if (msgTableInfo.rows.length > 0) {\n const msgResult = await this.client.execute(`SELECT * FROM ${messagesTableName}`);\n messageData = msgResult.rows;\n }\n\n // Start transaction for migration\n await this.client.execute(\"BEGIN TRANSACTION;\");\n\n // Create temporary tables with new schemas\n const tempConversationsTable = `${conversationsTableName}_temp`;\n const tempMessagesTable = `${messagesTableName}_temp`;\n\n await this.client.execute(`\n CREATE TABLE ${tempConversationsTable} (\n id TEXT PRIMARY KEY,\n resource_id TEXT NOT NULL,\n user_id TEXT NOT NULL,\n title TEXT NOT NULL,\n metadata TEXT NOT NULL,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL\n )\n `);\n\n await this.client.execute(`\n CREATE TABLE ${tempMessagesTable} (\n conversation_id TEXT NOT NULL,\n message_id TEXT NOT NULL,\n role TEXT NOT NULL,\n content TEXT NOT NULL,\n type TEXT NOT NULL,\n created_at TEXT NOT NULL,\n PRIMARY KEY (conversation_id, message_id)\n )\n `);\n\n let migratedCount = 0;\n const createdConversations = new Set<string>();\n\n // Process each message and create conversation if needed\n for (const row of messageData) {\n const conversationId = row.conversation_id as string;\n let userId = \"default\";\n\n // Get user_id from message if old schema has it\n if (hasUserIdInMessages && row.user_id) {\n userId = row.user_id as string;\n }\n\n // Check if conversation already exists (either migrated or auto-created)\n if (!createdConversations.has(conversationId)) {\n // Check if conversation exists in original conversations data\n const existingConversation = conversationData.find((conv) => conv.id === conversationId);\n\n if (existingConversation) {\n // Migrate existing conversation\n let convUserId = userId; // Use user_id from message\n\n // If conversation already has user_id, use it instead\n if (hasUserIdInConversations && existingConversation.user_id) {\n convUserId = existingConversation.user_id as string;\n }\n\n await this.client.execute({\n sql: `INSERT INTO ${tempConversationsTable} \n (id, resource_id, user_id, title, metadata, created_at, updated_at) \n VALUES (?, ?, ?, ?, ?, ?, ?)`,\n args: [\n existingConversation.id,\n existingConversation.resource_id,\n convUserId,\n existingConversation.title,\n existingConversation.metadata,\n existingConversation.created_at,\n existingConversation.updated_at,\n ],\n });\n } else {\n // Create new conversation from message data\n const now = new Date().toISOString();\n\n await this.client.execute({\n sql: `INSERT INTO ${tempConversationsTable} \n (id, resource_id, user_id, title, metadata, created_at, updated_at) \n VALUES (?, ?, ?, ?, ?, ?, ?)`,\n args: [\n conversationId,\n \"default\", // Default resource_id for auto-created conversations\n userId,\n \"Migrated Conversation\", // Default title\n safeStringify({}), // Empty metadata\n now,\n now,\n ],\n });\n }\n\n createdConversations.add(conversationId);\n migratedCount++;\n }\n\n // Migrate the message (without user_id column)\n await this.client.execute({\n sql: `INSERT INTO ${tempMessagesTable} \n (conversation_id, message_id, role, content, type, created_at) \n VALUES (?, ?, ?, ?, ?, ?)`,\n args: [\n row.conversation_id,\n row.message_id,\n row.role,\n row.content,\n row.type,\n row.created_at,\n ],\n });\n }\n\n // Handle any conversations that exist but have no messages\n for (const row of conversationData) {\n const conversationId = row.id as string;\n\n if (!createdConversations.has(conversationId)) {\n let userId = \"default\";\n\n // If conversation already has user_id, use it\n if (hasUserIdInConversations && row.user_id) {\n userId = row.user_id as string;\n }\n\n await this.client.execute({\n sql: `INSERT INTO ${tempConversationsTable} \n (id, resource_id, user_id, title, metadata, created_at, updated_at) \n VALUES (?, ?, ?, ?, ?, ?, ?)`,\n args: [\n row.id,\n row.resource_id,\n userId,\n row.title,\n row.metadata,\n row.created_at,\n row.updated_at,\n ],\n });\n migratedCount++;\n }\n }\n\n // Replace old tables with new ones\n await this.client.execute(`DROP TABLE IF EXISTS ${conversationsTableName};`);\n await this.client.execute(`DROP TABLE IF EXISTS ${messagesTableName};`);\n await this.client.execute(\n `ALTER TABLE ${tempConversationsTable} RENAME TO ${conversationsTableName};`,\n );\n await this.client.execute(`ALTER TABLE ${tempMessagesTable} RENAME TO ${messagesTableName};`);\n\n // Create indexes for the new schema\n await this.client.execute(`\n CREATE INDEX IF NOT EXISTS idx_${messagesTableName}_lookup\n ON ${messagesTableName}(conversation_id, created_at)\n `);\n\n await this.client.execute(`\n CREATE INDEX IF NOT EXISTS idx_${conversationsTableName}_resource\n ON ${conversationsTableName}(resource_id)\n `);\n\n await this.client.execute(`\n CREATE INDEX IF NOT EXISTS idx_${conversationsTableName}_user\n ON ${conversationsTableName}(user_id)\n `);\n\n // Commit transaction\n await this.client.execute(\"COMMIT;\");\n\n // Delete backups if requested\n if (deleteBackupAfterSuccess) {\n await this.client.execute(`DROP TABLE IF EXISTS ${conversationsBackupName};`);\n await this.client.execute(`DROP TABLE IF EXISTS ${messagesBackupName};`);\n }\n\n // Set migration flag to prevent future runs\n await this.setMigrationFlag(\"conversation_schema_migration\", migratedCount);\n\n this.debug(\n `Conversation schema migration completed successfully. Migrated ${migratedCount} conversations.`,\n );\n\n return {\n success: true,\n migratedCount,\n backupCreated: createBackup,\n };\n } catch (error) {\n this.debug(\"Error during conversation schema migration:\", error);\n\n // Rollback transaction if still active\n try {\n await this.client.execute(\"ROLLBACK;\");\n } catch (rollbackError) {\n this.debug(\"Error rolling back transaction:\", rollbackError);\n }\n\n return {\n success: false,\n error: error as Error,\n backupCreated: createBackup,\n };\n }\n }\n\n /**\n * Get conversations for a user with a fluent query builder interface\n * @param userId User ID to filter by\n * @returns Query builder object\n */\n public getUserConversations(userId: string) {\n return {\n /**\n * Limit the number of results\n * @param count Number of conversations to return\n * @returns Query builder\n */\n limit: (count: number) => ({\n /**\n * Order results by a specific field\n * @param field Field to order by\n * @param direction Sort direction\n * @returns Query builder\n */\n orderBy: (\n field: \"created_at\" | \"updated_at\" | \"title\" = \"updated_at\",\n direction: \"ASC\" | \"DESC\" = \"DESC\",\n ) => ({\n /**\n * Execute the query and return results\n * @returns Promise of conversations\n */\n execute: () =>\n this.getConversationsByUserId(userId, {\n limit: count,\n orderBy: field,\n orderDirection: direction,\n }),\n }),\n /**\n * Execute the query with default ordering\n * @returns Promise of conversations\n */\n execute: () => this.getConversationsByUserId(userId, { limit: count }),\n }),\n\n /**\n * Order results by a specific field\n * @param field Field to order by\n * @param direction Sort direction\n * @returns Query builder\n */\n orderBy: (\n field: \"created_at\" | \"updated_at\" | \"title\" = \"updated_at\",\n direction: \"ASC\" | \"DESC\" = \"DESC\",\n ) => ({\n /**\n * Limit the number of results\n * @param count Number of conversations to return\n * @returns Query builder\n */\n limit: (count: number) => ({\n /**\n * Execute the query and return results\n * @returns Promise of conversations\n */\n execute: () =>\n this.getConversationsByUserId(userId, {\n limit: count,\n orderBy: field,\n orderDirection: direction,\n }),\n }),\n /**\n * Execute the query without limit\n * @returns Promise of conversations\n */\n execute: () =>\n this.getConversationsByUserId(userId, {\n orderBy: field,\n orderDirection: direction,\n }),\n }),\n\n /**\n * Execute the query with default options\n * @returns Promise of conversations\n */\n execute: () => this.getConversationsByUserId(userId),\n };\n }\n\n /**\n * Get conversation by ID and ensure it belongs to the specified user\n * @param conversationId Conversation ID\n * @param userId User ID to validate ownership\n * @returns Conversation or null\n */\n public async getUserConversation(\n conversationId: string,\n userId: string,\n ): Promise<Conversation | null> {\n const conversation = await this.getConversation(conversationId);\n if (!conversation || conversation.userId !== userId) {\n return null;\n }\n return conversation;\n }\n\n /**\n * Get paginated conversations for a user\n * @param userId User ID\n * @param page Page number (1-based)\n * @param pageSize Number of items per page\n * @returns Object with conversations and pagination info\n */\n public async getPaginatedUserConversations(\n userId: string,\n page = 1,\n pageSize = 10,\n ): Promise<{\n conversations: Conversation[];\n page: number;\n pageSize: number;\n hasMore: boolean;\n }> {\n const offset = (page - 1) * pageSize;\n\n // Get one extra to check if there are more pages\n const conversations = await this.getConversationsByUserId(userId, {\n limit: pageSize + 1,\n offset,\n orderBy: \"updated_at\",\n orderDirection: \"DESC\",\n });\n\n const hasMore = conversations.length > pageSize;\n const results = hasMore ? conversations.slice(0, pageSize) : conversations;\n\n return {\n conversations: results,\n page,\n pageSize,\n hasMore,\n };\n }\n\n /**\n * Check and create migration flag table, return if migration already completed\n * @param migrationType Type of migration to check\n * @returns Object with completion status and details\n */\n private async checkMigrationFlag(migrationType: string): Promise<{\n alreadyCompleted: boolean;\n migrationCount?: number;\n completedAt?: string;\n }> {\n const conversationsTableName = `${this.options.tablePrefix}_conversations`;\n const migrationFlagTable = `${conversationsTableName}_migration_flags`;\n\n try {\n const result = await this.client.execute({\n sql: `SELECT * FROM ${migrationFlagTable} WHERE migration_type = ?`,\n args: [migrationType],\n });\n\n if (result.rows.length > 0) {\n const migrationFlag = result.rows[0];\n this.debug(`${migrationType} migration already completed`);\n this.debug(`Migration completed on: ${migrationFlag.completed_at}`);\n this.debug(`Migrated ${migrationFlag.migrated_count || 0} records previously`);\n return {\n alreadyCompleted: true,\n migrationCount: migrationFlag.migrated_count as number,\n completedAt: migrationFlag.completed_at as string,\n };\n }\n\n this.debug(\"Migration flags table found, but no migration flag exists yet\");\n return { alreadyCompleted: false };\n } catch (flagError) {\n // Migration flag table doesn't exist, create it\n this.debug(\"Migration flag table not found, creating it...\");\n this.debug(\"Original error:\", flagError);\n\n try {\n await this.client.execute(`\n CREATE TABLE IF NOT EXISTS ${migrationFlagTable} (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n migration_type TEXT NOT NULL UNIQUE,\n completed_at TEXT NOT NULL DEFAULT (datetime('now')),\n migrated_count INTEGER DEFAULT 0,\n metadata TEXT DEFAULT '{}'\n )\n `);\n this.debug(\"Migration flags table created successfully\");\n } catch (createError) {\n this.debug(\"Failed to create migration flags table:\", createError);\n // Continue with migration even if flag table creation fails\n }\n\n return { alreadyCompleted: false };\n }\n }\n\n /**\n * Set migration flag after successful completion\n * @param migrationType Type of migration completed\n * @param migratedCount Number of records migrated\n */\n private async setMigrationFlag(migrationType: string, migratedCount: number): Promise<void> {\n try {\n const conversationsTableName = `${this.options.tablePrefix}_conversations`;\n const migrationFlagTable = `${conversationsTableName}_migration_flags`;\n\n await this.client.execute({\n sql: `INSERT OR REPLACE INTO ${migrationFlagTable} \n (migration_type, completed_at, migrated_count) \n VALUES (?, datetime('now'), ?)`,\n args: [migrationType, migratedCount],\n });\n\n this.debug(\"Migration flag set successfully\");\n } catch (flagSetError) {\n this.debug(\"Could not set migration flag (non-critical):\", flagSetError);\n }\n }\n\n /**\n * Migrate agent history schema to add userId and conversationId columns\n */\n private async migrateAgentHistorySchema(): Promise<{\n success: boolean;\n error?: Error;\n }> {\n const historyTableName = `${this.options.tablePrefix}_agent_history`;\n\n try {\n this.debug(\"Starting agent history schema migration...\");\n\n // Check if migration has already been completed\n const flagCheck = await this.checkMigrationFlag(\"agent_history_schema_migration\");\n if (flagCheck.alreadyCompleted) {\n return { success: true };\n }\n\n // Check current table structure\n const tableInfo = await this.client.execute(`PRAGMA table_info(${historyTableName})`);\n\n // If table doesn't exist, no migration needed\n if (tableInfo.rows.length === 0) {\n this.debug(\"Agent history table doesn't exist, migration not needed\");\n return { success: true };\n }\n\n // Check if columns already exist\n const hasUserIdColumn = tableInfo.rows.some((row) => row.name === \"userId\");\n const hasConversationIdColumn = tableInfo.rows.some((row) => row.name === \"conversationId\");\n\n // If both columns already exist, skip migration\n if (hasUserIdColumn && hasConversationIdColumn) {\n this.debug(\"Both userId and conversationId columns already exist, skipping migration\");\n\n // Set migration flag\n await this.setMigrationFlag(\"agent_history_schema_migration\", 0);\n\n return { success: true };\n }\n\n // Add userId column if it doesn't exist\n if (!hasUserIdColumn) {\n await this.client.execute(`ALTER TABLE ${historyTableName} ADD COLUMN userId TEXT`);\n this.debug(\"Added userId column to agent history table\");\n }\n\n // Add conversationId column if it doesn't exist\n if (!hasConversationIdColumn) {\n await this.client.execute(`ALTER TABLE ${historyTableName} ADD COLUMN conversationId TEXT`);\n this.debug(\"Added conversationId column to agent history table\");\n }\n\n // Create indexes for new columns\n if (!hasUserIdColumn) {\n await this.client.execute(`\n CREATE INDEX IF NOT EXISTS idx_${historyTableName}_userId \n ON ${historyTableName}(userId)\n `);\n }\n\n if (!hasConversationIdColumn) {\n await this.client.execute(`\n CREATE INDEX IF NOT EXISTS idx_${historyTableName}_conversationId \n ON ${historyTableName}(conversationId)\n `);\n }\n\n // Set migration flag\n await this.setMigrationFlag(\"agent_history_schema_migration\", 0);\n\n this.debug(\"Agent history schema migration completed successfully\");\n\n return { success: true };\n } catch (error) {\n this.debug(\"Error during agent history schema migration:\", error);\n return {\n success: false,\n error: error as Error,\n };\n }\n }\n\n // ===== WorkflowMemory Interface Implementation =====\n // Delegate all workflow operations to the workflow extension\n\n async storeWorkflowHistory(entry: any): Promise<void> {\n await this.initialized;\n return this.workflowExtension.storeWorkflowHistory(entry);\n }\n\n async getWorkflowHistory(id: string): Promise<any> {\n await this.initialized;\n return this.workflowExtension.getWorkflowHistory(id);\n }\n\n async getWorkflowHistoryByWorkflowId(workflowId: string): Promise<any[]> {\n await this.initialized;\n return this.workflowExtension.getWorkflowHistoryByWorkflowId(workflowId);\n }\n\n async updateWorkflowHistory(id: string, updates: any): Promise<void> {\n await this.initialized;\n return this.workflowExtension.updateWorkflowHistory(id, updates);\n }\n\n async deleteWorkflowHistory(id: string): Promise<void> {\n await this.initialized;\n return this.workflowExtension.deleteWorkflowHistory(id);\n }\n\n async storeWorkflowStep(step: any): Promise<void> {\n await this.initialized;\n return this.workflowExtension.storeWorkflowStep(step);\n }\n\n async getWorkflowStep(id: string): Promise<any> {\n await this.initialized;\n return this.workflowExtension.getWorkflowStep(id);\n }\n\n async getWorkflowSteps(workflowHistoryId: string): Promise<any[]> {\n await this.initialized;\n return this.workflowExtension.getWorkflowSteps(workflowHistoryId);\n }\n\n async updateWorkflowStep(id: string, updates: any): Promise<void> {\n await this.initialized;\n return this.workflowExtension.updateWorkflowStep(id, updates);\n }\n\n async deleteWorkflowStep(id: string): Promise<void> {\n await this.initialized;\n return this.workflowExtension.deleteWorkflowStep(id);\n }\n\n async storeWorkflowTimelineEvent(event: any): Promise<void> {\n await this.initialized;\n return this.workflowExtension.storeWorkflowTimelineEvent(event);\n }\n\n async getWorkflowTimelineEvent(id: string): Promise<any> {\n await this.initialized;\n return this.workflowExtension.getWorkflowTimelineEvent(id);\n }\n\n async getWorkflowTimelineEvents(workflowHistoryId: string): Promise<any[]> {\n await this.initialized;\n return this.workflowExtension.getWorkflowTimelineEvents(workflowHistoryId);\n }\n\n async deleteWorkflowTimelineEvent(id: string): Promise<void> {\n await this.initialized;\n return this.workflowExtension.deleteWorkflowTimelineEvent(id);\n }\n\n async getAllWorkflowIds(): Promise<string[]> {\n await this.initialized;\n return this.workflowExtension.getAllWorkflowIds();\n }\n\n async getWorkflowStats(workflowId: string): Promise<any> {\n await this.initialized;\n return this.workflowExtension.getWorkflowStats(workflowId);\n }\n\n async getWorkflowHistoryWithStepsAndEvents(id: string): Promise<any> {\n await this.initialized;\n return this.workflowExtension.getWorkflowHistoryWithStepsAndEvents(id);\n }\n\n async deleteWorkflowHistoryWithRelated(id: string): Promise<void> {\n await this.initialized;\n return this.workflowExtension.deleteWorkflowHistoryWithRelated(id);\n }\n\n async cleanupOldWorkflowHistories(workflowId: string, maxEntries: number): Promise<number> {\n await this.initialized;\n return this.workflowExtension.cleanupOldWorkflowHistories(workflowId, maxEntries);\n }\n\n /**\n * Get the workflow extension for advanced workflow operations\n */\n public getWorkflowExtension(): LibSQLWorkflowExtension {\n return this.workflowExtension;\n }\n}\n","import type { Client } from \"@libsql/client\";\n\n/**\n * Migration to add 'suspended' status to workflow_history table\n */\nexport async function addSuspendedStatusMigration(\n db: Client,\n tablePrefix = \"voltagent_memory\",\n): Promise<void> {\n // First, check if migration is already applied\n const migrationName = \"add_suspended_status_to_workflow_history\";\n\n // Create migrations table if it doesn't exist\n await db.execute(`\n CREATE TABLE IF NOT EXISTS ${tablePrefix}_migrations (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n name TEXT NOT NULL UNIQUE,\n applied_at TEXT DEFAULT CURRENT_TIMESTAMP\n )\n `);\n\n // Check if this migration has already been applied\n const result = await db.execute({\n sql: `SELECT * FROM ${tablePrefix}_migrations WHERE name = ?`,\n args: [migrationName],\n });\n\n if (result.rows.length > 0) {\n return;\n }\n\n try {\n // Since SQLite doesn't support modifying CHECK constraints directly,\n // we need to recreate the table. But first, let's check if it's needed\n const needsMigration = await checkIfSuspendedStatusNeeded(db, tablePrefix);\n\n if (!needsMigration) {\n } else {\n // Perform the actual migration\n await performSuspendedStatusMigration(db, tablePrefix);\n }\n\n // Mark migration as applied\n await db.execute({\n sql: `INSERT INTO ${tablePrefix}_migrations (name) VALUES (?)`,\n args: [migrationName],\n });\n } catch (error) {\n console.error(`[Migration] Failed to apply '${migrationName}':`, error);\n throw error;\n }\n}\n\nasync function checkIfSuspendedStatusNeeded(db: Client, tablePrefix: string): Promise<boolean> {\n try {\n // Try to insert a test record with 'suspended' status\n const testId = `test-suspended-check-${Date.now()}`;\n\n await db.execute({\n sql: `\n INSERT INTO ${tablePrefix}_workflow_history \n (id, name, workflow_id, status, start_time) \n VALUES (?, 'test', 'test', 'suspended', datetime('now'))\n `,\n args: [testId],\n });\n\n // If successful, delete the test record\n await db.execute({\n sql: `DELETE FROM ${tablePrefix}_workflow_history WHERE id = ?`,\n args: [testId],\n });\n\n return false; // Migration not needed\n } catch (error: any) {\n if (error.message?.includes(\"CHECK constraint failed\")) {\n return true; // Migration needed\n }\n throw error; // Re-throw other errors\n }\n}\n\nasync function performSuspendedStatusMigration(db: Client, tablePrefix: string): Promise<void> {\n // Start a transaction\n await db.execute(\"BEGIN TRANSACTION\");\n\n try {\n // 1. Create a temporary table with the new schema\n await db.execute(`\n CREATE TABLE ${tablePrefix}_workflow_history_temp (\n id TEXT PRIMARY KEY,\n name TEXT NOT NULL,\n workflow_id TEXT NOT NULL,\n status TEXT NOT NULL CHECK (status IN ('running', 'completed', 'error', 'cancelled', 'suspended')),\n start_time TEXT NOT NULL,\n end_time TEXT,\n input TEXT,\n output TEXT,\n user_id TEXT,\n conversation_id TEXT,\n metadata TEXT,\n created_at TEXT DEFAULT CURRENT_TIMESTAMP,\n updated_at TEXT DEFAULT CURRENT_TIMESTAMP\n )\n `);\n\n // 2. Copy data from the old table\n await db.execute(`\n INSERT INTO ${tablePrefix}_workflow_history_temp \n SELECT * FROM ${tablePrefix}_workflow_history\n `);\n\n // 3. Drop the old table\n await db.execute(`DROP TABLE ${tablePrefix}_workflow_history`);\n\n // 4. Rename the temp table\n await db.execute(`\n ALTER TABLE ${tablePrefix}_workflow_history_temp \n RENAME TO ${tablePrefix}_workflow_history\n `);\n\n // 5. Recreate indexes\n await db.execute(\n `CREATE INDEX idx_${tablePrefix}_workflow_history_workflow_id ON ${tablePrefix}_workflow_history(workflow_id)`,\n );\n await db.execute(\n `CREATE INDEX idx_${tablePrefix}_workflow_history_status ON ${tablePrefix}_workflow_history(status)`,\n );\n await db.execute(\n `CREATE INDEX idx_${tablePrefix}_workflow_history_start_time ON ${tablePrefix}_workflow_history(start_time)`,\n );\n await db.execute(\n `CREATE INDEX idx_${tablePrefix}_workflow_history_user_id ON ${tablePrefix}_workflow_history(user_id)`,\n );\n await db.execute(\n `CREATE INDEX idx_${tablePrefix}_workflow_history_conversation_id ON ${tablePrefix}_workflow_history(conversation_id)`,\n );\n\n // Commit the transaction\n await db.execute(\"COMMIT\");\n } catch (error) {\n // Rollback on error\n await db.execute(\"ROLLBACK\");\n throw error;\n }\n}\n\n/**\n * Get all applied migrations\n */\nexport async function getAppliedMigrations(\n db: Client,\n tablePrefix = \"voltagent_memory\",\n): Promise<Array<{ name: string; applied_at: string }>> {\n // Ensure migrations table exists\n await db.execute(`\n CREATE TABLE IF NOT EXISTS ${tablePrefix}_migrations (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n name TEXT NOT NULL UNIQUE,\n applied_at TEXT DEFAULT CURRENT_TIMESTAMP\n )\n `);\n\n const result = await db.execute(`\n SELECT name, applied_at FROM ${tablePrefix}_migrations \n ORDER BY applied_at DESC\n `);\n\n return result.rows.map((row) => ({\n name: row.name as string,\n applied_at: row.applied_at as string,\n }));\n}\n","import type { Client } from \"@libsql/client\";\n\n/**\n * Create workflow-related tables in the database\n */\nexport async function createWorkflowTables(\n db: Client,\n tablePrefix = \"voltagent_memory\",\n): Promise<void> {\n // Create workflow_history table\n await db.execute(`\n CREATE TABLE IF NOT EXISTS ${tablePrefix}_workflow_history (\n id TEXT PRIMARY KEY,\n name TEXT NOT NULL,\n workflow_id TEXT NOT NULL,\n status TEXT NOT NULL CHECK (status IN ('running', 'completed', 'error', 'cancelled', 'suspended')),\n start_time TEXT NOT NULL,\n end_time TEXT,\n input TEXT,\n output TEXT,\n user_id TEXT,\n conversation_id TEXT,\n metadata TEXT,\n created_at TEXT DEFAULT CURRENT_TIMESTAMP,\n updated_at TEXT DEFAULT CURRENT_TIMESTAMP\n )\n `);\n\n // Create indexes for workflow_history\n await db.execute(\n `CREATE INDEX IF NOT EXISTS idx_${tablePrefix}_workflow_history_workflow_id ON ${tablePrefix}_workflow_history(workflow_id)`,\n );\n await db.execute(\n `CREATE INDEX IF NOT EXISTS idx_${tablePrefix}_workflow_history_status ON ${tablePrefix}_workflow_history(status)`,\n );\n await db.execute(\n `CREATE INDEX IF NOT EXISTS idx_${tablePrefix}_workflow_history_start_time ON ${tablePrefix}_workflow_history(start_time)`,\n );\n await db.execute(\n `CREATE INDEX IF NOT EXISTS idx_${tablePrefix}_workflow_history_user_id ON ${tablePrefix}_workflow_history(user_id)`,\n );\n await db.execute(\n `CREATE INDEX IF NOT EXISTS idx_${tablePrefix}_workflow_history_conversation_id ON ${tablePrefix}_workflow_history(conversation_id)`,\n );\n\n // Create workflow_steps table\n await db.execute(`\n CREATE TABLE IF NOT EXISTS ${tablePrefix}_workflow_steps (\n id TEXT PRIMARY KEY,\n workflow_history_id TEXT NOT NULL,\n step_index INTEGER NOT NULL,\n step_type TEXT NOT NULL,\n step_name TEXT NOT NULL,\n step_id TEXT,\n status TEXT NOT NULL CHECK (status IN ('running', 'completed', 'error', 'skipped')),\n start_time TEXT NOT NULL,\n end_time TEXT,\n input TEXT,\n output TEXT,\n error_message TEXT,\n agent_execution_id TEXT,\n parallel_index INTEGER,\n parent_step_id TEXT,\n metadata TEXT,\n created_at TEXT DEFAULT CURRENT_TIMESTAMP,\n updated_at TEXT DEFAULT CURRENT_TIMESTAMP\n )\n `);\n\n // Create indexes for workflow_steps\n await db.execute(\n `CREATE INDEX IF NOT EXISTS idx_${tablePrefix}_workflow_steps_workflow_history ON ${tablePrefix}_workflow_steps(workflow_history_id)`,\n );\n await db.execute(\n `CREATE INDEX IF NOT EXISTS idx_${tablePrefix}_workflow_steps_agent_execution ON ${tablePrefix}_workflow_steps(agent_execution_id)`,\n );\n await db.execute(\n `CREATE INDEX IF NOT EXISTS idx_${tablePrefix}_workflow_steps_step_index ON ${tablePrefix}_workflow_steps(workflow_history_id, step_index)`,\n );\n await db.execute(\n `CREATE INDEX IF NOT EXISTS idx_${tablePrefix}_workflow_steps_parallel ON ${tablePrefix}_workflow_steps(parent_step_id, parallel_index)`,\n );\n\n // Create workflow_timeline_events table\n await db.execute(`\n CREATE TABLE IF NOT EXISTS ${tablePrefix}_workflow_timeline_events (\n id TEXT PRIMARY KEY,\n workflow_history_id TEXT NOT NULL,\n event_id TEXT NOT NULL,\n name TEXT NOT NULL,\n type TEXT NOT NULL CHECK (type IN ('workflow', 'workflow-step')),\n start_time TEXT NOT NULL,\n end_time TEXT,\n status TEXT NOT NULL,\n level TEXT DEFAULT 'INFO',\n input TEXT,\n output TEXT,\n status_message TEXT,\n metadata TEXT,\n trace_id TEXT,\n parent_event_id TEXT,\n event_sequence INTEGER,\n created_at TEXT DEFAULT CURRENT_TIMESTAMP\n )\n `);\n\n // Create indexes for workflow_timeline_events\n await db.execute(\n `CREATE INDEX IF NOT EXISTS idx_${tablePrefix}_workflow_timeline_events_workflow_history ON ${tablePrefix}_workflow_timeline_events(workflow_history_id)`,\n );\n await db.execute(\n `CREATE INDEX IF NOT EXISTS idx_${tablePrefix}_workflow_timeline_events_trace ON ${tablePrefix}_workflow_timeline_events(trace_id)`,\n );\n await db.execute(\n `CREATE INDEX IF NOT EXISTS idx_${tablePrefix}_workflow_timeline_events_parent ON ${tablePrefix}_workflow_timeline_events(parent_event_id)`,\n );\n await db.execute(\n `CREATE INDEX IF NOT EXISTS idx_${tablePrefix}_workflow_timeline_events_type ON ${tablePrefix}_workflow_timeline_events(type)`,\n );\n await db.execute(\n `CREATE INDEX IF NOT EXISTS idx_${tablePrefix}_workflow_timeline_events_sequence ON ${tablePrefix}_workflow_timeline_events(event_sequence)`,\n );\n\n // Check if workflow_id column exists in agent_history table\n const checkWorkflowIdColumn = await db.execute(`\n SELECT COUNT(*) as count \n FROM pragma_table_info('agent_history') \n WHERE name = 'workflow_id'\n `);\n\n if (checkWorkflowIdColumn.rows[0].count === 0) {\n // Add workflow_id column to existing agent_history table\n await db.execute(\"ALTER TABLE agent_history ADD COLUMN workflow_id TEXT\");\n }\n\n // Check if workflow_step_id column exists in agent_history table\n const checkWorkflowStepIdColumn = await db.execute(`\n SELECT COUNT(*) as count \n FROM pragma_table_info('agent_history') \n WHERE name = 'workflow_step_id'\n `);\n\n if (checkWorkflowStepIdColumn.rows[0].count === 0) {\n // Add workflow_step_id column to existing agent_history table\n await db.execute(\"ALTER TABLE agent_history ADD COLUMN workflow_step_id TEXT\");\n }\n\n // Create indexes for new columns in agent_history\n await db.execute(\n \"CREATE INDEX IF NOT EXISTS idx_agent_history_workflow_id ON agent_history(workflow_id)\",\n );\n await db.execute(\n \"CREATE INDEX IF NOT EXISTS idx_agent_history_workflow_step ON agent_history(workflow_step_id)\",\n );\n}\n\n/**\n * Drop workflow-related tables (for testing purposes)\n */\nexport async function dropWorkflowTables(\n db: Client,\n tablePrefix = \"voltagent_memory\",\n): Promise<void> {\n // Drop tables in reverse order due to foreign key constraints\n await db.execute(`DROP TABLE IF EXISTS ${tablePrefix}_workflow_timeline_events`);\n await db.execute(`DROP TABLE IF EXISTS ${tablePrefix}_workflow_steps`);\n await db.execute(`DROP TABLE IF EXISTS ${tablePrefix}_workflow_history`);\n}\n\n/**\n * Reset workflow tables (drop and recreate)\n */\nexport async function resetWorkflowTables(\n db: Client,\n tablePrefix = \"voltagent_memory\",\n): Promise<void> {\n await dropWorkflowTables(db, tablePrefix);\n await createWorkflowTables(db, tablePrefix);\n}\n","import type { Client } from \"@libsql/client\";\nimport type {\n WorkflowHistoryEntry,\n WorkflowStats,\n WorkflowStepHistoryEntry,\n WorkflowTimelineEvent,\n} from \"@voltagent/core\";\nimport { safeStringify } from \"@voltagent/internal/utils\";\nimport { type Logger, createPinoLogger } from \"@voltagent/logger\";\n\n/**\n * LibSQL extension for workflow memory operations\n * This class provides workflow-specific storage operations for LibSQL\n */\nexport class LibSQLWorkflowExtension {\n private logger: Logger;\n\n constructor(\n private client: Client,\n private _tablePrefix = \"voltagent_memory\",\n logger?: Logger,\n ) {\n this.logger = logger || createPinoLogger({ name: \"libsql-workflow\" });\n }\n\n /**\n * Store a workflow history entry\n */\n async storeWorkflowHistory(entry: WorkflowHistoryEntry): Promise<void> {\n await this.client.execute({\n sql: `\n INSERT INTO ${this._tablePrefix}_workflow_history (\n id, name, workflow_id, status, start_time, end_time, \n input, output, user_id, conversation_id, metadata, created_at, updated_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `,\n args: [\n entry.id,\n entry.workflowName,\n entry.workflowId,\n entry.status,\n entry.startTime.toISOString(),\n entry.endTime?.toISOString() || null,\n safeStringify(entry.input),\n entry.output ? safeStringify(entry.output) : null,\n entry.userId || null,\n entry.conversationId || null,\n entry.metadata ? safeStringify(entry.metadata) : null,\n entry.createdAt?.toISOString() || new Date().toISOString(),\n entry.updatedAt?.toISOString() || new Date().toISOString(),\n ],\n });\n }\n\n /**\n * Get a workflow history entry by ID\n */\n async getWorkflowHistory(id: string): Promise<WorkflowHistoryEntry | null> {\n const result = await this.client.execute({\n sql: `SELECT * FROM ${this._tablePrefix}_workflow_history WHERE id = ?`,\n args: [id],\n });\n\n if (result.rows.length === 0) return null;\n\n return this.parseWorkflowHistoryRow(result.rows[0]);\n }\n\n /**\n * Get all workflow history entries for a specific workflow\n */\n async getWorkflowHistoryByWorkflowId(workflowId: string): Promise<WorkflowHistoryEntry[]> {\n const result = await this.client.execute({\n sql: `SELECT * FROM ${this._tablePrefix}_workflow_history WHERE workflow_id = ? ORDER BY start_time DESC`,\n args: [workflowId],\n });\n\n return result.rows.map((row) => this.parseWorkflowHistoryRow(row));\n }\n\n /**\n * Update a workflow history entry\n */\n async updateWorkflowHistory(id: string, updates: Partial<WorkflowHistoryEntry>): Promise<void> {\n this.logger.trace(`Updating workflow history ${id}`, {\n status: updates.status,\n hasMetadata: !!updates.metadata,\n hasSuspension: !!updates.metadata?.suspension,\n });\n\n const setClauses: string[] = [];\n const args: any[] = [];\n\n if (updates.status !== undefined) {\n setClauses.push(\"status = ?\");\n args.push(updates.status);\n }\n if (updates.endTime !== undefined) {\n setClauses.push(\"end_time = ?\");\n args.push(updates.endTime.toISOString());\n }\n if (updates.output !== undefined) {\n setClauses.push(\"output = ?\");\n args.push(safeStringify(updates.output));\n }\n if (updates.userId !== undefined) {\n setClauses.push(\"user_id = ?\");\n args.push(updates.userId);\n }\n if (updates.conversationId !== undefined) {\n setClauses.push(\"conversation_id = ?\");\n args.push(updates.conversationId);\n }\n if (updates.metadata !== undefined) {\n setClauses.push(\"metadata = ?\");\n const metadataJson = safeStringify(updates.metadata);\n args.push(metadataJson);\n this.logger.trace(`Setting metadata for ${id}:`, { metadata: metadataJson });\n }\n\n setClauses.push(\"updated_at = ?\");\n args.push(new Date().toISOString());\n args.push(id);\n\n const sql = `UPDATE ${this._tablePrefix}_workflow_history SET ${setClauses.join(\", \")} WHERE id = ?`;\n this.logger.trace(\"Executing SQL:\", { sql, args });\n\n try {\n const result = await this.client.execute({ sql, args });\n this.logger.trace(\n `Successfully updated workflow history ${id}, rows affected: ${result.rowsAffected}`,\n );\n } catch (error) {\n this.logger.error(`Failed to update workflow history ${id}:`, { error });\n throw error;\n }\n }\n\n /**\n * Delete a workflow history entry\n */\n async deleteWorkflowHistory(id: string): Promise<void> {\n await this.client.execute({\n sql: `DELETE FROM ${this._tablePrefix}_workflow_history WHERE id = ?`,\n args: [id],\n });\n }\n\n /**\n * Store a workflow step entry\n */\n async storeWorkflowStep(step: WorkflowStepHistoryEntry): Promise<void> {\n await this.client.execute({\n sql: `\n INSERT INTO ${this._tablePrefix}_workflow_steps (\n id, workflow_history_id, step_index, step_type, step_name, step_id,\n status, start_time, end_time, input, output, error_message,\n agent_execution_id, parallel_index, parent_step_id, metadata,\n created_at, updated_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `,\n args: [\n step.id,\n step.workflowHistoryId,\n step.stepIndex,\n step.stepType,\n step.stepName,\n step.stepId || null,\n step.status,\n step.startTime.toISOString(),\n step.endTime?.toISOString() || null,\n step.input ? safeStringify(step.input) : null,\n step.output ? safeStringify(step.output) : null,\n step.error ? safeStringify(step.error) : null,\n step.agentExecutionId || null,\n step.parallelIndex || null,\n step.parallelParentStepId || null,\n step.metadata ? safeStringify(step.metadata) : null,\n step.createdAt?.toISOString() || new Date().toISOString(),\n step.updatedAt?.toISOString() || new Date().toISOString(),\n ],\n });\n }\n\n /**\n * Get a workflow step by ID\n */\n async getWorkflowStep(id: string): Promise<WorkflowStepHistoryEntry | null> {\n const result = await this.client.execute({\n sql: `SELECT * FROM ${this._tablePrefix}_workflow_steps WHERE id = ?`,\n args: [id],\n });\n\n if (result.rows.length === 0) return null;\n\n return this.parseWorkflowStepRow(result.rows[0]);\n }\n\n /**\n * Get all workflow steps for a specific workflow history\n */\n async getWorkflowSteps(workflowHistoryId: string): Promise<WorkflowStepHistoryEntry[]> {\n const result = await this.client.execute({\n sql: `SELECT * FROM ${this._tablePrefix}_workflow_steps WHERE workflow_history_id = ? ORDER BY step_index ASC`,\n args: [workflowHistoryId],\n });\n\n return result.rows.map((row) => this.parseWorkflowStepRow(row));\n }\n\n /**\n * Update a workflow step\n */\n async updateWorkflowStep(id: string, updates: Partial<WorkflowStepHistoryEntry>): Promise<void> {\n const setClauses: string[] = [];\n const args: any[] = [];\n\n if (updates.status !== undefined) {\n setClauses.push(\"status = ?\");\n args.push(updates.status);\n }\n if (updates.endTime !== undefined) {\n setClauses.push(\"end_time = ?\");\n args.push(updates.endTime.toISOString());\n }\n if (updates.output !== undefined) {\n setClauses.push(\"output = ?\");\n args.push(safeStringify(updates.output));\n }\n if (updates.error !== undefined) {\n setClauses.push(\"error_message = ?\");\n args.push(safeStringify(updates.error));\n }\n if (updates.agentExecutionId !== undefined) {\n setClauses.push(\"agent_execution_id = ?\");\n args.push(updates.agentExecutionId);\n }\n if (updates.metadata !== undefined) {\n setClauses.push(\"metadata = ?\");\n args.push(safeStringify(updates.metadata));\n }\n\n setClauses.push(\"updated_at = ?\");\n args.push(new Date().toISOString());\n args.push(id);\n\n await this.client.execute({\n sql: `UPDATE ${this._tablePrefix}_workflow_steps SET ${setClauses.join(\", \")} WHERE id = ?`,\n args,\n });\n }\n\n /**\n * Delete a workflow step\n */\n async deleteWorkflowStep(id: string): Promise<void> {\n await this.client.execute({\n sql: `DELETE FROM ${this._tablePrefix}_workflow_steps WHERE id = ?`,\n args: [id],\n });\n }\n\n /**\n * Store a workflow timeline event\n */\n async storeWorkflowTimelineEvent(event: WorkflowTimelineEvent): Promise<void> {\n await this.client.execute({\n sql: `\n INSERT INTO ${this._tablePrefix}_workflow_timeline_events (\n id, workflow_history_id, event_id, name, type,\n start_time, end_time, status, level, input, output,\n status_message, metadata, trace_id, parent_event_id, event_sequence, created_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `,\n args: [\n event.id,\n event.workflowHistoryId,\n event.eventId,\n event.name,\n event.type,\n event.startTime,\n event.endTime || null,\n event.status,\n event.level || \"INFO\",\n event.input ? safeStringify(event.input) : null,\n event.output ? safeStringify(event.output) : null,\n event.statusMessage ? safeStringify(event.statusMessage) : null,\n event.metadata ? safeStringify(event.metadata) : null,\n event.traceId || null,\n event.parentEventId || null,\n event.eventSequence || null, // Event sequence for ordering\n event.createdAt.toISOString(),\n ],\n });\n }\n\n /**\n * Get a workflow timeline event by ID\n */\n async getWorkflowTimelineEvent(id: string): Promise<WorkflowTimelineEvent | null> {\n const result = await this.client.execute({\n sql: `SELECT * FROM ${this._tablePrefix}_workflow_timeline_events WHERE id = ?`,\n args: [id],\n });\n\n if (result.rows.length === 0) return null;\n\n return this.parseWorkflowTimelineEventRow(result.rows[0]);\n }\n\n /**\n * Get all workflow timeline events for a specific workflow history\n */\n async getWorkflowTimelineEvents(workflowHistoryId: string): Promise<WorkflowTimelineEvent[]> {\n const result = await this.client.execute({\n sql: `SELECT * FROM ${this._tablePrefix}_workflow_timeline_events WHERE workflow_history_id = ? ORDER BY event_sequence ASC, start_time ASC`,\n args: [workflowHistoryId],\n });\n\n return result.rows.map((row) => this.parseWorkflowTimelineEventRow(row));\n }\n\n /**\n * Delete a workflow timeline event\n */\n async deleteWorkflowTimelineEvent(id: string): Promise<void> {\n await this.client.execute({\n sql: `DELETE FROM ${this._tablePrefix}_workflow_timeline_events WHERE id = ?`,\n args: [id],\n });\n }\n\n /**\n * Get all workflow IDs\n */\n async getAllWorkflowIds(): Promise<string[]> {\n const result = await this.client.execute({\n sql: `SELECT DISTINCT workflow_id FROM ${this._tablePrefix}_workflow_history`,\n args: [],\n });\n\n return result.rows.map((row) => row.workflow_id as string);\n }\n\n /**\n * Get workflow statistics\n */\n async getWorkflowStats(workflowId: string): Promise<WorkflowStats> {\n const result = await this.client.execute({\n sql: `\n SELECT \n COUNT(*) as total_executions,\n SUM(CASE WHEN status = 'completed' THEN 1 ELSE 0 END) as successful_executions,\n SUM(CASE WHEN status = 'error' THEN 1 ELSE 0 END) as failed_executions,\n AVG(CASE WHEN end_time IS NOT NULL THEN \n (julianday(end_time) - julianday(start_time)) * 24 * 60 * 60 * 1000 \n ELSE NULL END) as avg_duration_ms,\n MAX(start_time) as last_execution_time\n FROM ${this._tablePrefix}_workflow_history \n WHERE workflow_id = ?\n `,\n args: [workflowId],\n });\n\n if (result.rows.length === 0) {\n return {\n totalExecutions: 0,\n successfulExecutions: 0,\n failedExecutions: 0,\n averageExecutionTime: 0,\n lastExecutionTime: undefined,\n };\n }\n\n const row = result.rows[0];\n return {\n totalExecutions: Number(row.total_executions) || 0,\n successfulExecutions: Number(row.successful_executions) || 0,\n failedExecutions: Number(row.failed_executions) || 0,\n averageExecutionTime: Number(row.avg_duration_ms) || 0,\n lastExecutionTime: row.last_execution_time\n ? new Date(row.last_execution_time as string)\n : undefined,\n };\n }\n\n /**\n * Get workflow history with all related data (steps and events)\n */\n async getWorkflowHistoryWithStepsAndEvents(id: string): Promise<WorkflowHistoryEntry | null> {\n const history = await this.getWorkflowHistory(id);\n if (!history) return null;\n\n // Load steps and events\n const [steps, events] = await Promise.all([\n this.getWorkflowSteps(id),\n this.getWorkflowTimelineEvents(id),\n ]);\n\n history.steps = steps;\n history.events = events;\n\n return history;\n }\n\n /**\n * Delete workflow history and all related data\n */\n async deleteWorkflowHistoryWithRelated(id: string): Promise<void> {\n // Foreign key constraints will handle cascade deletion\n await this.deleteWorkflowHistory(id);\n }\n\n /**\n * Clean up old workflow histories\n */\n async cleanupOldWorkflowHistories(workflowId: string, maxEntries: number): Promise<number> {\n // Get count of current entries\n const countResult = await this.client.execute({\n sql: `SELECT COUNT(*) as count FROM ${this._tablePrefix}_workflow_history WHERE workflow_id = ?`,\n args: [workflowId],\n });\n\n const currentCount = Number(countResult.rows[0].count);\n if (currentCount <= maxEntries) return 0;\n\n // Delete old entries beyond maxEntries\n const deleteCount = currentCount - maxEntries;\n const deleteResult = await this.client.execute({\n sql: `\n DELETE FROM ${this._tablePrefix}_workflow_history \n WHERE workflow_id = ? \n AND id IN (\n SELECT id FROM ${this._tablePrefix}_workflow_history \n WHERE workflow_id = ? \n ORDER BY start_time ASC \n LIMIT ?\n )\n `,\n args: [workflowId, workflowId, deleteCount],\n });\n\n return deleteResult.rowsAffected;\n }\n\n /**\n * Parse workflow history row from database\n */\n private parseWorkflowHistoryRow(row: any): WorkflowHistoryEntry {\n return {\n id: row.id as string,\n workflowName: row.name as string,\n workflowId: row.workflow_id as string,\n status: row.status as any,\n startTime: new Date(row.start_time as string),\n endTime: row.end_time ? new Date(row.end_time as string) : undefined,\n input: row.input ? JSON.parse(row.input as string) : null,\n output: row.output ? JSON.parse(row.output as string) : undefined,\n userId: row.user_id as string | undefined,\n conversationId: row.conversation_id as string | undefined,\n metadata: row.metadata ? JSON.parse(row.metadata as string) : undefined,\n steps: [], // Will be loaded separately if needed\n events: [], // Will be loaded separately if needed\n createdAt: new Date(row.created_at as string),\n updatedAt: new Date(row.updated_at as string),\n };\n }\n\n /**\n * Parse workflow step row from database\n */\n private parseWorkflowStepRow(row: any): WorkflowStepHistoryEntry {\n return {\n id: row.id as string,\n workflowHistoryId: row.workflow_history_id as string,\n stepIndex: Number(row.step_index),\n stepType: row.step_type as any,\n stepName: row.step_name as string,\n stepId: (row.step_id as string) || undefined,\n status: row.status as any,\n startTime: new Date(row.start_time as string),\n endTime: row.end_time ? new Date(row.end_time as string) : undefined,\n input: row.input ? JSON.parse(row.input as string) : undefined,\n output: row.output ? JSON.parse(row.output as string) : undefined,\n error: row.error_message ? JSON.parse(row.error_message as string) : undefined,\n agentExecutionId: (row.agent_execution_id as string) || undefined,\n parallelIndex: row.parallel_index ? Number(row.parallel_index) : undefined,\n parallelParentStepId: (row.parent_step_id as string) || undefined,\n metadata: row.metadata ? JSON.parse(row.metadata as string) : undefined,\n createdAt: new Date(row.created_at as string),\n updatedAt: new Date(row.updated_at as string),\n };\n }\n\n /**\n * Parse workflow timeline event row from database\n */\n private parseWorkflowTimelineEventRow(row: any): WorkflowTimelineEvent {\n return {\n id: row.id as string,\n workflowHistoryId: row.workflow_history_id as string,\n eventId: row.event_id as string,\n name: row.name as string,\n type: row.type as any,\n startTime: row.start_time as string,\n endTime: row.end_time ? (row.end_time as string) : undefined,\n status: row.status as string,\n level: (row.level as string) || undefined,\n input: row.input ? JSON.parse(row.input as string) : undefined,\n output: row.output ? JSON.parse(row.output as string) : undefined,\n statusMessage: row.status_message ? JSON.parse(row.status_message as string) : undefined,\n metadata: row.metadata ? JSON.parse(row.metadata as string) : undefined,\n traceId: (row.trace_id as string) || undefined,\n parentEventId: (row.parent_event_id as string) || undefined,\n eventSequence: Number(row.event_sequence),\n createdAt: new Date(row.created_at as string),\n };\n }\n}\n"],"mappings":"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","names":["import_utils","import_logger","row"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/memory-v2-adapter.ts","../src/observability-adapter.ts","../src/vector-adapter.ts"],"sourcesContent":["// Export Memory adapter\nexport { LibSQLMemoryAdapter } from \"./memory-v2-adapter\";\nexport type { LibSQLMemoryOptions } from \"./memory-v2-adapter\";\n\n// Export Observability adapter\nexport { LibSQLObservabilityAdapter } from \"./observability-adapter\";\nexport type { LibSQLObservabilityOptions } from \"./observability-adapter\";\n\n// Export Vector adapter\nexport { LibSQLVectorAdapter } from \"./vector-adapter\";\nexport type { LibSQLVectorOptions } from \"./vector-adapter\";\n","/**\n * LibSQL Storage Adapter for Memory\n * Stores conversations and messages in SQLite/Turso database\n * Compatible with existing LibSQL storage structure\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { type Client, createClient } from \"@libsql/client\";\nimport {\n AgentRegistry,\n ConversationAlreadyExistsError,\n ConversationNotFoundError,\n} from \"@voltagent/core\";\nimport type {\n Conversation,\n ConversationQueryOptions,\n CreateConversationInput,\n GetMessagesOptions,\n StorageAdapter,\n WorkflowStateEntry,\n WorkingMemoryScope,\n} from \"@voltagent/core\";\nimport { type Logger, createPinoLogger } from \"@voltagent/logger\";\nimport type { UIMessage } from \"ai\";\n\n/**\n * LibSQL configuration options for Memory\n */\nexport interface LibSQLMemoryOptions {\n /**\n * Database URL (e.g., 'file:./conversations.db' or 'libsql://...')\n * @default \"file:./.voltagent/memory.db\"\n */\n url?: string;\n\n /**\n * Auth token for remote connections (optional)\n */\n authToken?: string;\n\n /**\n * Maximum number of messages to store per conversation\n * @default 100\n */\n storageLimit?: number;\n\n /**\n * Prefix for table names\n * @default \"voltagent_memory\"\n */\n tablePrefix?: string;\n\n /**\n * Enable debug logging\n * @default false\n */\n debug?: boolean;\n\n /**\n * Logger instance\n */\n logger?: Logger;\n\n /**\n * Maximum number of retries for database operations\n * @default 3\n */\n maxRetries?: number;\n\n /**\n * Initial retry delay in milliseconds\n * @default 100\n */\n retryDelayMs?: number;\n}\n\n/**\n * LibSQL Storage Adapter for Memory\n * Production-ready storage for conversations and messages\n * Compatible with existing LibSQL storage structure\n */\nexport class LibSQLMemoryAdapter implements StorageAdapter {\n private client: Client;\n private storageLimit: number;\n private tablePrefix: string;\n private initialized = false;\n private logger: Logger;\n private maxRetries: number;\n private retryDelayMs: number;\n private url: string;\n\n constructor(options: LibSQLMemoryOptions = {}) {\n this.storageLimit = options.storageLimit ?? 100;\n this.tablePrefix = options.tablePrefix ?? \"voltagent_memory\";\n this.maxRetries = options.maxRetries ?? 3;\n this.retryDelayMs = options.retryDelayMs ?? 100;\n\n // Initialize logger - use provided logger, global logger, or create new one\n this.logger =\n options.logger ||\n AgentRegistry.getInstance().getGlobalLogger() ||\n createPinoLogger({ name: \"libsql-memory\" });\n\n this.url = options.url ?? \"file:./.voltagent/memory.db\";\n\n // Create directory for file-based databases\n if (this.url.startsWith(\"file:\")) {\n const dbPath = this.url.replace(\"file:\", \"\");\n const dbDir = path.dirname(dbPath);\n if (dbDir && dbDir !== \".\" && !fs.existsSync(dbDir)) {\n fs.mkdirSync(dbDir, { recursive: true });\n this.logger.debug(`Created database directory: ${dbDir}`);\n }\n }\n\n // Create LibSQL client\n this.client = createClient({\n url: this.url,\n authToken: options.authToken,\n });\n\n this.logger.debug(\"LibSQL Memory adapter initialized\", { url: this.url });\n }\n\n /**\n * Execute a database operation with retry logic\n */\n private async executeWithRetry<T>(\n operation: () => Promise<T>,\n operationName: string,\n ): Promise<T> {\n let lastError: Error | undefined;\n\n for (let attempt = 0; attempt < this.maxRetries; attempt++) {\n try {\n return await operation();\n } catch (error: any) {\n lastError = error;\n\n // Check if error is retryable (SQLITE_BUSY, etc.)\n if (\n error?.code === \"SQLITE_BUSY\" ||\n error?.message?.includes(\"SQLITE_BUSY\") ||\n error?.message?.includes(\"database is locked\")\n ) {\n const delay = this.retryDelayMs * 2 ** attempt; // Exponential backoff\n this.logger.debug(\n `Database busy, retrying ${operationName} (attempt ${attempt + 1}/${this.maxRetries}) after ${delay}ms`,\n );\n await new Promise((resolve) => setTimeout(resolve, delay));\n } else {\n // Non-retryable error, throw immediately\n throw error;\n }\n }\n }\n\n // All retries exhausted\n this.logger.error(\n `Failed to execute ${operationName} after ${this.maxRetries} attempts`,\n lastError,\n );\n throw lastError;\n }\n\n /**\n * Initialize database schema\n */\n private async initialize(): Promise<void> {\n if (this.initialized) return;\n\n const conversationsTable = `${this.tablePrefix}_conversations`;\n const messagesTable = `${this.tablePrefix}_messages`;\n const usersTable = `${this.tablePrefix}_users`;\n const workflowStatesTable = `${this.tablePrefix}_workflow_states`;\n\n // Set PRAGMA settings for better concurrency\n // Execute individually to handle errors gracefully\n const isMemoryDb = this.url === \":memory:\" || this.url.includes(\"mode=memory\");\n\n // Only set WAL mode for file-based databases (not for in-memory)\n if (!isMemoryDb && (this.url.startsWith(\"file:\") || this.url.startsWith(\"libsql:\"))) {\n try {\n await this.client.execute(\"PRAGMA journal_mode=WAL\");\n this.logger.debug(\"Set PRAGMA journal_mode=WAL\");\n } catch (err) {\n this.logger.debug(\"Failed to set PRAGMA journal_mode=WAL (non-critical)\", { err });\n }\n }\n\n // Set busy timeout (works for both memory and file databases)\n try {\n await this.client.execute(\"PRAGMA busy_timeout=5000\");\n this.logger.debug(\"Set PRAGMA busy_timeout=5000\");\n } catch (err) {\n this.logger.debug(\"Failed to set PRAGMA busy_timeout (non-critical)\", { err });\n }\n\n // Enable foreign keys (works for both memory and file databases)\n try {\n await this.client.execute(\"PRAGMA foreign_keys=ON\");\n this.logger.debug(\"Set PRAGMA foreign_keys=ON\");\n } catch (err) {\n this.logger.debug(\"Failed to set PRAGMA foreign_keys (non-critical)\", { err });\n }\n\n this.logger.debug(\"Applied PRAGMA settings for better concurrency\");\n\n await this.executeWithRetry(async () => {\n await this.client.batch([\n // Create users table (for user-level working memory)\n `CREATE TABLE IF NOT EXISTS ${usersTable} (\n id TEXT PRIMARY KEY,\n metadata TEXT,\n created_at TEXT DEFAULT CURRENT_TIMESTAMP,\n updated_at TEXT DEFAULT CURRENT_TIMESTAMP\n )`,\n\n // Create conversations table (matching existing structure)\n `CREATE TABLE IF NOT EXISTS ${conversationsTable} (\n id TEXT PRIMARY KEY,\n resource_id TEXT NOT NULL,\n user_id TEXT NOT NULL,\n title TEXT NOT NULL,\n metadata TEXT NOT NULL,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL\n )`,\n\n // Create messages table (matching existing structure)\n `CREATE TABLE IF NOT EXISTS ${messagesTable} (\n conversation_id TEXT NOT NULL,\n message_id TEXT NOT NULL,\n user_id TEXT NOT NULL,\n role TEXT NOT NULL,\n parts TEXT NOT NULL,\n metadata TEXT,\n format_version INTEGER DEFAULT 2,\n created_at TEXT NOT NULL,\n PRIMARY KEY (conversation_id, message_id)\n )`,\n\n // Create workflow states table\n `CREATE TABLE IF NOT EXISTS ${workflowStatesTable} (\n id TEXT PRIMARY KEY,\n workflow_id TEXT NOT NULL,\n workflow_name TEXT NOT NULL,\n status TEXT NOT NULL,\n suspension TEXT,\n user_id TEXT,\n conversation_id TEXT,\n metadata TEXT,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL\n )`,\n\n // Create indexes for better performance\n `CREATE INDEX IF NOT EXISTS idx_${conversationsTable}_user_id ON ${conversationsTable}(user_id)`,\n `CREATE INDEX IF NOT EXISTS idx_${conversationsTable}_resource_id ON ${conversationsTable}(resource_id)`,\n `CREATE INDEX IF NOT EXISTS idx_${messagesTable}_conversation_id ON ${messagesTable}(conversation_id)`,\n `CREATE INDEX IF NOT EXISTS idx_${messagesTable}_created_at ON ${messagesTable}(created_at)`,\n `CREATE INDEX IF NOT EXISTS idx_${workflowStatesTable}_workflow_id ON ${workflowStatesTable}(workflow_id)`,\n `CREATE INDEX IF NOT EXISTS idx_${workflowStatesTable}_status ON ${workflowStatesTable}(status)`,\n ]);\n }, \"initialize database schema\");\n\n // Add V2 columns to existing messages table if needed\n await this.addV2ColumnsToMessagesTable();\n\n // Migrate default user_id values to actual values from conversations\n await this.migrateDefaultUserIds();\n\n this.initialized = true;\n this.logger.debug(\"Database schema initialized\");\n }\n\n /**\n * Add new columns to messages table for V2 format if they don't exist\n * This allows existing tables to support both old and new message formats\n */\n private async addV2ColumnsToMessagesTable(): Promise<void> {\n const messagesTableName = `${this.tablePrefix}_messages`;\n\n try {\n // Check which columns exist\n const tableInfo = await this.client.execute(`PRAGMA table_info(${messagesTableName})`);\n const columns = tableInfo.rows.map((row) => row.name as string);\n\n // Step 1: Add new V2 columns if they don't exist\n if (!columns.includes(\"parts\")) {\n try {\n await this.client.execute(`ALTER TABLE ${messagesTableName} ADD COLUMN parts TEXT`);\n } catch (_e) {\n // Column might already exist\n }\n }\n\n if (!columns.includes(\"metadata\")) {\n try {\n await this.client.execute(`ALTER TABLE ${messagesTableName} ADD COLUMN metadata TEXT`);\n } catch (_e) {\n // Column might already exist\n }\n }\n\n if (!columns.includes(\"format_version\")) {\n try {\n await this.client.execute(\n `ALTER TABLE ${messagesTableName} ADD COLUMN format_version INTEGER DEFAULT 2`,\n );\n } catch (_e) {\n // Column might already exist\n }\n }\n\n if (!columns.includes(\"user_id\")) {\n try {\n await this.client.execute(\n `ALTER TABLE ${messagesTableName} ADD COLUMN user_id TEXT NOT NULL DEFAULT 'default'`,\n );\n } catch (_e) {\n // Column might already exist\n }\n }\n\n // Step 2: Migrate old columns to nullable versions if they exist\n // Check if content needs migration (check for NOT NULL constraint)\n const contentInfo = tableInfo.rows.find((row) => row.name === \"content\");\n if (contentInfo && contentInfo.notnull === 1) {\n try {\n // Create nullable temp column\n await this.client.execute(\n `ALTER TABLE ${messagesTableName} ADD COLUMN content_temp TEXT`,\n );\n\n // Copy data\n await this.client.execute(\n `UPDATE ${messagesTableName} SET content_temp = content WHERE content IS NOT NULL`,\n );\n\n // Try to drop old column (SQLite 3.35.0+)\n try {\n await this.client.execute(`ALTER TABLE ${messagesTableName} DROP COLUMN content`);\n\n // If drop succeeded, rename temp to original\n await this.client.execute(\n `ALTER TABLE ${messagesTableName} RENAME COLUMN content_temp TO content`,\n );\n } catch (_) {\n // If DROP not supported, keep both columns\n // Silent fail - not critical\n }\n } catch (_) {\n // Content migration error - not critical\n }\n }\n\n // Same for type column\n const typeInfo = tableInfo.rows.find((row) => row.name === \"type\");\n if (typeInfo && typeInfo.notnull === 1) {\n try {\n // Create nullable temp column\n await this.client.execute(`ALTER TABLE ${messagesTableName} ADD COLUMN type_temp TEXT`);\n\n // Copy data\n await this.client.execute(\n `UPDATE ${messagesTableName} SET type_temp = type WHERE type IS NOT NULL`,\n );\n\n // Try to drop old column (SQLite 3.35.0+)\n try {\n await this.client.execute(`ALTER TABLE ${messagesTableName} DROP COLUMN type`);\n\n // If drop succeeded, rename temp to original\n await this.client.execute(\n `ALTER TABLE ${messagesTableName} RENAME COLUMN type_temp TO type`,\n );\n } catch (_) {\n // If DROP not supported, keep both columns\n // Silent fail - not critical\n }\n } catch (_) {\n // Type migration error - not critical\n }\n }\n } catch (_) {\n // Don't throw - this is not critical for new installations\n }\n }\n\n /**\n * Migrate default user_id values in messages table\n * Updates messages with user_id='default' to use the actual user_id from their conversation\n */\n private async migrateDefaultUserIds(): Promise<void> {\n const messagesTableName = `${this.tablePrefix}_messages`;\n const conversationsTableName = `${this.tablePrefix}_conversations`;\n\n try {\n // First, check if there are any messages with default user_id\n const checkResult = await this.client.execute({\n sql: `SELECT COUNT(*) as count FROM ${messagesTableName} WHERE user_id = 'default'`,\n args: [],\n });\n\n const defaultCount = (checkResult.rows[0]?.count as number) || 0;\n\n if (defaultCount === 0) {\n return;\n }\n\n this.logger.debug(`Found ${defaultCount} messages with default user_id, starting migration`);\n\n // Update messages with the actual user_id from their conversation\n // Using a JOIN to get the user_id from the conversations table\n await this.executeWithRetry(async () => {\n const result = await this.client.execute({\n sql: `UPDATE ${messagesTableName}\n SET user_id = (\n SELECT c.user_id \n FROM ${conversationsTableName} c \n WHERE c.id = ${messagesTableName}.conversation_id\n )\n WHERE user_id = 'default'\n AND EXISTS (\n SELECT 1 \n FROM ${conversationsTableName} c \n WHERE c.id = ${messagesTableName}.conversation_id\n )`,\n args: [],\n });\n\n const updatedCount = result.rowsAffected || 0;\n this.logger.info(\n `Successfully migrated ${updatedCount} messages from default user_id to actual user_ids`,\n );\n\n // Check if there are any remaining messages with default user_id (orphaned messages)\n const remainingResult = await this.client.execute({\n sql: `SELECT COUNT(*) as count FROM ${messagesTableName} WHERE user_id = 'default'`,\n args: [],\n });\n\n const remainingCount = (remainingResult.rows[0]?.count as number) || 0;\n\n if (remainingCount > 0) {\n this.logger.warn(\n `${remainingCount} messages still have default user_id (possibly orphaned messages without valid conversations)`,\n );\n }\n }, \"migrate default user_ids\");\n } catch (error) {\n // Log the error but don't throw - this migration is not critical\n this.logger.error(\"Failed to migrate default user_ids\", error as Error);\n }\n }\n\n // ============================================================================\n // Message Operations\n // ============================================================================\n\n /**\n * Add a single message\n */\n async addMessage(message: UIMessage, userId: string, conversationId: string): Promise<void> {\n await this.initialize();\n\n const messagesTable = `${this.tablePrefix}_messages`;\n\n // Ensure conversation exists\n const conversation = await this.getConversation(conversationId);\n if (!conversation) {\n throw new ConversationNotFoundError(conversationId);\n }\n\n // Insert message\n await this.executeWithRetry(async () => {\n await this.client.execute({\n sql: `INSERT INTO ${messagesTable} (conversation_id, message_id, user_id, role, parts, metadata, format_version, created_at) \n VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,\n args: [\n conversationId,\n message.id,\n userId,\n message.role,\n JSON.stringify(message.parts),\n message.metadata ? JSON.stringify(message.metadata) : null,\n 2, // format_version\n new Date().toISOString(),\n ],\n });\n }, \"add message\");\n\n // Apply storage limit\n await this.applyStorageLimit(conversationId);\n }\n\n /**\n * Add multiple messages\n */\n async addMessages(messages: UIMessage[], userId: string, conversationId: string): Promise<void> {\n await this.initialize();\n\n const messagesTable = `${this.tablePrefix}_messages`;\n\n // Ensure conversation exists\n const conversation = await this.getConversation(conversationId);\n if (!conversation) {\n throw new ConversationNotFoundError(conversationId);\n }\n\n const now = new Date().toISOString();\n\n // Use transaction for batch insert\n await this.executeWithRetry(async () => {\n await this.client.batch(\n messages.map((message) => ({\n sql: `INSERT INTO ${messagesTable} (conversation_id, message_id, user_id, role, parts, metadata, format_version, created_at) \n VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,\n args: [\n conversationId,\n message.id,\n userId,\n message.role,\n JSON.stringify(message.parts),\n message.metadata ? JSON.stringify(message.metadata) : null,\n 2, // format_version\n now,\n ],\n })),\n );\n }, \"add batch messages\");\n\n // Apply storage limit\n await this.applyStorageLimit(conversationId);\n }\n\n /**\n * Apply storage limit to a conversation\n */\n private async applyStorageLimit(conversationId: string): Promise<void> {\n const messagesTable = `${this.tablePrefix}_messages`;\n\n // Delete old messages beyond the storage limit\n await this.executeWithRetry(async () => {\n await this.client.execute({\n sql: `DELETE FROM ${messagesTable}\n WHERE conversation_id = ? \n AND message_id NOT IN (\n SELECT message_id FROM ${messagesTable}\n WHERE conversation_id = ? \n ORDER BY created_at DESC \n LIMIT ?\n )`,\n args: [conversationId, conversationId, this.storageLimit],\n });\n }, \"apply storage limit\");\n }\n\n /**\n * Get messages with optional filtering\n */\n async getMessages(\n userId: string,\n conversationId: string,\n options?: GetMessagesOptions,\n ): Promise<UIMessage[]> {\n await this.initialize();\n\n const messagesTable = `${this.tablePrefix}_messages`;\n const { limit = this.storageLimit, before, after, roles } = options || {};\n\n // Build query with filters - use SELECT * to handle both old and new schemas safely\n let sql = `SELECT * FROM ${messagesTable}\n WHERE conversation_id = ? AND user_id = ?`;\n const args: any[] = [conversationId, userId];\n\n // Add role filter\n if (roles && roles.length > 0) {\n const placeholders = roles.map(() => \"?\").join(\",\");\n sql += ` AND role IN (${placeholders})`;\n args.push(...roles);\n }\n\n // Add time filters\n if (before) {\n sql += \" AND created_at < ?\";\n args.push(before.toISOString());\n }\n\n if (after) {\n sql += \" AND created_at > ?\";\n args.push(after.toISOString());\n }\n\n // Order by creation time and apply limit\n sql += \" ORDER BY created_at ASC\";\n if (limit && limit > 0) {\n sql += \" LIMIT ?\";\n args.push(limit);\n }\n\n const result = await this.client.execute({ sql, args });\n\n // Convert rows to UIMessages with on-the-fly migration for old format\n return result.rows.map((row) => {\n // Determine parts based on whether we have new format (parts) or old format (content)\n let parts: any;\n\n // Check for new format first (parts column exists and has value)\n if (row.parts !== undefined && row.parts !== null) {\n // New format - parse parts directly\n try {\n parts = JSON.parse(row.parts as string);\n } catch {\n parts = [];\n }\n }\n // Check for old format (content column exists and has value)\n else if (row.content !== undefined && row.content !== null) {\n // Old format - convert content to parts\n try {\n const content = JSON.parse(row.content as string);\n\n if (typeof content === \"string\") {\n // Simple string content -> text part\n parts = [{ type: \"text\", text: content }];\n } else if (Array.isArray(content)) {\n // Already an array of parts (old BaseMessage format with MessageContent array)\n parts = content;\n } else {\n // Unknown format - fallback to empty\n parts = [];\n }\n } catch {\n // If parsing fails, treat as plain text\n parts = [{ type: \"text\", text: row.content as string }];\n }\n } else {\n // No content at all - empty parts\n parts = [];\n }\n\n return {\n id: row.message_id as string,\n role: row.role as \"system\" | \"user\" | \"assistant\",\n parts,\n metadata: row.metadata ? JSON.parse(row.metadata as string) : undefined,\n };\n });\n }\n\n /**\n * Clear messages for a user\n */\n async clearMessages(userId: string, conversationId?: string): Promise<void> {\n await this.initialize();\n\n const messagesTable = `${this.tablePrefix}_messages`;\n const conversationsTable = `${this.tablePrefix}_conversations`;\n\n if (conversationId) {\n // Clear messages for specific conversation\n await this.client.execute({\n sql: `DELETE FROM ${messagesTable} WHERE conversation_id = ? AND user_id = ?`,\n args: [conversationId, userId],\n });\n } else {\n // Clear all messages for the user\n await this.client.execute({\n sql: `DELETE FROM ${messagesTable}\n WHERE conversation_id IN (\n SELECT id FROM ${conversationsTable} WHERE user_id = ?\n )`,\n args: [userId],\n });\n }\n }\n\n // ============================================================================\n // Conversation Operations\n // ============================================================================\n\n /**\n * Create a new conversation\n */\n async createConversation(input: CreateConversationInput): Promise<Conversation> {\n await this.initialize();\n\n const conversationsTable = `${this.tablePrefix}_conversations`;\n\n // Check if conversation already exists\n const existing = await this.getConversation(input.id);\n if (existing) {\n throw new ConversationAlreadyExistsError(input.id);\n }\n\n const now = new Date().toISOString();\n\n await this.executeWithRetry(async () => {\n await this.client.execute({\n sql: `INSERT INTO ${conversationsTable} (id, resource_id, user_id, title, metadata, created_at, updated_at) \n VALUES (?, ?, ?, ?, ?, ?, ?)`,\n args: [\n input.id,\n input.resourceId,\n input.userId,\n input.title,\n JSON.stringify(input.metadata || {}),\n now,\n now,\n ],\n });\n }, \"create conversation\");\n\n return {\n id: input.id,\n userId: input.userId,\n resourceId: input.resourceId,\n title: input.title,\n metadata: input.metadata || {},\n createdAt: now,\n updatedAt: now,\n };\n }\n\n /**\n * Get a conversation by ID\n */\n async getConversation(id: string): Promise<Conversation | null> {\n await this.initialize();\n\n const conversationsTable = `${this.tablePrefix}_conversations`;\n\n const result = await this.client.execute({\n sql: `SELECT * FROM ${conversationsTable} WHERE id = ?`,\n args: [id],\n });\n\n if (result.rows.length === 0) {\n return null;\n }\n\n const row = result.rows[0];\n return {\n id: row.id as string,\n userId: row.user_id as string,\n resourceId: row.resource_id as string,\n title: row.title as string,\n metadata: row.metadata ? JSON.parse(row.metadata as string) : {},\n createdAt: row.created_at as string,\n updatedAt: row.updated_at as string,\n };\n }\n\n /**\n * Get conversations by resource ID\n */\n async getConversations(resourceId: string): Promise<Conversation[]> {\n await this.initialize();\n\n const conversationsTable = `${this.tablePrefix}_conversations`;\n\n const result = await this.client.execute({\n sql: `SELECT * FROM ${conversationsTable} WHERE resource_id = ? ORDER BY updated_at DESC`,\n args: [resourceId],\n });\n\n return result.rows.map((row) => ({\n id: row.id as string,\n userId: row.user_id as string,\n resourceId: row.resource_id as string,\n title: row.title as string,\n metadata: row.metadata ? JSON.parse(row.metadata as string) : {},\n createdAt: row.created_at as string,\n updatedAt: row.updated_at as string,\n }));\n }\n\n /**\n * Get conversations by user ID\n */\n async getConversationsByUserId(\n userId: string,\n options?: Omit<ConversationQueryOptions, \"userId\">,\n ): Promise<Conversation[]> {\n return this.queryConversations({ ...options, userId });\n }\n\n /**\n * Query conversations with filters\n */\n async queryConversations(options: ConversationQueryOptions): Promise<Conversation[]> {\n await this.initialize();\n\n const conversationsTable = `${this.tablePrefix}_conversations`;\n let sql = `SELECT * FROM ${conversationsTable} WHERE 1=1`;\n const args: any[] = [];\n\n // Add filters\n if (options.userId) {\n sql += \" AND user_id = ?\";\n args.push(options.userId);\n }\n\n if (options.resourceId) {\n sql += \" AND resource_id = ?\";\n args.push(options.resourceId);\n }\n\n // Add ordering\n const orderBy = options.orderBy || \"updated_at\";\n const orderDirection = options.orderDirection || \"DESC\";\n sql += ` ORDER BY ${orderBy} ${orderDirection}`;\n\n // Add pagination\n if (options.limit) {\n sql += \" LIMIT ?\";\n args.push(options.limit);\n }\n\n if (options.offset) {\n sql += \" OFFSET ?\";\n args.push(options.offset);\n }\n\n const result = await this.client.execute({ sql, args });\n\n return result.rows.map((row) => ({\n id: row.id as string,\n userId: row.user_id as string,\n resourceId: row.resource_id as string,\n title: row.title as string,\n metadata: row.metadata ? JSON.parse(row.metadata as string) : {},\n createdAt: row.created_at as string,\n updatedAt: row.updated_at as string,\n }));\n }\n\n /**\n * Update a conversation\n */\n async updateConversation(\n id: string,\n updates: Partial<Omit<Conversation, \"id\" | \"createdAt\" | \"updatedAt\">>,\n ): Promise<Conversation> {\n await this.initialize();\n\n const conversationsTable = `${this.tablePrefix}_conversations`;\n const conversation = await this.getConversation(id);\n if (!conversation) {\n throw new ConversationNotFoundError(id);\n }\n\n const now = new Date().toISOString();\n const fieldsToUpdate: string[] = [\"updated_at = ?\"];\n const args: any[] = [now];\n\n if (updates.title !== undefined) {\n fieldsToUpdate.push(\"title = ?\");\n args.push(updates.title);\n }\n\n if (updates.resourceId !== undefined) {\n fieldsToUpdate.push(\"resource_id = ?\");\n args.push(updates.resourceId);\n }\n\n if (updates.metadata !== undefined) {\n fieldsToUpdate.push(\"metadata = ?\");\n args.push(JSON.stringify(updates.metadata));\n }\n\n args.push(id); // WHERE clause\n\n await this.client.execute({\n sql: `UPDATE ${conversationsTable} SET ${fieldsToUpdate.join(\", \")} WHERE id = ?`,\n args,\n });\n\n const updated = await this.getConversation(id);\n if (!updated) {\n throw new Error(`Conversation not found after update: ${id}`);\n }\n return updated;\n }\n\n /**\n * Delete a conversation\n */\n async deleteConversation(id: string): Promise<void> {\n await this.initialize();\n\n const conversationsTable = `${this.tablePrefix}_conversations`;\n\n await this.client.execute({\n sql: `DELETE FROM ${conversationsTable} WHERE id = ?`,\n args: [id],\n });\n }\n\n // ============================================================================\n // Working Memory Operations\n // ============================================================================\n\n /**\n * Get working memory\n */\n async getWorkingMemory(params: {\n conversationId?: string;\n userId?: string;\n scope: WorkingMemoryScope;\n }): Promise<string | null> {\n await this.initialize();\n\n if (params.scope === \"conversation\" && params.conversationId) {\n const conversation = await this.getConversation(params.conversationId);\n return (conversation?.metadata?.workingMemory as string) || null;\n }\n\n if (params.scope === \"user\" && params.userId) {\n const usersTable = `${this.tablePrefix}_users`;\n const result = await this.client.execute({\n sql: `SELECT metadata FROM ${usersTable} WHERE id = ?`,\n args: [params.userId],\n });\n\n if (result.rows.length > 0) {\n const metadata = result.rows[0].metadata\n ? JSON.parse(result.rows[0].metadata as string)\n : {};\n return metadata.workingMemory || null;\n }\n }\n\n return null;\n }\n\n /**\n * Set working memory\n */\n async setWorkingMemory(params: {\n conversationId?: string;\n userId?: string;\n content: string;\n scope: WorkingMemoryScope;\n }): Promise<void> {\n await this.initialize();\n\n if (params.scope === \"conversation\" && params.conversationId) {\n const conversation = await this.getConversation(params.conversationId);\n if (!conversation) {\n throw new ConversationNotFoundError(params.conversationId);\n }\n\n const metadata = conversation.metadata || {};\n metadata.workingMemory = params.content;\n\n await this.updateConversation(params.conversationId, { metadata });\n }\n\n if (params.scope === \"user\" && params.userId) {\n const usersTable = `${this.tablePrefix}_users`;\n const now = new Date().toISOString();\n\n // Check if user exists\n const result = await this.client.execute({\n sql: `SELECT metadata FROM ${usersTable} WHERE id = ?`,\n args: [params.userId],\n });\n\n if (result.rows.length > 0) {\n // User exists, update metadata\n const metadata = result.rows[0].metadata\n ? JSON.parse(result.rows[0].metadata as string)\n : {};\n metadata.workingMemory = params.content;\n\n await this.client.execute({\n sql: `UPDATE ${usersTable} SET metadata = ?, updated_at = ? WHERE id = ?`,\n args: [JSON.stringify(metadata), now, params.userId],\n });\n } else {\n // User doesn't exist, create new record\n await this.client.execute({\n sql: `INSERT INTO ${usersTable} (id, metadata, created_at, updated_at) VALUES (?, ?, ?, ?)`,\n args: [params.userId, JSON.stringify({ workingMemory: params.content }), now, now],\n });\n }\n }\n }\n\n /**\n * Delete working memory\n */\n async deleteWorkingMemory(params: {\n conversationId?: string;\n userId?: string;\n scope: WorkingMemoryScope;\n }): Promise<void> {\n await this.initialize();\n\n if (params.scope === \"conversation\" && params.conversationId) {\n const conversation = await this.getConversation(params.conversationId);\n if (conversation?.metadata?.workingMemory) {\n const metadata = { ...conversation.metadata };\n // biome-ignore lint/performance/noDelete: <explanation>\n delete metadata.workingMemory;\n await this.updateConversation(params.conversationId, { metadata });\n }\n }\n\n if (params.scope === \"user\" && params.userId) {\n const usersTable = `${this.tablePrefix}_users`;\n const result = await this.client.execute({\n sql: `SELECT metadata FROM ${usersTable} WHERE id = ?`,\n args: [params.userId],\n });\n\n if (result.rows.length > 0 && result.rows[0].metadata) {\n const metadata = JSON.parse(result.rows[0].metadata as string);\n if (metadata.workingMemory) {\n // biome-ignore lint/performance/noDelete: <explanation>\n delete metadata.workingMemory;\n await this.client.execute({\n sql: `UPDATE ${usersTable} SET metadata = ?, updated_at = ? WHERE id = ?`,\n args: [JSON.stringify(metadata), new Date().toISOString(), params.userId],\n });\n }\n }\n }\n }\n\n // ============================================================================\n // Workflow State Operations\n // ============================================================================\n\n /**\n * Get workflow state by execution ID\n */\n async getWorkflowState(executionId: string): Promise<WorkflowStateEntry | null> {\n await this.initialize();\n\n const workflowStatesTable = `${this.tablePrefix}_workflow_states`;\n const result = await this.client.execute({\n sql: `SELECT * FROM ${workflowStatesTable} WHERE id = ?`,\n args: [executionId],\n });\n\n if (result.rows.length === 0) {\n return null;\n }\n\n const row = result.rows[0];\n return {\n id: row.id as string,\n workflowId: row.workflow_id as string,\n workflowName: row.workflow_name as string,\n status: row.status as \"running\" | \"suspended\" | \"completed\" | \"error\",\n suspension: row.suspension ? JSON.parse(row.suspension as string) : undefined,\n userId: row.user_id as string | undefined,\n conversationId: row.conversation_id as string | undefined,\n metadata: row.metadata ? JSON.parse(row.metadata as string) : undefined,\n createdAt: new Date(row.created_at as string),\n updatedAt: new Date(row.updated_at as string),\n };\n }\n\n /**\n * Set workflow state\n */\n async setWorkflowState(executionId: string, state: WorkflowStateEntry): Promise<void> {\n await this.initialize();\n\n const workflowStatesTable = `${this.tablePrefix}_workflow_states`;\n await this.client.execute({\n sql: `INSERT OR REPLACE INTO ${workflowStatesTable} \n (id, workflow_id, workflow_name, status, suspension, user_id, conversation_id, metadata, created_at, updated_at) \n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n args: [\n executionId,\n state.workflowId,\n state.workflowName,\n state.status,\n state.suspension ? JSON.stringify(state.suspension) : null,\n state.userId || null,\n state.conversationId || null,\n state.metadata ? JSON.stringify(state.metadata) : null,\n state.createdAt.toISOString(),\n state.updatedAt.toISOString(),\n ],\n });\n }\n\n /**\n * Update workflow state\n */\n async updateWorkflowState(\n executionId: string,\n updates: Partial<WorkflowStateEntry>,\n ): Promise<void> {\n await this.initialize();\n\n const existing = await this.getWorkflowState(executionId);\n if (!existing) {\n throw new Error(`Workflow state ${executionId} not found`);\n }\n\n const updated: WorkflowStateEntry = {\n ...existing,\n ...updates,\n updatedAt: new Date(),\n };\n\n await this.setWorkflowState(executionId, updated);\n }\n\n /**\n * Get suspended workflow states for a workflow\n */\n async getSuspendedWorkflowStates(workflowId: string): Promise<WorkflowStateEntry[]> {\n await this.initialize();\n\n const workflowStatesTable = `${this.tablePrefix}_workflow_states`;\n const result = await this.client.execute({\n sql: `SELECT * FROM ${workflowStatesTable} WHERE workflow_id = ? AND status = 'suspended' ORDER BY created_at DESC`,\n args: [workflowId],\n });\n\n return result.rows.map((row) => ({\n id: row.id as string,\n workflowId: row.workflow_id as string,\n workflowName: row.workflow_name as string,\n status: \"suspended\" as const,\n suspension: row.suspension ? JSON.parse(row.suspension as string) : undefined,\n userId: row.user_id as string | undefined,\n conversationId: row.conversation_id as string | undefined,\n metadata: row.metadata ? JSON.parse(row.metadata as string) : undefined,\n createdAt: new Date(row.created_at as string),\n updatedAt: new Date(row.updated_at as string),\n }));\n }\n\n /**\n * Close database connection\n */\n async close(): Promise<void> {\n // LibSQL client doesn't have explicit close method\n // Connection is managed automatically\n this.logger.debug(\"Closing LibSQL Memory adapter\");\n }\n}\n","/**\n * LibSQL Observability Adapter\n * Provides persistent storage for OpenTelemetry spans using LibSQL/Turso database\n * Part of the OpenTelemetry observability migration (Phase 3)\n */\n\nimport { existsSync, mkdirSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport type { Client } from \"@libsql/client\";\nimport { createClient } from \"@libsql/client\";\nimport type {\n LogFilter,\n ObservabilityLogRecord,\n ObservabilitySpan,\n ObservabilityStorageAdapter,\n} from \"@voltagent/core\";\nimport { safeStringify } from \"@voltagent/internal/utils\";\nimport { type Logger, createPinoLogger } from \"@voltagent/logger\";\n\n/**\n * Options for configuring the LibSQLObservabilityAdapter\n */\nexport interface LibSQLObservabilityOptions {\n /**\n * LibSQL connection URL\n * Can be either a remote Turso URL or a local file path\n * @default \"file:./.voltagent/observability.db\"\n * @example \"libsql://your-database.turso.io\" for remote Turso\n * @example \"file:observability.db\" for local SQLite in current directory\n * @example \"file:.voltagent/observability.db\" for local SQLite in .voltagent folder\n */\n url?: string;\n\n /**\n * Auth token for LibSQL/Turso\n * Not needed for local SQLite\n */\n authToken?: string;\n\n /**\n * Prefix for table names\n * @default \"observability\"\n */\n tablePrefix?: string;\n\n /**\n * Whether to enable debug logging\n * @default false\n */\n debug?: boolean;\n\n /**\n * Optional logger instance\n */\n logger?: Logger;\n\n /**\n * Maximum number of spans to return in a single query\n * @default 1000\n */\n maxSpansPerQuery?: number;\n}\n\n/**\n * LibSQL Observability Adapter\n * Provides observability storage using LibSQL/Turso database\n * Implements the ObservabilityStorageAdapter interface for OpenTelemetry spans\n */\nexport class LibSQLObservabilityAdapter implements ObservabilityStorageAdapter {\n private client: Client;\n private tablePrefix: string;\n private debug: boolean;\n private logger: Logger;\n private initialized: Promise<void>;\n private maxSpansPerQuery: number;\n\n constructor(options: LibSQLObservabilityOptions = {}) {\n // Initialize the logger\n this.logger = options.logger || createPinoLogger({ name: \"libsql-observability\" });\n\n this.tablePrefix = options.tablePrefix || \"observability\";\n this.debug = options.debug || false;\n this.maxSpansPerQuery = options.maxSpansPerQuery || 1000;\n const url = options.url || \"file:./.voltagent/observability.db\";\n\n // Ensure parent directory exists for file-based databases\n if (url.startsWith(\"file:\") && !url.includes(\":memory:\")) {\n const filePath = url.substring(5); // Remove 'file:' prefix\n const dir = dirname(filePath);\n if (dir && dir !== \".\" && !existsSync(dir)) {\n try {\n mkdirSync(dir, { recursive: true });\n this.debugLog(\"Created directory for database\", { dir });\n } catch (error) {\n this.logger.warn(\"Failed to create directory for database\", { dir, error });\n }\n }\n }\n\n // Initialize the LibSQL client\n this.client = createClient({\n url,\n authToken: options.authToken,\n });\n\n this.debugLog(\"LibSQL observability adapter initialized with options\", {\n url,\n tablePrefix: this.tablePrefix,\n debug: this.debug,\n maxSpansPerQuery: this.maxSpansPerQuery,\n });\n\n // Initialize the database tables\n this.initialized = this.initializeDatabase();\n }\n\n /**\n * Log a debug message if debug is enabled\n */\n private debugLog(message: string, data?: unknown): void {\n if (this.debug) {\n this.logger.debug(`${message}`, data || \"\");\n }\n }\n\n /**\n * Initialize database tables for observability\n */\n private async initializeDatabase(): Promise<void> {\n try {\n // Create main spans table with entity columns\n await this.client.execute(`\n CREATE TABLE IF NOT EXISTS ${this.tablePrefix}_spans (\n span_id TEXT PRIMARY KEY,\n trace_id TEXT NOT NULL,\n parent_span_id TEXT,\n entity_id TEXT,\n entity_type TEXT,\n name TEXT NOT NULL,\n kind INTEGER DEFAULT 0,\n start_time TEXT NOT NULL,\n end_time TEXT,\n duration REAL,\n status_code INTEGER DEFAULT 0,\n status_message TEXT,\n attributes TEXT,\n events TEXT,\n links TEXT,\n resource TEXT,\n instrumentation_scope TEXT,\n created_at TEXT DEFAULT CURRENT_TIMESTAMP,\n updated_at TEXT DEFAULT CURRENT_TIMESTAMP\n )\n `);\n\n // Create indexes for efficient queries\n await this.client.execute(`\n CREATE INDEX IF NOT EXISTS idx_${this.tablePrefix}_spans_trace_id \n ON ${this.tablePrefix}_spans(trace_id)\n `);\n\n await this.client.execute(`\n CREATE INDEX IF NOT EXISTS idx_${this.tablePrefix}_spans_parent_span_id \n ON ${this.tablePrefix}_spans(parent_span_id)\n `);\n\n await this.client.execute(`\n CREATE INDEX IF NOT EXISTS idx_${this.tablePrefix}_spans_start_time \n ON ${this.tablePrefix}_spans(start_time)\n `);\n\n await this.client.execute(`\n CREATE INDEX IF NOT EXISTS idx_${this.tablePrefix}_spans_name \n ON ${this.tablePrefix}_spans(name)\n `);\n\n await this.client.execute(`\n CREATE INDEX IF NOT EXISTS idx_${this.tablePrefix}_spans_entity_id \n ON ${this.tablePrefix}_spans(entity_id)\n `);\n\n await this.client.execute(`\n CREATE INDEX IF NOT EXISTS idx_${this.tablePrefix}_spans_entity_type \n ON ${this.tablePrefix}_spans(entity_type)\n `);\n\n // Create trace metadata table for fast trace listing with entity columns\n await this.client.execute(`\n CREATE TABLE IF NOT EXISTS ${this.tablePrefix}_traces (\n trace_id TEXT PRIMARY KEY,\n root_span_id TEXT,\n entity_id TEXT,\n entity_type TEXT,\n start_time TEXT NOT NULL,\n end_time TEXT,\n span_count INTEGER DEFAULT 1,\n created_at TEXT DEFAULT CURRENT_TIMESTAMP,\n updated_at TEXT DEFAULT CURRENT_TIMESTAMP\n )\n `);\n\n await this.client.execute(`\n CREATE INDEX IF NOT EXISTS idx_${this.tablePrefix}_traces_start_time \n ON ${this.tablePrefix}_traces(start_time DESC)\n `);\n\n await this.client.execute(`\n CREATE INDEX IF NOT EXISTS idx_${this.tablePrefix}_traces_entity_id \n ON ${this.tablePrefix}_traces(entity_id)\n `);\n\n await this.client.execute(`\n CREATE INDEX IF NOT EXISTS idx_${this.tablePrefix}_traces_entity_type \n ON ${this.tablePrefix}_traces(entity_type)\n `);\n\n // Create logs table\n await this.client.execute(`\n CREATE TABLE IF NOT EXISTS ${this.tablePrefix}_logs (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n timestamp TEXT NOT NULL,\n trace_id TEXT,\n span_id TEXT,\n trace_flags INTEGER,\n severity_number INTEGER,\n severity_text TEXT,\n body TEXT NOT NULL,\n attributes TEXT,\n resource TEXT,\n instrumentation_scope TEXT,\n created_at TEXT DEFAULT CURRENT_TIMESTAMP\n )\n `);\n\n // Create indexes for logs\n await this.client.execute(`\n CREATE INDEX IF NOT EXISTS idx_${this.tablePrefix}_logs_trace_id \n ON ${this.tablePrefix}_logs(trace_id)\n `);\n\n await this.client.execute(`\n CREATE INDEX IF NOT EXISTS idx_${this.tablePrefix}_logs_span_id \n ON ${this.tablePrefix}_logs(span_id)\n `);\n\n await this.client.execute(`\n CREATE INDEX IF NOT EXISTS idx_${this.tablePrefix}_logs_timestamp \n ON ${this.tablePrefix}_logs(timestamp DESC)\n `);\n\n await this.client.execute(`\n CREATE INDEX IF NOT EXISTS idx_${this.tablePrefix}_logs_severity \n ON ${this.tablePrefix}_logs(severity_number)\n `);\n\n this.debugLog(\"Database tables initialized successfully\");\n } catch (error) {\n this.logger.error(\"Failed to initialize database tables\", { error });\n throw error;\n }\n }\n\n /**\n * Ensure database is initialized before operations\n */\n private async ensureInitialized(): Promise<void> {\n await this.initialized;\n }\n\n /**\n * Add a span to the database\n */\n async addSpan(span: ObservabilitySpan): Promise<void> {\n await this.ensureInitialized();\n\n try {\n // Extract entity information from attributes\n const entityId = (span.attributes?.[\"entity.id\"] as string) || null;\n const entityType = (span.attributes?.[\"entity.type\"] as string) || null;\n\n // Start a transaction for consistency\n await this.client.batch([\n // Insert the span with entity columns\n {\n sql: `\n INSERT INTO ${this.tablePrefix}_spans (\n span_id, trace_id, parent_span_id, entity_id, entity_type, name, kind,\n start_time, end_time, duration,\n status_code, status_message,\n attributes, events, links,\n resource, instrumentation_scope\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `,\n args: [\n span.spanId,\n span.traceId,\n span.parentSpanId || null,\n entityId,\n entityType,\n span.name,\n span.kind,\n span.startTime,\n span.endTime || null,\n span.duration || null,\n span.status.code,\n span.status.message || null,\n safeStringify(span.attributes),\n safeStringify(span.events),\n span.links ? safeStringify(span.links) : null,\n span.resource ? safeStringify(span.resource) : null,\n span.instrumentationScope ? safeStringify(span.instrumentationScope) : null,\n ],\n },\n // Update or insert trace metadata with entity columns\n {\n sql: `\n INSERT INTO ${this.tablePrefix}_traces (\n trace_id, root_span_id, entity_id, entity_type, start_time, end_time, span_count\n ) VALUES (?, ?, ?, ?, ?, ?, 1)\n ON CONFLICT(trace_id) DO UPDATE SET\n span_count = span_count + 1,\n entity_id = COALESCE(excluded.entity_id, entity_id),\n entity_type = COALESCE(excluded.entity_type, entity_type),\n start_time = MIN(start_time, excluded.start_time),\n end_time = MAX(COALESCE(end_time, excluded.end_time), excluded.end_time),\n updated_at = CURRENT_TIMESTAMP\n `,\n args: [\n span.traceId,\n span.parentSpanId ? null : span.spanId, // Root span if no parent\n entityId,\n entityType,\n span.startTime,\n span.endTime || null,\n ],\n },\n ]);\n\n this.debugLog(\"Span added successfully\", {\n spanId: span.spanId,\n traceId: span.traceId,\n });\n } catch (error) {\n this.logger.error(\"Failed to add span\", { error, span });\n throw error;\n }\n }\n\n /**\n * Update an existing span\n */\n async updateSpan(spanId: string, updates: Partial<ObservabilitySpan>): Promise<void> {\n await this.ensureInitialized();\n\n try {\n const setClauses: string[] = [];\n const args: any[] = [];\n\n // Build dynamic SET clause based on provided updates\n if (updates.endTime !== undefined) {\n setClauses.push(\"end_time = ?\");\n args.push(updates.endTime);\n }\n if (updates.duration !== undefined) {\n setClauses.push(\"duration = ?\");\n args.push(updates.duration);\n }\n if (updates.status !== undefined) {\n setClauses.push(\"status_code = ?, status_message = ?\");\n args.push(updates.status.code, updates.status.message || null);\n }\n if (updates.attributes !== undefined) {\n setClauses.push(\"attributes = ?\");\n args.push(safeStringify(updates.attributes));\n }\n if (updates.events !== undefined) {\n setClauses.push(\"events = ?\");\n args.push(safeStringify(updates.events));\n }\n if (updates.links !== undefined) {\n setClauses.push(\"links = ?\");\n args.push(safeStringify(updates.links));\n }\n\n if (setClauses.length === 0) {\n return; // Nothing to update\n }\n\n setClauses.push(\"updated_at = CURRENT_TIMESTAMP\");\n args.push(spanId);\n\n await this.client.execute({\n sql: `\n UPDATE ${this.tablePrefix}_spans \n SET ${setClauses.join(\", \")}\n WHERE span_id = ?\n `,\n args,\n });\n\n // If endTime was updated, also update trace metadata\n if (updates.endTime) {\n const span = await this.getSpan(spanId);\n if (span) {\n await this.client.execute({\n sql: `\n UPDATE ${this.tablePrefix}_traces\n SET end_time = MAX(COALESCE(end_time, ?), ?),\n updated_at = CURRENT_TIMESTAMP\n WHERE trace_id = ?\n `,\n args: [updates.endTime, updates.endTime, span.traceId],\n });\n }\n }\n\n this.debugLog(\"Span updated successfully\", { spanId, updates });\n } catch (error) {\n this.logger.error(\"Failed to update span\", { error, spanId, updates });\n throw error;\n }\n }\n\n /**\n * Get a span by ID\n */\n async getSpan(spanId: string): Promise<ObservabilitySpan | null> {\n await this.ensureInitialized();\n\n try {\n const result = await this.client.execute({\n sql: `\n SELECT * FROM ${this.tablePrefix}_spans\n WHERE span_id = ?\n `,\n args: [spanId],\n });\n\n if (result.rows.length === 0) {\n return null;\n }\n\n const row = result.rows[0];\n return this.rowToSpan(row);\n } catch (error) {\n this.logger.error(\"Failed to get span\", { error, spanId });\n throw error;\n }\n }\n\n /**\n * Get all spans in a trace\n */\n async getTrace(traceId: string): Promise<ObservabilitySpan[]> {\n await this.ensureInitialized();\n\n try {\n const result = await this.client.execute({\n sql: `\n SELECT * FROM ${this.tablePrefix}_spans\n WHERE trace_id = ?\n ORDER BY start_time ASC\n LIMIT ?\n `,\n args: [traceId, this.maxSpansPerQuery],\n });\n\n return result.rows.map((row) => this.rowToSpan(row));\n } catch (error) {\n this.logger.error(\"Failed to get trace\", { error, traceId });\n throw error;\n }\n }\n\n /**\n * List all traces with optional entity filter\n */\n async listTraces(\n limit = 100,\n offset = 0,\n filter?: {\n entityId?: string;\n entityType?: \"agent\" | \"workflow\";\n },\n ): Promise<string[]> {\n await this.ensureInitialized();\n\n try {\n let sql: string;\n let args: any[] = [];\n const conditions: string[] = [];\n\n if (filter?.entityId) {\n conditions.push(\"entity_id = ?\");\n args.push(filter.entityId);\n }\n\n if (filter?.entityType) {\n conditions.push(\"entity_type = ?\");\n args.push(filter.entityType);\n }\n\n if (conditions.length > 0) {\n // Filter by entity\n sql = `\n SELECT trace_id FROM ${this.tablePrefix}_traces\n WHERE ${conditions.join(\" AND \")}\n ORDER BY start_time DESC\n LIMIT ? OFFSET ?\n `;\n args.push(limit, offset);\n } else {\n // Get all traces\n sql = `\n SELECT trace_id FROM ${this.tablePrefix}_traces\n ORDER BY start_time DESC\n LIMIT ? OFFSET ?\n `;\n args = [limit, offset];\n }\n\n const result = await this.client.execute({ sql, args });\n return result.rows.map((row) => row.trace_id as string);\n } catch (error) {\n this.logger.error(\"Failed to list traces\", { error, limit, offset, filter });\n throw error;\n }\n }\n\n /**\n * Delete old spans\n */\n async deleteOldSpans(beforeTimestamp: number): Promise<number> {\n await this.ensureInitialized();\n\n try {\n const beforeDate = new Date(beforeTimestamp).toISOString();\n\n // Get affected trace IDs before deletion\n const tracesResult = await this.client.execute({\n sql: `\n SELECT DISTINCT trace_id FROM ${this.tablePrefix}_spans\n WHERE start_time < ?\n `,\n args: [beforeDate],\n });\n\n const affectedTraceIds = tracesResult.rows.map((row) => row.trace_id as string);\n\n // Delete old spans\n const deleteResult = await this.client.execute({\n sql: `\n DELETE FROM ${this.tablePrefix}_spans\n WHERE start_time < ?\n `,\n args: [beforeDate],\n });\n\n // Clean up trace metadata\n if (affectedTraceIds.length > 0) {\n // Update span counts for affected traces\n for (const traceId of affectedTraceIds) {\n const countResult = await this.client.execute({\n sql: `\n SELECT COUNT(*) as count FROM ${this.tablePrefix}_spans\n WHERE trace_id = ?\n `,\n args: [traceId],\n });\n\n const count = countResult.rows[0].count as number;\n if (count === 0) {\n // Delete trace metadata if no spans remain\n await this.client.execute({\n sql: `\n DELETE FROM ${this.tablePrefix}_traces\n WHERE trace_id = ?\n `,\n args: [traceId],\n });\n } else {\n // Update span count\n await this.client.execute({\n sql: `\n UPDATE ${this.tablePrefix}_traces\n SET span_count = ?,\n updated_at = CURRENT_TIMESTAMP\n WHERE trace_id = ?\n `,\n args: [count, traceId],\n });\n }\n }\n }\n\n const deletedCount = deleteResult.rowsAffected || 0;\n this.debugLog(\"Old spans deleted\", { deletedCount, beforeDate });\n return deletedCount;\n } catch (error) {\n this.logger.error(\"Failed to delete old spans\", { error, beforeTimestamp });\n throw error;\n }\n }\n\n /**\n * Clear all spans, traces, and logs\n */\n async clear(): Promise<void> {\n await this.ensureInitialized();\n\n try {\n await this.client.batch([\n { sql: `DELETE FROM ${this.tablePrefix}_spans`, args: [] },\n { sql: `DELETE FROM ${this.tablePrefix}_traces`, args: [] },\n { sql: `DELETE FROM ${this.tablePrefix}_logs`, args: [] },\n ]);\n\n this.debugLog(\"All spans, traces, and logs cleared\");\n } catch (error) {\n this.logger.error(\"Failed to clear data\", { error });\n throw error;\n }\n }\n\n /**\n * Convert a database row to an ObservabilitySpan\n */\n private rowToSpan(row: any): ObservabilitySpan {\n const span: ObservabilitySpan = {\n traceId: row.trace_id as string,\n spanId: row.span_id as string,\n name: row.name as string,\n kind: row.kind as number,\n startTime: row.start_time as string,\n status: {\n code: row.status_code as number,\n },\n attributes: row.attributes ? JSON.parse(row.attributes as string) : {},\n events: row.events ? JSON.parse(row.events as string) : [],\n };\n\n // Add optional fields only if they have values (not null)\n if (row.parent_span_id !== null) {\n span.parentSpanId = row.parent_span_id as string;\n }\n if (row.end_time !== null) {\n span.endTime = row.end_time as string;\n }\n if (row.duration !== null) {\n span.duration = row.duration as number;\n }\n if (row.status_message !== null) {\n span.status.message = row.status_message as string;\n }\n if (row.links && row.links !== \"null\") {\n const links = JSON.parse(row.links as string);\n if (links && links.length > 0) {\n span.links = links;\n }\n }\n if (row.resource && row.resource !== \"null\") {\n const resource = JSON.parse(row.resource as string);\n if (resource && Object.keys(resource).length > 0) {\n span.resource = resource;\n }\n }\n if (row.instrumentation_scope && row.instrumentation_scope !== \"null\") {\n const scope = JSON.parse(row.instrumentation_scope as string);\n if (scope) {\n span.instrumentationScope = scope;\n }\n }\n\n return span;\n }\n\n /**\n * Get statistics about stored spans\n */\n async getStats(): Promise<{\n spanCount: number;\n traceCount: number;\n oldestSpan?: Date;\n newestSpan?: Date;\n }> {\n await this.ensureInitialized();\n\n try {\n const [spanCountResult, traceCountResult, timeRangeResult] = await Promise.all([\n this.client.execute(`SELECT COUNT(*) as count FROM ${this.tablePrefix}_spans`),\n this.client.execute(`SELECT COUNT(*) as count FROM ${this.tablePrefix}_traces`),\n this.client.execute(`\n SELECT \n MIN(start_time) as oldest,\n MAX(start_time) as newest\n FROM ${this.tablePrefix}_spans\n `),\n ]);\n\n const stats: any = {\n spanCount: spanCountResult.rows[0].count as number,\n traceCount: traceCountResult.rows[0].count as number,\n };\n\n if (timeRangeResult.rows[0].oldest) {\n stats.oldestSpan = new Date(timeRangeResult.rows[0].oldest as string);\n }\n if (timeRangeResult.rows[0].newest) {\n stats.newestSpan = new Date(timeRangeResult.rows[0].newest as string);\n }\n\n return stats;\n } catch (error) {\n this.logger.error(\"Failed to get stats\", { error });\n throw error;\n }\n }\n\n /**\n * Save a log record to the database\n */\n async saveLogRecord(logRecord: any): Promise<void> {\n await this.ensureInitialized();\n\n try {\n // Convert timestamp if it's an array (OpenTelemetry HrTime format)\n let timestamp: string;\n if (Array.isArray(logRecord.hrTime)) {\n const timeMs = logRecord.hrTime[0] * 1000 + logRecord.hrTime[1] / 1000000;\n timestamp = new Date(timeMs).toISOString();\n } else if (logRecord.timestamp) {\n timestamp =\n typeof logRecord.timestamp === \"string\"\n ? logRecord.timestamp\n : new Date(logRecord.timestamp).toISOString();\n } else {\n timestamp = new Date().toISOString();\n }\n\n // Extract trace context\n const spanContext = logRecord.spanContext || {};\n const traceId = spanContext.traceId || null;\n const spanId = spanContext.spanId || null;\n const traceFlags = spanContext.traceFlags ?? null;\n\n // Extract log data\n const severityNumber = logRecord.severityNumber ?? null;\n const severityText = logRecord.severityText || null;\n const body =\n typeof logRecord.body === \"string\" ? logRecord.body : safeStringify(logRecord.body);\n const attributes = logRecord.attributes ? safeStringify(logRecord.attributes) : null;\n const resource = logRecord.resource?.attributes\n ? safeStringify(logRecord.resource.attributes)\n : null;\n const instrumentationScope =\n logRecord.instrumentationLibrary || logRecord.instrumentationScope\n ? safeStringify(logRecord.instrumentationLibrary || logRecord.instrumentationScope)\n : null;\n\n await this.client.execute({\n sql: `\n INSERT INTO ${this.tablePrefix}_logs (\n timestamp, trace_id, span_id, trace_flags,\n severity_number, severity_text, body,\n attributes, resource, instrumentation_scope\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `,\n args: [\n timestamp,\n traceId,\n spanId,\n traceFlags,\n severityNumber,\n severityText,\n body,\n attributes,\n resource,\n instrumentationScope,\n ],\n });\n\n this.debugLog(\"Log record saved successfully\", {\n timestamp,\n traceId,\n spanId,\n severityNumber,\n });\n } catch (error) {\n this.logger.error(\"Failed to save log record\", { error, logRecord });\n throw error;\n }\n }\n\n /**\n * Get logs by trace ID\n */\n async getLogsByTraceId(traceId: string): Promise<ObservabilityLogRecord[]> {\n await this.ensureInitialized();\n\n try {\n const result = await this.client.execute({\n sql: `\n SELECT * FROM ${this.tablePrefix}_logs\n WHERE trace_id = ?\n ORDER BY timestamp DESC\n LIMIT ?\n `,\n args: [traceId, this.maxSpansPerQuery],\n });\n\n return result.rows.map((row) => this.rowToLogRecord(row));\n } catch (error) {\n this.logger.error(\"Failed to get logs by trace ID\", { error, traceId });\n throw error;\n }\n }\n\n /**\n * Get logs by span ID\n */\n async getLogsBySpanId(spanId: string): Promise<ObservabilityLogRecord[]> {\n await this.ensureInitialized();\n\n try {\n const result = await this.client.execute({\n sql: `\n SELECT * FROM ${this.tablePrefix}_logs\n WHERE span_id = ?\n ORDER BY timestamp DESC\n LIMIT ?\n `,\n args: [spanId, this.maxSpansPerQuery],\n });\n\n return result.rows.map((row) => this.rowToLogRecord(row));\n } catch (error) {\n this.logger.error(\"Failed to get logs by span ID\", { error, spanId });\n throw error;\n }\n }\n\n /**\n * Query logs with flexible filtering\n */\n async queryLogs(filter: LogFilter): Promise<ObservabilityLogRecord[]> {\n await this.ensureInitialized();\n\n try {\n const whereClauses: string[] = [];\n const args: any[] = [];\n\n if (filter.traceId) {\n whereClauses.push(\"trace_id = ?\");\n args.push(filter.traceId);\n }\n if (filter.spanId) {\n whereClauses.push(\"span_id = ?\");\n args.push(filter.spanId);\n }\n if (filter.severityNumber !== undefined) {\n whereClauses.push(\"severity_number >= ?\");\n args.push(filter.severityNumber);\n }\n if (filter.severityText) {\n whereClauses.push(\"severity_text = ?\");\n args.push(filter.severityText);\n }\n if (filter.instrumentationScope) {\n whereClauses.push(\"instrumentation_scope LIKE ?\");\n args.push(`%${filter.instrumentationScope}%`);\n }\n if (filter.startTimeMin !== undefined) {\n const minTime = new Date(filter.startTimeMin).toISOString();\n whereClauses.push(\"timestamp >= ?\");\n args.push(minTime);\n }\n if (filter.startTimeMax !== undefined) {\n const maxTime = new Date(filter.startTimeMax).toISOString();\n whereClauses.push(\"timestamp <= ?\");\n args.push(maxTime);\n }\n if (filter.bodyContains) {\n whereClauses.push(\"body LIKE ?\");\n args.push(`%${filter.bodyContains}%`);\n }\n\n const whereClause = whereClauses.length > 0 ? `WHERE ${whereClauses.join(\" AND \")}` : \"\";\n\n const limit = filter.limit || this.maxSpansPerQuery;\n args.push(limit);\n\n const result = await this.client.execute({\n sql: `\n SELECT * FROM ${this.tablePrefix}_logs\n ${whereClause}\n ORDER BY timestamp DESC\n LIMIT ?\n `,\n args,\n });\n\n const logs = result.rows.map((row) => this.rowToLogRecord(row));\n\n // Filter by attributes if specified\n if (filter.attributeKey) {\n const key = filter.attributeKey;\n return logs.filter((log) => {\n if (!log.attributes) return false;\n if (filter.attributeValue !== undefined) {\n return log.attributes[key] === filter.attributeValue;\n }\n return key in log.attributes;\n });\n }\n\n return logs;\n } catch (error) {\n this.logger.error(\"Failed to query logs\", { error, filter });\n throw error;\n }\n }\n\n /**\n * Delete old logs\n */\n async deleteOldLogs(beforeTimestamp: number): Promise<number> {\n await this.ensureInitialized();\n\n try {\n const beforeDate = new Date(beforeTimestamp).toISOString();\n\n const result = await this.client.execute({\n sql: `\n DELETE FROM ${this.tablePrefix}_logs\n WHERE timestamp < ?\n `,\n args: [beforeDate],\n });\n\n const deletedCount = result.rowsAffected || 0;\n this.debugLog(\"Old logs deleted\", { deletedCount, beforeDate });\n return deletedCount;\n } catch (error) {\n this.logger.error(\"Failed to delete old logs\", { error, beforeTimestamp });\n throw error;\n }\n }\n\n /**\n * Convert a database row to an ObservabilityLogRecord\n */\n private rowToLogRecord(row: any): ObservabilityLogRecord {\n const log: ObservabilityLogRecord = {\n timestamp: row.timestamp as string,\n body: (() => {\n try {\n // Only parse if it looks like JSON and can actually be parsed\n const bodyStr = row.body as string;\n if (bodyStr.startsWith(\"{\") || bodyStr.startsWith(\"[\")) {\n return JSON.parse(bodyStr);\n }\n } catch {\n // If parsing fails, treat as string\n }\n return row.body as string;\n })(),\n };\n\n // Add optional fields only if they have values (not null)\n if (row.trace_id !== null) {\n log.traceId = row.trace_id as string;\n }\n if (row.span_id !== null) {\n log.spanId = row.span_id as string;\n }\n if (row.trace_flags !== null) {\n log.traceFlags = row.trace_flags as number;\n }\n if (row.severity_number !== null) {\n log.severityNumber = row.severity_number as number;\n }\n if (row.severity_text !== null) {\n log.severityText = row.severity_text as string;\n }\n if (row.attributes && row.attributes !== \"null\") {\n try {\n const attributes = JSON.parse(row.attributes as string);\n if (attributes && Object.keys(attributes).length > 0) {\n log.attributes = attributes;\n }\n } catch {\n // Skip if parsing fails\n }\n }\n if (row.resource && row.resource !== \"null\") {\n try {\n const resource = JSON.parse(row.resource as string);\n if (resource && Object.keys(resource).length > 0) {\n log.resource = resource;\n }\n } catch {\n // Skip if parsing fails\n }\n }\n if (row.instrumentation_scope && row.instrumentation_scope !== \"null\") {\n try {\n const scope = JSON.parse(row.instrumentation_scope as string);\n if (scope) {\n log.instrumentationScope = scope;\n }\n } catch {\n // Skip if parsing fails\n }\n }\n\n return log;\n }\n\n /**\n * Close the database connection\n */\n async close(): Promise<void> {\n // LibSQL client doesn't have an explicit close method\n this.debugLog(\"LibSQL observability adapter closed\");\n }\n}\n","/**\n * LibSQL Vector Adapter\n * Provides vector storage and similarity search using LibSQL/Turso database\n * Stores vectors as binary BLOBs for efficiency\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { type Client, createClient } from \"@libsql/client\";\nimport {\n type SearchResult,\n type VectorAdapter,\n type VectorItem,\n type VectorSearchOptions,\n cosineSimilarity,\n} from \"@voltagent/core\";\nimport { type Logger, createPinoLogger } from \"@voltagent/logger\";\n\n/**\n * LibSQL Vector Adapter configuration options\n */\nexport interface LibSQLVectorOptions {\n /**\n * Database URL (e.g., 'file:./memory.db' or 'libsql://...')\n * @default \"file:./.voltagent/memory.db\"\n */\n url?: string;\n\n /**\n * Auth token for remote connections (optional)\n */\n authToken?: string;\n\n /**\n * Prefix for table names\n * @default \"voltagent\"\n */\n tablePrefix?: string;\n\n /**\n * Maximum vector dimensions allowed\n * @default 1536\n */\n maxVectorDimensions?: number;\n\n /**\n * Size of the LRU cache for frequently accessed vectors\n * @default 100\n */\n cacheSize?: number;\n\n /**\n * Batch size for bulk operations\n * @default 100\n */\n batchSize?: number;\n\n /**\n * Enable debug logging\n * @default false\n */\n debug?: boolean;\n\n /**\n * Logger instance\n */\n logger?: Logger;\n\n /**\n * Maximum number of retries for database operations\n * @default 3\n */\n maxRetries?: number;\n\n /**\n * Initial retry delay in milliseconds\n * @default 100\n */\n retryDelayMs?: number;\n}\n\n/**\n * LibSQL Vector Adapter\n * Production-ready vector storage with similarity search\n */\nexport class LibSQLVectorAdapter implements VectorAdapter {\n private client: Client;\n private tablePrefix: string;\n private maxVectorDimensions: number;\n private cacheSize: number;\n private batchSize: number;\n private debug: boolean;\n private logger: Logger;\n private maxRetries: number;\n private retryDelayMs: number;\n private url: string;\n private initialized = false;\n private vectorCache: Map<string, VectorItem>;\n private dimensions: number | null = null;\n\n constructor(options: LibSQLVectorOptions = {}) {\n this.tablePrefix = options.tablePrefix ?? \"voltagent\";\n this.maxVectorDimensions = options.maxVectorDimensions ?? 1536;\n this.cacheSize = options.cacheSize ?? 100;\n this.batchSize = options.batchSize ?? 100;\n this.maxRetries = options.maxRetries ?? 3;\n this.retryDelayMs = options.retryDelayMs ?? 100;\n this.debug = options.debug ?? false;\n\n // Initialize logger\n this.logger =\n options.logger ??\n createPinoLogger({\n name: \"libsql-vector-adapter\",\n level: this.debug ? \"debug\" : \"info\",\n });\n\n // Normalize database URL\n const requestedUrl = options.url ?? \"file:./.voltagent/memory.db\";\n // In-memory: use cache=shared which is supported by @libsql/core for :memory:\n // Accept both \":memory:\" and \"file::memory:\" inputs and normalize to URI form.\n if (\n requestedUrl === \":memory:\" ||\n requestedUrl === \"file::memory:\" ||\n requestedUrl.startsWith(\"file::memory:\")\n ) {\n // Use private, per-connection in-memory database (no shared cache)\n // Accept either form and normalize to \":memory:\" which @libsql/core expands to file::memory:\n this.url = \":memory:\";\n } else {\n this.url = requestedUrl;\n }\n\n // Ensure directory exists for file-based databases (skip pure in-memory)\n if (this.url.startsWith(\"file:\") && !this.url.startsWith(\"file::memory:\")) {\n const dbPath = this.url.replace(\"file:\", \"\");\n const dbDir = path.dirname(dbPath);\n if (!fs.existsSync(dbDir)) {\n fs.mkdirSync(dbDir, { recursive: true });\n }\n }\n\n // Initialize LibSQL client\n this.client = createClient({\n url: this.url,\n authToken: options.authToken,\n });\n\n // Initialize cache\n this.vectorCache = new Map();\n }\n\n /**\n * Initialize the database schema\n */\n private async initialize(): Promise<void> {\n if (this.initialized) return;\n\n const tableName = `${this.tablePrefix}_vectors`;\n\n try {\n // Create vectors table and indexes atomically\n await this.client.executeMultiple(`\n BEGIN;\n CREATE TABLE IF NOT EXISTS ${tableName} (\n id TEXT PRIMARY KEY,\n vector BLOB NOT NULL,\n dimensions INTEGER NOT NULL,\n metadata TEXT,\n content TEXT,\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n updated_at DATETIME DEFAULT CURRENT_TIMESTAMP\n );\n CREATE INDEX IF NOT EXISTS idx_${tableName}_created ON ${tableName}(created_at);\n CREATE INDEX IF NOT EXISTS idx_${tableName}_dimensions ON ${tableName}(dimensions);\n COMMIT;\n `);\n\n this.initialized = true;\n this.logger.debug(\"Vector adapter initialized\");\n } catch (error) {\n this.logger.error(\"Failed to initialize vector adapter\", error as Error);\n throw error;\n }\n }\n\n /**\n * Serialize a vector to binary format\n */\n private serializeVector(vector: number[]): Buffer {\n const buffer = Buffer.allocUnsafe(vector.length * 4);\n for (let i = 0; i < vector.length; i++) {\n buffer.writeFloatLE(vector[i], i * 4);\n }\n return buffer;\n }\n\n /**\n * Deserialize a vector from binary format\n */\n private deserializeVector(buffer: Buffer | Uint8Array | ArrayBuffer): number[] {\n let bytes: Buffer;\n if (buffer instanceof Buffer) {\n bytes = buffer;\n } else if (buffer instanceof ArrayBuffer) {\n bytes = Buffer.from(buffer);\n } else {\n bytes = Buffer.from(buffer);\n }\n const vector: number[] = [];\n for (let i = 0; i < bytes.length; i += 4) {\n vector.push(bytes.readFloatLE(i));\n }\n return vector;\n }\n\n /**\n * Execute a database operation with retries\n */\n private async executeWithRetry<T>(operation: () => Promise<T>, context: string): Promise<T> {\n let lastError: Error | undefined;\n let delay = this.retryDelayMs;\n\n for (let attempt = 1; attempt <= this.maxRetries; attempt++) {\n try {\n return await operation();\n } catch (error) {\n lastError = error as Error;\n this.logger.warn(`Operation failed (attempt ${attempt}): ${context}`, error as Error);\n\n if (attempt < this.maxRetries) {\n await new Promise((resolve) => setTimeout(resolve, delay));\n delay *= 2; // Exponential backoff\n }\n }\n }\n\n this.logger.error(`Operation failed after ${this.maxRetries} attempts: ${context}`, lastError);\n throw lastError;\n }\n\n /**\n * Store a vector with associated metadata\n */\n async store(id: string, vector: number[], metadata?: Record<string, unknown>): Promise<void> {\n await this.initialize();\n\n // Validate vector contents\n if (!Array.isArray(vector) || vector.length === 0) {\n throw new Error(\"Vector must be a non-empty array\");\n }\n\n // Validate dimensions\n if (vector.length > this.maxVectorDimensions) {\n throw new Error(\n `Vector dimensions (${vector.length}) exceed maximum (${this.maxVectorDimensions})`,\n );\n }\n\n if (this.dimensions === null) {\n this.dimensions = vector.length;\n } else if (vector.length !== this.dimensions) {\n throw new Error(\n `Vector dimension mismatch. Expected ${this.dimensions}, got ${vector.length}`,\n );\n }\n\n const tableName = `${this.tablePrefix}_vectors`;\n const serializedVector = this.serializeVector(vector);\n const metadataJson = metadata ? JSON.stringify(metadata) : null;\n\n await this.executeWithRetry(async () => {\n await this.client.execute({\n sql: `\n INSERT OR REPLACE INTO ${tableName} \n (id, vector, dimensions, metadata, updated_at)\n VALUES (?, ?, ?, ?, CURRENT_TIMESTAMP)\n `,\n args: [id, serializedVector, vector.length, metadataJson],\n });\n }, `store vector ${id}`);\n\n // Update cache\n if (this.vectorCache.size >= this.cacheSize) {\n const firstKey = this.vectorCache.keys().next().value;\n if (firstKey) this.vectorCache.delete(firstKey);\n }\n this.vectorCache.set(id, { id, vector, metadata });\n\n this.logger.debug(`Vector stored: ${id} (${vector.length} dimensions)`);\n }\n\n /**\n * Store multiple vectors in batch\n */\n async storeBatch(items: VectorItem[]): Promise<void> {\n await this.initialize();\n\n if (items.length === 0) return;\n\n const tableName = `${this.tablePrefix}_vectors`;\n\n // Process in batches to avoid memory issues\n for (let i = 0; i < items.length; i += this.batchSize) {\n const batch = items.slice(i, i + this.batchSize);\n\n await this.executeWithRetry(async () => {\n const stmts: { sql: string; args: any[] }[] = [];\n for (const item of batch) {\n if (!Array.isArray(item.vector) || item.vector.length === 0) {\n throw new Error(\"Vector must be a non-empty array\");\n }\n // Validate dimensions\n if (this.dimensions === null) {\n this.dimensions = item.vector.length;\n } else if (item.vector.length !== this.dimensions) {\n throw new Error(\n `Vector dimension mismatch. Expected ${this.dimensions}, got ${item.vector.length}`,\n );\n }\n\n const serializedVector = this.serializeVector(item.vector);\n const metadataJson = item.metadata ? JSON.stringify(item.metadata) : null;\n const content = item.content ?? null;\n stmts.push({\n sql: `INSERT OR REPLACE INTO ${tableName} (id, vector, dimensions, metadata, content, updated_at) VALUES (?, ?, ?, ?, ?, CURRENT_TIMESTAMP)`,\n args: [item.id, serializedVector, item.vector.length, metadataJson, content],\n });\n }\n await this.client.batch(stmts, \"write\");\n }, `storeBatch ${batch.length} vectors`);\n\n this.logger.debug(`Batch of ${batch.length} vectors stored`);\n }\n }\n\n /**\n * Search for similar vectors using cosine similarity\n */\n async search(queryVector: number[], options?: VectorSearchOptions): Promise<SearchResult[]> {\n await this.initialize();\n\n const { limit = 10, threshold = 0, filter } = options || {};\n\n // Validate query vector dimensions\n if (this.dimensions !== null && queryVector.length !== this.dimensions) {\n throw new Error(\n `Query vector dimension mismatch. Expected ${this.dimensions}, got ${queryVector.length}`,\n );\n }\n\n const tableName = `${this.tablePrefix}_vectors`;\n\n // Build query with optional dimension filter\n let query = `SELECT id, vector, dimensions, metadata, content FROM ${tableName}`;\n const args: any[] = [];\n\n if (this.dimensions !== null) {\n query += \" WHERE dimensions = ?\";\n args.push(this.dimensions);\n }\n\n const result = await this.executeWithRetry(\n async () => await this.client.execute({ sql: query, args }),\n \"search vectors\",\n );\n\n const searchResults: SearchResult[] = [];\n\n // Calculate similarities for all vectors\n for (const row of result.rows) {\n const id = row.id as string;\n const vectorBlob = row.vector as Uint8Array | ArrayBuffer;\n const metadataJson = row.metadata as string | null;\n const content = (row.content as string | null) ?? undefined;\n\n // Parse metadata\n const metadata = metadataJson ? JSON.parse(metadataJson) : undefined;\n\n // Apply metadata filter if provided\n if (filter && !this.matchesFilter(metadata, filter)) {\n continue;\n }\n\n // Deserialize vector\n const vector = this.deserializeVector(vectorBlob);\n\n // Calculate cosine similarity\n const similarity = cosineSimilarity(queryVector, vector);\n\n // Convert similarity to score (0-1 range where 1 is most similar)\n const score = (similarity + 1) / 2;\n\n if (score >= threshold) {\n searchResults.push({\n id,\n vector,\n metadata,\n content,\n score,\n distance: 1 - similarity, // Convert to distance metric\n });\n }\n }\n\n // Sort by score (descending) and limit results\n searchResults.sort((a, b) => b.score - a.score);\n\n return searchResults.slice(0, limit);\n }\n\n /**\n * Check if metadata matches the filter criteria\n */\n private matchesFilter(\n metadata: Record<string, unknown> | undefined,\n filter: Record<string, unknown>,\n ): boolean {\n if (!metadata) {\n return false;\n }\n\n for (const [key, value] of Object.entries(filter)) {\n if (metadata[key] !== value) {\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * Delete a vector by ID\n */\n async delete(id: string): Promise<void> {\n await this.initialize();\n\n const tableName = `${this.tablePrefix}_vectors`;\n\n await this.executeWithRetry(async () => {\n await this.client.execute({\n sql: `DELETE FROM ${tableName} WHERE id = ?`,\n args: [id],\n });\n }, `delete vector ${id}`);\n\n // Remove from cache\n this.vectorCache.delete(id);\n\n this.logger.debug(`Vector deleted: ${id}`);\n }\n\n /**\n * Delete multiple vectors by IDs\n */\n async deleteBatch(ids: string[]): Promise<void> {\n await this.initialize();\n\n if (ids.length === 0) return;\n\n const tableName = `${this.tablePrefix}_vectors`;\n\n // Process in batches\n for (let i = 0; i < ids.length; i += this.batchSize) {\n const batch = ids.slice(i, i + this.batchSize);\n const placeholders = batch.map(() => \"?\").join(\",\");\n\n await this.executeWithRetry(async () => {\n await this.client.execute({\n sql: `DELETE FROM ${tableName} WHERE id IN (${placeholders})`,\n args: batch,\n });\n }, `deleteBatch ${batch.length} vectors`);\n\n // Remove from cache\n for (const id of batch) {\n this.vectorCache.delete(id);\n }\n\n this.logger.debug(`Batch of ${batch.length} vectors deleted`);\n }\n }\n\n /**\n * Clear all vectors\n */\n async clear(): Promise<void> {\n await this.initialize();\n\n const tableName = `${this.tablePrefix}_vectors`;\n\n await this.executeWithRetry(async () => {\n await this.client.execute(`DELETE FROM ${tableName}`);\n }, \"clear all vectors\");\n\n // Clear cache and reset dimensions\n this.vectorCache.clear();\n this.dimensions = null;\n\n this.logger.debug(\"All vectors cleared\");\n }\n\n /**\n * Get total count of stored vectors\n */\n async count(): Promise<number> {\n await this.initialize();\n\n const tableName = `${this.tablePrefix}_vectors`;\n\n const result = await this.executeWithRetry(\n async () => await this.client.execute(`SELECT COUNT(*) as count FROM ${tableName}`),\n \"count vectors\",\n );\n\n const raw = result.rows[0]?.count as any;\n // libsql/sqlite may return number, string, or bigint depending on driver\n if (typeof raw === \"bigint\") return Number(raw);\n if (typeof raw === \"string\") return Number.parseInt(raw, 10) || 0;\n return (raw as number) ?? 0;\n }\n\n /**\n * Get a specific vector by ID\n */\n async get(id: string): Promise<VectorItem | null> {\n await this.initialize();\n\n // Check cache first\n if (this.vectorCache.has(id)) {\n const cached = this.vectorCache.get(id);\n if (cached) {\n return {\n ...cached,\n vector: [...cached.vector], // Return a copy\n metadata: cached.metadata ? { ...cached.metadata } : undefined,\n };\n }\n }\n\n const tableName = `${this.tablePrefix}_vectors`;\n\n const result = await this.executeWithRetry(\n async () =>\n await this.client.execute({\n sql: `SELECT id, vector, metadata, content FROM ${tableName} WHERE id = ?`,\n args: [id],\n }),\n `get vector ${id}`,\n );\n\n if (result.rows.length === 0) {\n return null;\n }\n\n const row = result.rows[0];\n const vectorBlob = row.vector as unknown as Uint8Array | ArrayBuffer;\n const metadataJson = row.metadata as string | null;\n const content = row.content as string | null;\n\n const vector = this.deserializeVector(vectorBlob);\n const metadata = metadataJson ? JSON.parse(metadataJson) : undefined;\n\n const item: VectorItem = {\n id,\n vector,\n metadata,\n content: content ?? undefined,\n };\n\n // Update cache\n if (this.vectorCache.size >= this.cacheSize) {\n const firstKey = this.vectorCache.keys().next().value;\n if (firstKey) this.vectorCache.delete(firstKey);\n }\n this.vectorCache.set(id, item);\n\n return item;\n }\n\n /**\n * Close the database connection\n */\n async close(): Promise<void> {\n this.vectorCache.clear();\n this.logger.debug(\"Vector adapter closed\");\n try {\n (this.client as any)?.close?.();\n } catch {\n // ignore\n }\n }\n\n /**\n * Get statistics about the vector table and cache\n */\n async getStats(): Promise<{\n count: number;\n dimensions: number | null;\n cacheSize: number;\n tableSizeBytes: number;\n }> {\n await this.initialize();\n\n const tableName = `${this.tablePrefix}_vectors`;\n\n const [countResult, sizeResult] = await Promise.all([\n this.executeWithRetry(\n async () =>\n await this.client.execute(\n `SELECT COUNT(*) as count, MAX(dimensions) as dims FROM ${tableName}`,\n ),\n \"getStats count\",\n ),\n // Approximate table size by summing blob/text lengths\n this.executeWithRetry(\n async () =>\n await this.client.execute({\n sql: `SELECT \n COALESCE(SUM(LENGTH(id)),0) + \n COALESCE(SUM(LENGTH(vector)),0) + \n COALESCE(SUM(LENGTH(metadata)),0) +\n COALESCE(SUM(LENGTH(content)),0) AS size\n FROM ${tableName}`,\n }),\n \"getStats size\",\n ),\n ]);\n\n const row1 = countResult.rows[0] as any;\n const row2 = sizeResult.rows[0] as any;\n\n const countRaw = row1?.count as any;\n const dimsRaw = row1?.dims as any;\n const sizeRaw = row2?.size as any;\n\n const normalize = (v: any): number =>\n typeof v === \"bigint\"\n ? Number(v)\n : typeof v === \"string\"\n ? Number.parseInt(v, 10) || 0\n : (v ?? 0);\n\n return {\n count: normalize(countRaw),\n dimensions: dimsRaw != null ? normalize(dimsRaw) : this.dimensions,\n cacheSize: this.vectorCache.size,\n tableSizeBytes: normalize(sizeRaw),\n };\n }\n}\n"],"mappings":"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","names":["path","fs","import_node_fs","import_node_path","import_client","import_logger","import_node_fs","import_node_path","import_client","import_core","import_logger","path","fs"]}