"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.mask = mask;
const constants_1 = require("./constants");
const openinference_semantic_conventions_1 = require("@arizeai/openinference-semantic-conventions");
/**
 * Masks (redacts) input text in LLM input messages.
 * Will mask information stored under the key `llm.input_messages.[i].message.content`.
 * @example
 * ```typescript
 *  maskInputTextRule.condition({
 *      config: {hideInputText: true},
 *      key: "llm.input_messages.[i].message.content"
 *  }) // returns true so the rule applies and the value will be redacted
 */
const maskInputTextRule = {
    condition: ({ config, key }) => config.hideInputText &&
        key.includes(openinference_semantic_conventions_1.SemanticConventions.LLM_INPUT_MESSAGES) &&
        key.includes(openinference_semantic_conventions_1.SemanticConventions.MESSAGE_CONTENT) &&
        !key.includes(openinference_semantic_conventions_1.SemanticConventions.MESSAGE_CONTENTS),
    action: () => constants_1.REDACTED_VALUE,
};
/**
 * Masks (redacts) output text in LLM output messages.
 * Will mask information stored under the key `llm.output_messages.[i].message.content`.
 * @example
 * ```typescript
 *  maskOutputTextRule.condition({
 *      config: {hideOutputText: true},
 *      key: "llm.output_messages.[i].message.content"
 *  }) // returns true so the rule applies and the value will be redacted
 * ```
 */
const maskOutputTextRule = {
    condition: ({ config, key }) => config.hideOutputText &&
        key.includes(openinference_semantic_conventions_1.SemanticConventions.LLM_OUTPUT_MESSAGES) &&
        key.includes(openinference_semantic_conventions_1.SemanticConventions.MESSAGE_CONTENT) &&
        !key.includes(openinference_semantic_conventions_1.SemanticConventions.MESSAGE_CONTENTS),
    action: () => constants_1.REDACTED_VALUE,
};
/**
 * Masks (redacts) input text content in LLM input messages.
 * Will mask information stored under the key `llm.input_messages.[i].message.contents.[j].message_content.text`.
 * @example
 * ```typescript
 *  maskOutputTextRule.condition({
 *      config: {hideInputText: true},
 *      key: "llm.input_messages.[i].message.contents.[j].message_content.text"
 *  }) // returns true so the rule applies and the value will be redacted
 */
const maskInputTextContentRule = {
    condition: ({ config, key }) => config.hideInputText &&
        key.includes(openinference_semantic_conventions_1.SemanticConventions.LLM_INPUT_MESSAGES) &&
        key.includes(openinference_semantic_conventions_1.SemanticConventions.MESSAGE_CONTENT_TEXT),
    action: () => constants_1.REDACTED_VALUE,
};
/**
 * Masks (redacts) output text content in LLM output messages.
 * @example
 * ```typescript
 *  maskOutputTextRule.condition({
 *      config: {hideOutputText: true},
 *      key: "llm.output_messages.[i].message.contents.[j].message_content.text"
 *  }) // returns true so the rule applies and the value will be redacted
 */
const maskOutputTextContentRule = {
    condition: ({ config, key }) => config.hideOutputText &&
        key.includes(openinference_semantic_conventions_1.SemanticConventions.LLM_OUTPUT_MESSAGES) &&
        key.includes(openinference_semantic_conventions_1.SemanticConventions.MESSAGE_CONTENT_TEXT),
    action: () => constants_1.REDACTED_VALUE,
};
/**
 * Masks (removes) input images in LLM input messages.
 * @example
 * ```typescript
 *  maskOutputTextRule.condition({
 *      config: {hideInputImages: true},
 *      key: "llm.input_messages.[i].message.contents.[j].message_content.image"
 *  }) // returns true so the rule applies and the value will be removed
 */
const maskInputImagesRule = {
    condition: ({ config, key }) => config.hideInputImages &&
        key.includes(openinference_semantic_conventions_1.SemanticConventions.LLM_INPUT_MESSAGES) &&
        key.includes(openinference_semantic_conventions_1.SemanticConventions.MESSAGE_CONTENT_IMAGE),
    action: () => undefined,
};
function isBase64Url(url) {
    return (typeof url === "string" &&
        url.startsWith("data:image/") &&
        url.includes("base64"));
}
/**
 * Masks (redacts) base64 images that are too long.
 *  * @example
 * ```typescript
 *  maskOutputTextRule.condition({
 *      config: {base64ImageMaxLength: 10},
 *      key: "llm.input_messages.[i].message.contents.[j].message_content.image.url",
 *      value: "data:image/base64,verylongbase64string"
 *  }) // returns true so the rule applies and the value will be redacted
 */
