@axiom-lattice/pg-stores 1.0.13 → 1.0.14

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/stores/PostgreSQLThreadStore.ts","../src/migrations/migration.ts","../src/migrations/thread_migrations.ts","../src/stores/PostgreSQLAssistantStore.ts","../src/migrations/assistant_migrations.ts","../src/stores/PostgreSQLScheduleStorage.ts","../src/migrations/schedule_migrations.ts","../src/stores/PostgreSQLSkillStore.ts","../src/migrations/skill_migrations.ts"],"sourcesContent":["/**\n * PostgreSQL implementation of ThreadStore\n */\n\nimport { Pool, PoolClient, PoolConfig } from \"pg\";\nimport {\n ThreadStore,\n Thread,\n CreateThreadRequest,\n} from \"@axiom-lattice/protocols\";\nimport { MigrationManager } from \"../migrations/migration\";\nimport { createThreadsTable } from \"../migrations/thread_migrations\";\n\n/**\n * PostgreSQL ThreadStore options\n */\nexport interface PostgreSQLThreadStoreOptions {\n /**\n * PostgreSQL connection pool configuration\n * Can be a connection string or PoolConfig object\n */\n poolConfig: string | PoolConfig;\n\n /**\n * Whether to run migrations automatically on initialization\n * @default true\n */\n autoMigrate?: boolean;\n}\n\n/**\n * PostgreSQL implementation of ThreadStore\n */\nexport class PostgreSQLThreadStore implements ThreadStore {\n private pool: Pool;\n private migrationManager: MigrationManager;\n private initialized: boolean = false;\n private ownsPool: boolean = true;\n private initPromise: Promise<void> | null = null; // Promise-based lock to prevent concurrent initialization\n\n constructor(options: PostgreSQLThreadStoreOptions) {\n // Create Pool from config\n if (typeof options.poolConfig === \"string\") {\n this.pool = new Pool({ connectionString: options.poolConfig });\n } else {\n this.pool = new Pool(options.poolConfig);\n }\n\n this.migrationManager = new MigrationManager(this.pool);\n this.migrationManager.register(createThreadsTable);\n\n // Auto-migrate by default\n if (options.autoMigrate !== false) {\n this.initialize().catch((error) => {\n console.error(\"Failed to initialize PostgreSQLThreadStore:\", error);\n throw error;\n });\n }\n }\n\n /**\n * Dispose resources and close the connection pool\n * Should be called when the store is no longer needed\n */\n async dispose(): Promise<void> {\n if (this.ownsPool && this.pool) {\n await this.pool.end();\n }\n }\n\n /**\n * Initialize the store and run migrations\n * Uses a promise-based lock to prevent concurrent initialization\n */\n async initialize(): Promise<void> {\n // If already initialized, return immediately\n if (this.initialized) {\n return;\n }\n\n // If initialization is in progress, wait for it\n if (this.initPromise) {\n return this.initPromise;\n }\n\n // Start initialization and store the promise\n this.initPromise = (async () => {\n try {\n await this.migrationManager.migrate();\n this.initialized = true;\n } finally {\n // Clear the promise after completion (success or failure)\n this.initPromise = null;\n }\n })();\n\n return this.initPromise;\n }\n\n /**\n * Get all threads for a specific assistant\n */\n async getThreadsByAssistantId(assistantId: string): Promise<Thread[]> {\n await this.ensureInitialized();\n\n const result = await this.pool.query<{\n id: string;\n assistant_id: string;\n metadata: any;\n created_at: Date;\n updated_at: Date;\n }>(\n `\n SELECT id, assistant_id, metadata, created_at, updated_at\n FROM lattice_threads\n WHERE assistant_id = $1\n ORDER BY created_at DESC\n `,\n [assistantId]\n );\n\n return result.rows.map(this.mapRowToThread);\n }\n\n /**\n * Get a thread by ID for a specific assistant\n */\n async getThreadById(\n assistantId: string,\n threadId: string\n ): Promise<Thread | undefined> {\n await this.ensureInitialized();\n\n const result = await this.pool.query<{\n id: string;\n assistant_id: string;\n metadata: any;\n created_at: Date;\n updated_at: Date;\n }>(\n `\n SELECT id, assistant_id, metadata, created_at, updated_at\n FROM lattice_threads\n WHERE id = $1 AND assistant_id = $2\n `,\n [threadId, assistantId]\n );\n\n if (result.rows.length === 0) {\n return undefined;\n }\n\n return this.mapRowToThread(result.rows[0]);\n }\n\n /**\n * Create a new thread for an assistant\n */\n async createThread(\n assistantId: string,\n threadId: string,\n data: CreateThreadRequest\n ): Promise<Thread> {\n await this.ensureInitialized();\n\n const now = new Date();\n const metadata = data.metadata || {};\n\n await this.pool.query(\n `\n INSERT INTO lattice_threads (id, assistant_id, metadata, created_at, updated_at)\n VALUES ($1, $2, $3, $4, $5)\n ON CONFLICT (id, assistant_id) DO UPDATE SET\n metadata = EXCLUDED.metadata,\n updated_at = EXCLUDED.updated_at\n `,\n [threadId, assistantId, JSON.stringify(metadata), now, now]\n );\n\n return {\n id: threadId,\n assistantId,\n metadata,\n createdAt: now,\n updatedAt: now,\n };\n }\n\n /**\n * Update an existing thread\n */\n async updateThread(\n assistantId: string,\n threadId: string,\n updates: Partial<CreateThreadRequest>\n ): Promise<Thread | null> {\n await this.ensureInitialized();\n\n // Get existing thread\n const existing = await this.getThreadById(assistantId, threadId);\n if (!existing) {\n return null;\n }\n\n // Merge metadata\n const updatedMetadata = {\n ...existing.metadata,\n ...(updates.metadata || {}),\n };\n\n const now = new Date();\n\n await this.pool.query(\n `\n UPDATE lattice_threads\n SET metadata = $1, updated_at = $2\n WHERE id = $3 AND assistant_id = $4\n `,\n [JSON.stringify(updatedMetadata), now, threadId, assistantId]\n );\n\n return {\n ...existing,\n metadata: updatedMetadata,\n updatedAt: now,\n };\n }\n\n /**\n * Delete a thread by ID\n */\n async deleteThread(assistantId: string, threadId: string): Promise<boolean> {\n await this.ensureInitialized();\n\n const result = await this.pool.query(\n `\n DELETE FROM lattice_threads\n WHERE id = $1 AND assistant_id = $2\n `,\n [threadId, assistantId]\n );\n\n return result.rowCount !== null && result.rowCount > 0;\n }\n\n /**\n * Check if thread exists\n */\n async hasThread(assistantId: string, threadId: string): Promise<boolean> {\n await this.ensureInitialized();\n\n const result = await this.pool.query(\n `\n SELECT 1 FROM lattice_threads\n WHERE id = $1 AND assistant_id = $2\n LIMIT 1\n `,\n [threadId, assistantId]\n );\n\n return result.rows.length > 0;\n }\n\n /**\n * Ensure store is initialized\n */\n private async ensureInitialized(): Promise<void> {\n if (!this.initialized) {\n await this.initialize();\n }\n }\n\n /**\n * Map database row to Thread object\n */\n private mapRowToThread(row: {\n id: string;\n assistant_id: string;\n metadata: any;\n created_at: Date;\n updated_at: Date;\n }): Thread {\n return {\n id: row.id,\n assistantId: row.assistant_id,\n metadata:\n typeof row.metadata === \"string\"\n ? JSON.parse(row.metadata)\n : row.metadata || {},\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n };\n }\n}\n","/**\n * Migration system for database schema management\n */\n\nimport { Pool, PoolClient } from \"pg\";\n\n/**\n * Migration record stored in database\n */\ninterface MigrationRecord {\n version: number;\n name: string;\n applied_at: Date;\n}\n\n/**\n * Migration definition\n */\nexport interface Migration {\n version: number;\n name: string;\n up: (client: PoolClient) => Promise<void>;\n down?: (client: PoolClient) => Promise<void>;\n}\n\n/**\n * Migration manager\n */\nexport class MigrationManager {\n private pool: Pool;\n private migrations: Migration[] = [];\n\n constructor(pool: Pool) {\n this.pool = pool;\n }\n\n /**\n * Register a migration\n */\n register(migration: Migration): void {\n this.migrations.push(migration);\n // Sort migrations by version\n this.migrations.sort((a, b) => a.version - b.version);\n }\n\n /**\n * Initialize migrations table if it doesn't exist\n */\n private async ensureMigrationsTable(client: PoolClient): Promise<void> {\n await client.query(`\n CREATE TABLE IF NOT EXISTS lattice_schema_migrations (\n version INTEGER PRIMARY KEY,\n name VARCHAR(255) NOT NULL,\n applied_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP\n )\n `);\n }\n\n /**\n * Get applied migrations from database\n */\n private async getAppliedMigrations(\n client: PoolClient\n ): Promise<MigrationRecord[]> {\n await client.query(`\n CREATE TABLE IF NOT EXISTS lattice_schema_migrations (\n version INTEGER PRIMARY KEY,\n name VARCHAR(255) NOT NULL,\n applied_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP\n )\n `);\n\n const result = await client.query<MigrationRecord>(\n \"SELECT version, name, applied_at FROM lattice_schema_migrations ORDER BY version\"\n );\n return result.rows;\n }\n\n /**\n * Apply pending migrations\n * Uses PostgreSQL advisory locks to prevent concurrent migrations\n */\n async migrate(): Promise<void> {\n const client = await this.pool.connect();\n try {\n // Use advisory lock to prevent concurrent migrations\n // Lock ID: 123456789 (arbitrary but consistent)\n const lockId = 123456789;\n \n // Acquire advisory lock (blocks until lock is available)\n // This ensures only one migration runs at a time across all instances\n await client.query(\"SELECT pg_advisory_lock($1)\", [lockId]);\n \n try {\n await client.query(\"BEGIN\");\n\n await this.ensureMigrationsTable(client);\n const appliedMigrations = await this.getAppliedMigrations(client);\n const appliedVersions = new Set(appliedMigrations.map((m) => m.version));\n\n // Find pending migrations\n const pendingMigrations = this.migrations.filter(\n (m) => !appliedVersions.has(m.version)\n );\n\n if (pendingMigrations.length === 0) {\n console.log(\"No pending migrations\");\n await client.query(\"COMMIT\");\n return;\n }\n\n // Apply pending migrations\n for (const migration of pendingMigrations) {\n console.log(\n `Applying migration ${migration.version}: ${migration.name}`\n );\n await migration.up(client);\n // Use ON CONFLICT DO NOTHING to handle race conditions gracefully\n await client.query(\n \"INSERT INTO lattice_schema_migrations (version, name) VALUES ($1, $2) ON CONFLICT (version) DO NOTHING\",\n [migration.version, migration.name]\n );\n }\n\n await client.query(\"COMMIT\");\n console.log(`Applied ${pendingMigrations.length} migration(s)`);\n } catch (error) {\n await client.query(\"ROLLBACK\");\n throw error;\n } finally {\n // Release advisory lock\n await client.query(\"SELECT pg_advisory_unlock($1)\", [lockId]);\n }\n } catch (error) {\n throw error;\n } finally {\n client.release();\n }\n }\n\n /**\n * Rollback last migration\n */\n async rollback(): Promise<void> {\n const client = await this.pool.connect();\n try {\n await client.query(\"BEGIN\");\n\n const appliedMigrations = await this.getAppliedMigrations(client);\n if (appliedMigrations.length === 0) {\n console.log(\"No migrations to rollback\");\n await client.query(\"COMMIT\");\n return;\n }\n\n const lastMigration = appliedMigrations[appliedMigrations.length - 1];\n const migration = this.migrations.find(\n (m) => m.version === lastMigration.version\n );\n\n if (!migration || !migration.down) {\n throw new Error(\n `Migration ${lastMigration.version} does not have a down migration`\n );\n }\n\n console.log(\n `Rolling back migration ${lastMigration.version}: ${lastMigration.name}`\n );\n await migration.down(client);\n await client.query(\n \"DELETE FROM lattice_schema_migrations WHERE version = $1\",\n [lastMigration.version]\n );\n\n await client.query(\"COMMIT\");\n console.log(\"Rollback completed\");\n } catch (error) {\n await client.query(\"ROLLBACK\");\n throw error;\n } finally {\n client.release();\n }\n }\n\n /**\n * Get current migration version\n */\n async getCurrentVersion(): Promise<number> {\n const client = await this.pool.connect();\n try {\n const appliedMigrations = await this.getAppliedMigrations(client);\n if (appliedMigrations.length === 0) {\n return 0;\n }\n return Math.max(...appliedMigrations.map((m) => m.version));\n } finally {\n client.release();\n }\n }\n}\n","/**\n * Thread table migrations\n */\n\nimport { PoolClient } from \"pg\";\nimport { Migration } from \"./migration\";\n\n/**\n * Initial migration: Create threads table\n */\nexport const createThreadsTable: Migration = {\n version: 1,\n name: \"create_threads_table\",\n up: async (client: PoolClient) => {\n await client.query(`\n CREATE TABLE IF NOT EXISTS lattice_threads (\n id VARCHAR(255) NOT NULL,\n assistant_id VARCHAR(255) NOT NULL,\n metadata JSONB DEFAULT '{}',\n created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n PRIMARY KEY (id, assistant_id)\n )\n `);\n\n // Create indexes for better query performance\n await client.query(`\n CREATE INDEX IF NOT EXISTS idx_lattice_threads_assistant_id \n ON lattice_threads(assistant_id)\n `);\n\n await client.query(`\n CREATE INDEX IF NOT EXISTS idx_lattice_threads_created_at \n ON lattice_threads(created_at DESC)\n `);\n },\n down: async (client: PoolClient) => {\n await client.query(\"DROP INDEX IF EXISTS idx_lattice_threads_created_at\");\n await client.query(\"DROP INDEX IF EXISTS idx_lattice_threads_assistant_id\");\n await client.query(\"DROP TABLE IF EXISTS lattice_threads\");\n },\n};\n","/**\n * PostgreSQL implementation of AssistantStore\n */\n\nimport { Pool, PoolClient, PoolConfig } from \"pg\";\nimport {\n AssistantStore,\n Assistant,\n CreateAssistantRequest,\n} from \"@axiom-lattice/protocols\";\nimport { MigrationManager } from \"../migrations/migration\";\nimport { createAssistantsTable } from \"../migrations/assistant_migrations\";\n\n/**\n * PostgreSQL AssistantStore options\n */\nexport interface PostgreSQLAssistantStoreOptions {\n /**\n * PostgreSQL connection pool configuration\n * Can be a connection string or PoolConfig object\n */\n poolConfig: string | PoolConfig;\n\n /**\n * Whether to run migrations automatically on initialization\n * @default true\n */\n autoMigrate?: boolean;\n}\n\n/**\n * PostgreSQL implementation of AssistantStore\n */\nexport class PostgreSQLAssistantStore implements AssistantStore {\n private pool: Pool;\n private migrationManager: MigrationManager;\n private initialized: boolean = false;\n private ownsPool: boolean = true;\n\n constructor(options: PostgreSQLAssistantStoreOptions) {\n // Create Pool from config\n if (typeof options.poolConfig === \"string\") {\n this.pool = new Pool({ connectionString: options.poolConfig });\n } else {\n this.pool = new Pool(options.poolConfig);\n }\n\n this.migrationManager = new MigrationManager(this.pool);\n this.migrationManager.register(createAssistantsTable);\n\n // Auto-migrate by default\n if (options.autoMigrate !== false) {\n this.initialize().catch((error) => {\n console.error(\"Failed to initialize PostgreSQLAssistantStore:\", error);\n throw error;\n });\n }\n }\n\n /**\n * Initialize the store and run migrations\n */\n async initialize(): Promise<void> {\n if (this.initialized) {\n return;\n }\n\n await this.migrationManager.migrate();\n this.initialized = true;\n }\n\n /**\n * Get all assistants\n */\n async getAllAssistants(): Promise<Assistant[]> {\n await this.ensureInitialized();\n\n const result = await this.pool.query<{\n id: string;\n name: string;\n description: string | null;\n graph_definition: any;\n created_at: Date;\n updated_at: Date;\n }>(\n `\n SELECT id, name, description, graph_definition, created_at, updated_at\n FROM lattice_assistants\n ORDER BY created_at DESC\n `\n );\n\n return result.rows.map(this.mapRowToAssistant);\n }\n\n /**\n * Get assistant by ID\n */\n async getAssistantById(id: string): Promise<Assistant | null> {\n await this.ensureInitialized();\n\n const result = await this.pool.query<{\n id: string;\n name: string;\n description: string | null;\n graph_definition: any;\n created_at: Date;\n updated_at: Date;\n }>(\n `\n SELECT id, name, description, graph_definition, created_at, updated_at\n FROM lattice_assistants\n WHERE id = $1\n `,\n [id]\n );\n\n if (result.rows.length === 0) {\n return null;\n }\n\n return this.mapRowToAssistant(result.rows[0]);\n }\n\n /**\n * Create a new assistant\n */\n async createAssistant(\n id: string,\n data: CreateAssistantRequest\n ): Promise<Assistant> {\n await this.ensureInitialized();\n\n const now = new Date();\n\n await this.pool.query(\n `\n INSERT INTO lattice_assistants (id, name, description, graph_definition, created_at, updated_at)\n VALUES ($1, $2, $3, $4, $5, $6)\n ON CONFLICT (id) DO UPDATE SET\n name = EXCLUDED.name,\n description = EXCLUDED.description,\n graph_definition = EXCLUDED.graph_definition,\n updated_at = EXCLUDED.updated_at\n `,\n [\n id,\n data.name,\n data.description || null,\n JSON.stringify(data.graphDefinition),\n now,\n now,\n ]\n );\n\n return {\n id,\n name: data.name,\n description: data.description,\n graphDefinition: data.graphDefinition,\n createdAt: now,\n updatedAt: now,\n };\n }\n\n /**\n * Update an existing assistant\n */\n async updateAssistant(\n id: string,\n updates: Partial<CreateAssistantRequest>\n ): Promise<Assistant | null> {\n await this.ensureInitialized();\n\n // Get existing assistant\n const existing = await this.getAssistantById(id);\n if (!existing) {\n return null;\n }\n\n // Build update query dynamically based on provided fields\n const updateFields: string[] = [];\n const updateValues: any[] = [];\n let paramIndex = 1;\n\n if (updates.name !== undefined) {\n updateFields.push(`name = $${paramIndex++}`);\n updateValues.push(updates.name);\n }\n\n if (updates.description !== undefined) {\n updateFields.push(`description = $${paramIndex++}`);\n updateValues.push(updates.description || null);\n }\n\n if (updates.graphDefinition !== undefined) {\n updateFields.push(`graph_definition = $${paramIndex++}`);\n updateValues.push(JSON.stringify(updates.graphDefinition));\n }\n\n if (updateFields.length === 0) {\n // No fields to update\n return existing;\n }\n\n // Always update updated_at\n updateFields.push(`updated_at = $${paramIndex++}`);\n updateValues.push(new Date());\n\n // Add id for WHERE clause\n updateValues.push(id);\n\n await this.pool.query(\n `\n UPDATE lattice_assistants\n SET ${updateFields.join(\", \")}\n WHERE id = $${paramIndex}\n `,\n updateValues\n );\n\n // Return updated assistant\n return await this.getAssistantById(id);\n }\n\n /**\n * Delete an assistant by ID\n */\n async deleteAssistant(id: string): Promise<boolean> {\n await this.ensureInitialized();\n\n const result = await this.pool.query(\n `\n DELETE FROM lattice_assistants\n WHERE id = $1\n `,\n [id]\n );\n\n return result.rowCount !== null && result.rowCount > 0;\n }\n\n /**\n * Check if assistant exists\n */\n async hasAssistant(id: string): Promise<boolean> {\n await this.ensureInitialized();\n\n const result = await this.pool.query(\n `\n SELECT 1 FROM lattice_assistants\n WHERE id = $1\n LIMIT 1\n `,\n [id]\n );\n\n return result.rows.length > 0;\n }\n\n /**\n * Dispose resources and close the connection pool\n * Should be called when the store is no longer needed\n */\n async dispose(): Promise<void> {\n if (this.ownsPool && this.pool) {\n await this.pool.end();\n }\n }\n\n /**\n * Ensure store is initialized\n */\n private async ensureInitialized(): Promise<void> {\n if (!this.initialized) {\n await this.initialize();\n }\n }\n\n /**\n * Map database row to Assistant object\n */\n private mapRowToAssistant(row: {\n id: string;\n name: string;\n description: string | null;\n graph_definition: any;\n created_at: Date;\n updated_at: Date;\n }): Assistant {\n return {\n id: row.id,\n name: row.name,\n description: row.description || undefined,\n graphDefinition:\n typeof row.graph_definition === \"string\"\n ? JSON.parse(row.graph_definition)\n : row.graph_definition,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n };\n }\n}\n","/**\n * Assistant table migrations\n */\n\nimport { PoolClient } from \"pg\";\nimport { Migration } from \"./migration\";\n\n/**\n * Initial migration: Create assistants table\n */\nexport const createAssistantsTable: Migration = {\n version: 3,\n name: \"create_assistants_table\",\n up: async (client: PoolClient) => {\n await client.query(`\n CREATE TABLE IF NOT EXISTS lattice_assistants (\n id VARCHAR(255) PRIMARY KEY,\n name VARCHAR(255) NOT NULL,\n description TEXT,\n graph_definition JSONB NOT NULL,\n created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP\n )\n `);\n\n // Create indexes for better query performance\n await client.query(`\n CREATE INDEX IF NOT EXISTS idx_lattice_assistants_name \n ON lattice_assistants(name)\n `);\n\n await client.query(`\n CREATE INDEX IF NOT EXISTS idx_lattice_assistants_created_at \n ON lattice_assistants(created_at DESC)\n `);\n },\n down: async (client: PoolClient) => {\n await client.query(\n \"DROP INDEX IF EXISTS idx_lattice_assistants_created_at\"\n );\n await client.query(\"DROP INDEX IF EXISTS idx_lattice_assistants_name\");\n await client.query(\"DROP TABLE IF EXISTS lattice_assistants\");\n },\n};\n","/**\n * PostgreSQL implementation of ScheduleStorage\n *\n * Provides persistent storage for scheduled tasks\n * Data survives service restarts\n */\n\nimport { Pool, PoolConfig } from \"pg\";\nimport {\n ScheduleStorage,\n ScheduledTaskDefinition,\n ScheduledTaskStatus,\n ScheduleExecutionType,\n} from \"@axiom-lattice/protocols\";\nimport { MigrationManager } from \"../migrations/migration\";\nimport { createScheduledTasksTable } from \"../migrations/schedule_migrations\";\n\n/**\n * PostgreSQL ScheduleStorage options\n */\nexport interface PostgreSQLScheduleStorageOptions {\n /**\n * PostgreSQL connection pool configuration\n * Can be a connection string or PoolConfig object\n */\n poolConfig: string | PoolConfig;\n\n /**\n * Whether to run migrations automatically on initialization\n * @default true\n */\n autoMigrate?: boolean;\n}\n\n/**\n * Database row type for scheduled tasks\n */\ninterface ScheduledTaskRow {\n task_id: string;\n task_type: string;\n payload: string | Record<string, any>;\n assistant_id: string | null;\n thread_id: string | null;\n execution_type: string;\n execute_at: Date | null;\n delay_ms: number | null;\n cron_expression: string | null;\n timezone: string | null;\n next_run_at: Date | null;\n last_run_at: Date | null;\n status: string;\n run_count: number;\n max_runs: number | null;\n retry_count: number;\n max_retries: number;\n last_error: string | null;\n created_at: Date;\n updated_at: Date;\n expires_at: Date | null;\n metadata: string | Record<string, any> | null;\n}\n\n/**\n * PostgreSQL implementation of ScheduleStorage\n */\nexport class PostgreSQLScheduleStorage implements ScheduleStorage {\n private pool: Pool;\n private migrationManager: MigrationManager;\n private initialized: boolean = false;\n\n constructor(options: PostgreSQLScheduleStorageOptions) {\n // Create Pool from config\n if (typeof options.poolConfig === \"string\") {\n this.pool = new Pool({ connectionString: options.poolConfig });\n } else {\n this.pool = new Pool(options.poolConfig);\n }\n\n this.migrationManager = new MigrationManager(this.pool);\n this.migrationManager.register(createScheduledTasksTable);\n\n // Auto-migrate by default\n if (options.autoMigrate !== false) {\n this.initialize().catch((error) => {\n console.error(\"Failed to initialize PostgreSQLScheduleStorage:\", error);\n throw error;\n });\n }\n }\n\n /**\n * Dispose resources and close the connection pool\n */\n async dispose(): Promise<void> {\n if (this.pool) {\n await this.pool.end();\n }\n }\n\n /**\n * Initialize the store and run migrations\n */\n async initialize(): Promise<void> {\n if (this.initialized) {\n return;\n }\n\n await this.migrationManager.migrate();\n this.initialized = true;\n }\n\n /**\n * Ensure store is initialized\n */\n private async ensureInitialized(): Promise<void> {\n if (!this.initialized) {\n await this.initialize();\n }\n }\n\n /**\n * Save a new task\n */\n async save(task: ScheduledTaskDefinition): Promise<void> {\n await this.ensureInitialized();\n\n await this.pool.query(\n `\n INSERT INTO lattice_scheduled_tasks (\n task_id, task_type, payload, assistant_id, thread_id, execution_type,\n execute_at, delay_ms, cron_expression, timezone,\n next_run_at, last_run_at, status, run_count, max_runs,\n retry_count, max_retries, last_error,\n created_at, updated_at, expires_at, metadata\n ) VALUES (\n $1, $2, $3, $4, $5, $6,\n $7, $8, $9, $10,\n $11, $12, $13, $14, $15,\n $16, $17, $18,\n $19, $20, $21, $22\n )\n ON CONFLICT (task_id) DO UPDATE SET\n task_type = EXCLUDED.task_type,\n payload = EXCLUDED.payload,\n assistant_id = EXCLUDED.assistant_id,\n thread_id = EXCLUDED.thread_id,\n execution_type = EXCLUDED.execution_type,\n execute_at = EXCLUDED.execute_at,\n delay_ms = EXCLUDED.delay_ms,\n cron_expression = EXCLUDED.cron_expression,\n timezone = EXCLUDED.timezone,\n next_run_at = EXCLUDED.next_run_at,\n last_run_at = EXCLUDED.last_run_at,\n status = EXCLUDED.status,\n run_count = EXCLUDED.run_count,\n max_runs = EXCLUDED.max_runs,\n retry_count = EXCLUDED.retry_count,\n max_retries = EXCLUDED.max_retries,\n last_error = EXCLUDED.last_error,\n updated_at = EXCLUDED.updated_at,\n expires_at = EXCLUDED.expires_at,\n metadata = EXCLUDED.metadata\n `,\n [\n task.taskId,\n task.taskType,\n JSON.stringify(task.payload),\n task.assistantId ?? null,\n task.threadId ?? null,\n task.executionType,\n task.executeAt ? new Date(task.executeAt) : null,\n task.delayMs ?? null,\n task.cronExpression ?? null,\n task.timezone ?? null,\n task.nextRunAt ? new Date(task.nextRunAt) : null,\n task.lastRunAt ? new Date(task.lastRunAt) : null,\n task.status,\n task.runCount,\n task.maxRuns ?? null,\n task.retryCount,\n task.maxRetries,\n task.lastError ?? null,\n new Date(task.createdAt),\n new Date(task.updatedAt),\n task.expiresAt ? new Date(task.expiresAt) : null,\n task.metadata ? JSON.stringify(task.metadata) : null,\n ]\n );\n }\n\n /**\n * Get task by ID\n */\n async get(taskId: string): Promise<ScheduledTaskDefinition | null> {\n await this.ensureInitialized();\n\n const result = await this.pool.query<ScheduledTaskRow>(\n `SELECT * FROM lattice_scheduled_tasks WHERE task_id = $1`,\n [taskId]\n );\n\n if (result.rows.length === 0) {\n return null;\n }\n\n return this.mapRowToTask(result.rows[0]);\n }\n\n /**\n * Update task\n */\n async update(\n taskId: string,\n updates: Partial<ScheduledTaskDefinition>\n ): Promise<void> {\n await this.ensureInitialized();\n\n const setClauses: string[] = [];\n const values: any[] = [];\n let paramIndex = 1;\n\n // Build dynamic UPDATE query\n if (updates.taskType !== undefined) {\n setClauses.push(`task_type = $${paramIndex++}`);\n values.push(updates.taskType);\n }\n if (updates.payload !== undefined) {\n setClauses.push(`payload = $${paramIndex++}`);\n values.push(JSON.stringify(updates.payload));\n }\n if (updates.assistantId !== undefined) {\n setClauses.push(`assistant_id = $${paramIndex++}`);\n values.push(updates.assistantId);\n }\n if (updates.threadId !== undefined) {\n setClauses.push(`thread_id = $${paramIndex++}`);\n values.push(updates.threadId);\n }\n if (updates.executionType !== undefined) {\n setClauses.push(`execution_type = $${paramIndex++}`);\n values.push(updates.executionType);\n }\n if (updates.executeAt !== undefined) {\n setClauses.push(`execute_at = $${paramIndex++}`);\n values.push(updates.executeAt ? new Date(updates.executeAt) : null);\n }\n if (updates.delayMs !== undefined) {\n setClauses.push(`delay_ms = $${paramIndex++}`);\n values.push(updates.delayMs);\n }\n if (updates.cronExpression !== undefined) {\n setClauses.push(`cron_expression = $${paramIndex++}`);\n values.push(updates.cronExpression);\n }\n if (updates.timezone !== undefined) {\n setClauses.push(`timezone = $${paramIndex++}`);\n values.push(updates.timezone);\n }\n if (updates.nextRunAt !== undefined) {\n setClauses.push(`next_run_at = $${paramIndex++}`);\n values.push(updates.nextRunAt ? new Date(updates.nextRunAt) : null);\n }\n if (updates.lastRunAt !== undefined) {\n setClauses.push(`last_run_at = $${paramIndex++}`);\n values.push(updates.lastRunAt ? new Date(updates.lastRunAt) : null);\n }\n if (updates.status !== undefined) {\n setClauses.push(`status = $${paramIndex++}`);\n values.push(updates.status);\n }\n if (updates.runCount !== undefined) {\n setClauses.push(`run_count = $${paramIndex++}`);\n values.push(updates.runCount);\n }\n if (updates.maxRuns !== undefined) {\n setClauses.push(`max_runs = $${paramIndex++}`);\n values.push(updates.maxRuns);\n }\n if (updates.retryCount !== undefined) {\n setClauses.push(`retry_count = $${paramIndex++}`);\n values.push(updates.retryCount);\n }\n if (updates.maxRetries !== undefined) {\n setClauses.push(`max_retries = $${paramIndex++}`);\n values.push(updates.maxRetries);\n }\n if (updates.lastError !== undefined) {\n setClauses.push(`last_error = $${paramIndex++}`);\n values.push(updates.lastError);\n }\n if (updates.expiresAt !== undefined) {\n setClauses.push(`expires_at = $${paramIndex++}`);\n values.push(updates.expiresAt ? new Date(updates.expiresAt) : null);\n }\n if (updates.metadata !== undefined) {\n setClauses.push(`metadata = $${paramIndex++}`);\n values.push(updates.metadata ? JSON.stringify(updates.metadata) : null);\n }\n\n // Always update updated_at\n setClauses.push(`updated_at = $${paramIndex++}`);\n values.push(new Date());\n\n // Add taskId as the last parameter\n values.push(taskId);\n\n if (setClauses.length === 0) {\n return;\n }\n\n await this.pool.query(\n `UPDATE lattice_scheduled_tasks SET ${setClauses.join(\n \", \"\n )} WHERE task_id = $${paramIndex}`,\n values\n );\n }\n\n /**\n * Delete task\n */\n async delete(taskId: string): Promise<void> {\n await this.ensureInitialized();\n\n await this.pool.query(\n `DELETE FROM lattice_scheduled_tasks WHERE task_id = $1`,\n [taskId]\n );\n }\n\n /**\n * Get all active tasks (pending or paused)\n */\n async getActiveTasks(): Promise<ScheduledTaskDefinition[]> {\n await this.ensureInitialized();\n\n const result = await this.pool.query<ScheduledTaskRow>(\n `SELECT * FROM lattice_scheduled_tasks WHERE status IN ($1, $2) ORDER BY created_at ASC`,\n [ScheduledTaskStatus.PENDING, ScheduledTaskStatus.PAUSED]\n );\n\n return result.rows.map((row) => this.mapRowToTask(row));\n }\n\n /**\n * Get tasks by type\n */\n async getTasksByType(taskType: string): Promise<ScheduledTaskDefinition[]> {\n await this.ensureInitialized();\n\n const result = await this.pool.query<ScheduledTaskRow>(\n `SELECT * FROM lattice_scheduled_tasks WHERE task_type = $1 ORDER BY created_at DESC`,\n [taskType]\n );\n\n return result.rows.map((row) => this.mapRowToTask(row));\n }\n\n /**\n * Get tasks by status\n */\n async getTasksByStatus(\n status: ScheduledTaskStatus\n ): Promise<ScheduledTaskDefinition[]> {\n await this.ensureInitialized();\n\n const result = await this.pool.query<ScheduledTaskRow>(\n `SELECT * FROM lattice_scheduled_tasks WHERE status = $1 ORDER BY created_at DESC`,\n [status]\n );\n\n return result.rows.map((row) => this.mapRowToTask(row));\n }\n\n /**\n * Get tasks by execution type\n */\n async getTasksByExecutionType(\n executionType: ScheduleExecutionType\n ): Promise<ScheduledTaskDefinition[]> {\n await this.ensureInitialized();\n\n const result = await this.pool.query<ScheduledTaskRow>(\n `SELECT * FROM lattice_scheduled_tasks WHERE execution_type = $1 ORDER BY created_at DESC`,\n [executionType]\n );\n\n return result.rows.map((row) => this.mapRowToTask(row));\n }\n\n /**\n * Get tasks by assistant ID\n */\n async getTasksByAssistantId(\n assistantId: string\n ): Promise<ScheduledTaskDefinition[]> {\n await this.ensureInitialized();\n\n const result = await this.pool.query<ScheduledTaskRow>(\n `SELECT * FROM lattice_scheduled_tasks WHERE assistant_id = $1 ORDER BY created_at DESC`,\n [assistantId]\n );\n\n return result.rows.map((row) => this.mapRowToTask(row));\n }\n\n /**\n * Get tasks by thread ID\n */\n async getTasksByThreadId(\n threadId: string\n ): Promise<ScheduledTaskDefinition[]> {\n await this.ensureInitialized();\n\n const result = await this.pool.query<ScheduledTaskRow>(\n `SELECT * FROM lattice_scheduled_tasks WHERE thread_id = $1 ORDER BY created_at DESC`,\n [threadId]\n );\n\n return result.rows.map((row) => this.mapRowToTask(row));\n }\n\n /**\n * Get all tasks with optional filters\n */\n async getAllTasks(filters?: {\n status?: ScheduledTaskStatus;\n executionType?: ScheduleExecutionType;\n taskType?: string;\n assistantId?: string;\n threadId?: string;\n limit?: number;\n offset?: number;\n }): Promise<ScheduledTaskDefinition[]> {\n await this.ensureInitialized();\n\n const whereClauses: string[] = [];\n const values: any[] = [];\n let paramIndex = 1;\n\n if (filters?.status !== undefined) {\n whereClauses.push(`status = $${paramIndex++}`);\n values.push(filters.status);\n }\n if (filters?.executionType !== undefined) {\n whereClauses.push(`execution_type = $${paramIndex++}`);\n values.push(filters.executionType);\n }\n if (filters?.taskType !== undefined) {\n whereClauses.push(`task_type = $${paramIndex++}`);\n values.push(filters.taskType);\n }\n if (filters?.assistantId !== undefined) {\n whereClauses.push(`assistant_id = $${paramIndex++}`);\n values.push(filters.assistantId);\n }\n if (filters?.threadId !== undefined) {\n whereClauses.push(`thread_id = $${paramIndex++}`);\n values.push(filters.threadId);\n }\n\n let query = `SELECT * FROM lattice_scheduled_tasks`;\n if (whereClauses.length > 0) {\n query += ` WHERE ${whereClauses.join(\" AND \")}`;\n }\n query += ` ORDER BY created_at DESC`;\n\n if (filters?.limit !== undefined) {\n query += ` LIMIT $${paramIndex++}`;\n values.push(filters.limit);\n }\n if (filters?.offset !== undefined) {\n query += ` OFFSET $${paramIndex++}`;\n values.push(filters.offset);\n }\n\n const result = await this.pool.query<ScheduledTaskRow>(query, values);\n\n return result.rows.map((row) => this.mapRowToTask(row));\n }\n\n /**\n * Count tasks with optional filters\n */\n async countTasks(filters?: {\n status?: ScheduledTaskStatus;\n executionType?: ScheduleExecutionType;\n taskType?: string;\n assistantId?: string;\n threadId?: string;\n }): Promise<number> {\n await this.ensureInitialized();\n\n const whereClauses: string[] = [];\n const values: any[] = [];\n let paramIndex = 1;\n\n if (filters?.status !== undefined) {\n whereClauses.push(`status = $${paramIndex++}`);\n values.push(filters.status);\n }\n if (filters?.executionType !== undefined) {\n whereClauses.push(`execution_type = $${paramIndex++}`);\n values.push(filters.executionType);\n }\n if (filters?.taskType !== undefined) {\n whereClauses.push(`task_type = $${paramIndex++}`);\n values.push(filters.taskType);\n }\n if (filters?.assistantId !== undefined) {\n whereClauses.push(`assistant_id = $${paramIndex++}`);\n values.push(filters.assistantId);\n }\n if (filters?.threadId !== undefined) {\n whereClauses.push(`thread_id = $${paramIndex++}`);\n values.push(filters.threadId);\n }\n\n let query = `SELECT COUNT(*) as count FROM lattice_scheduled_tasks`;\n if (whereClauses.length > 0) {\n query += ` WHERE ${whereClauses.join(\" AND \")}`;\n }\n\n const result = await this.pool.query<{ count: string }>(query, values);\n\n return parseInt(result.rows[0].count, 10);\n }\n\n /**\n * Delete completed/cancelled/failed tasks older than specified time\n */\n async deleteOldTasks(olderThanMs: number): Promise<number> {\n await this.ensureInitialized();\n\n const cutoff = new Date(Date.now() - olderThanMs);\n\n const result = await this.pool.query(\n `\n DELETE FROM lattice_scheduled_tasks \n WHERE status IN ($1, $2, $3) \n AND updated_at < $4\n `,\n [\n ScheduledTaskStatus.COMPLETED,\n ScheduledTaskStatus.CANCELLED,\n ScheduledTaskStatus.FAILED,\n cutoff,\n ]\n );\n\n return result.rowCount ?? 0;\n }\n\n /**\n * Map database row to ScheduledTaskDefinition\n */\n private mapRowToTask(row: ScheduledTaskRow): ScheduledTaskDefinition {\n return {\n taskId: row.task_id,\n taskType: row.task_type,\n payload:\n typeof row.payload === \"string\"\n ? JSON.parse(row.payload)\n : row.payload || {},\n assistantId: row.assistant_id ?? undefined,\n threadId: row.thread_id ?? undefined,\n executionType: row.execution_type as ScheduleExecutionType,\n executeAt: row.execute_at ? row.execute_at.getTime() : undefined,\n delayMs: row.delay_ms ?? undefined,\n cronExpression: row.cron_expression ?? undefined,\n timezone: row.timezone ?? undefined,\n nextRunAt: row.next_run_at ? row.next_run_at.getTime() : undefined,\n lastRunAt: row.last_run_at ? row.last_run_at.getTime() : undefined,\n status: row.status as ScheduledTaskStatus,\n runCount: row.run_count,\n maxRuns: row.max_runs ?? undefined,\n retryCount: row.retry_count,\n maxRetries: row.max_retries,\n lastError: row.last_error ?? undefined,\n createdAt: row.created_at.getTime(),\n updatedAt: row.updated_at.getTime(),\n expiresAt: row.expires_at ? row.expires_at.getTime() : undefined,\n metadata:\n row.metadata === null\n ? undefined\n : typeof row.metadata === \"string\"\n ? JSON.parse(row.metadata)\n : row.metadata,\n };\n }\n}\n","/**\n * PostgreSQL migrations for scheduled tasks table\n */\n\nimport { Migration } from \"./migration\";\n\n/**\n * Create the scheduled_tasks table\n */\nexport const createScheduledTasksTable: Migration = {\n name: \"create_scheduled_tasks_table\",\n version: 2,\n\n up: async (client) => {\n await client.query(`\n CREATE TABLE IF NOT EXISTS lattice_scheduled_tasks (\n -- Primary key\n task_id VARCHAR(255) PRIMARY KEY,\n \n -- Task type (maps to handler)\n task_type VARCHAR(255) NOT NULL,\n \n -- Payload (JSON-serializable data)\n payload JSONB NOT NULL DEFAULT '{}',\n \n -- Context fields for querying\n assistant_id VARCHAR(255),\n thread_id VARCHAR(255),\n \n -- Execution type: 'once' or 'cron'\n execution_type VARCHAR(50) NOT NULL,\n \n -- For ONCE type\n execute_at TIMESTAMPTZ,\n delay_ms BIGINT,\n \n -- For CRON type\n cron_expression VARCHAR(255),\n timezone VARCHAR(100),\n next_run_at TIMESTAMPTZ,\n last_run_at TIMESTAMPTZ,\n \n -- Status\n status VARCHAR(50) NOT NULL DEFAULT 'pending',\n \n -- Execution tracking\n run_count INTEGER NOT NULL DEFAULT 0,\n max_runs INTEGER,\n \n -- Error handling\n retry_count INTEGER NOT NULL DEFAULT 0,\n max_retries INTEGER NOT NULL DEFAULT 0,\n last_error TEXT,\n \n -- Timestamps\n created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n expires_at TIMESTAMPTZ,\n \n -- Metadata\n metadata JSONB\n );\n\n -- Index for querying active tasks\n CREATE INDEX IF NOT EXISTS idx_scheduled_tasks_status \n ON lattice_scheduled_tasks (status);\n \n -- Index for querying by task type\n CREATE INDEX IF NOT EXISTS idx_scheduled_tasks_task_type \n ON lattice_scheduled_tasks (task_type);\n \n -- Index for querying by execution type\n CREATE INDEX IF NOT EXISTS idx_scheduled_tasks_execution_type \n ON lattice_scheduled_tasks (execution_type);\n \n -- Index for querying by assistant ID\n CREATE INDEX IF NOT EXISTS idx_scheduled_tasks_assistant_id \n ON lattice_scheduled_tasks (assistant_id)\n WHERE assistant_id IS NOT NULL;\n \n -- Index for querying by thread ID\n CREATE INDEX IF NOT EXISTS idx_scheduled_tasks_thread_id \n ON lattice_scheduled_tasks (thread_id)\n WHERE thread_id IS NOT NULL;\n \n -- Index for querying pending tasks by next run time\n CREATE INDEX IF NOT EXISTS idx_scheduled_tasks_next_run \n ON lattice_scheduled_tasks (next_run_at) \n WHERE status = 'pending';\n \n -- Index for querying pending one-time tasks by execute time\n CREATE INDEX IF NOT EXISTS idx_scheduled_tasks_execute_at \n ON lattice_scheduled_tasks (execute_at) \n WHERE status = 'pending' AND execution_type = 'once';\n \n -- Index for cleanup queries (old completed/cancelled tasks)\n CREATE INDEX IF NOT EXISTS idx_scheduled_tasks_cleanup \n ON lattice_scheduled_tasks (updated_at) \n WHERE status IN ('completed', 'cancelled', 'failed');\n `);\n },\n\n down: async (client) => {\n await client.query(`\n DROP INDEX IF EXISTS idx_scheduled_tasks_cleanup;\n DROP INDEX IF EXISTS idx_scheduled_tasks_execute_at;\n DROP INDEX IF EXISTS idx_scheduled_tasks_next_run;\n DROP INDEX IF EXISTS idx_scheduled_tasks_thread_id;\n DROP INDEX IF EXISTS idx_scheduled_tasks_assistant_id;\n DROP INDEX IF EXISTS idx_scheduled_tasks_execution_type;\n DROP INDEX IF EXISTS idx_scheduled_tasks_task_type;\n DROP INDEX IF EXISTS idx_scheduled_tasks_status;\n DROP TABLE IF EXISTS lattice_scheduled_tasks;\n `);\n },\n};\n","/**\n * PostgreSQL implementation of SkillStore\n */\n\nimport { Pool, PoolConfig } from \"pg\";\nimport {\n SkillStore,\n Skill,\n CreateSkillRequest,\n} from \"@axiom-lattice/protocols\";\nimport { MigrationManager } from \"../migrations/migration\";\nimport { createSkillsTable } from \"../migrations/skill_migrations\";\n\n/**\n * PostgreSQL SkillStore options\n */\nexport interface PostgreSQLSkillStoreOptions {\n /**\n * PostgreSQL connection pool configuration\n * Can be a connection string or PoolConfig object\n */\n poolConfig: string | PoolConfig;\n\n /**\n * Whether to run migrations automatically on initialization\n * @default true\n */\n autoMigrate?: boolean;\n}\n\n/**\n * PostgreSQL implementation of SkillStore\n */\nexport class PostgreSQLSkillStore implements SkillStore {\n private pool: Pool;\n private migrationManager: MigrationManager;\n private initialized: boolean = false;\n private ownsPool: boolean = true;\n\n constructor(options: PostgreSQLSkillStoreOptions) {\n // Create Pool from config\n if (typeof options.poolConfig === \"string\") {\n this.pool = new Pool({ connectionString: options.poolConfig });\n } else {\n this.pool = new Pool(options.poolConfig);\n }\n\n this.migrationManager = new MigrationManager(this.pool);\n this.migrationManager.register(createSkillsTable);\n\n // Auto-migrate by default\n if (options.autoMigrate !== false) {\n this.initialize().catch((error) => {\n console.error(\"Failed to initialize PostgreSQLSkillStore:\", error);\n throw error;\n });\n }\n }\n\n /**\n * Dispose resources and close the connection pool\n * Should be called when the store is no longer needed\n */\n async dispose(): Promise<void> {\n if (this.ownsPool && this.pool) {\n await this.pool.end();\n }\n }\n\n /**\n * Initialize the store and run migrations\n */\n async initialize(): Promise<void> {\n if (this.initialized) {\n return;\n }\n\n await this.migrationManager.migrate();\n this.initialized = true;\n }\n\n /**\n * Ensure store is initialized\n */\n private async ensureInitialized(): Promise<void> {\n if (!this.initialized) {\n await this.initialize();\n }\n }\n\n /**\n * Map database row to Skill object\n */\n private mapRowToSkill(row: {\n id: string;\n name: string;\n description: string;\n license: string | null;\n compatibility: string | null;\n metadata: any;\n content: string | null;\n sub_skills: any;\n created_at: Date;\n updated_at: Date;\n }): Skill {\n return {\n id: row.id,\n name: row.name,\n description: row.description,\n license: row.license || undefined,\n compatibility: row.compatibility || undefined,\n metadata: row.metadata || {},\n content: row.content || undefined,\n subSkills: Array.isArray(row.sub_skills) && row.sub_skills.length > 0 \n ? row.sub_skills \n : undefined,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n };\n }\n\n /**\n * Get all skills\n */\n async getAllSkills(): Promise<Skill[]> {\n await this.ensureInitialized();\n\n const result = await this.pool.query<{\n id: string;\n name: string;\n description: string;\n license: string | null;\n compatibility: string | null;\n metadata: any;\n content: string | null;\n sub_skills: any;\n created_at: Date;\n updated_at: Date;\n }>(\n `\n SELECT id, name, description, license, compatibility, metadata, content, sub_skills, created_at, updated_at\n FROM lattice_skills\n ORDER BY created_at DESC\n `\n );\n\n return result.rows.map(this.mapRowToSkill);\n }\n\n /**\n * Get skill by ID\n */\n async getSkillById(id: string): Promise<Skill | null> {\n await this.ensureInitialized();\n\n const result = await this.pool.query<{\n id: string;\n name: string;\n description: string;\n license: string | null;\n compatibility: string | null;\n metadata: any;\n content: string | null;\n sub_skills: any;\n created_at: Date;\n updated_at: Date;\n }>(\n `\n SELECT id, name, description, license, compatibility, metadata, content, sub_skills, created_at, updated_at\n FROM lattice_skills\n WHERE id = $1\n `,\n [id]\n );\n\n if (result.rows.length === 0) {\n return null;\n }\n\n return this.mapRowToSkill(result.rows[0]);\n }\n\n /**\n * Create a new skill\n */\n async createSkill(id: string, data: CreateSkillRequest): Promise<Skill> {\n await this.ensureInitialized();\n\n const now = new Date();\n const metadata = data.metadata || {};\n\n await this.pool.query(\n `\n INSERT INTO lattice_skills (id, name, description, license, compatibility, metadata, content, sub_skills, created_at, updated_at)\n VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)\n ON CONFLICT (id) DO UPDATE SET\n name = EXCLUDED.name,\n description = EXCLUDED.description,\n license = EXCLUDED.license,\n compatibility = EXCLUDED.compatibility,\n metadata = EXCLUDED.metadata,\n content = EXCLUDED.content,\n sub_skills = EXCLUDED.sub_skills,\n updated_at = EXCLUDED.updated_at\n `,\n [\n id,\n data.name,\n data.description,\n data.license || null,\n data.compatibility || null,\n JSON.stringify(metadata),\n data.content || null,\n JSON.stringify(data.subSkills || []),\n now,\n now,\n ]\n );\n\n return this.getSkillById(id) as Promise<Skill>;\n }\n\n /**\n * Update an existing skill\n */\n async updateSkill(\n id: string,\n updates: Partial<CreateSkillRequest>\n ): Promise<Skill | null> {\n await this.ensureInitialized();\n\n const updateFields: string[] = [];\n const values: any[] = [];\n let paramIndex = 1;\n\n if (updates.name !== undefined) {\n updateFields.push(`name = $${paramIndex++}`);\n values.push(updates.name);\n }\n\n if (updates.description !== undefined) {\n updateFields.push(`description = $${paramIndex++}`);\n values.push(updates.description);\n }\n\n if (updates.license !== undefined) {\n updateFields.push(`license = $${paramIndex++}`);\n values.push(updates.license || null);\n }\n\n if (updates.compatibility !== undefined) {\n updateFields.push(`compatibility = $${paramIndex++}`);\n values.push(updates.compatibility || null);\n }\n\n if (updates.metadata !== undefined) {\n updateFields.push(`metadata = $${paramIndex++}`);\n values.push(JSON.stringify(updates.metadata || {}));\n }\n\n if (updates.content !== undefined) {\n updateFields.push(`content = $${paramIndex++}`);\n values.push(updates.content || null);\n }\n\n if (updates.subSkills !== undefined) {\n updateFields.push(`sub_skills = $${paramIndex++}`);\n values.push(JSON.stringify(updates.subSkills || []));\n }\n\n if (updateFields.length === 0) {\n return this.getSkillById(id);\n }\n\n updateFields.push(`updated_at = $${paramIndex++}`);\n values.push(new Date());\n values.push(id);\n\n await this.pool.query(\n `\n UPDATE lattice_skills\n SET ${updateFields.join(\", \")}\n WHERE id = $${paramIndex}\n `,\n values\n );\n\n return this.getSkillById(id);\n }\n\n /**\n * Delete a skill by ID\n */\n async deleteSkill(id: string): Promise<boolean> {\n await this.ensureInitialized();\n\n const result = await this.pool.query(\n `\n DELETE FROM lattice_skills\n WHERE id = $1\n `,\n [id]\n );\n\n return result.rowCount !== null && result.rowCount > 0;\n }\n\n /**\n * Check if skill exists\n */\n async hasSkill(id: string): Promise<boolean> {\n await this.ensureInitialized();\n\n const result = await this.pool.query<{ count: string }>(\n `\n SELECT COUNT(*) as count\n FROM lattice_skills\n WHERE id = $1\n `,\n [id]\n );\n\n return parseInt(result.rows[0].count, 10) > 0;\n }\n\n /**\n * Search skills by metadata\n */\n async searchByMetadata(\n metadataKey: string,\n metadataValue: string\n ): Promise<Skill[]> {\n await this.ensureInitialized();\n\n const result = await this.pool.query<{\n id: string;\n name: string;\n description: string;\n license: string | null;\n compatibility: string | null;\n metadata: any;\n content: string | null;\n sub_skills: any;\n created_at: Date;\n updated_at: Date;\n }>(\n `\n SELECT id, name, description, license, compatibility, metadata, content, sub_skills, created_at, updated_at\n FROM lattice_skills\n WHERE metadata->>$1 = $2\n ORDER BY created_at DESC\n `,\n [metadataKey, metadataValue]\n );\n\n return result.rows.map(this.mapRowToSkill);\n }\n\n /**\n * Filter skills by compatibility\n */\n async filterByCompatibility(compatibility: string): Promise<Skill[]> {\n await this.ensureInitialized();\n\n const result = await this.pool.query<{\n id: string;\n name: string;\n description: string;\n license: string | null;\n compatibility: string | null;\n metadata: any;\n content: string | null;\n sub_skills: any;\n created_at: Date;\n updated_at: Date;\n }>(\n `\n SELECT id, name, description, license, compatibility, metadata, content, sub_skills, created_at, updated_at\n FROM lattice_skills\n WHERE compatibility = $1\n ORDER BY created_at DESC\n `,\n [compatibility]\n );\n\n return result.rows.map(this.mapRowToSkill);\n }\n\n /**\n * Filter skills by license\n */\n async filterByLicense(license: string): Promise<Skill[]> {\n await this.ensureInitialized();\n\n const result = await this.pool.query<{\n id: string;\n name: string;\n description: string;\n license: string | null;\n compatibility: string | null;\n metadata: any;\n content: string | null;\n sub_skills: any;\n created_at: Date;\n updated_at: Date;\n }>(\n `\n SELECT id, name, description, license, compatibility, metadata, content, sub_skills, created_at, updated_at\n FROM lattice_skills\n WHERE license = $1\n ORDER BY created_at DESC\n `,\n [license]\n );\n\n return result.rows.map(this.mapRowToSkill);\n }\n\n /**\n * Get sub-skills of a parent skill\n */\n async getSubSkills(parentSkillName: string): Promise<Skill[]> {\n await this.ensureInitialized();\n\n const parentSkill = await this.getSkillById(parentSkillName);\n if (!parentSkill || !parentSkill.subSkills || parentSkill.subSkills.length === 0) {\n return [];\n }\n\n // Query all sub-skills in one query\n const placeholders = parentSkill.subSkills.map((_, index) => `$${index + 1}`).join(\", \");\n const result = await this.pool.query<{\n id: string;\n name: string;\n description: string;\n license: string | null;\n compatibility: string | null;\n metadata: any;\n content: string | null;\n sub_skills: any;\n created_at: Date;\n updated_at: Date;\n }>(\n `\n SELECT id, name, description, license, compatibility, metadata, content, sub_skills, created_at, updated_at\n FROM lattice_skills\n WHERE name IN (${placeholders})\n ORDER BY created_at DESC\n `,\n parentSkill.subSkills\n );\n\n return result.rows.map(this.mapRowToSkill);\n }\n}\n","/**\n * Skill table migrations\n */\n\nimport { PoolClient } from \"pg\";\nimport { Migration } from \"./migration\";\n\n/**\n * Initial migration: Create skills table\n */\nexport const createSkillsTable: Migration = {\n version: 4,\n name: \"create_skills_table\",\n up: async (client: PoolClient) => {\n await client.query(`\n CREATE TABLE IF NOT EXISTS lattice_skills (\n id VARCHAR(255) PRIMARY KEY,\n name VARCHAR(255) NOT NULL,\n description TEXT NOT NULL,\n license VARCHAR(255),\n compatibility VARCHAR(255),\n metadata JSONB DEFAULT '{}',\n content TEXT,\n sub_skills JSONB DEFAULT '[]',\n created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP\n )\n `);\n\n // Create indexes for better query performance\n await client.query(`\n CREATE INDEX IF NOT EXISTS idx_lattice_skills_name \n ON lattice_skills(name)\n `);\n\n await client.query(`\n CREATE INDEX IF NOT EXISTS idx_lattice_skills_license \n ON lattice_skills(license)\n `);\n\n await client.query(`\n CREATE INDEX IF NOT EXISTS idx_lattice_skills_compatibility \n ON lattice_skills(compatibility)\n `);\n\n await client.query(`\n CREATE INDEX IF NOT EXISTS idx_lattice_skills_created_at \n ON lattice_skills(created_at DESC)\n `);\n\n // Create GIN index for metadata JSONB queries\n await client.query(`\n CREATE INDEX IF NOT EXISTS idx_lattice_skills_metadata \n ON lattice_skills USING GIN (metadata)\n `);\n },\n down: async (client: PoolClient) => {\n await client.query(\"DROP INDEX IF EXISTS idx_lattice_skills_metadata\");\n await client.query(\"DROP INDEX IF EXISTS idx_lattice_skills_created_at\");\n await client.query(\"DROP INDEX IF EXISTS idx_lattice_skills_compatibility\");\n await client.query(\"DROP INDEX IF EXISTS idx_lattice_skills_license\");\n await client.query(\"DROP INDEX IF EXISTS idx_lattice_skills_name\");\n await client.query(\"DROP TABLE IF EXISTS lattice_skills\");\n },\n};\n"],"mappings":"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","names":["Pool","Pool","Pool","Pool","Pool","Pool"]}
1
+ {"version":3,"sources":["../src/stores/PostgreSQLThreadStore.ts","../src/migrations/migration.ts","../src/migrations/thread_migrations.ts","../src/stores/PostgreSQLAssistantStore.ts","../src/migrations/assistant_migrations.ts","../src/stores/PostgreSQLScheduleStorage.ts","../src/migrations/schedule_migrations.ts","../src/stores/PostgreSQLSkillStore.ts","../src/migrations/skill_migrations.ts","../src/stores/PostgreSQLDatabaseConfigStore.ts","../src/migrations/database_config_migrations.ts","../src/stores/PostgreSQLWorkspaceStore.ts","../src/migrations/workspace_migrations.ts","../src/stores/PostgreSQLProjectStore.ts","../src/migrations/project_migrations.ts"],"sourcesContent":["/**\n * PostgreSQL implementation of ThreadStore\n */\n\nimport { Pool, PoolClient, PoolConfig } from \"pg\";\nimport {\n ThreadStore,\n Thread,\n CreateThreadRequest,\n} from \"@axiom-lattice/protocols\";\nimport { MigrationManager } from \"../migrations/migration\";\nimport { createThreadsTable } from \"../migrations/thread_migrations\";\n\n/**\n * PostgreSQL ThreadStore options\n */\nexport interface PostgreSQLThreadStoreOptions {\n /**\n * PostgreSQL connection pool configuration\n * Can be a connection string or PoolConfig object\n */\n poolConfig: string | PoolConfig;\n\n /**\n * Whether to run migrations automatically on initialization\n * @default true\n */\n autoMigrate?: boolean;\n}\n\n/**\n * PostgreSQL implementation of ThreadStore\n */\nexport class PostgreSQLThreadStore implements ThreadStore {\n private pool: Pool;\n private migrationManager: MigrationManager;\n private initialized: boolean = false;\n private ownsPool: boolean = true;\n private initPromise: Promise<void> | null = null; // Promise-based lock to prevent concurrent initialization\n\n constructor(options: PostgreSQLThreadStoreOptions) {\n // Create Pool from config\n if (typeof options.poolConfig === \"string\") {\n this.pool = new Pool({ connectionString: options.poolConfig });\n } else {\n this.pool = new Pool(options.poolConfig);\n }\n\n this.migrationManager = new MigrationManager(this.pool);\n this.migrationManager.register(createThreadsTable);\n\n // Auto-migrate by default\n if (options.autoMigrate !== false) {\n this.initialize().catch((error) => {\n console.error(\"Failed to initialize PostgreSQLThreadStore:\", error);\n throw error;\n });\n }\n }\n\n /**\n * Dispose resources and close the connection pool\n * Should be called when the store is no longer needed\n */\n async dispose(): Promise<void> {\n if (this.ownsPool && this.pool) {\n await this.pool.end();\n }\n }\n\n /**\n * Initialize the store and run migrations\n * Uses a promise-based lock to prevent concurrent initialization\n */\n async initialize(): Promise<void> {\n // If already initialized, return immediately\n if (this.initialized) {\n return;\n }\n\n // If initialization is in progress, wait for it\n if (this.initPromise) {\n return this.initPromise;\n }\n\n // Start initialization and store the promise\n this.initPromise = (async () => {\n try {\n await this.migrationManager.migrate();\n this.initialized = true;\n } finally {\n // Clear the promise after completion (success or failure)\n this.initPromise = null;\n }\n })();\n\n return this.initPromise;\n }\n\n /**\n * Get all threads for a specific assistant\n */\n async getThreadsByAssistantId(assistantId: string): Promise<Thread[]> {\n await this.ensureInitialized();\n\n const result = await this.pool.query<{\n id: string;\n assistant_id: string;\n metadata: any;\n created_at: Date;\n updated_at: Date;\n }>(\n `\n SELECT id, assistant_id, metadata, created_at, updated_at\n FROM lattice_threads\n WHERE assistant_id = $1\n ORDER BY created_at DESC\n `,\n [assistantId]\n );\n\n return result.rows.map(this.mapRowToThread);\n }\n\n /**\n * Get a thread by ID for a specific assistant\n */\n async getThreadById(\n assistantId: string,\n threadId: string\n ): Promise<Thread | undefined> {\n await this.ensureInitialized();\n\n const result = await this.pool.query<{\n id: string;\n assistant_id: string;\n metadata: any;\n created_at: Date;\n updated_at: Date;\n }>(\n `\n SELECT id, assistant_id, metadata, created_at, updated_at\n FROM lattice_threads\n WHERE id = $1 AND assistant_id = $2\n `,\n [threadId, assistantId]\n );\n\n if (result.rows.length === 0) {\n return undefined;\n }\n\n return this.mapRowToThread(result.rows[0]);\n }\n\n /**\n * Create a new thread for an assistant\n */\n async createThread(\n assistantId: string,\n threadId: string,\n data: CreateThreadRequest\n ): Promise<Thread> {\n await this.ensureInitialized();\n\n const now = new Date();\n const metadata = data.metadata || {};\n\n await this.pool.query(\n `\n INSERT INTO lattice_threads (id, assistant_id, metadata, created_at, updated_at)\n VALUES ($1, $2, $3, $4, $5)\n ON CONFLICT (id, assistant_id) DO UPDATE SET\n metadata = EXCLUDED.metadata,\n updated_at = EXCLUDED.updated_at\n `,\n [threadId, assistantId, JSON.stringify(metadata), now, now]\n );\n\n return {\n id: threadId,\n assistantId,\n metadata,\n createdAt: now,\n updatedAt: now,\n };\n }\n\n /**\n * Update an existing thread\n */\n async updateThread(\n assistantId: string,\n threadId: string,\n updates: Partial<CreateThreadRequest>\n ): Promise<Thread | null> {\n await this.ensureInitialized();\n\n // Get existing thread\n const existing = await this.getThreadById(assistantId, threadId);\n if (!existing) {\n return null;\n }\n\n // Merge metadata\n const updatedMetadata = {\n ...existing.metadata,\n ...(updates.metadata || {}),\n };\n\n const now = new Date();\n\n await this.pool.query(\n `\n UPDATE lattice_threads\n SET metadata = $1, updated_at = $2\n WHERE id = $3 AND assistant_id = $4\n `,\n [JSON.stringify(updatedMetadata), now, threadId, assistantId]\n );\n\n return {\n ...existing,\n metadata: updatedMetadata,\n updatedAt: now,\n };\n }\n\n /**\n * Delete a thread by ID\n */\n async deleteThread(assistantId: string, threadId: string): Promise<boolean> {\n await this.ensureInitialized();\n\n const result = await this.pool.query(\n `\n DELETE FROM lattice_threads\n WHERE id = $1 AND assistant_id = $2\n `,\n [threadId, assistantId]\n );\n\n return result.rowCount !== null && result.rowCount > 0;\n }\n\n /**\n * Check if thread exists\n */\n async hasThread(assistantId: string, threadId: string): Promise<boolean> {\n await this.ensureInitialized();\n\n const result = await this.pool.query(\n `\n SELECT 1 FROM lattice_threads\n WHERE id = $1 AND assistant_id = $2\n LIMIT 1\n `,\n [threadId, assistantId]\n );\n\n return result.rows.length > 0;\n }\n\n /**\n * Ensure store is initialized\n */\n private async ensureInitialized(): Promise<void> {\n if (!this.initialized) {\n await this.initialize();\n }\n }\n\n /**\n * Map database row to Thread object\n */\n private mapRowToThread(row: {\n id: string;\n assistant_id: string;\n metadata: any;\n created_at: Date;\n updated_at: Date;\n }): Thread {\n return {\n id: row.id,\n assistantId: row.assistant_id,\n metadata:\n typeof row.metadata === \"string\"\n ? JSON.parse(row.metadata)\n : row.metadata || {},\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n };\n }\n}\n","/**\n * Migration system for database schema management\n */\n\nimport { Pool, PoolClient } from \"pg\";\n\n/**\n * Migration record stored in database\n */\ninterface MigrationRecord {\n version: number;\n name: string;\n applied_at: Date;\n}\n\n/**\n * Migration definition\n */\nexport interface Migration {\n version: number;\n name: string;\n up: (client: PoolClient) => Promise<void>;\n down?: (client: PoolClient) => Promise<void>;\n}\n\n/**\n * Migration manager\n */\nexport class MigrationManager {\n private pool: Pool;\n private migrations: Migration[] = [];\n\n constructor(pool: Pool) {\n this.pool = pool;\n }\n\n /**\n * Register a migration\n */\n register(migration: Migration): void {\n this.migrations.push(migration);\n // Sort migrations by version\n this.migrations.sort((a, b) => a.version - b.version);\n }\n\n /**\n * Initialize migrations table if it doesn't exist\n */\n private async ensureMigrationsTable(client: PoolClient): Promise<void> {\n await client.query(`\n CREATE TABLE IF NOT EXISTS lattice_schema_migrations (\n version INTEGER PRIMARY KEY,\n name VARCHAR(255) NOT NULL,\n applied_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP\n )\n `);\n }\n\n /**\n * Get applied migrations from database\n */\n private async getAppliedMigrations(\n client: PoolClient\n ): Promise<MigrationRecord[]> {\n await client.query(`\n CREATE TABLE IF NOT EXISTS lattice_schema_migrations (\n version INTEGER PRIMARY KEY,\n name VARCHAR(255) NOT NULL,\n applied_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP\n )\n `);\n\n const result = await client.query<MigrationRecord>(\n \"SELECT version, name, applied_at FROM lattice_schema_migrations ORDER BY version\"\n );\n return result.rows;\n }\n\n /**\n * Apply pending migrations\n * Uses PostgreSQL advisory locks to prevent concurrent migrations\n */\n async migrate(): Promise<void> {\n const client = await this.pool.connect();\n try {\n // Use advisory lock to prevent concurrent migrations\n // Lock ID: 123456789 (arbitrary but consistent)\n const lockId = 123456789;\n \n // Acquire advisory lock (blocks until lock is available)\n // This ensures only one migration runs at a time across all instances\n await client.query(\"SELECT pg_advisory_lock($1)\", [lockId]);\n \n try {\n await client.query(\"BEGIN\");\n\n await this.ensureMigrationsTable(client);\n const appliedMigrations = await this.getAppliedMigrations(client);\n const appliedVersions = new Set(appliedMigrations.map((m) => m.version));\n\n // Find pending migrations\n const pendingMigrations = this.migrations.filter(\n (m) => !appliedVersions.has(m.version)\n );\n\n if (pendingMigrations.length === 0) {\n console.log(\"No pending migrations\");\n await client.query(\"COMMIT\");\n return;\n }\n\n // Apply pending migrations\n for (const migration of pendingMigrations) {\n console.log(\n `Applying migration ${migration.version}: ${migration.name}`\n );\n await migration.up(client);\n // Use ON CONFLICT DO NOTHING to handle race conditions gracefully\n await client.query(\n \"INSERT INTO lattice_schema_migrations (version, name) VALUES ($1, $2) ON CONFLICT (version) DO NOTHING\",\n [migration.version, migration.name]\n );\n }\n\n await client.query(\"COMMIT\");\n console.log(`Applied ${pendingMigrations.length} migration(s)`);\n } catch (error) {\n await client.query(\"ROLLBACK\");\n throw error;\n } finally {\n // Release advisory lock\n await client.query(\"SELECT pg_advisory_unlock($1)\", [lockId]);\n }\n } catch (error) {\n throw error;\n } finally {\n client.release();\n }\n }\n\n /**\n * Rollback last migration\n */\n async rollback(): Promise<void> {\n const client = await this.pool.connect();\n try {\n await client.query(\"BEGIN\");\n\n const appliedMigrations = await this.getAppliedMigrations(client);\n if (appliedMigrations.length === 0) {\n console.log(\"No migrations to rollback\");\n await client.query(\"COMMIT\");\n return;\n }\n\n const lastMigration = appliedMigrations[appliedMigrations.length - 1];\n const migration = this.migrations.find(\n (m) => m.version === lastMigration.version\n );\n\n if (!migration || !migration.down) {\n throw new Error(\n `Migration ${lastMigration.version} does not have a down migration`\n );\n }\n\n console.log(\n `Rolling back migration ${lastMigration.version}: ${lastMigration.name}`\n );\n await migration.down(client);\n await client.query(\n \"DELETE FROM lattice_schema_migrations WHERE version = $1\",\n [lastMigration.version]\n );\n\n await client.query(\"COMMIT\");\n console.log(\"Rollback completed\");\n } catch (error) {\n await client.query(\"ROLLBACK\");\n throw error;\n } finally {\n client.release();\n }\n }\n\n /**\n * Get current migration version\n */\n async getCurrentVersion(): Promise<number> {\n const client = await this.pool.connect();\n try {\n const appliedMigrations = await this.getAppliedMigrations(client);\n if (appliedMigrations.length === 0) {\n return 0;\n }\n return Math.max(...appliedMigrations.map((m) => m.version));\n } finally {\n client.release();\n }\n }\n}\n","/**\n * Thread table migrations\n */\n\nimport { PoolClient } from \"pg\";\nimport { Migration } from \"./migration\";\n\n/**\n * Initial migration: Create threads table\n */\nexport const createThreadsTable: Migration = {\n version: 1,\n name: \"create_threads_table\",\n up: async (client: PoolClient) => {\n await client.query(`\n CREATE TABLE IF NOT EXISTS lattice_threads (\n id VARCHAR(255) NOT NULL,\n assistant_id VARCHAR(255) NOT NULL,\n metadata JSONB DEFAULT '{}',\n created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n PRIMARY KEY (id, assistant_id)\n )\n `);\n\n // Create indexes for better query performance\n await client.query(`\n CREATE INDEX IF NOT EXISTS idx_lattice_threads_assistant_id \n ON lattice_threads(assistant_id)\n `);\n\n await client.query(`\n CREATE INDEX IF NOT EXISTS idx_lattice_threads_created_at \n ON lattice_threads(created_at DESC)\n `);\n },\n down: async (client: PoolClient) => {\n await client.query(\"DROP INDEX IF EXISTS idx_lattice_threads_created_at\");\n await client.query(\"DROP INDEX IF EXISTS idx_lattice_threads_assistant_id\");\n await client.query(\"DROP TABLE IF EXISTS lattice_threads\");\n },\n};\n","/**\n * PostgreSQL implementation of AssistantStore\n */\n\nimport { Pool, PoolClient, PoolConfig } from \"pg\";\nimport {\n AssistantStore,\n Assistant,\n CreateAssistantRequest,\n} from \"@axiom-lattice/protocols\";\nimport { MigrationManager } from \"../migrations/migration\";\nimport { createAssistantsTable } from \"../migrations/assistant_migrations\";\n\n/**\n * PostgreSQL AssistantStore options\n */\nexport interface PostgreSQLAssistantStoreOptions {\n /**\n * PostgreSQL connection pool configuration\n * Can be a connection string or PoolConfig object\n */\n poolConfig: string | PoolConfig;\n\n /**\n * Whether to run migrations automatically on initialization\n * @default true\n */\n autoMigrate?: boolean;\n}\n\n/**\n * PostgreSQL implementation of AssistantStore\n */\nexport class PostgreSQLAssistantStore implements AssistantStore {\n private pool: Pool;\n private migrationManager: MigrationManager;\n private initialized: boolean = false;\n private ownsPool: boolean = true;\n\n constructor(options: PostgreSQLAssistantStoreOptions) {\n // Create Pool from config\n if (typeof options.poolConfig === \"string\") {\n this.pool = new Pool({ connectionString: options.poolConfig });\n } else {\n this.pool = new Pool(options.poolConfig);\n }\n\n this.migrationManager = new MigrationManager(this.pool);\n this.migrationManager.register(createAssistantsTable);\n\n // Auto-migrate by default\n if (options.autoMigrate !== false) {\n this.initialize().catch((error) => {\n console.error(\"Failed to initialize PostgreSQLAssistantStore:\", error);\n throw error;\n });\n }\n }\n\n /**\n * Initialize the store and run migrations\n */\n async initialize(): Promise<void> {\n if (this.initialized) {\n return;\n }\n\n await this.migrationManager.migrate();\n this.initialized = true;\n }\n\n /**\n * Get all assistants\n */\n async getAllAssistants(): Promise<Assistant[]> {\n await this.ensureInitialized();\n\n const result = await this.pool.query<{\n id: string;\n name: string;\n description: string | null;\n graph_definition: any;\n created_at: Date;\n updated_at: Date;\n }>(\n `\n SELECT id, name, description, graph_definition, created_at, updated_at\n FROM lattice_assistants\n ORDER BY created_at DESC\n `\n );\n\n return result.rows.map(this.mapRowToAssistant);\n }\n\n /**\n * Get assistant by ID\n */\n async getAssistantById(id: string): Promise<Assistant | null> {\n await this.ensureInitialized();\n\n const result = await this.pool.query<{\n id: string;\n name: string;\n description: string | null;\n graph_definition: any;\n created_at: Date;\n updated_at: Date;\n }>(\n `\n SELECT id, name, description, graph_definition, created_at, updated_at\n FROM lattice_assistants\n WHERE id = $1\n `,\n [id]\n );\n\n if (result.rows.length === 0) {\n return null;\n }\n\n return this.mapRowToAssistant(result.rows[0]);\n }\n\n /**\n * Create a new assistant\n */\n async createAssistant(\n id: string,\n data: CreateAssistantRequest\n ): Promise<Assistant> {\n await this.ensureInitialized();\n\n const now = new Date();\n\n await this.pool.query(\n `\n INSERT INTO lattice_assistants (id, name, description, graph_definition, created_at, updated_at)\n VALUES ($1, $2, $3, $4, $5, $6)\n ON CONFLICT (id) DO UPDATE SET\n name = EXCLUDED.name,\n description = EXCLUDED.description,\n graph_definition = EXCLUDED.graph_definition,\n updated_at = EXCLUDED.updated_at\n `,\n [\n id,\n data.name,\n data.description || null,\n JSON.stringify(data.graphDefinition),\n now,\n now,\n ]\n );\n\n return {\n id,\n name: data.name,\n description: data.description,\n graphDefinition: data.graphDefinition,\n createdAt: now,\n updatedAt: now,\n };\n }\n\n /**\n * Update an existing assistant\n */\n async updateAssistant(\n id: string,\n updates: Partial<CreateAssistantRequest>\n ): Promise<Assistant | null> {\n await this.ensureInitialized();\n\n // Get existing assistant\n const existing = await this.getAssistantById(id);\n if (!existing) {\n return null;\n }\n\n // Build update query dynamically based on provided fields\n const updateFields: string[] = [];\n const updateValues: any[] = [];\n let paramIndex = 1;\n\n if (updates.name !== undefined) {\n updateFields.push(`name = $${paramIndex++}`);\n updateValues.push(updates.name);\n }\n\n if (updates.description !== undefined) {\n updateFields.push(`description = $${paramIndex++}`);\n updateValues.push(updates.description || null);\n }\n\n if (updates.graphDefinition !== undefined) {\n updateFields.push(`graph_definition = $${paramIndex++}`);\n updateValues.push(JSON.stringify(updates.graphDefinition));\n }\n\n if (updateFields.length === 0) {\n // No fields to update\n return existing;\n }\n\n // Always update updated_at\n updateFields.push(`updated_at = $${paramIndex++}`);\n updateValues.push(new Date());\n\n // Add id for WHERE clause\n updateValues.push(id);\n\n await this.pool.query(\n `\n UPDATE lattice_assistants\n SET ${updateFields.join(\", \")}\n WHERE id = $${paramIndex}\n `,\n updateValues\n );\n\n // Return updated assistant\n return await this.getAssistantById(id);\n }\n\n /**\n * Delete an assistant by ID\n */\n async deleteAssistant(id: string): Promise<boolean> {\n await this.ensureInitialized();\n\n const result = await this.pool.query(\n `\n DELETE FROM lattice_assistants\n WHERE id = $1\n `,\n [id]\n );\n\n return result.rowCount !== null && result.rowCount > 0;\n }\n\n /**\n * Check if assistant exists\n */\n async hasAssistant(id: string): Promise<boolean> {\n await this.ensureInitialized();\n\n const result = await this.pool.query(\n `\n SELECT 1 FROM lattice_assistants\n WHERE id = $1\n LIMIT 1\n `,\n [id]\n );\n\n return result.rows.length > 0;\n }\n\n /**\n * Dispose resources and close the connection pool\n * Should be called when the store is no longer needed\n */\n async dispose(): Promise<void> {\n if (this.ownsPool && this.pool) {\n await this.pool.end();\n }\n }\n\n /**\n * Ensure store is initialized\n */\n private async ensureInitialized(): Promise<void> {\n if (!this.initialized) {\n await this.initialize();\n }\n }\n\n /**\n * Map database row to Assistant object\n */\n private mapRowToAssistant(row: {\n id: string;\n name: string;\n description: string | null;\n graph_definition: any;\n created_at: Date;\n updated_at: Date;\n }): Assistant {\n return {\n id: row.id,\n name: row.name,\n description: row.description || undefined,\n graphDefinition:\n typeof row.graph_definition === \"string\"\n ? JSON.parse(row.graph_definition)\n : row.graph_definition,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n };\n }\n}\n","/**\n * Assistant table migrations\n */\n\nimport { PoolClient } from \"pg\";\nimport { Migration } from \"./migration\";\n\n/**\n * Initial migration: Create assistants table\n */\nexport const createAssistantsTable: Migration = {\n version: 3,\n name: \"create_assistants_table\",\n up: async (client: PoolClient) => {\n await client.query(`\n CREATE TABLE IF NOT EXISTS lattice_assistants (\n id VARCHAR(255) PRIMARY KEY,\n name VARCHAR(255) NOT NULL,\n description TEXT,\n graph_definition JSONB NOT NULL,\n created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP\n )\n `);\n\n // Create indexes for better query performance\n await client.query(`\n CREATE INDEX IF NOT EXISTS idx_lattice_assistants_name \n ON lattice_assistants(name)\n `);\n\n await client.query(`\n CREATE INDEX IF NOT EXISTS idx_lattice_assistants_created_at \n ON lattice_assistants(created_at DESC)\n `);\n },\n down: async (client: PoolClient) => {\n await client.query(\n \"DROP INDEX IF EXISTS idx_lattice_assistants_created_at\"\n );\n await client.query(\"DROP INDEX IF EXISTS idx_lattice_assistants_name\");\n await client.query(\"DROP TABLE IF EXISTS lattice_assistants\");\n },\n};\n","/**\n * PostgreSQL implementation of ScheduleStorage\n *\n * Provides persistent storage for scheduled tasks\n * Data survives service restarts\n */\n\nimport { Pool, PoolConfig } from \"pg\";\nimport {\n ScheduleStorage,\n ScheduledTaskDefinition,\n ScheduledTaskStatus,\n ScheduleExecutionType,\n} from \"@axiom-lattice/protocols\";\nimport { MigrationManager } from \"../migrations/migration\";\nimport { createScheduledTasksTable } from \"../migrations/schedule_migrations\";\n\n/**\n * PostgreSQL ScheduleStorage options\n */\nexport interface PostgreSQLScheduleStorageOptions {\n /**\n * PostgreSQL connection pool configuration\n * Can be a connection string or PoolConfig object\n */\n poolConfig: string | PoolConfig;\n\n /**\n * Whether to run migrations automatically on initialization\n * @default true\n */\n autoMigrate?: boolean;\n}\n\n/**\n * Database row type for scheduled tasks\n */\ninterface ScheduledTaskRow {\n task_id: string;\n task_type: string;\n payload: string | Record<string, any>;\n assistant_id: string | null;\n thread_id: string | null;\n execution_type: string;\n execute_at: Date | null;\n delay_ms: number | null;\n cron_expression: string | null;\n timezone: string | null;\n next_run_at: Date | null;\n last_run_at: Date | null;\n status: string;\n run_count: number;\n max_runs: number | null;\n retry_count: number;\n max_retries: number;\n last_error: string | null;\n created_at: Date;\n updated_at: Date;\n expires_at: Date | null;\n metadata: string | Record<string, any> | null;\n}\n\n/**\n * PostgreSQL implementation of ScheduleStorage\n */\nexport class PostgreSQLScheduleStorage implements ScheduleStorage {\n private pool: Pool;\n private migrationManager: MigrationManager;\n private initialized: boolean = false;\n\n constructor(options: PostgreSQLScheduleStorageOptions) {\n // Create Pool from config\n if (typeof options.poolConfig === \"string\") {\n this.pool = new Pool({ connectionString: options.poolConfig });\n } else {\n this.pool = new Pool(options.poolConfig);\n }\n\n this.migrationManager = new MigrationManager(this.pool);\n this.migrationManager.register(createScheduledTasksTable);\n\n // Auto-migrate by default\n if (options.autoMigrate !== false) {\n this.initialize().catch((error) => {\n console.error(\"Failed to initialize PostgreSQLScheduleStorage:\", error);\n throw error;\n });\n }\n }\n\n /**\n * Dispose resources and close the connection pool\n */\n async dispose(): Promise<void> {\n if (this.pool) {\n await this.pool.end();\n }\n }\n\n /**\n * Initialize the store and run migrations\n */\n async initialize(): Promise<void> {\n if (this.initialized) {\n return;\n }\n\n await this.migrationManager.migrate();\n this.initialized = true;\n }\n\n /**\n * Ensure store is initialized\n */\n private async ensureInitialized(): Promise<void> {\n if (!this.initialized) {\n await this.initialize();\n }\n }\n\n /**\n * Save a new task\n */\n async save(task: ScheduledTaskDefinition): Promise<void> {\n await this.ensureInitialized();\n\n await this.pool.query(\n `\n INSERT INTO lattice_scheduled_tasks (\n task_id, task_type, payload, assistant_id, thread_id, execution_type,\n execute_at, delay_ms, cron_expression, timezone,\n next_run_at, last_run_at, status, run_count, max_runs,\n retry_count, max_retries, last_error,\n created_at, updated_at, expires_at, metadata\n ) VALUES (\n $1, $2, $3, $4, $5, $6,\n $7, $8, $9, $10,\n $11, $12, $13, $14, $15,\n $16, $17, $18,\n $19, $20, $21, $22\n )\n ON CONFLICT (task_id) DO UPDATE SET\n task_type = EXCLUDED.task_type,\n payload = EXCLUDED.payload,\n assistant_id = EXCLUDED.assistant_id,\n thread_id = EXCLUDED.thread_id,\n execution_type = EXCLUDED.execution_type,\n execute_at = EXCLUDED.execute_at,\n delay_ms = EXCLUDED.delay_ms,\n cron_expression = EXCLUDED.cron_expression,\n timezone = EXCLUDED.timezone,\n next_run_at = EXCLUDED.next_run_at,\n last_run_at = EXCLUDED.last_run_at,\n status = EXCLUDED.status,\n run_count = EXCLUDED.run_count,\n max_runs = EXCLUDED.max_runs,\n retry_count = EXCLUDED.retry_count,\n max_retries = EXCLUDED.max_retries,\n last_error = EXCLUDED.last_error,\n updated_at = EXCLUDED.updated_at,\n expires_at = EXCLUDED.expires_at,\n metadata = EXCLUDED.metadata\n `,\n [\n task.taskId,\n task.taskType,\n JSON.stringify(task.payload),\n task.assistantId ?? null,\n task.threadId ?? null,\n task.executionType,\n task.executeAt ? new Date(task.executeAt) : null,\n task.delayMs ?? null,\n task.cronExpression ?? null,\n task.timezone ?? null,\n task.nextRunAt ? new Date(task.nextRunAt) : null,\n task.lastRunAt ? new Date(task.lastRunAt) : null,\n task.status,\n task.runCount,\n task.maxRuns ?? null,\n task.retryCount,\n task.maxRetries,\n task.lastError ?? null,\n new Date(task.createdAt),\n new Date(task.updatedAt),\n task.expiresAt ? new Date(task.expiresAt) : null,\n task.metadata ? JSON.stringify(task.metadata) : null,\n ]\n );\n }\n\n /**\n * Get task by ID\n */\n async get(taskId: string): Promise<ScheduledTaskDefinition | null> {\n await this.ensureInitialized();\n\n const result = await this.pool.query<ScheduledTaskRow>(\n `SELECT * FROM lattice_scheduled_tasks WHERE task_id = $1`,\n [taskId]\n );\n\n if (result.rows.length === 0) {\n return null;\n }\n\n return this.mapRowToTask(result.rows[0]);\n }\n\n /**\n * Update task\n */\n async update(\n taskId: string,\n updates: Partial<ScheduledTaskDefinition>\n ): Promise<void> {\n await this.ensureInitialized();\n\n const setClauses: string[] = [];\n const values: any[] = [];\n let paramIndex = 1;\n\n // Build dynamic UPDATE query\n if (updates.taskType !== undefined) {\n setClauses.push(`task_type = $${paramIndex++}`);\n values.push(updates.taskType);\n }\n if (updates.payload !== undefined) {\n setClauses.push(`payload = $${paramIndex++}`);\n values.push(JSON.stringify(updates.payload));\n }\n if (updates.assistantId !== undefined) {\n setClauses.push(`assistant_id = $${paramIndex++}`);\n values.push(updates.assistantId);\n }\n if (updates.threadId !== undefined) {\n setClauses.push(`thread_id = $${paramIndex++}`);\n values.push(updates.threadId);\n }\n if (updates.executionType !== undefined) {\n setClauses.push(`execution_type = $${paramIndex++}`);\n values.push(updates.executionType);\n }\n if (updates.executeAt !== undefined) {\n setClauses.push(`execute_at = $${paramIndex++}`);\n values.push(updates.executeAt ? new Date(updates.executeAt) : null);\n }\n if (updates.delayMs !== undefined) {\n setClauses.push(`delay_ms = $${paramIndex++}`);\n values.push(updates.delayMs);\n }\n if (updates.cronExpression !== undefined) {\n setClauses.push(`cron_expression = $${paramIndex++}`);\n values.push(updates.cronExpression);\n }\n if (updates.timezone !== undefined) {\n setClauses.push(`timezone = $${paramIndex++}`);\n values.push(updates.timezone);\n }\n if (updates.nextRunAt !== undefined) {\n setClauses.push(`next_run_at = $${paramIndex++}`);\n values.push(updates.nextRunAt ? new Date(updates.nextRunAt) : null);\n }\n if (updates.lastRunAt !== undefined) {\n setClauses.push(`last_run_at = $${paramIndex++}`);\n values.push(updates.lastRunAt ? new Date(updates.lastRunAt) : null);\n }\n if (updates.status !== undefined) {\n setClauses.push(`status = $${paramIndex++}`);\n values.push(updates.status);\n }\n if (updates.runCount !== undefined) {\n setClauses.push(`run_count = $${paramIndex++}`);\n values.push(updates.runCount);\n }\n if (updates.maxRuns !== undefined) {\n setClauses.push(`max_runs = $${paramIndex++}`);\n values.push(updates.maxRuns);\n }\n if (updates.retryCount !== undefined) {\n setClauses.push(`retry_count = $${paramIndex++}`);\n values.push(updates.retryCount);\n }\n if (updates.maxRetries !== undefined) {\n setClauses.push(`max_retries = $${paramIndex++}`);\n values.push(updates.maxRetries);\n }\n if (updates.lastError !== undefined) {\n setClauses.push(`last_error = $${paramIndex++}`);\n values.push(updates.lastError);\n }\n if (updates.expiresAt !== undefined) {\n setClauses.push(`expires_at = $${paramIndex++}`);\n values.push(updates.expiresAt ? new Date(updates.expiresAt) : null);\n }\n if (updates.metadata !== undefined) {\n setClauses.push(`metadata = $${paramIndex++}`);\n values.push(updates.metadata ? JSON.stringify(updates.metadata) : null);\n }\n\n // Always update updated_at\n setClauses.push(`updated_at = $${paramIndex++}`);\n values.push(new Date());\n\n // Add taskId as the last parameter\n values.push(taskId);\n\n if (setClauses.length === 0) {\n return;\n }\n\n await this.pool.query(\n `UPDATE lattice_scheduled_tasks SET ${setClauses.join(\n \", \"\n )} WHERE task_id = $${paramIndex}`,\n values\n );\n }\n\n /**\n * Delete task\n */\n async delete(taskId: string): Promise<void> {\n await this.ensureInitialized();\n\n await this.pool.query(\n `DELETE FROM lattice_scheduled_tasks WHERE task_id = $1`,\n [taskId]\n );\n }\n\n /**\n * Get all active tasks (pending or paused)\n */\n async getActiveTasks(): Promise<ScheduledTaskDefinition[]> {\n await this.ensureInitialized();\n\n const result = await this.pool.query<ScheduledTaskRow>(\n `SELECT * FROM lattice_scheduled_tasks WHERE status IN ($1, $2) ORDER BY created_at ASC`,\n [ScheduledTaskStatus.PENDING, ScheduledTaskStatus.PAUSED]\n );\n\n return result.rows.map((row) => this.mapRowToTask(row));\n }\n\n /**\n * Get tasks by type\n */\n async getTasksByType(taskType: string): Promise<ScheduledTaskDefinition[]> {\n await this.ensureInitialized();\n\n const result = await this.pool.query<ScheduledTaskRow>(\n `SELECT * FROM lattice_scheduled_tasks WHERE task_type = $1 ORDER BY created_at DESC`,\n [taskType]\n );\n\n return result.rows.map((row) => this.mapRowToTask(row));\n }\n\n /**\n * Get tasks by status\n */\n async getTasksByStatus(\n status: ScheduledTaskStatus\n ): Promise<ScheduledTaskDefinition[]> {\n await this.ensureInitialized();\n\n const result = await this.pool.query<ScheduledTaskRow>(\n `SELECT * FROM lattice_scheduled_tasks WHERE status = $1 ORDER BY created_at DESC`,\n [status]\n );\n\n return result.rows.map((row) => this.mapRowToTask(row));\n }\n\n /**\n * Get tasks by execution type\n */\n async getTasksByExecutionType(\n executionType: ScheduleExecutionType\n ): Promise<ScheduledTaskDefinition[]> {\n await this.ensureInitialized();\n\n const result = await this.pool.query<ScheduledTaskRow>(\n `SELECT * FROM lattice_scheduled_tasks WHERE execution_type = $1 ORDER BY created_at DESC`,\n [executionType]\n );\n\n return result.rows.map((row) => this.mapRowToTask(row));\n }\n\n /**\n * Get tasks by assistant ID\n */\n async getTasksByAssistantId(\n assistantId: string\n ): Promise<ScheduledTaskDefinition[]> {\n await this.ensureInitialized();\n\n const result = await this.pool.query<ScheduledTaskRow>(\n `SELECT * FROM lattice_scheduled_tasks WHERE assistant_id = $1 ORDER BY created_at DESC`,\n [assistantId]\n );\n\n return result.rows.map((row) => this.mapRowToTask(row));\n }\n\n /**\n * Get tasks by thread ID\n */\n async getTasksByThreadId(\n threadId: string\n ): Promise<ScheduledTaskDefinition[]> {\n await this.ensureInitialized();\n\n const result = await this.pool.query<ScheduledTaskRow>(\n `SELECT * FROM lattice_scheduled_tasks WHERE thread_id = $1 ORDER BY created_at DESC`,\n [threadId]\n );\n\n return result.rows.map((row) => this.mapRowToTask(row));\n }\n\n /**\n * Get all tasks with optional filters\n */\n async getAllTasks(filters?: {\n status?: ScheduledTaskStatus;\n executionType?: ScheduleExecutionType;\n taskType?: string;\n assistantId?: string;\n threadId?: string;\n limit?: number;\n offset?: number;\n }): Promise<ScheduledTaskDefinition[]> {\n await this.ensureInitialized();\n\n const whereClauses: string[] = [];\n const values: any[] = [];\n let paramIndex = 1;\n\n if (filters?.status !== undefined) {\n whereClauses.push(`status = $${paramIndex++}`);\n values.push(filters.status);\n }\n if (filters?.executionType !== undefined) {\n whereClauses.push(`execution_type = $${paramIndex++}`);\n values.push(filters.executionType);\n }\n if (filters?.taskType !== undefined) {\n whereClauses.push(`task_type = $${paramIndex++}`);\n values.push(filters.taskType);\n }\n if (filters?.assistantId !== undefined) {\n whereClauses.push(`assistant_id = $${paramIndex++}`);\n values.push(filters.assistantId);\n }\n if (filters?.threadId !== undefined) {\n whereClauses.push(`thread_id = $${paramIndex++}`);\n values.push(filters.threadId);\n }\n\n let query = `SELECT * FROM lattice_scheduled_tasks`;\n if (whereClauses.length > 0) {\n query += ` WHERE ${whereClauses.join(\" AND \")}`;\n }\n query += ` ORDER BY created_at DESC`;\n\n if (filters?.limit !== undefined) {\n query += ` LIMIT $${paramIndex++}`;\n values.push(filters.limit);\n }\n if (filters?.offset !== undefined) {\n query += ` OFFSET $${paramIndex++}`;\n values.push(filters.offset);\n }\n\n const result = await this.pool.query<ScheduledTaskRow>(query, values);\n\n return result.rows.map((row) => this.mapRowToTask(row));\n }\n\n /**\n * Count tasks with optional filters\n */\n async countTasks(filters?: {\n status?: ScheduledTaskStatus;\n executionType?: ScheduleExecutionType;\n taskType?: string;\n assistantId?: string;\n threadId?: string;\n }): Promise<number> {\n await this.ensureInitialized();\n\n const whereClauses: string[] = [];\n const values: any[] = [];\n let paramIndex = 1;\n\n if (filters?.status !== undefined) {\n whereClauses.push(`status = $${paramIndex++}`);\n values.push(filters.status);\n }\n if (filters?.executionType !== undefined) {\n whereClauses.push(`execution_type = $${paramIndex++}`);\n values.push(filters.executionType);\n }\n if (filters?.taskType !== undefined) {\n whereClauses.push(`task_type = $${paramIndex++}`);\n values.push(filters.taskType);\n }\n if (filters?.assistantId !== undefined) {\n whereClauses.push(`assistant_id = $${paramIndex++}`);\n values.push(filters.assistantId);\n }\n if (filters?.threadId !== undefined) {\n whereClauses.push(`thread_id = $${paramIndex++}`);\n values.push(filters.threadId);\n }\n\n let query = `SELECT COUNT(*) as count FROM lattice_scheduled_tasks`;\n if (whereClauses.length > 0) {\n query += ` WHERE ${whereClauses.join(\" AND \")}`;\n }\n\n const result = await this.pool.query<{ count: string }>(query, values);\n\n return parseInt(result.rows[0].count, 10);\n }\n\n /**\n * Delete completed/cancelled/failed tasks older than specified time\n */\n async deleteOldTasks(olderThanMs: number): Promise<number> {\n await this.ensureInitialized();\n\n const cutoff = new Date(Date.now() - olderThanMs);\n\n const result = await this.pool.query(\n `\n DELETE FROM lattice_scheduled_tasks \n WHERE status IN ($1, $2, $3) \n AND updated_at < $4\n `,\n [\n ScheduledTaskStatus.COMPLETED,\n ScheduledTaskStatus.CANCELLED,\n ScheduledTaskStatus.FAILED,\n cutoff,\n ]\n );\n\n return result.rowCount ?? 0;\n }\n\n /**\n * Map database row to ScheduledTaskDefinition\n */\n private mapRowToTask(row: ScheduledTaskRow): ScheduledTaskDefinition {\n return {\n taskId: row.task_id,\n taskType: row.task_type,\n payload:\n typeof row.payload === \"string\"\n ? JSON.parse(row.payload)\n : row.payload || {},\n assistantId: row.assistant_id ?? undefined,\n threadId: row.thread_id ?? undefined,\n executionType: row.execution_type as ScheduleExecutionType,\n executeAt: row.execute_at ? row.execute_at.getTime() : undefined,\n delayMs: row.delay_ms ?? undefined,\n cronExpression: row.cron_expression ?? undefined,\n timezone: row.timezone ?? undefined,\n nextRunAt: row.next_run_at ? row.next_run_at.getTime() : undefined,\n lastRunAt: row.last_run_at ? row.last_run_at.getTime() : undefined,\n status: row.status as ScheduledTaskStatus,\n runCount: row.run_count,\n maxRuns: row.max_runs ?? undefined,\n retryCount: row.retry_count,\n maxRetries: row.max_retries,\n lastError: row.last_error ?? undefined,\n createdAt: row.created_at.getTime(),\n updatedAt: row.updated_at.getTime(),\n expiresAt: row.expires_at ? row.expires_at.getTime() : undefined,\n metadata:\n row.metadata === null\n ? undefined\n : typeof row.metadata === \"string\"\n ? JSON.parse(row.metadata)\n : row.metadata,\n };\n }\n}\n","/**\n * PostgreSQL migrations for scheduled tasks table\n */\n\nimport { Migration } from \"./migration\";\n\n/**\n * Create the scheduled_tasks table\n */\nexport const createScheduledTasksTable: Migration = {\n name: \"create_scheduled_tasks_table\",\n version: 2,\n\n up: async (client) => {\n await client.query(`\n CREATE TABLE IF NOT EXISTS lattice_scheduled_tasks (\n -- Primary key\n task_id VARCHAR(255) PRIMARY KEY,\n \n -- Task type (maps to handler)\n task_type VARCHAR(255) NOT NULL,\n \n -- Payload (JSON-serializable data)\n payload JSONB NOT NULL DEFAULT '{}',\n \n -- Context fields for querying\n assistant_id VARCHAR(255),\n thread_id VARCHAR(255),\n \n -- Execution type: 'once' or 'cron'\n execution_type VARCHAR(50) NOT NULL,\n \n -- For ONCE type\n execute_at TIMESTAMPTZ,\n delay_ms BIGINT,\n \n -- For CRON type\n cron_expression VARCHAR(255),\n timezone VARCHAR(100),\n next_run_at TIMESTAMPTZ,\n last_run_at TIMESTAMPTZ,\n \n -- Status\n status VARCHAR(50) NOT NULL DEFAULT 'pending',\n \n -- Execution tracking\n run_count INTEGER NOT NULL DEFAULT 0,\n max_runs INTEGER,\n \n -- Error handling\n retry_count INTEGER NOT NULL DEFAULT 0,\n max_retries INTEGER NOT NULL DEFAULT 0,\n last_error TEXT,\n \n -- Timestamps\n created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n expires_at TIMESTAMPTZ,\n \n -- Metadata\n metadata JSONB\n );\n\n -- Index for querying active tasks\n CREATE INDEX IF NOT EXISTS idx_scheduled_tasks_status \n ON lattice_scheduled_tasks (status);\n \n -- Index for querying by task type\n CREATE INDEX IF NOT EXISTS idx_scheduled_tasks_task_type \n ON lattice_scheduled_tasks (task_type);\n \n -- Index for querying by execution type\n CREATE INDEX IF NOT EXISTS idx_scheduled_tasks_execution_type \n ON lattice_scheduled_tasks (execution_type);\n \n -- Index for querying by assistant ID\n CREATE INDEX IF NOT EXISTS idx_scheduled_tasks_assistant_id \n ON lattice_scheduled_tasks (assistant_id)\n WHERE assistant_id IS NOT NULL;\n \n -- Index for querying by thread ID\n CREATE INDEX IF NOT EXISTS idx_scheduled_tasks_thread_id \n ON lattice_scheduled_tasks (thread_id)\n WHERE thread_id IS NOT NULL;\n \n -- Index for querying pending tasks by next run time\n CREATE INDEX IF NOT EXISTS idx_scheduled_tasks_next_run \n ON lattice_scheduled_tasks (next_run_at) \n WHERE status = 'pending';\n \n -- Index for querying pending one-time tasks by execute time\n CREATE INDEX IF NOT EXISTS idx_scheduled_tasks_execute_at \n ON lattice_scheduled_tasks (execute_at) \n WHERE status = 'pending' AND execution_type = 'once';\n \n -- Index for cleanup queries (old completed/cancelled tasks)\n CREATE INDEX IF NOT EXISTS idx_scheduled_tasks_cleanup \n ON lattice_scheduled_tasks (updated_at) \n WHERE status IN ('completed', 'cancelled', 'failed');\n `);\n },\n\n down: async (client) => {\n await client.query(`\n DROP INDEX IF EXISTS idx_scheduled_tasks_cleanup;\n DROP INDEX IF EXISTS idx_scheduled_tasks_execute_at;\n DROP INDEX IF EXISTS idx_scheduled_tasks_next_run;\n DROP INDEX IF EXISTS idx_scheduled_tasks_thread_id;\n DROP INDEX IF EXISTS idx_scheduled_tasks_assistant_id;\n DROP INDEX IF EXISTS idx_scheduled_tasks_execution_type;\n DROP INDEX IF EXISTS idx_scheduled_tasks_task_type;\n DROP INDEX IF EXISTS idx_scheduled_tasks_status;\n DROP TABLE IF EXISTS lattice_scheduled_tasks;\n `);\n },\n};\n","/**\n * PostgreSQL implementation of SkillStore\n */\n\nimport { Pool, PoolConfig } from \"pg\";\nimport {\n SkillStore,\n Skill,\n CreateSkillRequest,\n} from \"@axiom-lattice/protocols\";\nimport { MigrationManager } from \"../migrations/migration\";\nimport { createSkillsTable } from \"../migrations/skill_migrations\";\n\n/**\n * PostgreSQL SkillStore options\n */\nexport interface PostgreSQLSkillStoreOptions {\n /**\n * PostgreSQL connection pool configuration\n * Can be a connection string or PoolConfig object\n */\n poolConfig: string | PoolConfig;\n\n /**\n * Whether to run migrations automatically on initialization\n * @default true\n */\n autoMigrate?: boolean;\n}\n\n/**\n * PostgreSQL implementation of SkillStore\n */\nexport class PostgreSQLSkillStore implements SkillStore {\n private pool: Pool;\n private migrationManager: MigrationManager;\n private initialized: boolean = false;\n private ownsPool: boolean = true;\n\n constructor(options: PostgreSQLSkillStoreOptions) {\n // Create Pool from config\n if (typeof options.poolConfig === \"string\") {\n this.pool = new Pool({ connectionString: options.poolConfig });\n } else {\n this.pool = new Pool(options.poolConfig);\n }\n\n this.migrationManager = new MigrationManager(this.pool);\n this.migrationManager.register(createSkillsTable);\n\n // Auto-migrate by default\n if (options.autoMigrate !== false) {\n this.initialize().catch((error) => {\n console.error(\"Failed to initialize PostgreSQLSkillStore:\", error);\n throw error;\n });\n }\n }\n\n /**\n * Dispose resources and close the connection pool\n * Should be called when the store is no longer needed\n */\n async dispose(): Promise<void> {\n if (this.ownsPool && this.pool) {\n await this.pool.end();\n }\n }\n\n /**\n * Initialize the store and run migrations\n */\n async initialize(): Promise<void> {\n if (this.initialized) {\n return;\n }\n\n await this.migrationManager.migrate();\n this.initialized = true;\n }\n\n /**\n * Ensure store is initialized\n */\n private async ensureInitialized(): Promise<void> {\n if (!this.initialized) {\n await this.initialize();\n }\n }\n\n /**\n * Map database row to Skill object\n */\n private mapRowToSkill(row: {\n id: string;\n name: string;\n description: string;\n license: string | null;\n compatibility: string | null;\n metadata: any;\n content: string | null;\n sub_skills: any;\n created_at: Date;\n updated_at: Date;\n }): Skill {\n return {\n id: row.id,\n name: row.name,\n description: row.description,\n license: row.license || undefined,\n compatibility: row.compatibility || undefined,\n metadata: row.metadata || {},\n content: row.content || undefined,\n subSkills: Array.isArray(row.sub_skills) && row.sub_skills.length > 0 \n ? row.sub_skills \n : undefined,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n };\n }\n\n /**\n * Get all skills\n */\n async getAllSkills(): Promise<Skill[]> {\n await this.ensureInitialized();\n\n const result = await this.pool.query<{\n id: string;\n name: string;\n description: string;\n license: string | null;\n compatibility: string | null;\n metadata: any;\n content: string | null;\n sub_skills: any;\n created_at: Date;\n updated_at: Date;\n }>(\n `\n SELECT id, name, description, license, compatibility, metadata, content, sub_skills, created_at, updated_at\n FROM lattice_skills\n ORDER BY created_at DESC\n `\n );\n\n return result.rows.map(this.mapRowToSkill);\n }\n\n /**\n * Get skill by ID\n */\n async getSkillById(id: string): Promise<Skill | null> {\n await this.ensureInitialized();\n\n const result = await this.pool.query<{\n id: string;\n name: string;\n description: string;\n license: string | null;\n compatibility: string | null;\n metadata: any;\n content: string | null;\n sub_skills: any;\n created_at: Date;\n updated_at: Date;\n }>(\n `\n SELECT id, name, description, license, compatibility, metadata, content, sub_skills, created_at, updated_at\n FROM lattice_skills\n WHERE id = $1\n `,\n [id]\n );\n\n if (result.rows.length === 0) {\n return null;\n }\n\n return this.mapRowToSkill(result.rows[0]);\n }\n\n /**\n * Create a new skill\n */\n async createSkill(id: string, data: CreateSkillRequest): Promise<Skill> {\n await this.ensureInitialized();\n\n const now = new Date();\n const metadata = data.metadata || {};\n\n await this.pool.query(\n `\n INSERT INTO lattice_skills (id, name, description, license, compatibility, metadata, content, sub_skills, created_at, updated_at)\n VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)\n ON CONFLICT (id) DO UPDATE SET\n name = EXCLUDED.name,\n description = EXCLUDED.description,\n license = EXCLUDED.license,\n compatibility = EXCLUDED.compatibility,\n metadata = EXCLUDED.metadata,\n content = EXCLUDED.content,\n sub_skills = EXCLUDED.sub_skills,\n updated_at = EXCLUDED.updated_at\n `,\n [\n id,\n data.name,\n data.description,\n data.license || null,\n data.compatibility || null,\n JSON.stringify(metadata),\n data.content || null,\n JSON.stringify(data.subSkills || []),\n now,\n now,\n ]\n );\n\n return this.getSkillById(id) as Promise<Skill>;\n }\n\n /**\n * Update an existing skill\n */\n async updateSkill(\n id: string,\n updates: Partial<CreateSkillRequest>\n ): Promise<Skill | null> {\n await this.ensureInitialized();\n\n const updateFields: string[] = [];\n const values: any[] = [];\n let paramIndex = 1;\n\n if (updates.name !== undefined) {\n updateFields.push(`name = $${paramIndex++}`);\n values.push(updates.name);\n }\n\n if (updates.description !== undefined) {\n updateFields.push(`description = $${paramIndex++}`);\n values.push(updates.description);\n }\n\n if (updates.license !== undefined) {\n updateFields.push(`license = $${paramIndex++}`);\n values.push(updates.license || null);\n }\n\n if (updates.compatibility !== undefined) {\n updateFields.push(`compatibility = $${paramIndex++}`);\n values.push(updates.compatibility || null);\n }\n\n if (updates.metadata !== undefined) {\n updateFields.push(`metadata = $${paramIndex++}`);\n values.push(JSON.stringify(updates.metadata || {}));\n }\n\n if (updates.content !== undefined) {\n updateFields.push(`content = $${paramIndex++}`);\n values.push(updates.content || null);\n }\n\n if (updates.subSkills !== undefined) {\n updateFields.push(`sub_skills = $${paramIndex++}`);\n values.push(JSON.stringify(updates.subSkills || []));\n }\n\n if (updateFields.length === 0) {\n return this.getSkillById(id);\n }\n\n updateFields.push(`updated_at = $${paramIndex++}`);\n values.push(new Date());\n values.push(id);\n\n await this.pool.query(\n `\n UPDATE lattice_skills\n SET ${updateFields.join(\", \")}\n WHERE id = $${paramIndex}\n `,\n values\n );\n\n return this.getSkillById(id);\n }\n\n /**\n * Delete a skill by ID\n */\n async deleteSkill(id: string): Promise<boolean> {\n await this.ensureInitialized();\n\n const result = await this.pool.query(\n `\n DELETE FROM lattice_skills\n WHERE id = $1\n `,\n [id]\n );\n\n return result.rowCount !== null && result.rowCount > 0;\n }\n\n /**\n * Check if skill exists\n */\n async hasSkill(id: string): Promise<boolean> {\n await this.ensureInitialized();\n\n const result = await this.pool.query<{ count: string }>(\n `\n SELECT COUNT(*) as count\n FROM lattice_skills\n WHERE id = $1\n `,\n [id]\n );\n\n return parseInt(result.rows[0].count, 10) > 0;\n }\n\n /**\n * Search skills by metadata\n */\n async searchByMetadata(\n metadataKey: string,\n metadataValue: string\n ): Promise<Skill[]> {\n await this.ensureInitialized();\n\n const result = await this.pool.query<{\n id: string;\n name: string;\n description: string;\n license: string | null;\n compatibility: string | null;\n metadata: any;\n content: string | null;\n sub_skills: any;\n created_at: Date;\n updated_at: Date;\n }>(\n `\n SELECT id, name, description, license, compatibility, metadata, content, sub_skills, created_at, updated_at\n FROM lattice_skills\n WHERE metadata->>$1 = $2\n ORDER BY created_at DESC\n `,\n [metadataKey, metadataValue]\n );\n\n return result.rows.map(this.mapRowToSkill);\n }\n\n /**\n * Filter skills by compatibility\n */\n async filterByCompatibility(compatibility: string): Promise<Skill[]> {\n await this.ensureInitialized();\n\n const result = await this.pool.query<{\n id: string;\n name: string;\n description: string;\n license: string | null;\n compatibility: string | null;\n metadata: any;\n content: string | null;\n sub_skills: any;\n created_at: Date;\n updated_at: Date;\n }>(\n `\n SELECT id, name, description, license, compatibility, metadata, content, sub_skills, created_at, updated_at\n FROM lattice_skills\n WHERE compatibility = $1\n ORDER BY created_at DESC\n `,\n [compatibility]\n );\n\n return result.rows.map(this.mapRowToSkill);\n }\n\n /**\n * Filter skills by license\n */\n async filterByLicense(license: string): Promise<Skill[]> {\n await this.ensureInitialized();\n\n const result = await this.pool.query<{\n id: string;\n name: string;\n description: string;\n license: string | null;\n compatibility: string | null;\n metadata: any;\n content: string | null;\n sub_skills: any;\n created_at: Date;\n updated_at: Date;\n }>(\n `\n SELECT id, name, description, license, compatibility, metadata, content, sub_skills, created_at, updated_at\n FROM lattice_skills\n WHERE license = $1\n ORDER BY created_at DESC\n `,\n [license]\n );\n\n return result.rows.map(this.mapRowToSkill);\n }\n\n /**\n * Get sub-skills of a parent skill\n */\n async getSubSkills(parentSkillName: string): Promise<Skill[]> {\n await this.ensureInitialized();\n\n const parentSkill = await this.getSkillById(parentSkillName);\n if (!parentSkill || !parentSkill.subSkills || parentSkill.subSkills.length === 0) {\n return [];\n }\n\n // Query all sub-skills in one query\n const placeholders = parentSkill.subSkills.map((_, index) => `$${index + 1}`).join(\", \");\n const result = await this.pool.query<{\n id: string;\n name: string;\n description: string;\n license: string | null;\n compatibility: string | null;\n metadata: any;\n content: string | null;\n sub_skills: any;\n created_at: Date;\n updated_at: Date;\n }>(\n `\n SELECT id, name, description, license, compatibility, metadata, content, sub_skills, created_at, updated_at\n FROM lattice_skills\n WHERE name IN (${placeholders})\n ORDER BY created_at DESC\n `,\n parentSkill.subSkills\n );\n\n return result.rows.map(this.mapRowToSkill);\n }\n}\n","/**\n * Skill table migrations\n */\n\nimport { PoolClient } from \"pg\";\nimport { Migration } from \"./migration\";\n\n/**\n * Initial migration: Create skills table\n */\nexport const createSkillsTable: Migration = {\n version: 4,\n name: \"create_skills_table\",\n up: async (client: PoolClient) => {\n await client.query(`\n CREATE TABLE IF NOT EXISTS lattice_skills (\n id VARCHAR(255) PRIMARY KEY,\n name VARCHAR(255) NOT NULL,\n description TEXT NOT NULL,\n license VARCHAR(255),\n compatibility VARCHAR(255),\n metadata JSONB DEFAULT '{}',\n content TEXT,\n sub_skills JSONB DEFAULT '[]',\n created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP\n )\n `);\n\n // Create indexes for better query performance\n await client.query(`\n CREATE INDEX IF NOT EXISTS idx_lattice_skills_name \n ON lattice_skills(name)\n `);\n\n await client.query(`\n CREATE INDEX IF NOT EXISTS idx_lattice_skills_license \n ON lattice_skills(license)\n `);\n\n await client.query(`\n CREATE INDEX IF NOT EXISTS idx_lattice_skills_compatibility \n ON lattice_skills(compatibility)\n `);\n\n await client.query(`\n CREATE INDEX IF NOT EXISTS idx_lattice_skills_created_at \n ON lattice_skills(created_at DESC)\n `);\n\n // Create GIN index for metadata JSONB queries\n await client.query(`\n CREATE INDEX IF NOT EXISTS idx_lattice_skills_metadata \n ON lattice_skills USING GIN (metadata)\n `);\n },\n down: async (client: PoolClient) => {\n await client.query(\"DROP INDEX IF EXISTS idx_lattice_skills_metadata\");\n await client.query(\"DROP INDEX IF EXISTS idx_lattice_skills_created_at\");\n await client.query(\"DROP INDEX IF EXISTS idx_lattice_skills_compatibility\");\n await client.query(\"DROP INDEX IF EXISTS idx_lattice_skills_license\");\n await client.query(\"DROP INDEX IF EXISTS idx_lattice_skills_name\");\n await client.query(\"DROP TABLE IF EXISTS lattice_skills\");\n },\n};\n","/**\n * PostgreSQL implementation of DatabaseConfigStore\n */\n\nimport { Pool, PoolClient, PoolConfig } from 'pg';\nimport {\n DatabaseConfigStore,\n DatabaseConfigEntry,\n CreateDatabaseConfigRequest,\n UpdateDatabaseConfigRequest,\n DatabaseConfig,\n} from '@axiom-lattice/protocols';\nimport { MigrationManager } from '../migrations/migration';\nimport { createDatabaseConfigsTable } from '../migrations/database_config_migrations';\nimport { encrypt, decrypt } from '@axiom-lattice/core';\n\n/**\n * PostgreSQL DatabaseConfigStore options\n */\nexport interface PostgreSQLDatabaseConfigStoreOptions {\n /**\n * PostgreSQL connection pool configuration\n * Can be a connection string or PoolConfig object\n */\n poolConfig: string | PoolConfig;\n\n /**\n * Whether to run migrations automatically on initialization\n * @default true\n */\n autoMigrate?: boolean;\n}\n\n/**\n * PostgreSQL implementation of DatabaseConfigStore\n * \n * Features:\n * - Multi-tenant isolation via tenant_id\n * - Automatic password encryption/decryption\n * - Unique constraint on (tenant_id, key)\n */\nexport class PostgreSQLDatabaseConfigStore implements DatabaseConfigStore {\n private pool: Pool;\n private migrationManager: MigrationManager;\n private initialized: boolean = false;\n private initPromise: Promise<void> | null = null;\n\n constructor(options: PostgreSQLDatabaseConfigStoreOptions) {\n // Create Pool from config\n if (typeof options.poolConfig === 'string') {\n this.pool = new Pool({ connectionString: options.poolConfig });\n } else {\n this.pool = new Pool(options.poolConfig);\n }\n\n this.migrationManager = new MigrationManager(this.pool);\n this.migrationManager.register(createDatabaseConfigsTable);\n\n // Auto-migrate by default\n if (options.autoMigrate !== false) {\n this.initialize().catch((error) => {\n console.error('Failed to initialize PostgreSQLDatabaseConfigStore:', error);\n throw error;\n });\n }\n }\n\n /**\n * Initialize the store and run migrations\n * Uses a promise-based lock to prevent concurrent initialization\n */\n async initialize(): Promise<void> {\n if (this.initialized) {\n return;\n }\n\n if (this.initPromise) {\n return this.initPromise;\n }\n\n this.initPromise = (async () => {\n try {\n await this.migrationManager.migrate();\n this.initialized = true;\n } finally {\n this.initPromise = null;\n }\n })();\n\n return this.initPromise;\n }\n\n /**\n * Get all database configurations for a tenant\n */\n async getAllConfigs(tenantId: string): Promise<DatabaseConfigEntry[]> {\n await this.ensureInitialized();\n\n const result = await this.pool.query<{\n id: string;\n tenant_id: string;\n key: string;\n name: string | null;\n description: string | null;\n config: any;\n created_at: Date;\n updated_at: Date;\n }>(\n `\n SELECT id, tenant_id, key, name, description, config, created_at, updated_at\n FROM lattice_database_configs\n WHERE tenant_id = $1\n ORDER BY created_at DESC\n `,\n [tenantId]\n );\n\n return result.rows.map((row) => this.mapRowToEntry(row));\n }\n\n /**\n * Get all database configurations across all tenants\n */\n async getAllConfigsWithoutTenant(): Promise<DatabaseConfigEntry[]> {\n await this.ensureInitialized();\n\n const result = await this.pool.query<{\n id: string;\n tenant_id: string;\n key: string;\n name: string | null;\n description: string | null;\n config: any;\n created_at: Date;\n updated_at: Date;\n }>(\n `\n SELECT id, tenant_id, key, name, description, config, created_at, updated_at\n FROM lattice_database_configs\n ORDER BY created_at DESC\n `\n );\n\n return result.rows.map((row) => this.mapRowToEntry(row));\n }\n\n /**\n * Get database configuration by ID\n */\n async getConfigById(tenantId: string, id: string): Promise<DatabaseConfigEntry | null> {\n await this.ensureInitialized();\n\n const result = await this.pool.query<{\n id: string;\n tenant_id: string;\n key: string;\n name: string | null;\n description: string | null;\n config: any;\n created_at: Date;\n updated_at: Date;\n }>(\n `\n SELECT id, tenant_id, key, name, description, config, created_at, updated_at\n FROM lattice_database_configs\n WHERE tenant_id = $1 AND id = $2\n `,\n [tenantId, id]\n );\n\n if (result.rows.length === 0) {\n return null;\n }\n\n return this.mapRowToEntry(result.rows[0]);\n }\n\n /**\n * Get database configuration by business key\n */\n async getConfigByKey(tenantId: string, key: string): Promise<DatabaseConfigEntry | null> {\n await this.ensureInitialized();\n\n const result = await this.pool.query<{\n id: string;\n tenant_id: string;\n key: string;\n name: string | null;\n description: string | null;\n config: any;\n created_at: Date;\n updated_at: Date;\n }>(\n `\n SELECT id, tenant_id, key, name, description, config, created_at, updated_at\n FROM lattice_database_configs\n WHERE tenant_id = $1 AND key = $2\n `,\n [tenantId, key]\n );\n\n if (result.rows.length === 0) {\n return null;\n }\n\n return this.mapRowToEntry(result.rows[0]);\n }\n\n /**\n * Create a new database configuration\n */\n async createConfig(\n tenantId: string,\n id: string,\n data: CreateDatabaseConfigRequest\n ): Promise<DatabaseConfigEntry> {\n await this.ensureInitialized();\n\n const now = new Date();\n const nowString = now.toISOString();\n const configWithEncryptedPassword = this.encryptPasswordInConfig(data.config);\n\n await this.pool.query(\n `\n INSERT INTO lattice_database_configs (id, tenant_id, key, name, description, config, created_at, updated_at)\n VALUES ($1, $2, $3, $4, $5, $6, $7::timestamp, $8::timestamp)\n ON CONFLICT (tenant_id, id) DO UPDATE SET\n key = EXCLUDED.key,\n name = EXCLUDED.name,\n description = EXCLUDED.description,\n config = EXCLUDED.config,\n updated_at = EXCLUDED.updated_at\n `,\n [\n id,\n tenantId,\n data.key,\n data.name || null,\n data.description || null,\n JSON.stringify(configWithEncryptedPassword),\n nowString,\n nowString,\n ]\n );\n\n return {\n id,\n tenantId,\n key: data.key,\n config: data.config,\n name: data.name,\n description: data.description,\n createdAt: now,\n updatedAt: now,\n };\n }\n\n /**\n * Update an existing database configuration\n */\n async updateConfig(\n tenantId: string,\n id: string,\n updates: Partial<UpdateDatabaseConfigRequest>\n ): Promise<DatabaseConfigEntry | null> {\n await this.ensureInitialized();\n\n const existing = await this.getConfigById(tenantId, id);\n if (!existing) {\n return null;\n }\n\n // Build update fields and values as key-value pairs for clarity\n const updateData: Record<string, any> = {};\n\n if (updates.key !== undefined) {\n updateData.key = updates.key;\n }\n\n if (updates.name !== undefined) {\n updateData.name = updates.name || null;\n }\n\n if (updates.description !== undefined) {\n updateData.description = updates.description || null;\n }\n\n if (updates.config !== undefined) {\n const configWithEncryptedPassword = this.encryptPasswordInConfig(updates.config);\n updateData.config = JSON.stringify(configWithEncryptedPassword);\n }\n\n if (Object.keys(updateData).length === 0) {\n return existing;\n }\n\n // Always update the updated_at timestamp\n updateData.updated_at = new Date().toISOString();\n\n // Build SQL with tenantId and id at fixed positions at the end\n const fields = Object.keys(updateData);\n const values = Object.values(updateData);\n \n // Add WHERE clause values at the end\n values.push(tenantId);\n values.push(id);\n\n // Build SET clause with numbered parameters\n const setClauses = fields.map((field, index) => {\n if (field === 'updated_at') {\n return `${field} = $${index + 1}::timestamp`;\n }\n return `${field} = $${index + 1}`;\n });\n\n // WHERE clause parameters are at the end\n const whereTenantIndex = fields.length + 1;\n const whereIdIndex = fields.length + 2;\n\n const sql = `\n UPDATE lattice_database_configs\n SET ${setClauses.join(', ')}\n WHERE tenant_id = $${whereTenantIndex} AND id = $${whereIdIndex}\n `;\n\n await this.pool.query(sql, values);\n\n return await this.getConfigById(tenantId, id);\n }\n\n /**\n * Delete a database configuration by ID\n */\n async deleteConfig(tenantId: string, id: string): Promise<boolean> {\n await this.ensureInitialized();\n\n const result = await this.pool.query(\n `\n DELETE FROM lattice_database_configs\n WHERE tenant_id = $1 AND id = $2\n `,\n [tenantId, id]\n );\n\n return result.rowCount !== null && result.rowCount > 0;\n }\n\n /**\n * Check if configuration exists\n */\n async hasConfig(tenantId: string, id: string): Promise<boolean> {\n await this.ensureInitialized();\n\n const result = await this.pool.query(\n `\n SELECT 1 FROM lattice_database_configs\n WHERE tenant_id = $1 AND id = $2\n LIMIT 1\n `,\n [tenantId, id]\n );\n\n return result.rows.length > 0;\n }\n\n /**\n * Dispose resources and close the connection pool\n */\n async dispose(): Promise<void> {\n await this.pool.end();\n }\n\n /**\n * Ensure store is initialized\n */\n private async ensureInitialized(): Promise<void> {\n if (!this.initialized) {\n await this.initialize();\n }\n }\n\n /**\n * Map database row to DatabaseConfigEntry object\n * Automatically decrypts password if present\n */\n private mapRowToEntry(row: {\n id: string;\n tenant_id: string;\n key: string;\n name: string | null;\n description: string | null;\n config: any;\n created_at: Date;\n updated_at: Date;\n }): DatabaseConfigEntry {\n const config: DatabaseConfig = typeof row.config === 'string'\n ? JSON.parse(row.config)\n : row.config;\n\n // Decrypt password if present\n if (config.password) {\n try {\n config.password = decrypt(config.password);\n } catch (error) {\n console.error('Failed to decrypt database password:', error);\n throw new Error('Failed to decrypt database configuration');\n }\n }\n\n return {\n id: row.id,\n tenantId: row.tenant_id,\n key: row.key,\n config,\n name: row.name || undefined,\n description: row.description || undefined,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n };\n }\n\n /**\n * Encrypt password in config before storing\n */\n private encryptPasswordInConfig(config: DatabaseConfig): DatabaseConfig {\n const configCopy = { ...config };\n \n if (configCopy.password) {\n configCopy.password = encrypt(configCopy.password);\n }\n \n return configCopy;\n }\n}\n","/**\n * Database configuration table migrations\n */\n\nimport { PoolClient } from 'pg';\nimport { Migration } from './migration';\n\n/**\n * Initial migration: Create database configs table\n */\nexport const createDatabaseConfigsTable: Migration = {\n version: 4,\n name: 'create_database_configs_table',\n up: async (client: PoolClient) => {\n await client.query(`\n CREATE TABLE IF NOT EXISTS lattice_database_configs (\n id VARCHAR(255) NOT NULL,\n tenant_id VARCHAR(255) NOT NULL,\n key VARCHAR(255) NOT NULL,\n name VARCHAR(255),\n description TEXT,\n config JSONB NOT NULL,\n created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n \n PRIMARY KEY (tenant_id, id),\n CONSTRAINT uk_lattice_database_configs_tenant_key UNIQUE (tenant_id, key)\n )\n `);\n\n // Create indexes for better query performance\n await client.query(`\n CREATE INDEX IF NOT EXISTS idx_lattice_database_configs_tenant_id \n ON lattice_database_configs(tenant_id)\n `);\n\n await client.query(`\n CREATE INDEX IF NOT EXISTS idx_lattice_database_configs_key \n ON lattice_database_configs(key)\n `);\n },\n down: async (client: PoolClient) => {\n await client.query('DROP INDEX IF EXISTS idx_lattice_database_configs_key');\n await client.query('DROP INDEX IF EXISTS idx_lattice_database_configs_tenant_id');\n await client.query('DROP TABLE IF EXISTS lattice_database_configs');\n },\n};\n","/**\n * PostgreSQL implementation of WorkspaceStore\n */\n\nimport { Pool, PoolConfig } from \"pg\";\nimport {\n WorkspaceStore,\n Workspace,\n CreateWorkspaceRequest,\n UpdateWorkspaceRequest,\n} from \"@axiom-lattice/protocols\";\nimport { MigrationManager } from \"../migrations/migration\";\nimport { createWorkspacesTable } from \"../migrations/workspace_migrations\";\n\n/**\n * PostgreSQL WorkspaceStore options\n */\nexport interface PostgreSQLWorkspaceStoreOptions {\n /**\n * PostgreSQL connection pool configuration\n * Can be a connection string or PoolConfig object\n */\n poolConfig: string | PoolConfig;\n\n /**\n * Whether to run migrations automatically on initialization\n * @default true\n */\n autoMigrate?: boolean;\n}\n\n/**\n * PostgreSQL implementation of WorkspaceStore\n */\nexport class PostgreSQLWorkspaceStore implements WorkspaceStore {\n private pool: Pool;\n private migrationManager: MigrationManager;\n private initialized: boolean = false;\n private ownsPool: boolean = true;\n\n constructor(options: PostgreSQLWorkspaceStoreOptions) {\n // Create Pool from config\n if (typeof options.poolConfig === \"string\") {\n this.pool = new Pool({ connectionString: options.poolConfig });\n } else {\n this.pool = new Pool(options.poolConfig);\n }\n\n this.migrationManager = new MigrationManager(this.pool);\n this.migrationManager.register(createWorkspacesTable);\n\n // Auto-migrate by default\n if (options.autoMigrate !== false) {\n this.initialize().catch((error) => {\n console.error(\"Failed to initialize PostgreSQLWorkspaceStore:\", error);\n throw error;\n });\n }\n }\n\n /**\n * Dispose resources and close the connection pool\n * Should be called when the store is no longer needed\n */\n async dispose(): Promise<void> {\n if (this.ownsPool && this.pool) {\n await this.pool.end();\n }\n }\n\n /**\n * Initialize the store and run migrations\n */\n async initialize(): Promise<void> {\n if (this.initialized) {\n return;\n }\n\n await this.migrationManager.migrate();\n this.initialized = true;\n }\n\n /**\n * Ensure store is initialized\n */\n private async ensureInitialized(): Promise<void> {\n if (!this.initialized) {\n await this.initialize();\n }\n }\n\n /**\n * Map database row to Workspace object\n */\n private mapRowToWorkspace(row: {\n id: string;\n tenant_id: string;\n name: string;\n description: string | null;\n storage_type: string;\n created_at: Date;\n updated_at: Date;\n }): Workspace {\n return {\n id: row.id,\n tenantId: row.tenant_id,\n name: row.name,\n description: row.description || undefined,\n storageType: row.storage_type as Workspace[\"storageType\"],\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n };\n }\n\n /**\n * Get all workspaces for a tenant\n */\n async getAllWorkspaces(tenantId: string): Promise<Workspace[]> {\n await this.ensureInitialized();\n\n const result = await this.pool.query<{\n id: string;\n tenant_id: string;\n name: string;\n description: string | null;\n storage_type: string;\n created_at: Date;\n updated_at: Date;\n }>(\n `\n SELECT id, tenant_id, name, description, storage_type, created_at, updated_at\n FROM lattice_workspaces\n WHERE tenant_id = $1\n ORDER BY created_at DESC\n `,\n [tenantId]\n );\n\n return result.rows.map(this.mapRowToWorkspace);\n }\n\n /**\n * Get a workspace by ID for a specific tenant\n */\n async getWorkspaceById(tenantId: string, id: string): Promise<Workspace | null> {\n await this.ensureInitialized();\n\n const result = await this.pool.query<{\n id: string;\n tenant_id: string;\n name: string;\n description: string | null;\n storage_type: string;\n created_at: Date;\n updated_at: Date;\n }>(\n `\n SELECT id, tenant_id, name, description, storage_type, created_at, updated_at\n FROM lattice_workspaces\n WHERE id = $1 AND tenant_id = $2\n `,\n [id, tenantId]\n );\n\n if (result.rows.length === 0) {\n return null;\n }\n\n return this.mapRowToWorkspace(result.rows[0]);\n }\n\n /**\n * Create a new workspace\n */\n async createWorkspace(\n tenantId: string,\n id: string,\n data: CreateWorkspaceRequest\n ): Promise<Workspace> {\n await this.ensureInitialized();\n\n const now = new Date();\n\n await this.pool.query(\n `\n INSERT INTO lattice_workspaces (id, tenant_id, name, description, storage_type, created_at, updated_at)\n VALUES ($1, $2, $3, $4, $5, $6, $7)\n ON CONFLICT (id, tenant_id) DO UPDATE SET\n name = EXCLUDED.name,\n description = EXCLUDED.description,\n storage_type = EXCLUDED.storage_type,\n updated_at = EXCLUDED.updated_at\n `,\n [id, tenantId, data.name, data.description || null, data.storageType, now, now]\n );\n\n return {\n id,\n tenantId,\n name: data.name,\n description: data.description,\n storageType: data.storageType,\n createdAt: now,\n updatedAt: now,\n };\n }\n\n /**\n * Update an existing workspace\n */\n async updateWorkspace(\n tenantId: string,\n id: string,\n updates: UpdateWorkspaceRequest\n ): Promise<Workspace | null> {\n await this.ensureInitialized();\n\n // Get existing workspace\n const existing = await this.getWorkspaceById(tenantId, id);\n if (!existing) {\n return null;\n }\n\n // Build update query dynamically based on provided fields\n const updateFields: string[] = [];\n const updateValues: any[] = [];\n let paramIndex = 1;\n\n if (updates.name !== undefined) {\n updateFields.push(`name = $${paramIndex++}`);\n updateValues.push(updates.name);\n }\n\n if (updates.description !== undefined) {\n updateFields.push(`description = $${paramIndex++}`);\n updateValues.push(updates.description || null);\n }\n\n if (updates.storageType !== undefined) {\n updateFields.push(`storage_type = $${paramIndex++}`);\n updateValues.push(updates.storageType);\n }\n\n if (updateFields.length === 0) {\n // No fields to update\n return existing;\n }\n\n // Always update updated_at\n updateFields.push(`updated_at = $${paramIndex++}`);\n updateValues.push(new Date());\n\n // Add id and tenant_id for WHERE clause\n updateValues.push(id);\n updateValues.push(tenantId);\n\n await this.pool.query(\n `\n UPDATE lattice_workspaces\n SET ${updateFields.join(\", \")}\n WHERE id = $${paramIndex} AND tenant_id = $${paramIndex + 1}\n `,\n updateValues\n );\n\n // Return updated workspace\n return await this.getWorkspaceById(tenantId, id);\n }\n\n /**\n * Delete a workspace by ID\n */\n async deleteWorkspace(tenantId: string, id: string): Promise<boolean> {\n await this.ensureInitialized();\n\n const result = await this.pool.query(\n `\n DELETE FROM lattice_workspaces\n WHERE id = $1 AND tenant_id = $2\n `,\n [id, tenantId]\n );\n\n return result.rowCount !== null && result.rowCount > 0;\n }\n}\n","/**\n * Workspace table migrations\n */\n\nimport { PoolClient } from \"pg\";\nimport { Migration } from \"./migration\";\n\n/**\n * Initial migration: Create workspaces table\n */\nexport const createWorkspacesTable: Migration = {\n version: 5,\n name: \"create_workspaces_table\",\n up: async (client: PoolClient) => {\n await client.query(`\n CREATE TABLE IF NOT EXISTS lattice_workspaces (\n id VARCHAR(255) NOT NULL,\n tenant_id VARCHAR(255) NOT NULL,\n name VARCHAR(255) NOT NULL,\n description TEXT,\n storage_type VARCHAR(50) NOT NULL DEFAULT 'sandbox',\n created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n PRIMARY KEY (id, tenant_id)\n )\n `);\n\n // Create indexes for better query performance\n await client.query(`\n CREATE INDEX IF NOT EXISTS idx_lattice_workspaces_tenant_id \n ON lattice_workspaces(tenant_id)\n `);\n\n await client.query(`\n CREATE INDEX IF NOT EXISTS idx_lattice_workspaces_created_at \n ON lattice_workspaces(created_at DESC)\n `);\n },\n down: async (client: PoolClient) => {\n await client.query(\"DROP INDEX IF EXISTS idx_lattice_workspaces_created_at\");\n await client.query(\"DROP INDEX IF EXISTS idx_lattice_workspaces_tenant_id\");\n await client.query(\"DROP TABLE IF EXISTS lattice_workspaces\");\n },\n};\n","/**\n * PostgreSQL implementation of ProjectStore\n */\n\nimport { Pool, PoolConfig } from \"pg\";\nimport {\n ProjectStore,\n Project,\n CreateProjectRequest,\n UpdateProjectRequest,\n} from \"@axiom-lattice/protocols\";\nimport { MigrationManager } from \"../migrations/migration\";\nimport { createProjectsTable } from \"../migrations/project_migrations\";\n\n/**\n * PostgreSQL ProjectStore options\n */\nexport interface PostgreSQLProjectStoreOptions {\n /**\n * PostgreSQL connection pool configuration\n * Can be a connection string or PoolConfig object\n */\n poolConfig: string | PoolConfig;\n\n /**\n * Whether to run migrations automatically on initialization\n * @default true\n */\n autoMigrate?: boolean;\n}\n\n/**\n * PostgreSQL implementation of ProjectStore\n */\nexport class PostgreSQLProjectStore implements ProjectStore {\n private pool: Pool;\n private migrationManager: MigrationManager;\n private initialized: boolean = false;\n private ownsPool: boolean = true;\n\n constructor(options: PostgreSQLProjectStoreOptions) {\n // Create Pool from config\n if (typeof options.poolConfig === \"string\") {\n this.pool = new Pool({ connectionString: options.poolConfig });\n } else {\n this.pool = new Pool(options.poolConfig);\n }\n\n this.migrationManager = new MigrationManager(this.pool);\n this.migrationManager.register(createProjectsTable);\n\n // Auto-migrate by default\n if (options.autoMigrate !== false) {\n this.initialize().catch((error) => {\n console.error(\"Failed to initialize PostgreSQLProjectStore:\", error);\n throw error;\n });\n }\n }\n\n /**\n * Dispose resources and close the connection pool\n * Should be called when the store is no longer needed\n */\n async dispose(): Promise<void> {\n if (this.ownsPool && this.pool) {\n await this.pool.end();\n }\n }\n\n /**\n * Initialize the store and run migrations\n */\n async initialize(): Promise<void> {\n if (this.initialized) {\n return;\n }\n\n await this.migrationManager.migrate();\n this.initialized = true;\n }\n\n /**\n * Ensure store is initialized\n */\n private async ensureInitialized(): Promise<void> {\n if (!this.initialized) {\n await this.initialize();\n }\n }\n\n /**\n * Map database row to Project object\n */\n private mapRowToProject(row: {\n id: string;\n tenant_id: string;\n workspace_id: string;\n name: string;\n description: string | null;\n created_at: Date;\n updated_at: Date;\n }): Project {\n return {\n id: row.id,\n tenantId: row.tenant_id,\n workspaceId: row.workspace_id,\n name: row.name,\n description: row.description || undefined,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n };\n }\n\n /**\n * Get all projects for a specific workspace\n */\n async getProjectsByWorkspace(tenantId: string, workspaceId: string): Promise<Project[]> {\n await this.ensureInitialized();\n\n const result = await this.pool.query<{\n id: string;\n tenant_id: string;\n workspace_id: string;\n name: string;\n description: string | null;\n created_at: Date;\n updated_at: Date;\n }>(\n `\n SELECT id, tenant_id, workspace_id, name, description, created_at, updated_at\n FROM lattice_projects\n WHERE tenant_id = $1 AND workspace_id = $2\n ORDER BY created_at DESC\n `,\n [tenantId, workspaceId]\n );\n\n return result.rows.map(this.mapRowToProject);\n }\n\n /**\n * Get a project by ID for a specific tenant\n */\n async getProjectById(tenantId: string, id: string): Promise<Project | null> {\n await this.ensureInitialized();\n\n const result = await this.pool.query<{\n id: string;\n tenant_id: string;\n workspace_id: string;\n name: string;\n description: string | null;\n created_at: Date;\n updated_at: Date;\n }>(\n `\n SELECT id, tenant_id, workspace_id, name, description, created_at, updated_at\n FROM lattice_projects\n WHERE id = $1 AND tenant_id = $2\n `,\n [id, tenantId]\n );\n\n if (result.rows.length === 0) {\n return null;\n }\n\n return this.mapRowToProject(result.rows[0]);\n }\n\n /**\n * Create a new project\n */\n async createProject(\n tenantId: string,\n workspaceId: string,\n id: string,\n data: CreateProjectRequest\n ): Promise<Project> {\n await this.ensureInitialized();\n\n const now = new Date();\n\n await this.pool.query(\n `\n INSERT INTO lattice_projects (id, tenant_id, workspace_id, name, description, created_at, updated_at)\n VALUES ($1, $2, $3, $4, $5, $6, $7)\n ON CONFLICT (id, tenant_id) DO UPDATE SET\n workspace_id = EXCLUDED.workspace_id,\n name = EXCLUDED.name,\n description = EXCLUDED.description,\n updated_at = EXCLUDED.updated_at\n `,\n [id, tenantId, workspaceId, data.name, data.description || null, now, now]\n );\n\n return {\n id,\n tenantId,\n workspaceId,\n name: data.name,\n description: data.description,\n createdAt: now,\n updatedAt: now,\n };\n }\n\n /**\n * Update an existing project\n */\n async updateProject(\n tenantId: string,\n id: string,\n updates: UpdateProjectRequest\n ): Promise<Project | null> {\n await this.ensureInitialized();\n\n // Get existing project\n const existing = await this.getProjectById(tenantId, id);\n if (!existing) {\n return null;\n }\n\n // Build update query dynamically based on provided fields\n const updateFields: string[] = [];\n const updateValues: any[] = [];\n let paramIndex = 1;\n\n if (updates.name !== undefined) {\n updateFields.push(`name = $${paramIndex++}`);\n updateValues.push(updates.name);\n }\n\n if (updates.description !== undefined) {\n updateFields.push(`description = $${paramIndex++}`);\n updateValues.push(updates.description || null);\n }\n\n if (updateFields.length === 0) {\n // No fields to update\n return existing;\n }\n\n // Always update updated_at\n updateFields.push(`updated_at = $${paramIndex++}`);\n updateValues.push(new Date());\n\n // Add id and tenant_id for WHERE clause\n updateValues.push(id);\n updateValues.push(tenantId);\n\n await this.pool.query(\n `\n UPDATE lattice_projects\n SET ${updateFields.join(\", \")}\n WHERE id = $${paramIndex} AND tenant_id = $${paramIndex + 1}\n `,\n updateValues\n );\n\n // Return updated project\n return await this.getProjectById(tenantId, id);\n }\n\n /**\n * Delete a project by ID\n */\n async deleteProject(tenantId: string, id: string): Promise<boolean> {\n await this.ensureInitialized();\n\n const result = await this.pool.query(\n `\n DELETE FROM lattice_projects\n WHERE id = $1 AND tenant_id = $2\n `,\n [id, tenantId]\n );\n\n return result.rowCount !== null && result.rowCount > 0;\n }\n}\n","/**\n * Project table migrations\n */\n\nimport { PoolClient } from \"pg\";\nimport { Migration } from \"./migration\";\n\n/**\n * Initial migration: Create projects table\n */\nexport const createProjectsTable: Migration = {\n version: 6,\n name: \"create_projects_table\",\n up: async (client: PoolClient) => {\n await client.query(`\n CREATE TABLE IF NOT EXISTS lattice_projects (\n id VARCHAR(255) NOT NULL,\n tenant_id VARCHAR(255) NOT NULL,\n workspace_id VARCHAR(255) NOT NULL,\n name VARCHAR(255) NOT NULL,\n description TEXT,\n created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n PRIMARY KEY (id, tenant_id)\n )\n `);\n\n // Create indexes for better query performance\n await client.query(`\n CREATE INDEX IF NOT EXISTS idx_lattice_projects_tenant_id \n ON lattice_projects(tenant_id)\n `);\n\n await client.query(`\n CREATE INDEX IF NOT EXISTS idx_lattice_projects_workspace_id \n ON lattice_projects(workspace_id)\n `);\n\n await client.query(`\n CREATE INDEX IF NOT EXISTS idx_lattice_projects_created_at \n ON lattice_projects(created_at DESC)\n `);\n },\n down: async (client: PoolClient) => {\n await client.query(\"DROP INDEX IF EXISTS idx_lattice_projects_created_at\");\n await client.query(\"DROP INDEX IF EXISTS idx_lattice_projects_workspace_id\");\n await client.query(\"DROP INDEX IF EXISTS idx_lattice_projects_tenant_id\");\n await client.query(\"DROP TABLE IF EXISTS lattice_projects\");\n },\n};\n"],"mappings":"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","names":["Pool","Pool","Pool","Pool","Pool","Pool","Pool","Pool","Pool","Pool","Pool","Pool"]}