{"version":3,"sources":["../../../../src/server/stores/memory-drizzle/index.ts","../../../../src/server/stores/memory-drizzle/adapter.ts","../../../../src/server/memory/extract.ts","../../../../src/server/stores/drizzle/client.ts","../../../../src/server/stores/drizzle/schema.ts","../../../../src/server/stores/memory-drizzle/schema.ts","../../../../src/server/stores/knowledge-drizzle/schema.ts"],"sourcesContent":["/**\n * Default Drizzle/Postgres memory adapter — public entry.\n *\n *   import { createDrizzleMemory } from '@mordn/chat-widget/server/memory/drizzle';\n *   import { openai } from '@ai-sdk/openai';\n *   createChatHandler({\n *     memory: {\n *       adapter: createDrizzleMemory({\n *         agentId: 'support-bot',\n *         embeddingModel: openai.embedding('text-embedding-3-small'), // omit → keyword mode\n *         extractionModel: openai('gpt-4o-mini'),                     // omit → heuristic mode\n *         retentionDays: 365,                                         // omit → keep forever\n *       }),\n *     },\n *   });\n *\n * The schema is exported so `drizzle-kit` can generate base migrations; the\n * shipped 0001_memory.sql adds the optional pgvector column + ANN index.\n */\nimport 'server-only';\n\nexport { createDrizzleMemory, type DrizzleMemoryOptions } from './adapter';\nexport * as schema from './schema';\nexport type { MemoryRow, NewMemoryRow } from './schema';\n","/**\n * Default long-term memory adapter — Postgres via Drizzle.\n *\n * Mirrors `createDrizzleChatStore`: a shared pool, a per-request user-bound\n * instance, security invariants upheld in every method (every query starts\n * scoped to (userId, agentId) — the boundary). Adds zero new runtime deps and\n * degrades gracefully:\n *   • no embedding model → keyword (full-text) retrieval, no embeddings stored;\n *   • no extraction model → heuristic extraction;\n *   • no pgvector → still works (the embedding column stays NULL).\n */\n\nimport 'server-only';\nimport { and, desc, eq, gt, isNull, or, sql, type SQL } from 'drizzle-orm';\nimport { embed, generateId, type EmbeddingModel, type LanguageModel } from 'ai';\nimport { createHash } from 'node:crypto';\n\nimport type {\n  ListOptions,\n  Memory,\n  MemoryAdapter,\n  MemoryAdapterFactory,\n  MemoryScope,\n  RecordOptions,\n  RetrieveOptions,\n} from '../../memory/types';\nimport {\n  heuristicExtract,\n  llmExtract,\n  redactDelta,\n  renderTurn,\n  type MemoryDelta,\n} from '../../memory/extract';\nimport { getDrizzleDb, type DrizzleClientOptions, type DrizzleDb } from '../drizzle/client';\nimport { memories, type MemoryRow } from './schema';\n\nconst MAX_RETRIEVE = 8;\nconst MAX_LIST = 100;\nconst EXISTING_SLICE = 50;\n\nfunction normalise(text: string): string {\n  return text.trim().toLowerCase().replace(/\\s+/g, ' ');\n}\nfunction contentHash(text: string): string {\n  return createHash('sha256').update(normalise(text)).digest('hex');\n}\n\nfunction toMemory(row: MemoryRow, score?: number): Memory {\n  return {\n    id: row.id,\n    text: row.text,\n    score,\n    scope: (row.scope as MemoryScope) ?? 'user',\n    createdAt: row.createdAt.toISOString(),\n    metadata: {\n      kind: row.kind,\n      sourceConversationId: row.sourceConversationId ?? undefined,\n      orgId: row.orgId ?? undefined,\n      ...((row.metadata as Record<string, unknown>) ?? {}),\n    },\n  };\n}\n\nclass DrizzleMemoryAdapter implements MemoryAdapter {\n  constructor(\n    public readonly userId: string,\n    private readonly db: DrizzleDb,\n    private readonly agentId: string,\n    private readonly embeddingModel: EmbeddingModel | null,\n    private readonly extractionModel: LanguageModel | null,\n    private readonly ttlDays: number | null,\n  ) {}\n\n  /** Every query starts scoped to (user, agent) — the isolation boundary. */\n  private base() {\n    return and(eq(memories.userId, this.userId), eq(memories.agentId, this.agentId));\n  }\n\n  /** Exclude expired rows (TTL). */\n  private notExpired() {\n    return or(isNull(memories.expiresAt), gt(memories.expiresAt, new Date()));\n  }\n\n  /**\n   * Build the WHERE predicate for a set of tiers (#167). 'user'/'session' are\n   * scoped to the bound (user, agent); 'org' is shared by (org_id, agent) and\n   * therefore requires a server-verified `orgId`. A requested tier missing its\n   * required key (session→conversationId, org→orgId) is dropped — a mis-config\n   * never widens access — and if nothing resolves we fall back to the bound\n   * user's own 'user' tier.\n   */\n  private scopeWhere(scopes: MemoryScope[], conversationId?: string, orgId?: string): SQL {\n    const agent = this.agentId;\n    const want = new Set<MemoryScope>(scopes.length ? scopes : ['user']);\n    const clauses: SQL[] = [];\n    if (want.has('user')) {\n      clauses.push(sql`(user_id = ${this.userId} AND agent_id = ${agent} AND scope = 'user')`);\n    }\n    if (want.has('session') && conversationId) {\n      clauses.push(\n        sql`(user_id = ${this.userId} AND agent_id = ${agent} AND scope = 'session' AND source_conversation_id = ${conversationId})`,\n      );\n    }\n    if (want.has('org') && orgId) {\n      clauses.push(sql`(org_id = ${orgId} AND agent_id = ${agent} AND scope = 'org')`);\n    }\n    if (clauses.length === 0) {\n      clauses.push(sql`(user_id = ${this.userId} AND agent_id = ${agent} AND scope = 'user')`);\n    }\n    return sql`(${sql.join(clauses, sql` OR `)})`;\n  }\n\n  async retrieve(opts: RetrieveOptions): Promise<Memory[]> {\n    const limit = Math.min(Math.max(opts.limit ?? MAX_RETRIEVE, 1), MAX_RETRIEVE);\n    // Tiers to search (#167). Default ['user'] preserves Phase-1 behaviour.\n    const where = this.scopeWhere(opts.scopes ?? ['user'], opts.conversationId, opts.orgId);\n    try {\n      // Semantic path when we have both an embedding model and a query.\n      if (this.embeddingModel && opts.query) {\n        const { embedding } = await embed({ model: this.embeddingModel, value: opts.query });\n        const vec = sql.raw(`'[${embedding.join(',')}]'::vector`);\n        const rows = await this.db.execute(sql`\n          SELECT id, user_id, agent_id, scope, org_id, text, kind, content_hash, source_conversation_id,\n                 metadata, expires_at, created_at, updated_at,\n                 (1 - (embedding <=> ${vec})) AS score\n          FROM ${memories}\n          WHERE ${where}\n            AND embedding IS NOT NULL\n            AND (expires_at IS NULL OR expires_at > now())\n          ORDER BY score DESC\n          LIMIT ${limit}\n        `);\n        const list = (rows as unknown as { rows?: unknown[] }).rows ?? (rows as unknown as unknown[]);\n        return (list as Array<Record<string, unknown>>)\n          .map((r) => ({ row: rawToRow(r), score: Number(r.score ?? 0) }))\n          .filter((r) => r.score >= (opts.minScore ?? 0))\n          .map((r) => toMemory(r.row, r.score));\n      }\n\n      // Keyword fallback (no embedding model): Postgres FTS, or most-recent.\n      if (opts.query) {\n        const rows = await this.db.execute(sql`\n          SELECT id, user_id, agent_id, scope, org_id, text, kind, content_hash, source_conversation_id,\n                 metadata, expires_at, created_at, updated_at,\n                 ts_rank(to_tsvector('english', text), plainto_tsquery('english', ${opts.query})) AS score\n          FROM ${memories}\n          WHERE ${where}\n            AND (expires_at IS NULL OR expires_at > now())\n            AND to_tsvector('english', text) @@ plainto_tsquery('english', ${opts.query})\n          ORDER BY score DESC\n          LIMIT ${limit}\n        `);\n        const list = (rows as unknown as { rows?: unknown[] }).rows ?? (rows as unknown as unknown[]);\n        const mapped = (list as Array<Record<string, unknown>>).map((r) =>\n          toMemory(rawToRow(r), Number(r.score ?? 0)),\n        );\n        if (mapped.length) return mapped;\n        // FTS found nothing → fall through to most-recent so memory still helps.\n      }\n\n      const recent = await this.db\n        .select()\n        .from(memories)\n        .where(and(where, this.notExpired()))\n        .orderBy(desc(memories.updatedAt))\n        .limit(limit);\n      return recent.map((r) => toMemory(r));\n    } catch {\n      // Fail soft — a memory hiccup must never block a reply.\n      return [];\n    }\n  }\n\n  async record(opts: RecordOptions): Promise<void> {\n    const turnText = renderTurn(opts.messages);\n    if (!turnText.trim()) return;\n\n    // Tier to extract into (#167). Default 'user' preserves Phase-1 behaviour.\n    const scope: MemoryScope = opts.scope ?? 'user';\n    const orgId = scope === 'org' ? opts.orgId ?? null : null;\n    // An 'org' write with no verified orgId can't be attributed to a tenant and\n    // would create an un-dedupable null-org row — skip rather than mislabel it.\n    if (scope === 'org' && !orgId) {\n      console.warn('[chat-widget] memory.record(scope:\"org\") skipped — no orgId resolved.');\n      return;\n    }\n\n    // Pull a small slice of existing SAME-TIER memories so the extractor can\n    // dedupe/supersede within the tier. Scoped to the tier's real OWNER: org by\n    // TENANT (org_id, across users), every other tier by the bound (user, agent)\n    // — mirroring the partial unique indexes the upsert conflicts on below.\n    const dedupeScope =\n      scope === 'org'\n        ? and(eq(memories.orgId, orgId!), eq(memories.agentId, this.agentId), eq(memories.scope, 'org'))\n        : and(this.base(), eq(memories.scope, scope));\n    const existing = await this.db\n      .select({ id: memories.id, text: memories.text })\n      .from(memories)\n      .where(dedupeScope)\n      .orderBy(desc(memories.updatedAt))\n      .limit(EXISTING_SLICE);\n\n    let delta: MemoryDelta = this.extractionModel\n      ? await llmExtract(this.extractionModel, turnText, existing)\n      : heuristicExtract(turnText);\n    delta = redactDelta(delta);\n    if (!delta.upserts.length && !delta.deletes.length) return;\n\n    // Supersede stale facts the extractor flagged.\n    for (const id of delta.deletes) await this.forget(id);\n\n    const expiresAt = this.ttlDays ? new Date(Date.now() + this.ttlDays * 864e5) : null;\n\n    // Embed in one batch when possible.\n    let vectors: (number[] | null)[] = delta.upserts.map(() => null);\n    if (this.embeddingModel && delta.upserts.length) {\n      try {\n        // embed one-by-one to keep the dep surface minimal; small N (<=20).\n        vectors = await Promise.all(\n          delta.upserts.map(async (u) => {\n            const { embedding } = await embed({ model: this.embeddingModel!, value: u.text });\n            return embedding;\n          }),\n        );\n      } catch {\n        vectors = delta.upserts.map(() => null);\n      }\n    }\n\n    for (let i = 0; i < delta.upserts.length; i++) {\n      const u = delta.upserts[i];\n      await this.db\n        .insert(memories)\n        .values({\n          id: generateId(),\n          userId: this.userId,\n          agentId: this.agentId,\n          scope,\n          orgId,\n          text: u.text,\n          kind: u.kind,\n          embedding: vectors[i] ?? null,\n          contentHash: contentHash(u.text),\n          sourceConversationId: opts.conversationId,\n          expiresAt,\n          metadata: {},\n        })\n        .onConflictDoUpdate(\n          scope === 'org'\n            ? {\n                // Org tier dedupes per TENANT — matches the partial unique index\n                // `WHERE scope = 'org'` on (org_id, agent_id, content_hash).\n                target: [memories.orgId, memories.agentId, memories.contentHash],\n                targetWhere: sql`${memories.scope} = 'org'`,\n                set: { updatedAt: new Date(), sourceConversationId: opts.conversationId },\n              }\n            : {\n                // Non-org tiers dedupe per WRITER — matches the partial unique index\n                // `WHERE scope <> 'org'` on (user_id, agent_id, scope, content_hash).\n                target: [memories.userId, memories.agentId, memories.scope, memories.contentHash],\n                targetWhere: sql`${memories.scope} <> 'org'`,\n                set: { updatedAt: new Date(), sourceConversationId: opts.conversationId },\n              },\n        );\n    }\n  }\n\n  async list(opts?: ListOptions): Promise<Memory[]> {\n    // Default to the bound user's own 'user' tier (Phase-1 behaviour). Callers\n    // pass `scope` to broaden; 'org' additionally needs `orgId`.\n    const scopes: MemoryScope[] = opts?.scope\n      ? Array.isArray(opts.scope)\n        ? opts.scope\n        : [opts.scope]\n      : ['user'];\n    const where = this.scopeWhere(scopes, undefined, opts?.orgId);\n    const rows = await this.db\n      .select()\n      .from(memories)\n      .where(and(where, this.notExpired()))\n      .orderBy(desc(memories.createdAt))\n      .limit(MAX_LIST);\n    return rows.map((r) => toMemory(r));\n  }\n\n  async forget(id: string): Promise<void> {\n    // Scope the delete to the bound user+agent: a foreign id deletes nothing.\n    await this.db.delete(memories).where(and(eq(memories.id, id), this.base()));\n  }\n\n  async forgetAll(opts?: { scope?: MemoryScope }): Promise<void> {\n    // Always scoped to the bound user (base) so a user erasure never bulk-deletes\n    // another user's shared 'org' memories. `opts.scope` narrows to one tier.\n    const where = opts?.scope ? and(this.base(), eq(memories.scope, opts.scope)) : this.base();\n    await this.db.delete(memories).where(where);\n  }\n}\n\n/** Coerce a raw SQL row (snake_case) into a typed MemoryRow. */\nfunction rawToRow(r: Record<string, unknown>): MemoryRow {\n  return {\n    id: String(r.id),\n    userId: String(r.user_id),\n    agentId: String(r.agent_id),\n    scope: String(r.scope ?? 'user'),\n    orgId: (r.org_id as string) ?? null,\n    text: String(r.text),\n    kind: String(r.kind),\n    embedding: null,\n    contentHash: String(r.content_hash),\n    sourceConversationId: (r.source_conversation_id as string) ?? null,\n    metadata: (r.metadata as Record<string, unknown>) ?? null,\n    expiresAt: r.expires_at ? new Date(r.expires_at as string) : null,\n    createdAt: new Date(r.created_at as string),\n    updatedAt: new Date(r.updated_at as string),\n  };\n}\n\nexport interface DrizzleMemoryOptions {\n  /** Agent namespace; scopes every query by (userId, agentId). Default 'default'. */\n  agentId?: string;\n  /** Embedding model. Omit → keyword-only mode (no embeddings stored). */\n  embeddingModel?: EmbeddingModel;\n  /** Extraction model. Omit → heuristic extraction (no extra model call). */\n  extractionModel?: LanguageModel;\n  /** Retention TTL in days. Omit → keep forever. */\n  retentionDays?: number;\n  /** Drizzle client options (connection string / pool size). */\n  client?: DrizzleClientOptions;\n}\n\n/**\n * Create a `MemoryAdapterFactory` backed by the default Drizzle/Postgres memory.\n * Pass to `createChatHandler({ memory: { adapter: createDrizzleMemory({...}) } })`.\n */\nexport function createDrizzleMemory(opts: DrizzleMemoryOptions = {}): MemoryAdapterFactory {\n  const db = getDrizzleDb(opts.client);\n  const agentId = opts.agentId ?? 'default';\n  return (userId) =>\n    new DrizzleMemoryAdapter(\n      userId,\n      db,\n      agentId,\n      opts.embeddingModel ?? null,\n      opts.extractionModel ?? null,\n      opts.retentionDays ?? null,\n    );\n}\n","/**\n * Post-turn memory extraction.\n *\n * Two strategies, both producing a `{ upserts, deletes }` delta:\n *   1. LLM extraction (recommended) — `generateObject` against a cheap/fast\n *      model with a structured schema; can add new facts AND supersede stale\n *      ones. The system prompt forbids storing secrets/credentials/unvolunteered\n *      PII.\n *   2. Heuristic (fallback, no extra model call) — a small rule set that\n *      captures explicit imperative preferences (\"always…\", \"I prefer…\",\n *      \"call me…\", \"remember that…\") and stores them verbatim.\n *\n * Either way the output runs a redaction pass that drops obvious secret patterns\n * before persistence.\n */\n\nimport 'server-only';\nimport { generateObject, type LanguageModel } from 'ai';\nimport { z } from 'zod';\n\nexport interface MemoryDelta {\n  upserts: { text: string; kind: string }[];\n  deletes: string[];\n}\n\n/** Structured-output schema for LLM extraction (add facts + supersede stale). */\nconst MemoryDeltaSchema = z.object({\n  upserts: z.array(\n    z.object({\n      text: z.string().max(280),\n      kind: z.enum(['preference', 'fact', 'goal', 'context', 'instruction']),\n    }),\n  ),\n  deletes: z.array(z.string()).describe('ids of now-stale memories to remove'),\n});\n\nconst EXTRACTION_SYSTEM_PROMPT = [\n  'You extract durable, salient facts about the USER from a conversation turn.',\n  'Output self-contained, first-person-about-the-user statements (e.g. \"Prefers',\n  'TypeScript\", \"Is migrating off Firebase\"). Prefer UPDATING or SUPERSEDING',\n  'existing facts over duplicating them: if a new statement makes an existing',\n  'memory stale, add the new fact AND list the stale memory id in `deletes`.',\n  'NEVER store secrets, credentials, API keys, tokens, passwords, or PII the',\n  'user did not volunteer as a durable preference. Ignore ephemeral chit-chat',\n  'and one-off task details. If nothing is worth keeping, return empty arrays.',\n  'Each fact <= 280 chars. Allowed kinds: preference, fact, goal, context, instruction.',\n].join(' ');\n\n/** Obvious secret patterns to strip before persistence (defence in depth). */\nconst SECRET_PATTERNS: RegExp[] = [\n  /\\b(sk|pk|rk)-[A-Za-z0-9]{16,}\\b/g, // OpenAI-style keys\n  /\\b[A-Za-z0-9_-]*[Aa][Pp][Ii][_-]?[Kk][Ee][Yy][:=]\\s*\\S+/g, // api_key=...\n  /\\bBearer\\s+[A-Za-z0-9._-]{16,}\\b/gi, // bearer tokens\n  /\\b[A-Fa-f0-9]{40,}\\b/g, // long hex blobs (hashes/keys)\n  /\\beyJ[A-Za-z0-9_-]{10,}\\.[A-Za-z0-9_-]{10,}\\.[A-Za-z0-9_-]{10,}\\b/g, // JWTs\n];\n\n/** True if a string smells like it contains a secret (drop it entirely). */\nfunction looksSecret(text: string): boolean {\n  return SECRET_PATTERNS.some((re) => {\n    re.lastIndex = 0;\n    return re.test(text);\n  });\n}\n\n/** Drop any upsert that looks like it carries a secret. */\nexport function redactDelta(delta: MemoryDelta): MemoryDelta {\n  return {\n    upserts: delta.upserts.filter((u) => u.text.trim().length > 0 && !looksSecret(u.text)),\n    deletes: delta.deletes,\n  };\n}\n\n/** Flatten a UI/Model message's text parts for the extraction prompt. */\nexport function renderTurn(messages: unknown[]): string {\n  const lines: string[] = [];\n  for (const m of messages) {\n    const msg = m as { role?: string; parts?: Array<{ type?: string; text?: string }>; content?: unknown };\n    const role = msg.role ?? 'user';\n    let text = '';\n    if (Array.isArray(msg.parts)) {\n      text = msg.parts\n        .filter((p) => p?.type === 'text' && typeof p.text === 'string')\n        .map((p) => p.text)\n        .join('');\n    } else if (typeof msg.content === 'string') {\n      text = msg.content;\n    }\n    if (text.trim()) lines.push(`${role.toUpperCase()}: ${text.trim()}`);\n  }\n  return lines.join('\\n');\n}\n\n/** LLM extraction via `generateObject`. Returns an empty delta on any failure. */\nexport async function llmExtract(\n  model: LanguageModel,\n  turnText: string,\n  existing: { id: string; text: string }[],\n): Promise<MemoryDelta> {\n  const existingBlock = existing.length\n    ? existing.map((e) => `- [${e.id}] ${e.text}`).join('\\n')\n    : '(none)';\n  const prompt = [\n    'Existing memories for this user:',\n    existingBlock,\n    '',\n    'Conversation turn:',\n    turnText,\n    '',\n    'Extract durable facts about the user. Return JSON only.',\n  ].join('\\n');\n\n  try {\n    const { object } = await generateObject({\n      model,\n      schema: MemoryDeltaSchema,\n      system: EXTRACTION_SYSTEM_PROMPT,\n      prompt,\n    });\n    return {\n      upserts: Array.isArray(object.upserts) ? object.upserts.slice(0, 20) : [],\n      deletes: Array.isArray(object.deletes) ? object.deletes.slice(0, 20) : [],\n    };\n  } catch {\n    return { upserts: [], deletes: [] };\n  }\n}\n\n/**\n * Heuristic extraction — zero extra model call. Captures explicit imperative\n * preferences the user states. Lower recall, no cost/latency.\n */\nexport function heuristicExtract(turnText: string): MemoryDelta {\n  const upserts: { text: string; kind: string }[] = [];\n  // Only mine USER lines.\n  const userLines = turnText\n    .split('\\n')\n    .filter((l) => l.startsWith('USER:'))\n    .map((l) => l.slice('USER:'.length).trim());\n\n  const triggers: Array<{ re: RegExp; kind: string }> = [\n    { re: /\\b(i prefer|i'd prefer|i like|i love|i hate|i dislike)\\b/i, kind: 'preference' },\n    { re: /\\b(always|never|in future|from now on|going forward)\\b/i, kind: 'instruction' },\n    { re: /\\b(call me|my name is|i am called)\\b/i, kind: 'fact' },\n    { re: /\\b(remember that|note that|keep in mind|fyi)\\b/i, kind: 'context' },\n    { re: /\\b(i'm building|i am building|i'm working on|my goal is|i want to)\\b/i, kind: 'goal' },\n  ];\n\n  for (const line of userLines) {\n    // Consider sentence-level fragments so one long line yields tight facts.\n    for (const sentence of line.split(/(?<=[.!?])\\s+/)) {\n      const s = sentence.trim();\n      if (s.length < 4 || s.length > 280) continue;\n      const hit = triggers.find((t) => t.re.test(s));\n      if (hit) upserts.push({ text: s.replace(/\\s+/g, ' '), kind: hit.kind });\n    }\n  }\n  // De-dupe by text.\n  const seen = new Set<string>();\n  return {\n    upserts: upserts.filter((u) => (seen.has(u.text) ? false : (seen.add(u.text), true))).slice(0, 10),\n    deletes: [],\n  };\n}\n","/**\n * Postgres connection for the default Drizzle store.\n *\n * Carries forward the connection hygiene the original package got right:\n *   • cache the client on globalThis so Next.js dev HMR doesn't leak a fresh\n *     pool on every reload (which eventually exhausts Supabase's pooler),\n *   • `prepare: false` for the Supabase transaction-mode pooler,\n *   • a small, bounded pool.\n *\n * The connection string is read from `DATABASE_URL` by default but can be\n * passed explicitly so a host app with multiple databases stays in control.\n */\n\nimport 'server-only';\nimport { drizzle } from 'drizzle-orm/postgres-js';\nimport postgres from 'postgres';\nimport * as schema from './schema';\n\nexport type DrizzleDb = ReturnType<typeof drizzle<typeof schema>>;\n\nexport interface DrizzleClientOptions {\n  /** Postgres connection string. Defaults to `process.env.DATABASE_URL`. */\n  connectionString?: string;\n  /** Max pool connections. Defaults to 5 (dev-friendly; raise in prod). */\n  max?: number;\n}\n\nconst globalForDb = globalThis as unknown as {\n  __mordnChatWidgetDb?: Map<string, DrizzleDb>;\n};\n\n/**\n * Get (or lazily create + cache) a Drizzle db for a connection string. Cached\n * by connection string so multiple stores over the same DB share one pool.\n */\nexport function getDrizzleDb(options: DrizzleClientOptions = {}): DrizzleDb {\n  const connectionString = options.connectionString ?? process.env.DATABASE_URL;\n  if (!connectionString) {\n    throw new Error(\n      '[chat-widget] DATABASE_URL is not set and no connectionString was ' +\n        'provided to the default Drizzle store.',\n    );\n  }\n\n  const cache = (globalForDb.__mordnChatWidgetDb ??= new Map());\n  const cached = cache.get(connectionString);\n  if (cached) return cached;\n\n  const client = postgres(connectionString, {\n    prepare: false, // required for Supabase transaction-mode pooler\n    max: options.max ?? 5,\n    idle_timeout: 20,\n    connect_timeout: 10,\n  });\n  const db = drizzle(client, { schema });\n\n  // Only cache in non-prod: in prod each server instance loads the module once\n  // so caching buys nothing and would pin a pool across the process lifetime.\n  if (process.env.NODE_ENV !== 'production') cache.set(connectionString, db);\n  return db;\n}\n","/**\n * Drizzle schema for the default ChatStore (v2, parts-first).\n *\n * This is the schema the *default* store uses. A BYO store may use any schema\n * it likes — this one is not part of the public contract, the `ChatStore`\n * interface is. It's exported so consumers on the default path can run\n * `drizzle-kit` against it and so the migration can reference it.\n *\n * What changed from v0.7.1\n * ------------------------\n * The old schema stored a flattened `content: text` as the apparent source of\n * truth and tucked the real AI SDK `parts` into a `metadata` jsonb blob. That\n * inverted the actual authority — `parts` (text + reasoning + tool calls +\n * sources + files) is what the AI SDK round-trips and what rendering needs;\n * `content` was a lossy shadow.\n *\n * v2 makes that authority explicit:\n *   • `parts`  — jsonb NOT NULL — the canonical AI SDK message parts. Source\n *                of truth for rendering and model replay.\n *   • `text`   — text — a denormalised projection of the text parts, for\n *                cheap previews / titles / search. Never authoritative.\n *\n * A backfill migration populates these from the old columns so existing\n * installs upgrade without data loss (see migrations/).\n */\n\nimport { pgTable, text, timestamp, jsonb, index } from 'drizzle-orm/pg-core';\nimport type { UIMessage } from 'ai';\n\nexport const conversations = pgTable(\n  'chat_conversations',\n  {\n    id: text('id').primaryKey(),\n    userId: text('user_id').notNull(),\n    title: text('title').notNull().default('New Chat'),\n    /** Free-form host-app metadata. Never read by the core. */\n    metadata: jsonb('metadata').$type<Record<string, unknown>>(),\n    createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),\n    updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),\n  },\n  (table) => [\n    // Drives the history list (WHERE user_id = ? ORDER BY updated_at DESC).\n    index('chat_conversations_user_updated_idx').on(table.userId, table.updatedAt),\n  ],\n);\n\nexport const messages = pgTable(\n  'chat_messages',\n  {\n    id: text('id').primaryKey(),\n    conversationId: text('conversation_id')\n      .notNull()\n      .references(() => conversations.id, { onDelete: 'cascade' }),\n    role: text('role').notNull().$type<'user' | 'assistant' | 'system'>(),\n    /** Canonical AI SDK parts — source of truth. */\n    parts: jsonb('parts').$type<UIMessage['parts']>().notNull(),\n    /** Denormalised plain-text projection for previews/search. */\n    text: text('text').notNull().default(''),\n    /** Model that produced this message (assistant turns). */\n    model: text('model'),\n    createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),\n  },\n  (table) => [\n    // Drives history load (WHERE conversation_id = ? ORDER BY created_at).\n    index('chat_messages_conversation_created_idx').on(table.conversationId, table.createdAt),\n  ],\n);\n\nexport type ConversationRow = typeof conversations.$inferSelect;\nexport type NewConversationRow = typeof conversations.$inferInsert;\nexport type MessageRow = typeof messages.$inferSelect;\nexport type NewMessageRow = typeof messages.$inferInsert;\n","/**\n * Drizzle schema for the default long-term memory adapter (Postgres).\n *\n * As with the chat/knowledge schemas, this is NOT the public contract — the\n * `MemoryAdapter` interface is. It's exported so consumers on the default path\n * can run `drizzle-kit` against it.\n *\n * pgvector is OPTIONAL here. If the `vector` extension + an embedding model are\n * present, the adapter stores and ANN-searches embeddings; if not, it degrades\n * to Postgres full-text search over `text`. The `embedding` column is therefore\n * NULLABLE — one column, one code-path choice at construction.\n */\n\nimport { sql } from 'drizzle-orm';\nimport { pgTable, text, timestamp, jsonb, index, uniqueIndex } from 'drizzle-orm/pg-core';\nimport { vector, EMBED_DIM } from '../knowledge-drizzle/schema';\n\nexport const memories = pgTable(\n  'chat_memories',\n  {\n    id: text('id').primaryKey(),\n    /** Server-verified end-user id — the isolation boundary. */\n    userId: text('user_id').notNull(),\n    /** Agent namespace so multiple bots don't share a user's memory. */\n    agentId: text('agent_id').notNull().default('default'),\n    /** Semantic horizon (#167): 'session' | 'user' | 'org'. Phase-1 rows = 'user'. */\n    scope: text('scope').notNull().default('user'),\n    /** Tenant id for 'org'-tier memories (shared across users). NULL otherwise. */\n    orgId: text('org_id'),\n    /** The self-contained remembered statement. */\n    text: text('text').notNull(),\n    /** Coarse kind for filtering/UI (preference/fact/goal/context/instruction). */\n    kind: text('kind').notNull().default('fact'),\n    /** Embedding for semantic recall. NULL → keyword-only mode. */\n    embedding: vector('embedding', EMBED_DIM),\n    /** Content hash (sha256 of normalised text) for idempotent dedupe. */\n    contentHash: text('content_hash').notNull(),\n    /** Provenance + GDPR cascade: which conversation produced this. */\n    sourceConversationId: text('source_conversation_id'),\n    metadata: jsonb('metadata').$type<Record<string, unknown>>(),\n    /** Optional retention TTL: hard-delete after this instant. NULL = keep. */\n    expiresAt: timestamp('expires_at', { withTimezone: true }),\n    createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),\n    updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),\n  },\n  (t) => [\n    // Drives retrieval + list (WHERE user_id = ? AND agent_id = ?).\n    index('chat_memories_user_agent_idx').on(t.userId, t.agentId),\n    // Tier-aware retrieval/list for the bound user (#167).\n    index('chat_memories_user_agent_scope_idx').on(t.userId, t.agentId, t.scope),\n    // Shared 'org'-tier reads (WHERE org_id = ? AND agent_id = ? AND scope = 'org').\n    index('chat_memories_org_idx').on(t.orgId, t.agentId, t.scope),\n    // Dedupe keys (#167/#172). Two PARTIAL unique indexes so each tier dedupes\n    // by its real owner:\n    //   • non-org tiers (session/user) dedupe per WRITER → (user, agent, scope, hash).\n    //   • org tier dedupes per TENANT → (org_id, agent, hash). Keying org rows by\n    //     user_id would let the same shared fact accumulate one row per user and\n    //     never converge; org_id is the owner of org-tier memory.\n    uniqueIndex('chat_memories_dedupe_idx')\n      .on(t.userId, t.agentId, t.scope, t.contentHash)\n      .where(sql`${t.scope} <> 'org'`),\n    uniqueIndex('chat_memories_org_dedupe_idx')\n      .on(t.orgId, t.agentId, t.contentHash)\n      .where(sql`${t.scope} = 'org'`),\n    // ANN index (created only when pgvector is available; the migration guards\n    // on the extension). Cosine distance.\n  ],\n);\n\nexport type MemoryRow = typeof memories.$inferSelect;\nexport type NewMemoryRow = typeof memories.$inferInsert;\n","/**\n * Drizzle schema for the default Postgres + pgvector KnowledgeStore.\n *\n * As with the chat schema, this is NOT the public contract — the\n * `KnowledgeStore`/`Retriever` interfaces are. It's exported so consumers on the\n * default path can run `drizzle-kit` against it and so the shipped SQL migration\n * can reference it.\n *\n * Two tables:\n *   • knowledge_sources — one row per logical source, holding `contentHash` for\n *     cheap resync diffing (is this source unchanged? → one indexed lookup).\n *   • knowledge_chunks  — the vectors + a generated tsvector for hybrid lexical\n *     search.\n *\n * The `vector(1536)` column and the generated `tsv` column + their indexes are\n * created in the shipped SQL migration (drizzle-kit can't model pgvector or a\n * GENERATED tsvector column directly). The custom `vector` type below lets the\n * store SELECT/INSERT the column through Drizzle.\n */\n\nimport {\n  pgTable,\n  text,\n  integer,\n  timestamp,\n  jsonb,\n  index,\n  uniqueIndex,\n  customType,\n} from 'drizzle-orm/pg-core';\n\n/**\n * pgvector column type. Dimension is fixed at migration time and MUST match the\n * embedder. We serialise to the `'[1,2,3]'` text form pgvector accepts, and\n * parse the same form back.\n */\nexport const vector = (name: string, dim: number) =>\n  customType<{ data: number[]; driverData: string }>({\n    dataType() {\n      return `vector(${dim})`;\n    },\n    toDriver(value: number[]): string {\n      return `[${value.join(',')}]`;\n    },\n    fromDriver(value: string): number[] {\n      // pgvector returns e.g. \"[0.1,0.2,...]\"; tolerate already-parsed arrays.\n      if (Array.isArray(value)) return value as unknown as number[];\n      return value.slice(1, -1).split(',').map(Number);\n    },\n  })(name);\n\n/**\n * Default embedding dimension (Gemini gemini-embedding-2 at output\n * dimensionality 1536, L2-normalized). Override in a host migration if you pick\n * a different model — the column width is the source of truth and must equal the\n * embedder's `dimensions`.\n */\nexport const EMBED_DIM = 1536;\n\nexport const knowledgeSources = pgTable(\n  'knowledge_sources',\n  {\n    /** `<namespace>::<source>` — stable per (namespace, source). */\n    id: text('id').primaryKey(),\n    /** Isolation boundary (agent:… / tenant:… / user:…:…). */\n    namespace: text('namespace').notNull(),\n    /** Logical source: URL / file key / slug. */\n    source: text('source').notNull(),\n    /** Coarse type for the dashboard (url/sitemap/crawl/file/text). */\n    type: text('type').notNull().default('text'),\n    title: text('title').notNull().default(''),\n    /** 'ready' | 'error' (extensible). */\n    status: text('status').notNull().default('ready'),\n    /** sha256 of the raw/cleaned source content → resync diff short-circuit. */\n    contentHash: text('content_hash').notNull(),\n    chunkCount: integer('chunk_count').notNull().default(0),\n    error: text('error'),\n    metadata: jsonb('metadata').$type<Record<string, unknown>>(),\n    createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),\n    updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),\n  },\n  (t) => [uniqueIndex('knowledge_sources_ns_source_idx').on(t.namespace, t.source)],\n);\n\nexport const knowledgeChunks = pgTable(\n  'knowledge_chunks',\n  {\n    /** `<namespace>::<source>::<chunkIndex>`. */\n    id: text('id').primaryKey(),\n    namespace: text('namespace').notNull(),\n    source: text('source').notNull(),\n    title: text('title').notNull().default(''),\n    chunkIndex: integer('chunk_index').notNull(),\n    /** The chunk text (also the basis for the generated tsvector). */\n    content: text('content').notNull(),\n    embedding: vector('embedding', EMBED_DIM).notNull(),\n    // `tsv tsvector GENERATED ALWAYS AS (to_tsvector('english', content)) STORED`\n    // is created in the SQL migration — not modelled here (Drizzle can't express\n    // a generated tsvector column). Queries reference it via raw SQL.\n    contentHash: text('content_hash').notNull(),\n    metadata: jsonb('metadata').$type<Record<string, unknown>>(),\n    createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),\n  },\n  (t) => [\n    uniqueIndex('knowledge_chunks_unique_idx').on(t.namespace, t.source, t.chunkIndex),\n    // The hot retrieval filter is WHERE namespace = ANY($1); keep it btree-indexed\n    // so the ANN scan is over a small partition, not the whole table.\n    index('knowledge_chunks_namespace_idx').on(t.namespace),\n  ],\n);\n\nexport type KnowledgeSourceRow = typeof knowledgeSources.$inferSelect;\nexport type NewKnowledgeSourceRow = typeof knowledgeSources.$inferInsert;\nexport type KnowledgeChunkRow = typeof knowledgeChunks.$inferSelect;\nexport type NewKnowledgeChunkRow = typeof knowledgeChunks.$inferInsert;\n"],"mappings":"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","names":["sql","text","messages","schema_exports","pgTable","text","timestamp","jsonb","index","uniqueIndex","pgTable","text","timestamp","jsonb","index","pgTable","text","jsonb","timestamp","index","uniqueIndex","text","sql"]}