const maskLongBase64ImageRule = {
    condition: ({ config, key, value }) => typeof value === "string" &&
        isBase64Url(value) &&
        value.length > config.base64ImageMaxLength &&
        key.includes(openinference_semantic_conventions_1.SemanticConventions.LLM_INPUT_MESSAGES) &&
        key.includes(openinference_semantic_conventions_1.SemanticConventions.MESSAGE_CONTENT_IMAGE) &&
        key.endsWith(openinference_semantic_conventions_1.SemanticConventions.IMAGE_URL),
    action: () => constants_1.REDACTED_VALUE,
};
/**
 * Masks (removes) embedding vectors.
 *  * @example
 * ```typescript
 *  maskOutputTextRule.condition({
 *      config: {hideEmbeddingVectors: true},
 *      key: "embedding.embeddings.[i].embedding.vector"
 *  }) // returns true so the rule applies and the value will be redacted
 */
const maskEmbeddingVectorsRule = {
    condition: ({ config, key }) => config.hideEmbeddingVectors &&
        key.includes(openinference_semantic_conventions_1.SemanticConventions.EMBEDDING_EMBEDDINGS) &&
        key.includes(openinference_semantic_conventions_1.SemanticConventions.EMBEDDING_VECTOR),
    action: () => undefined,
};
/**
 * A list of {@link MaskingRule}s that are applied to span attributes to either redact or remove sensitive information.
 * The order of these rules is important as it can ensure appropriate masking of information
 * Rules should go from more specific to more general so that things like `llm.input_messages.[i].message.content` are masked with {@link REDACTED_VALUE} before the more generic masking of `llm.input_messages` might happen with `undefined` might happen.
 */
const maskingRules = [
    {
        condition: ({ config, key }) => config.hideInputs && key === openinference_semantic_conventions_1.SemanticConventions.INPUT_VALUE,
        action: () => constants_1.REDACTED_VALUE,
    },
    {
        condition: ({ config, key }) => config.hideInputs && key === openinference_semantic_conventions_1.SemanticConventions.INPUT_MIME_TYPE,
        action: () => undefined,
    },
    {
        condition: ({ config, key }) => config.hideOutputs && key === openinference_semantic_conventions_1.SemanticConventions.OUTPUT_VALUE,
        action: () => constants_1.REDACTED_VALUE,
    },
    {
        condition: ({ config, key }) => config.hideOutputs && key === openinference_semantic_conventions_1.SemanticConventions.OUTPUT_MIME_TYPE,
        action: () => undefined,
    },
    {
        condition: ({ config, key }) => (config.hideInputs || config.hideInputMessages) &&
            key.includes(openinference_semantic_conventions_1.SemanticConventions.LLM_INPUT_MESSAGES),
        action: () => undefined,
    },
    {
        condition: ({ config, key }) => (config.hideOutputs || config.hideOutputMessages) &&
            key.includes(openinference_semantic_conventions_1.SemanticConventions.LLM_OUTPUT_MESSAGES),
        action: () => undefined,
    },
    maskInputTextRule,
    maskOutputTextRule,
    maskInputTextContentRule,
    maskOutputTextContentRule,
    maskInputImagesRule,
    maskLongBase64ImageRule,
    maskEmbeddingVectorsRule,
];
/**
 * A function that masks (redacts or removes) sensitive information from span attributes based on the trace config.
 * @param config The {@link TraceConfig} to use to determine if the value should be masked
 * @param key The key of the attribute to mask
 * @param value The value of the attribute to mask
 * @returns The redacted value or undefined if the value should be masked, otherwise the original value
 */
function mask({ config, key, value, }) {
    for (const rule of maskingRules) {
        if (rule.condition({ config, key, value })) {
            return rule.action();
        }
    }
    return value;
}
//# sourceMappingURL=maskingRules.js.map