{"version":3,"file":"storage/SQLiteStorageProvider.mjs","sources":["webpack://@agent-tars/server/./src/storage/SQLiteStorageProvider.ts"],"sourcesContent":["/*\n * Copyright (c) 2025 Bytedance, Inc. and its affiliates.\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport path from 'path';\nimport fs from 'fs';\nimport { DatabaseSync } from 'node:sqlite';\nimport { AgentEventStream } from '@agent-tars/core';\nimport { StorageProvider, SessionMetadata } from './types';\n\n// Define row types for better type safety\ninterface SessionRow {\n  id: string;\n  createdAt: number;\n  updatedAt: number;\n  name: string | null;\n  workingDirectory: string;\n  tags: string | null;\n}\n\ninterface EventRow {\n  id: number;\n  sessionId: string;\n  timestamp: number;\n  eventData: string;\n}\n\ninterface ExistsResult {\n  existsFlag: number;\n}\n\n/**\n * SQLite-based storage provider using Node.js native SQLite\n * Provides high-performance, file-based storage using the built-in SQLite module\n * Optimized for handling large amounts of event data\n */\nexport class SQLiteStorageProvider implements StorageProvider {\n  private db: DatabaseSync;\n  private initialized = false;\n  public readonly dbPath: string;\n\n  constructor(storagePath?: string) {\n    // Default to the user's home directory\n    const defaultPath = process.env.HOME || process.env.USERPROFILE || '.';\n    const baseDir = storagePath || path.join(defaultPath, '.agent-tars');\n\n    // Create the directory if it doesn't exist\n    if (!fs.existsSync(baseDir)) {\n      fs.mkdirSync(baseDir, { recursive: true });\n    }\n\n    this.dbPath = path.join(baseDir, 'agent-tars.db');\n    this.db = new DatabaseSync(this.dbPath, { open: false });\n  }\n\n  async initialize(): Promise<void> {\n    if (!this.initialized) {\n      try {\n        // Open the database\n        this.db.open();\n\n        // Enable WAL mode for better concurrent performance\n        this.db.exec('PRAGMA journal_mode = WAL');\n\n        // Create sessions table\n        this.db.exec(`\n          CREATE TABLE IF NOT EXISTS sessions (\n            id TEXT PRIMARY KEY,\n            createdAt INTEGER NOT NULL,\n            updatedAt INTEGER NOT NULL,\n            name TEXT,\n            workingDirectory TEXT NOT NULL,\n            tags TEXT\n          )\n        `);\n\n        // Create events table with foreign key to sessions\n        this.db.exec(`\n          CREATE TABLE IF NOT EXISTS events (\n            id INTEGER PRIMARY KEY AUTOINCREMENT,\n            sessionId TEXT NOT NULL,\n            timestamp INTEGER NOT NULL,\n            eventData TEXT NOT NULL,\n            FOREIGN KEY (sessionId) REFERENCES sessions (id) ON DELETE CASCADE\n          )\n        `);\n\n        // Create index on sessionId for faster queries\n        this.db.exec(`\n          CREATE INDEX IF NOT EXISTS idx_events_sessionId ON events (sessionId)\n        `);\n\n        // Enable foreign keys\n        this.db.exec('PRAGMA foreign_keys = ON');\n\n        this.initialized = true;\n      } catch (error) {\n        console.error('Failed to initialize SQLite database:', error);\n        throw error;\n      }\n    }\n  }\n\n  async createSession(metadata: SessionMetadata): Promise<SessionMetadata> {\n    await this.ensureInitialized();\n\n    const sessionData = {\n      ...metadata,\n      createdAt: metadata.createdAt || Date.now(),\n      updatedAt: metadata.updatedAt || Date.now(),\n    };\n\n    const tagsJson = sessionData.tags ? JSON.stringify(sessionData.tags) : null;\n\n    try {\n      const stmt = this.db.prepare(`\n        INSERT INTO sessions (id, createdAt, updatedAt, name, workingDirectory, tags)\n        VALUES (?, ?, ?, ?, ?, ?)\n      `);\n\n      stmt.run(\n        sessionData.id,\n        sessionData.createdAt,\n        sessionData.updatedAt,\n        sessionData.name || null,\n        sessionData.workingDirectory,\n        tagsJson,\n      );\n      return sessionData;\n    } catch (error) {\n      console.error(`Failed to create session ${sessionData.id}:`, error);\n      throw new Error(\n        `Failed to create session: ${error instanceof Error ? error.message : String(error)}`,\n      );\n    }\n  }\n\n  async updateSessionMetadata(\n    sessionId: string,\n    metadata: Partial<Omit<SessionMetadata, 'id'>>,\n  ): Promise<SessionMetadata> {\n    await this.ensureInitialized();\n\n    // First, get the current session data\n    const session = await this.getSessionMetadata(sessionId);\n    if (!session) {\n      throw new Error(`Session not found: ${sessionId}`);\n    }\n\n    const updatedSession = {\n      ...session,\n      ...metadata,\n      updatedAt: Date.now(),\n    };\n\n    try {\n      const params: Array<string | number | null> = [];\n      const setClauses: string[] = [];\n\n      if (metadata.name !== undefined) {\n        setClauses.push('name = ?');\n        params.push(metadata.name || null);\n      }\n\n      if (metadata.workingDirectory !== undefined) {\n        setClauses.push('workingDirectory = ?');\n        params.push(metadata.workingDirectory);\n      }\n\n      if (metadata.tags !== undefined) {\n        setClauses.push('tags = ?');\n        params.push(metadata.tags ? JSON.stringify(metadata.tags) : null);\n      }\n\n      // Always update the timestamp\n      setClauses.push('updatedAt = ?');\n      params.push(updatedSession.updatedAt);\n\n      // Add the session ID for the WHERE clause\n      params.push(sessionId);\n\n      if (setClauses.length === 0) {\n        return updatedSession; // Nothing to update\n      }\n\n      const updateQuery = `\n        UPDATE sessions\n        SET ${setClauses.join(', ')}\n        WHERE id = ?\n      `;\n\n      const updateStmt = this.db.prepare(updateQuery);\n      updateStmt.run(...params);\n\n      return updatedSession;\n    } catch (error) {\n      console.error(`Failed to update session ${sessionId}:`, error);\n      throw new Error(\n        `Failed to update session: ${error instanceof Error ? error.message : String(error)}`,\n      );\n    }\n  }\n\n  async getSessionMetadata(sessionId: string): Promise<SessionMetadata | null> {\n    await this.ensureInitialized();\n\n    try {\n      const stmt = this.db.prepare(`\n        SELECT id, createdAt, updatedAt, name, workingDirectory, tags\n        FROM sessions\n        WHERE id = ?\n      `);\n\n      const row = stmt.get(sessionId) as SessionRow | undefined;\n\n      if (!row) {\n        return null;\n      }\n\n      return {\n        id: row.id,\n        createdAt: row.createdAt,\n        updatedAt: row.updatedAt,\n        name: row.name || undefined,\n        workingDirectory: row.workingDirectory,\n        tags: row.tags ? JSON.parse(row.tags) : undefined,\n      };\n    } catch (error) {\n      console.error(`Failed to get session ${sessionId}:`, error);\n      throw new Error(\n        `Failed to get session: ${error instanceof Error ? error.message : String(error)}`,\n      );\n    }\n  }\n\n  async getAllSessions(): Promise<SessionMetadata[]> {\n    await this.ensureInitialized();\n\n    try {\n      const stmt = this.db.prepare(`\n        SELECT id, createdAt, updatedAt, name, workingDirectory, tags\n        FROM sessions\n        ORDER BY updatedAt DESC\n      `);\n\n      const rows = stmt.all() as unknown as SessionRow[];\n\n      return rows.map((row) => ({\n        id: row.id,\n        createdAt: row.createdAt,\n        updatedAt: row.updatedAt,\n        name: row.name || undefined,\n        workingDirectory: row.workingDirectory,\n        tags: row.tags ? JSON.parse(row.tags) : undefined,\n      }));\n    } catch (error) {\n      console.error('Failed to get all sessions:', error);\n      throw new Error(\n        `Failed to get all sessions: ${error instanceof Error ? error.message : String(error)}`,\n      );\n    }\n  }\n\n  async deleteSession(sessionId: string): Promise<boolean> {\n    await this.ensureInitialized();\n\n    try {\n      // Delete events first (though the foreign key would handle this)\n      const deleteEventsStmt = this.db.prepare('DELETE FROM events WHERE sessionId = ?');\n      deleteEventsStmt.run(sessionId);\n\n      // Delete the session\n      const deleteSessionStmt = this.db.prepare('DELETE FROM sessions WHERE id = ?');\n      const result = deleteSessionStmt.run(sessionId);\n\n      return result.changes > 0;\n    } catch (error) {\n      console.error(`Failed to delete session ${sessionId}:`, error);\n      throw new Error(\n        `Failed to delete session: ${error instanceof Error ? error.message : String(error)}`,\n      );\n    }\n  }\n\n  async saveEvent(sessionId: string, event: AgentEventStream.Event): Promise<void> {\n    await this.ensureInitialized();\n\n    try {\n      // Check if session exists\n      const sessionExistsStmt = this.db.prepare(`\n        SELECT 1 as existsFlag FROM sessions WHERE id = ?\n      `);\n\n      const sessionExists = sessionExistsStmt.get(sessionId) as ExistsResult | undefined;\n      if (!sessionExists || !sessionExists.existsFlag) {\n        throw new Error(`Session not found: ${sessionId}`);\n      }\n\n      const timestamp = Date.now();\n      const eventData = JSON.stringify(event);\n\n      // Insert the event\n      const insertEventStmt = this.db.prepare(`\n        INSERT INTO events (sessionId, timestamp, eventData)\n        VALUES (?, ?, ?)\n      `);\n\n      insertEventStmt.run(sessionId, timestamp, eventData);\n\n      // Update session's updatedAt timestamp\n      const updateSessionStmt = this.db.prepare(`\n        UPDATE sessions SET updatedAt = ? WHERE id = ?\n      `);\n\n      updateSessionStmt.run(timestamp, sessionId);\n    } catch (error) {\n      console.error(`Failed to save event for session ${sessionId}:`, error);\n      throw new Error(\n        `Failed to save event: ${error instanceof Error ? error.message : String(error)}`,\n      );\n    }\n  }\n\n  async getSessionEvents(sessionId: string): Promise<AgentEventStream.Event[]> {\n    await this.ensureInitialized();\n\n    try {\n      const sessionExistsStmt = this.db.prepare(`\n        SELECT 1 as existsFlag FROM sessions WHERE id = ?\n      `);\n\n      const sessionExists = sessionExistsStmt.get(sessionId) as ExistsResult | undefined;\n      if (!sessionExists || !sessionExists.existsFlag) {\n        throw new Error(`Session not found: ${sessionId}`);\n      }\n\n      const stmt = this.db.prepare(`\n        SELECT eventData\n        FROM events\n        WHERE sessionId = ?\n        ORDER BY timestamp ASC, id ASC\n      `);\n\n      const rows = stmt.all(sessionId) as unknown as { eventData: string }[];\n\n      return rows.map((row) => {\n        try {\n          return JSON.parse(row.eventData) as AgentEventStream.Event;\n        } catch (error) {\n          console.error(`Failed to parse event data: ${row.eventData}`);\n          return {\n            type: 'system',\n            message: 'Failed to parse event data',\n            timestamp: Date.now(),\n          } as AgentEventStream.Event;\n        }\n      });\n    } catch (error) {\n      console.error(`Failed to get events for session ${sessionId}:`, error);\n      throw new Error(\n        `Failed to get session events: ${error instanceof Error ? error.message : String(error)}`,\n      );\n    }\n  }\n\n  async close(): Promise<void> {\n    if (this.db && this.db.isOpen) {\n      this.db.close();\n    }\n  }\n\n  private async ensureInitialized(): Promise<void> {\n    if (!this.initialized) {\n      await this.initialize();\n    }\n  }\n}"],"names":["SQLiteStorageProvider","error","console","metadata","sessionData","Date","tagsJson","JSON","stmt","Error","String","sessionId","session","updatedSession","params","setClauses","undefined","updateQuery","updateStmt","row","rows","deleteEventsStmt","deleteSessionStmt","result","event","sessionExistsStmt","sessionExists","timestamp","eventData","insertEventStmt","updateSessionStmt","storagePath","defaultPath","process","baseDir","path","fs","DatabaseSync"],"mappings":"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"}