{"version":3,"file":"factory.mjs","sources":["../../../src/memory/factory.ts"],"sourcesContent":["/**\n * Factory for building a memory backend from environment variables.\n *\n * Called once at startup by host's singleton (`api/server/services/memoryStore.js`).\n * Returns `null` — never throws — when required env vars are missing, so\n * agents with `memory_enabled=true` still run, just without memory. Host\n * logs a single warning on boot instead of crashing.\n */\nimport { Pool } from 'pg';\nimport { DEFAULT_MEMORY_TABLE } from './constants';\nimport { PgvectorMemoryStore } from './pgvectorStore';\nimport { runMemoryMigration } from './migrate';\nimport { PgvectorRecallTracker, type RecallTracker } from './recallTracking';\nimport type { MemoryBackend } from './types';\n\nexport interface BuildMemoryBackendResult {\n  backend: MemoryBackend;\n  pool: Pool;\n  /** Phase 2 — shared recall tracker bound to the same pool/migration. */\n  recallTracker: RecallTracker;\n}\n\ninterface PgConfig {\n  host: string;\n  port: number;\n  user: string;\n  password: string;\n  database: string;\n  ssl: boolean;\n}\n\nfunction readPgConfig(): PgConfig | null {\n  // Dev shortcut: single URL overrides discrete fields if present.\n  const url = process.env.MEMORY_DATABASE_URL;\n  if (url) {\n    try {\n      const u = new URL(url);\n      return {\n        host: u.hostname,\n        port: Number(u.port || 5432),\n        user: decodeURIComponent(u.username),\n        password: decodeURIComponent(u.password),\n        database: u.pathname.replace(/^\\//, ''),\n        ssl: (process.env.MEMORY_POSTGRES_SSL ?? 'disable') === 'require',\n      };\n    } catch {\n      return null;\n    }\n  }\n\n  const host = process.env.MEMORY_POSTGRES_HOST;\n  const user = process.env.MEMORY_POSTGRES_USER;\n  const password = process.env.MEMORY_POSTGRES_PASSWORD;\n  const database = process.env.MEMORY_POSTGRES_DB;\n  if (!host || !user || !password || !database) {\n    return null;\n  }\n  return {\n    host,\n    port: Number(process.env.MEMORY_POSTGRES_PORT ?? 5432),\n    user,\n    password,\n    database,\n    ssl: (process.env.MEMORY_POSTGRES_SSL ?? 'disable') === 'require',\n  };\n}\n\n/**\n * Try to build a configured memory backend. Returns null when the required\n * env vars are absent — caller should log a single \"memory disabled\" warning\n * and continue. Never throws on missing config.\n */\nexport async function buildMemoryBackendFromEnv(): Promise<BuildMemoryBackendResult | null> {\n  const cfg = readPgConfig();\n  if (!cfg) return null;\n\n  const pool = new Pool({\n    host: cfg.host,\n    port: cfg.port,\n    user: cfg.user,\n    password: cfg.password,\n    database: cfg.database,\n    ssl: cfg.ssl ? { rejectUnauthorized: false } : undefined,\n    max: 10,\n  });\n\n  const table = process.env.MEMORY_TABLE_NAME ?? DEFAULT_MEMORY_TABLE;\n\n  try {\n    await runMemoryMigration({ pool, table });\n  } catch (err) {\n    // Migration failures ARE fatal — they mean dimension mismatch or\n    // permissions wrong, and silently running past that would produce\n    // corrupt or missing memory reads.\n    await pool.end().catch(() => undefined);\n    throw err;\n  }\n\n  const backend = new PgvectorMemoryStore({ pool, table });\n\n  // Phase 2 — recall tracker migration is best-effort at boot. If it fails,\n  // tool wiring continues with a null tracker rather than crashing host.\n  const recallTracker = new PgvectorRecallTracker(pool);\n  try {\n    await recallTracker.migrate();\n  } catch {\n    // [phase2-recall-tracking] debug: migration skipped — non-fatal\n  }\n\n  return { backend, pool, recallTracker };\n}\n"],"names":[],"mappings":"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"}