"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
function _export(target, all) {
    for(var name in all)Object.defineProperty(target, name, {
        enumerable: true,
        get: all[name]
    });
}
_export(exports, {
    extractDataUrlComponents: function() {
        return extractDataUrlComponents;
    },
    extractImage: function() {
        return extractImage;
    },
    extractSingleText: function() {
        return extractSingleText;
    },
    extractText: function() {
        return extractText;
    },
    streamCallbacks: function() {
        return streamCallbacks;
    },
    streamConverter: function() {
        return streamConverter;
    },
    streamReducer: function() {
        return streamReducer;
    },
    wrapLLMEvent: function() {
        return wrapLLMEvent;
    }
});
const _env = require("@llamaindex/env");
const _CallbackManager = require("../internal/settings/CallbackManager.js");
async function* streamConverter(stream, converter) {
    for await (const data of stream){
        const newData = converter(data);
        if (newData === null) {
            return;
        }
        yield newData;
    }
}
async function* streamCallbacks(stream, callbacks) {
    let value;
    for await (value of stream){
        yield value;
    }
    if (callbacks.finished) {
        callbacks.finished(value);
    }
}
async function* streamReducer(params) {
    let value = params.initialValue;
    for await (const data of params.stream){
        value = params.reducer(value, data);
        yield data;
    }
    if (params.finished) {
        params.finished(value);
    }
}
function extractText(message) {
    if (typeof message !== "string" && !Array.isArray(message)) {
        console.warn("extractText called with non-MessageContent message, this is likely a bug.");
        return `${message}`;
    } else if (typeof message !== "string" && Array.isArray(message)) {
        // message is of type MessageContentDetail[] - retrieve just the text parts and concatenate them
        // so we can pass them to the context generator
        return message.filter((c)=>c.type === "text").map((c)=>c.text).join("\n\n");
    } else {
        return message;
    }
}
function extractSingleText(message) {
    if (message.type === "text") {
        return message.text;
    }
    return null;
}
function extractImage(message) {
    if (message.type === "image_url") {
        return new URL(message.image_url.url);
    }
    return null;
}
const extractDataUrlComponents = (dataUrl)=>{
    const parts = dataUrl.split(";base64,");
    if (parts.length !== 2 || !parts[0].startsWith("data:")) {
        throw new Error("Invalid data URL");
    }
    const mimeType = parts[0].slice(5);
    const base64 = parts[1];
    return {
        mimeType,
        base64
    };
};
function wrapLLMEvent(originalMethod, _context) {
    return async function withLLMEvent(...params) {
        const id = (0, _env.randomUUID)();
        (0, _CallbackManager.getCallbackManager)().dispatchEvent("llm-start", {
            payload: {
                id,
                messages: params[0].messages
            }
        });
        const response = await originalMethod.call(this, ...params);
        if (Symbol.asyncIterator in response) {
            // save snapshot to restore it after the response is done
            const snapshot = _env.AsyncLocalStorage.snapshot();
            const originalAsyncIterator = {
                [Symbol.asyncIterator]: response[Symbol.asyncIterator].bind(response)
            };
            response[Symbol.asyncIterator] = async function*() {
                const finalResponse = {
                    raw: [],
                    message: {
                        content: "",
                        role: "assistant",
                        options: {}
                    }
                };
                let firstOne = false;
                for await (const chunk of originalAsyncIterator){
                    if (!firstOne) {
                        firstOne = true;
                        finalResponse.message.content = chunk.delta;
                    } else {
                        finalResponse.message.content += chunk.delta;
                    }
                    if (chunk.options) {
                        finalResponse.message.options = {
                            ...finalResponse.message.options,
                            ...chunk.options
                        };
                    }
                    (0, _CallbackManager.getCallbackManager)().dispatchEvent("llm-stream", {
                        payload: {
                            id,
                            chunk
                        }
                    });
                    finalResponse.raw.push(chunk);
                    yield chunk;
                }
                snapshot(()=>{
                    (0, _CallbackManager.getCallbackManager)().dispatchEvent("llm-end", {
                        payload: {
                            id,
                            response: finalResponse
                        }
                    });
                });
            };
        } else {
            (0, _CallbackManager.getCallbackManager)().dispatchEvent("llm-end", {
                payload: {
                    id,
                    response
                }
            });
        }
        return response;
    };
}
