"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.LanguagePlugin = void 0;
const utils_1 = require("../utils");
const minimatch_1 = require("minimatch");
const config_1 = require("../config");
const types_1 = require("../types");
const PluginBase_1 = require("./PluginBase");
class LanguagePlugin extends PluginBase_1.PluginBase {
    static meta = {
        key: "language",
        name: "Language Plugin",
        requires: [],
    };
    meta = LanguagePlugin.meta;
    eventService;
    constructor(context) {
        super(context);
        this.eventService = context.Events;
        this.setupEventHandlers();
    }
    async setupEventHandlers() {
        try {
            const languageConfig = await (0, config_1.getLanguageConfig)();
            const allEvents = new Set();
            Object.values(languageConfig).forEach((termConfig) => {
                if (termConfig.events) {
                    termConfig.events.forEach((event) => allEvents.add(event));
                }
            });
            const fileEvents = Array.from(allEvents).filter((e) => e.startsWith("file"));
            const otherEvents = Array.from(allEvents).filter((e) => !e.startsWith("file"));
            fileEvents.forEach((eventType) => {
                this.eventService.on(eventType, async (eventData) => {
                    await this.handleFileEvent(eventType, eventData);
                });
            });
            otherEvents.forEach((eventType) => {
                this.eventService.on(eventType, async (eventData) => {
                    await this.handleGenericEvent(eventType, eventData);
                });
            });
        }
        catch (error) {
            this.log("LANGUAGE PLUGIN: Error setting up event handlers: " + error, "error");
        }
    }
    async resolveSources(matchingTerms) {
        const languageConfig = await (0, config_1.getLanguageConfig)();
        const config = await (0, config_1.getConfig)();
        const sources = matchingTerms.flatMap((term) => languageConfig[term].sources);
        const contexts = [];
        const filesToLoad = sources
            .filter((f) => f.kind === "file")
            .map((f) => f.data)
            .flat();
        const fileContents = await Promise.all(filesToLoad.map(async (filePath) => {
            const exists = await (0, utils_1.fileExists)(filePath);
            if (!exists) {
                return { filePath, content: `File ${filePath} does not exist` };
            }
            const stat = await (0, utils_1.fileStat)(filePath);
            if (stat.isDirectory()) {
                throw new Error(`Cannot read directories: ${filePath}`);
            }
            const content = (await (0, utils_1.readFile)(filePath, "utf8")).toString();
            return { filePath, content };
        }));
        contexts.push(...fileContents);
        const textContexts = matchingTerms
            .flatMap((term) => languageConfig[term].sources.filter((s) => s.kind === "text"))
            .map((s) => s.data);
        contexts.push(...textContexts);
        const plugins = this.context.Plugins.listPlugins();
        for (const plugin of plugins) {
            if ((0, types_1.getEnabledPlugins)(config.plugins).includes(plugin)) {
                const matchingSources = sources.filter((s) => s.kind === plugin);
                if (matchingSources.length === 0) {
                    continue;
                }
                const data = matchingSources
                    .map((s) => s.data)
                    .flat()
                    .join("\n");
                const pluginContext = await this.context.Plugins.call(plugin, data);
                contexts.push(...pluginContext);
            }
        }
        return contexts;
    }
    async handleFileEvent(eventType, eventData) {
        try {
            const languageConfig = await (0, config_1.getLanguageConfig)();
            const filePath = eventData?.filePath || eventData?.path;
            const fileContent = await (0, utils_1.readFile)(filePath, "utf8");
            if (!filePath) {
                return;
            }
            const matchingFileTerms = Object.entries(languageConfig)
                .filter(([term, config]) => {
                if (!config.events || !config.events.includes(eventType)) {
                    return false;
                }
                const patterns = term.split(",").map((p) => p.trim());
                const matches = patterns.some((pattern) => (0, minimatch_1.minimatch)(filePath, pattern) ||
                    fileContent
                        .toString()
                        .toLowerCase()
                        .includes(pattern.toLowerCase()));
                return matches;
            })
                .map(([term]) => term);
            if (matchingFileTerms.length > 0) {
                const resolvedSources = await this.resolveSources(matchingFileTerms);
                const message = `These terms are directly related to the file operation so be sure to contextualize your response to this information.`;
                this.emitAgentMessage(eventType, matchingFileTerms, resolvedSources, message);
            }
        }
        catch (error) {
            this.log("LANGUAGE PLUGIN: Error handling file event: " + error, "error");
        }
    }
    emitAgentMessage(eventType, matchingTerms, resolvedSources, context) {
        this.eventService.emit("agent:msg", `<Workflow>
      ${JSON.stringify({
            type: "language_context_trigger",
            eventType,
            matchingTerms,
            resolvedSources,
            contextMessage: `LANGUAGE PLUGIN: Agent event ${eventType} triggered contextual expansions for terms: ${matchingTerms.join(", ")}.
            Expanded context: ${JSON.stringify(resolvedSources)}
            These terms are directly related to what the agent is discussing so be sure to contextualize your response to this information.
            ${context}
        `,
        })}
      </Workflow>
      `);
    }
    async handleGenericEvent(eventType, eventData) {
        try {
            const languageConfig = await (0, config_1.getLanguageConfig)();
            const userPrompt = JSON.stringify(eventData);
            const isJsonObj = userPrompt.startsWith("{") && userPrompt.endsWith("}");
            if (userPrompt.includes("language_context_trigger")) {
                return;
            }
            const matchingTerms = await this.getMatchingTerms(userPrompt);
            if (matchingTerms.length > 0) {
                const resolvedSources = await this.resolveSources(matchingTerms);
                const message = `These terms are directly related to the agent's message so be sure to contextualize your response to this information.`;
                this.emitAgentMessage(eventType, matchingTerms, resolvedSources, message);
            }
        }
        catch (error) {
            this.log("LANGUAGE PLUGIN: Error handling agent event: " + error, "error");
        }
    }
    async embed(userPrompt) {
        return [];
    }
    async getMatchingTerms(userPrompt) {
        const languageConfig = await (0, config_1.getLanguageConfig)();
        const terms = Object.keys(languageConfig);
        const matchingTerms = terms.filter((term) => {
            return term.split(",").some((pattern) => {
                const trimmedPattern = pattern.trim();
                return trimmedPattern.includes("*")
                    ? (0, minimatch_1.minimatch)(userPrompt, trimmedPattern)
                    : userPrompt.toLowerCase().includes(trimmedPattern.toLowerCase());
            });
        });
        return matchingTerms;
    }
    async call(userPrompt) {
        const matchingTerms = await this.getMatchingTerms(userPrompt);
        if (matchingTerms.length === 0) {
            return "LANGUAGE PLUGIN: No matching terms found";
        }
        const contexts = await this.resolveSources(matchingTerms);
        this.log("LANGUAGE PLUGIN: Matching terms found: " + matchingTerms);
        const output = contexts.every((c) => typeof c === "string")
            ? contexts.join("")
            : JSON.stringify(contexts, null, 2);
        return `LANGUAGE PLUGIN: The user mentioned these terms triggering contextual expansions ${matchingTerms} expanded to: ${output}
    These terms are directly related to what the user is asking about so be sure to contextualize your response to this information.
    `;
    }
}
exports.LanguagePlugin = LanguagePlugin;
//# sourceMappingURL=language.js.map