"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var vectors_exports = {};
__export(vectors_exports, {
  DocsVectorManager: () => DocsVectorManager
});
module.exports = __toCommonJS(vectors_exports);
var import_errors = require("../errors");
const MAX_TOKEN_CHARS = 2e3;
let transformers = null;
let pipeline = null;
let pipelineModel = null;
async function getTransformers() {
  if (!transformers) {
    transformers = await import("@huggingface/transformers");
  }
  return transformers;
}
async function getPipeline(modelName, cacheDir) {
  if (pipeline && pipelineModel === modelName) return pipeline;
  const tf = await getTransformers();
  pipeline = await tf.pipeline("feature-extraction", modelName, {
    cache_dir: cacheDir,
    dtype: "fp32"
  });
  pipelineModel = modelName;
  return pipeline;
}
function sectionToText(section) {
  const parts = [section.title];
  if (section.summary) parts.push(section.summary);
  const text = parts.join(": ");
  return text.length > MAX_TOKEN_CHARS ? text.slice(0, MAX_TOKEN_CHARS) : text;
}
function cosine(a, b) {
  let dot = 0, na = 0, nb = 0;
  for (let i = 0; i < a.length; i++) {
    dot += a[i] * b[i];
    na += a[i] * a[i];
    nb += b[i] * b[i];
  }
  const denom = Math.sqrt(na) * Math.sqrt(nb);
  return denom === 0 ? 0 : dot / denom;
}
class DocsVectorManager {
  constructor(config, db) {
    this.config = config;
    this.db = db;
    this.modelName = config.embeddingModel ?? "nomic-ai/nomic-embed-text-v1.5";
    const { homedir } = require("os");
    const path = require("path");
    this.cacheDir = path.join(homedir(), ".kirograph", "models");
  }
  /**
   * Check if embeddings are enabled in config.
   */
  isEnabled() {
    return !!this.config.enableEmbeddings;
  }
  /**
   * Embed a single doc section and store in doc_vectors.
   */
  async embedSection(section) {
    if (!this.isEnabled()) return;
    try {
      const text = sectionToText(section);
      const embedding = await this.embed(text);
      if (embedding) {
        const buffer = Buffer.from(embedding.buffer);
        this.db.run(
          "INSERT OR REPLACE INTO doc_vectors (section_id, embedding, model, created_at) VALUES (?, ?, ?, ?)",
          [section.id, buffer, this.modelName, Date.now()]
        );
      }
    } catch (err) {
      (0, import_errors.logWarn)(`Failed to embed doc section ${section.id}: ${err}`);
    }
  }
  /**
   * Embed multiple sections in batch.
   */
  async embedBatch(sections) {
    if (!this.isEnabled()) return 0;
    let embedded = 0;
    for (const section of sections) {
      try {
        await this.embedSection(section);
        embedded++;
      } catch (err) {
        (0, import_errors.logWarn)(`Failed to embed doc section ${section.id}: ${err}`);
      }
    }
    return embedded;
  }
  /**
   * Vector search over doc sections.
   * Returns scored sections sorted by cosine similarity.
   * Falls back to empty results if embeddings are disabled.
   */
  async search(query, limit = 10) {
    if (!this.isEnabled()) return [];
    try {
      const queryEmbedding = await this.embed(query);
      if (!queryEmbedding) return [];
      const allVectors = this.db.all(
        "SELECT section_id, embedding FROM doc_vectors WHERE model = ?",
        [this.modelName]
      );
      if (allVectors.length === 0) return [];
      const scored = [];
      for (const { section_id, embedding } of allVectors) {
        const vec = new Float32Array(
          embedding.buffer,
          embedding.byteOffset,
          embedding.byteLength / 4
        );
        const score = cosine(queryEmbedding, vec);
        scored.push({ sectionId: section_id, score });
      }
      scored.sort((a, b) => b.score - a.score);
      return scored.slice(0, limit);
    } catch (err) {
      (0, import_errors.logError)("Docs vector search failed", { error: err });
      return [];
    }
  }
  /**
   * Check if there are vectors with a mismatched model.
   */
  hasModelMismatch() {
    const mismatch = this.db.get(
      "SELECT COUNT(*) as cnt FROM doc_vectors WHERE model != ?",
      [this.modelName]
    )?.cnt ?? 0;
    return mismatch > 0;
  }
  /**
   * Get vector stats.
   */
  getStats() {
    const total = this.db.get("SELECT COUNT(*) as cnt FROM doc_vectors")?.cnt ?? 0;
    const currentModel = this.db.get(
      "SELECT COUNT(*) as cnt FROM doc_vectors WHERE model = ?",
      [this.modelName]
    )?.cnt ?? 0;
    return { total, currentModel, mismatch: total - currentModel };
  }
  /**
   * Re-embed all doc sections with the current model.
   */
  async reembed(batchSize = 32) {
    this.db.run("DELETE FROM doc_vectors");
    const rows = this.db.all("SELECT * FROM doc_sections ORDER BY file_path, position");
    const sections = rows.map((row) => ({
      id: row.id,
      filePath: row.file_path,
      title: row.title,
      level: row.level,
      parentId: row.parent_id ?? null,
      summary: row.summary ?? null,
      byteStart: row.byte_start,
      byteEnd: row.byte_end,
      contentHash: row.content_hash,
      tags: row.tags ? JSON.parse(row.tags) : [],
      position: row.position,
      updatedAt: row.updated_at
    }));
    let embedded = 0;
    for (let i = 0; i < sections.length; i += batchSize) {
      const batch = sections.slice(i, i + batchSize);
      embedded += await this.embedBatch(batch);
    }
    return embedded;
  }
  // ── Private ────────────────────────────────────────────────────────────────
  async embed(text) {
    try {
      const pipe = await getPipeline(this.modelName, this.cacheDir);
      const output = await pipe(text, { pooling: "mean", normalize: true });
      return output.data;
    } catch (err) {
      (0, import_errors.logDebug)(`Doc embedding failed: ${err}`);
      return null;
    }
  }
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  DocsVectorManager
});
//# sourceMappingURL=vectors.js.map
