"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
Object.defineProperty(exports, "PineconeVectorStore", {
    enumerable: true,
    get: function() {
        return PineconeVectorStore;
    }
});
const _types = require("./types.js");
const _env = require("@llamaindex/env");
const _utils = require("./utils.js");
class PineconeVectorStore extends _types.VectorStoreBase {
    storesText = true;
    /*
    FROM @pinecone-database/pinecone:
      PINECONE_API_KEY="your_api_key"
      PINECONE_ENVIRONMENT="your_environment"
    Our addition:
      PINECONE_INDEX_NAME="llama"
      PINECONE_CHUNK_SIZE=100
  */ db;
    indexName;
    namespace;
    chunkSize;
    textKey;
    constructor(params){
        super(params?.embedModel);
        this.indexName = params?.indexName ?? (0, _env.getEnv)("PINECONE_INDEX_NAME") ?? "llama";
        this.namespace = params?.namespace ?? (0, _env.getEnv)("PINECONE_NAMESPACE") ?? "";
        this.chunkSize = params?.chunkSize ?? Number.parseInt((0, _env.getEnv)("PINECONE_CHUNK_SIZE") ?? "100");
        this.textKey = params?.textKey ?? "text";
    }
    async getDb() {
        if (!this.db) {
            const { Pinecone } = await import("@pinecone-database/pinecone");
            this.db = await new Pinecone();
        }
        return Promise.resolve(this.db);
    }
    /**
   * Connects to the Pinecone account specified in environment vars.
   * This method also checks and creates the named index if not found.
   * @returns Pinecone client, or the error encountered while connecting/setting up.
   */ client() {
        return this.getDb();
    }
    async index() {
        const db = await this.getDb();
        return db.index(this.indexName).namespace(this.namespace);
    }
    /**
   * Delete all records for the current index.
   * NOTE: This operation is not supported by Pinecone for "Starter" (free) indexes.
   * @returns The result of the delete query.
   */ async clearIndex() {
        const idx = await this.index();
        return await idx.deleteAll();
    }
    /**
   * Adds vector record(s) to the table.
   * @TODO Does not create or insert sparse vectors.
   * @param embeddingResults The Nodes to be inserted, optionally including metadata tuples.
   * @returns Due to limitations in the Pinecone client, does not return the upserted ID list, only a Promise resolve/reject.
   */ async add(embeddingResults) {
        if (embeddingResults.length == 0) {
            return Promise.resolve([]);
        }
        const idx = await this.index();
        const nodes = embeddingResults.map(this.nodeToRecord);
        for(let i = 0; i < nodes.length; i += this.chunkSize){
            const chunk = nodes.slice(i, i + this.chunkSize);
            const result = await this.saveChunk(idx, chunk);
            if (!result) {
                return Promise.reject();
            }
        }
        return Promise.resolve([]);
    }
    async saveChunk(idx, chunk) {
        try {
            await idx.upsert(chunk);
            return true;
        } catch (err) {
            const msg = `${err}`;
            console.log(msg, err);
            return false;
        }
    }
    /**
   * Deletes a single record from the database by id.
   * NOTE: Uses the collection property controlled by setCollection/getCollection.
   * @param refDocId Unique identifier for the record to delete.
   * @param deleteKwargs Required by VectorStore interface.  Currently ignored.
   * @returns Promise that resolves if the delete query did not throw an error.
   */ async delete(refDocId, deleteKwargs) {
        const idx = await this.index();
        return idx.deleteOne(refDocId);
    }
    /**
   * Query the vector store for the closest matching data to the query embeddings
   * @TODO QUERY TYPES
   * @param query The VectorStoreQuery to be used
   * @param options Required by VectorStore interface.  Currently ignored.
   * @returns Zero or more Document instances with data from the vector store.
   */ async query(query, _options) {
        const filter = this.toPineconeFilter(query.filters);
        const defaultOptions = {
            vector: query.queryEmbedding,
            topK: query.similarityTopK,
            includeValues: true,
            includeMetadata: true,
            filter: filter
        };
        const idx = await this.index();
        const results = await idx.query(defaultOptions);
        const idList = results.matches.map((row)=>row.id);
        const records = await idx.fetch(idList);
        const rows = Object.values(records.records);
        const nodes = rows.map((row)=>{
            const node = (0, _utils.metadataDictToNode)(row.metadata, {
                fallback: {
                    id: row.id,
                    text: this.textFromResultRow(row),
                    metadata: this.metaWithoutText(row.metadata),
                    embedding: row.values
                }
            });
            return node;
        });
        const ret = {
            nodes: nodes,
            similarities: results.matches.map((row)=>row.score || 999),
            ids: results.matches.map((row)=>row.id)
        };
        return Promise.resolve(ret);
    }
    /**
   * Required by VectorStore interface.  Currently ignored.
   * @param persistPath
   * @param fs
   * @returns Resolved Promise.
   */ persist(persistPath) {
        return Promise.resolve();
    }
    toPineconeFilter(stdFilters) {
        return stdFilters?.filters?.reduce((carry, item)=>{
            carry[item.key] = item.value;
            return carry;
        }, {});
    }
    textFromResultRow(row) {
        return row.metadata?.[this.textKey] ?? "";
    }
    metaWithoutText(meta) {
        return Object.keys(meta).filter((key)=>key != this.textKey).reduce((acc, key)=>{
            acc[key] = meta[key];
            return acc;
        }, {});
    }
    nodeToRecord(node) {
        const id = node.id_.length ? node.id_ : null;
        return {
            id: id,
            values: node.getEmbedding(),
            metadata: (0, _utils.nodeToMetadata)(node)
        };
    }
}
