import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);

// src/index/vectors.ts
import Database from "better-sqlite3";
import * as sqliteVec from "sqlite-vec";
var VectorIndex = class {
  db;
  dimensions;
  constructor(dbPath, dimensions) {
    this.dimensions = dimensions;
    this.db = new Database(dbPath);
    sqliteVec.load(this.db);
    this.init();
  }
  init() {
    this.db.exec(`
      CREATE TABLE IF NOT EXISTS vec_metadata (
        id TEXT PRIMARY KEY,
        type TEXT NOT NULL DEFAULT '',
        importance TEXT NOT NULL DEFAULT '',
        session_id TEXT NOT NULL DEFAULT '',
        file_path TEXT NOT NULL DEFAULT '',
        branch TEXT NOT NULL DEFAULT '',
        created TEXT NOT NULL DEFAULT (datetime('now'))
      );
      CREATE VIRTUAL TABLE IF NOT EXISTS vec_embeddings USING vec0(
        id TEXT PRIMARY KEY,
        embedding float[${this.dimensions}]
      );
    `);
  }
  upsert(id, embedding, metadata = {}) {
    this.db.prepare("DELETE FROM vec_metadata WHERE id = ?").run(id);
    this.db.prepare("DELETE FROM vec_embeddings WHERE id = ?").run(id);
    this.db.prepare(
      "INSERT INTO vec_metadata (id, type, importance, session_id, file_path, branch) VALUES (?, ?, ?, ?, ?, ?)"
    ).run(id, metadata.type ?? "", metadata.importance ?? "", metadata.session_id ?? "", metadata.file_path ?? "", metadata.branch ?? "");
    this.db.prepare("INSERT INTO vec_embeddings (id, embedding) VALUES (?, ?)").run(id, new Float32Array(embedding));
  }
  search(query, options = {}) {
    const limit = options.limit ?? 10;
    const knnParams = [new Float32Array(query), limit * 4];
    const knnRows = this.db.prepare(`
      SELECT id, distance
      FROM vec_embeddings
      WHERE embedding MATCH ?
      ORDER BY distance
      LIMIT ?
    `).all(...knnParams);
    if (knnRows.length === 0) return [];
    const metaConditions = ["id IN (" + knnRows.map(() => "?").join(",") + ")"];
    const metaParams = knnRows.map((r) => r.id);
    if (options.type) {
      metaConditions.push("type = ?");
      metaParams.push(options.type);
    }
    if (options.importance) {
      metaConditions.push("importance = ?");
      metaParams.push(options.importance);
    }
    const metaRows = this.db.prepare(`
      SELECT id, type, importance, session_id, file_path, branch
      FROM vec_metadata
      WHERE ${metaConditions.join(" AND ")}
    `).all(...metaParams);
    const metaMap = new Map(metaRows.map((m) => [m.id, m]));
    const scored = knnRows.filter((r) => metaMap.has(r.id)).map((r) => {
      const m = metaMap.get(r.id);
      return {
        id: r.id,
        similarity: 1 - r.distance,
        metadata: { type: m.type, importance: m.importance, session_id: m.session_id, file_path: m.file_path, branch: m.branch }
      };
    });
    if (scored.length === 0) return [];
    const topScore = scored[0].similarity;
    const threshold = options.relativeThreshold ?? 0.5;
    const floor = topScore * threshold;
    return scored.filter((r) => r.similarity >= floor).slice(0, limit);
  }
  /** Retrieve the stored embedding for a given ID, or null if not found. */
  getEmbedding(id) {
    const row = this.db.prepare("SELECT embedding FROM vec_embeddings WHERE id = ?").get(id);
    if (!row) return null;
    return Array.from(new Float32Array(row.embedding.buffer, row.embedding.byteOffset, row.embedding.byteLength / 4));
  }
  /** Check whether an embedding exists for the given ID. */
  has(id) {
    const row = this.db.prepare("SELECT 1 FROM vec_metadata WHERE id = ?").get(id);
    return row !== void 0;
  }
  delete(id) {
    this.db.prepare("DELETE FROM vec_metadata WHERE id = ?").run(id);
    this.db.prepare("DELETE FROM vec_embeddings WHERE id = ?").run(id);
  }
  count() {
    return this.db.prepare("SELECT COUNT(*) as c FROM vec_metadata").get().c;
  }
  close() {
    this.db.close();
  }
};

export {
  VectorIndex
};
//# sourceMappingURL=chunk-4RMSHZE4.js.map