import { BaseChatMemory } from "./chat_memory.js";
/**
 * Class that manages and manipulates previous chat messages. It extends
 * from the BaseChatMemory class and implements the CombinedMemoryInput
 * interface.
 */
export class CombinedMemory extends BaseChatMemory {
    constructor(fields) {
        super({
            chatHistory: fields?.chatHistory,
            returnMessages: fields?.returnMessages ?? false,
            inputKey: fields?.inputKey,
            outputKey: fields?.outputKey,
        });
        Object.defineProperty(this, "humanPrefix", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: "Human"
        });
        Object.defineProperty(this, "aiPrefix", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: "AI"
        });
        Object.defineProperty(this, "memoryKey", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: "history"
        });
        Object.defineProperty(this, "memories", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: []
        });
        this.memories = fields?.memories ?? this.memories;
        this.humanPrefix = fields?.humanPrefix ?? this.humanPrefix;
        this.aiPrefix = fields?.aiPrefix ?? this.aiPrefix;
        this.memoryKey = fields?.memoryKey ?? this.memoryKey;
        this.checkRepeatedMemoryVariable();
        this.checkInputKey();
    }
    /**
     * Checks for repeated memory variables across all memory objects. Throws
     * an error if any are found.
     */
    checkRepeatedMemoryVariable() {
        const allVariables = [];
        for (const memory of this.memories) {
            const overlap = allVariables.filter((x) => memory.memoryKeys.includes(x));
            if (overlap.length > 0) {
                throw new Error(`The same variables ${[
                    ...overlap,
                ]} are found in multiple memory objects, which is not allowed by CombinedMemory.`);
            }
            allVariables.push(...memory.memoryKeys);
        }
    }
    /**
     * Checks if input keys are set for all memory objects. Logs a warning if
     * any are missing.
     */
    checkInputKey() {
        for (const memory of this.memories) {
            if (memory.chatHistory !== undefined &&
                memory.inputKey === undefined) {
                console.warn(`When using CombinedMemory, input keys should be set so the input is known. Was not set on ${memory}.`);
            }
        }
    }
    /**
     * Loads memory variables from all memory objects.
     * @param inputValues Input values to load memory variables from.
     * @returns Promise that resolves with an object containing the loaded memory variables.
     */
    async loadMemoryVariables(inputValues) {
        let memoryData = {};
        for (const memory of this.memories) {
            const data = await memory.loadMemoryVariables(inputValues);
            memoryData = {
                ...memoryData,
                ...data,
            };
        }
        return memoryData;
    }
    /**
     * Saves the context to all memory objects.
     * @param inputValues Input values to save.
     * @param outputValues Output values to save.
     * @returns Promise that resolves when the context has been saved to all memory objects.
     */
    async saveContext(inputValues, outputValues) {
        for (const memory of this.memories) {
            await memory.saveContext(inputValues, outputValues);
        }
    }
    /**
     * Clears all memory objects.
     * @returns Promise that resolves when all memory objects have been cleared.
     */
    async clear() {
        for (const memory of this.memories) {
            if (typeof memory.clear === "function") {
                await memory.clear();
            }
        }
    }
    get memoryKeys() {
        const memoryKeys = [];
        for (const memory of this.memories) {
            memoryKeys.push(...memory.memoryKeys);
        }
        return memoryKeys;
    }
}
