"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, {
  MemoryVectorManager: () => MemoryVectorManager
});
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 observationToText(obs) {
  const parts = [`[${obs.kind}] ${obs.content}`];
  if (obs.tags && obs.tags.length > 0) {
    parts.push(`tags: ${obs.tags.join(", ")}`);
  }
  const text = parts.join("\n");
  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 MemoryVectorManager {
  constructor(config, memDb) {
    this.config = config;
    this.memDb = memDb;
    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 observation and store in mem_vectors.
   */
  async embedObservation(obs) {
    if (!this.isEnabled()) return;
    try {
      const text = observationToText(obs);
      const embedding = await this.embed(text);
      if (embedding) {
        const buffer = Buffer.from(embedding.buffer);
        this.memDb.insertVector(obs.id, buffer, this.modelName);
      }
    } catch (err) {
      (0, import_errors.logWarn)(`Failed to embed observation ${obs.id}: ${err}`);
    }
  }
  /**
   * Embed multiple observations in batch.
   */
  async embedBatch(observations) {
    if (!this.isEnabled()) return 0;
    let embedded = 0;
    for (const obs of observations) {
      try {
        await this.embedObservation(obs);
        embedded++;
      } catch (err) {
        (0, import_errors.logWarn)(`Failed to embed observation ${obs.id}: ${err}`);
      }
    }
    return embedded;
  }
  /**
   * Vector search over memory observations.
   * Falls back to empty results if embeddings are disabled or model mismatches.
   */
  async search(query, limit = 10) {
    if (!this.isEnabled()) return [];
    try {
      const queryEmbedding = await this.embed(query);
      if (!queryEmbedding) return [];
      const allVectors = this.memDb.getAllVectors(this.modelName);
      if (allVectors.length === 0) return [];
      const scored = [];
      for (const { observationId, embedding } of allVectors) {
        const vec = new Float32Array(embedding.buffer, embedding.byteOffset, embedding.byteLength / 4);
        const score = cosine(queryEmbedding, vec);
        scored.push({ observationId, score });
      }
      scored.sort((a, b) => b.score - a.score);
      const topN = scored.slice(0, limit);
      const results = [];
      for (const { observationId, score } of topN) {
        const obs = this.memDb.getObservation(observationId);
        if (obs) {
          results.push({ observation: obs, score, scoreSource: "vector" });
        }
      }
      return results;
    } catch (err) {
      (0, import_errors.logError)("Memory vector search failed", { error: err });
      return [];
    }
  }
  /**
   * Check if there are vectors with a mismatched model.
   */
  hasModelMismatch() {
    return this.memDb.getVectorModelMismatch(this.modelName) > 0;
  }
  /**
   * Re-embed all observations with the current model.
   */
  async reembed(batchSize = 32) {
    this.memDb.deleteVectors();
    const db = this.memDb.db;
    const rows = db.all("SELECT * FROM mem_observations ORDER BY created_at");
    const observations = rows.map((row) => ({
      id: row.id,
      sessionId: row.session_id ?? void 0,
      content: row.content,
      contentRaw: row.content_raw ?? void 0,
      contentHash: row.content_hash,
      kind: row.kind,
      source: row.source,
      tags: row.tags ? JSON.parse(row.tags) : void 0,
      createdAt: row.created_at
    }));
    let embedded = 0;
    for (let i = 0; i < observations.length; i += batchSize) {
      const batch = observations.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)(`Embedding failed: ${err}`);
      return null;
    }
  }
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  MemoryVectorManager
});
//# sourceMappingURL=vectors.js.map
