import { r as e, h as t, H as n } from "./p-9b9ccd0c.js";

import "./p-6534555e.js";

import { html as a, nothing as o } from "lit";

import { when as s } from "lit/directives/when.js";

import { ifDefined as i } from "lit/directives/if-defined.js";

// TODO: The functions on this file are a WA until Chameleon 7 is released and we can reuse
// the existing functions from Chameleon. At the moment, we have to copy paste the functions
// because in Chameleon 6 we can import them.
// The following utils were copied from Chamelmeon (src/components/chat/utils.ts or src/common/utils.ts)
const getMessageSerializedContentAll = e => typeof e.content === "string" ? e.content : JSON.stringify(e.content, undefined, 2);

const getMessageContent = e => typeof e.content === "string" ? e.content : e.content.message
/**
 * Converts an object mapping token keys to booleans into a space-separated
 * string containing the token keys that map to truthy values.
 * @example
 *   part={tokenMap({
 *     header: true,
 *     disabled: this.disabled,
 *     selected: this.selected,
 *     [levelPart]: canShowLines,
 *     "expand-button":
 *       canShowLines && !this.leaf && this.expandableButton !== "no"
 *   })}
 */;

const tokenMap = e => {
  const t = Object.keys(e);
  let n = "";
  for (let a = 0; a < t.length; a++) {
    const o = t[a];
    const s = e[o];
    if (s) {
      n += n === "" ? o : ` ${o}`;
    }
  }
  return n;
};

const copyToTheClipboard = e => navigator.clipboard.writeText(e);

const copyButtonClickHandler = (e, t) => {
  copyToTheClipboard(t);
  const n = e.currentTarget;
  if (n) {
    const e = n.getAttribute("part");
    const t = `${e} copying`;
    n.setAttribute("disabled", "disabled");
    n.setAttribute("part", t);
    setTimeout((() => {
      n.removeAttribute("disabled");
      n.setAttribute("part", e || "");
    }), 1500);
  }
};

const r = "complete";

const copyClickHandler = (e, t) => {
  // We use the whole message to support copying the files and/or sources
  const n = getMessageSerializedContentAll(t);
  copyButtonClickHandler(e, n);
};

const customActionsRender = (e, t) => {
  const {accessibleName: n} = t.translations;
  const o = e.role === "assistant" && (e.status === "complete" || !e.status);
  const i = e.role === "error";
  return s(o || i, (() => a`<div part="actions-container"><button aria-label="${n.copyMessageContent}" part="${tokenMap({
    [`action-button action-copy-message ${e.id}`]: true,
    ...e.parts ? {
      [e.parts]: true
    } : {}
  })}" type="button" @click="${t => copyClickHandler(t, e)}"></button></div>`));
};

const downloadCodeBlockCallback = (e, t, n) => () => n(e, t);

const customCodeBlockRender = e => t => {
  const {accessibleName: n, text: o} = e.translations;
  const i = e.callbacks?.downloadCodeBlock;
  return a`<div part="code-block"><div part="code-block__header"><span part="code-block__header-caption">${t.language ?? "txt"}</span><div part="code-block__header-actions"><button class="button-copy-code" aria-label="${o.copyCodeButton}" part="code-block__button--icon-only code-block__copy-code-button" type="button" @click="${e => copyButtonClickHandler(e, t.plainText)}"></button> ${s(i, (() => a`<button aria-label="${n.downloadCodeButton}" part="code-block__button--icon-only code-block__download-code-button" @click="${downloadCodeBlockCallback(t.plainText, t.language, i)}"></button>`))}</div></div><ch-code .language="${t.language}" .lastNestedChildClass="${t.lastNestedChildClass}" part="code-block__content" .showIndicator="${t.showIndicator}" .value="${t.plainText}"></ch-code></div>`;
};

const c = "uploaded";

// /**
//  * Returns a skeleton element shown while a file is being uploaded.
//  *
//  * In Mercury, the loading state is visually represented in the footer,
//  * so this skeleton is currently unused. However, it is recommended to keep
//  * this function in the file in case the design changes and a visual loader
//  * inside the file container becomes necessary again.
//  *
//  * @param file - The file object containing metadata and upload state.
//  * @param fileFormat - The format type of the file (e.g., text, image, etc.).
//  * @returns A TemplateResult with the skeleton element or `nothing` if not loading.
//  */
// const fileSkeleton = (
//   file: ChatMessageFile,
//   fileFormat: keyof ChMimeTypeFormatMap
// ): TemplateResult | typeof nothing => {
//   return file.uploadState === "in-progress"
//     ? html`<div
//         part=${tokenMap({
//           [`file-skeleton format-${fileFormat} ${file.mimeType} ${
//             file.uploadState ?? DEFAULT_FILE_UPLOAD_STATE
//           }`]: true,
//           [file.extension!]: !!file.extension,
//           [file.parts!]: !!file.parts
//         })}
//       ></div>`
//     : nothing;
// };
const fileFooter = (e, t) => a`<div class="elevation-1" part="${tokenMap({
  [`file-footer format-${t} ${e.mimeType} ${e.uploadState ?? c}`]: true,
  [e.extension]: !!e.extension,
  [e.parts]: !!e.parts
})}"><span part="file-caption">${e.caption}${e.extension && "." + e.extension.toLowerCase()} </span>${e.uploadState === "in-progress" ? a`<mer-spinner></mer-spinner>` : o}</div>`;

const getFileContainerParts = (e, t) => tokenMap({
  [`file-container format-${t} ${e.mimeType} ${e.uploadState ?? c}`]: true,
  [e.extension]: !!e.extension,
  [e.parts]: !!e.parts
});

const getFileParts = (e, t) => tokenMap({
  [`file format-${t} ${e.mimeType} ${e.uploadState ?? c}`]: true,
  [e.extension]: !!e.extension,
  [e.parts]: !!e.parts
})
// TODO: Improve accessibility by exposing progress or spin states while
// uploading
;

const d = {
  audio: e => a`<li class="file-container" part="${getFileContainerParts(e, "audio")}"><audio aria-label="${i(e.accessibleName)}" part="${getFileParts(e, "audio")}" src="${i(e.uploadState === "in-progress" ? undefined : e.url)}" controls></audio>${fileFooter(e, "audio")}</li>`,
  video: e => a`<li class="file-container" part="${getFileContainerParts(e, "video")}"><video aria-label="${i(e.accessibleName)}" part="${getFileParts(e, "video")}" src="${i(e.uploadState === "in-progress" ? undefined : e.url)}" controls></video>${fileFooter(e, "video")}</li>`,
  image: e => a`<li class="file-container" part="${getFileContainerParts(e, "image")}"><img aria-label="${i(e.accessibleName)}" part="${getFileParts(e, "image")}" src="${e.url}" alt="${e.alternativeText ?? e.accessibleName ?? ""}" loading="lazy"> ${fileFooter(e, "image")}</li>`,
  file: e => {
    const t = e.uploadState === "in-progress";
    return a`<li class="file-container" part="${getFileContainerParts(e, "file")}"><a aria-label="${i(e.accessibleName)}" role="${t ? "link" : o}" aria-disabled="${t ? "true" : o}" part="${getFileParts(e, "file")}" href="${t ? o : e.url}" target="_blank"></a> ${fileFooter(e, "file")}</li>`;
  }
};

/*
README:
This file contains two utilities:

1) [Sections for customitizing the ch-chat renderItem]
The following sections are being customized at the time of writting:
- actions: customActionsRender,
- codeBlock: customCodeBlockRender,
- content: customContentRender

What for?

- actions: In order to be able to customize the copy button, by adding a part
"copying" when the user copies the message. This additional part allows changing
the current button icon of "copy" to a "checked" icon.
- codeBlock: Same reason as "actions" section.
- content: Mercury includes a "header" section for the assistant message. This
header includes an avatar, the assistant name, and optionally the message time.
This header requires custom markup, and for this reason this section has to be
customized.

2) [Configuration for the ch-chat sendContainerLayout property]
The chat styles are designed for a specific layout, so users must use the sendContainerLayout provided by Mercury. Customizing it is not supported.
*/
// 1) [Sections for customitizing the ch-chat renderItem.]
/**
 * Mercury section that includes the assistant the assistant name, and an optional message time.
 *
 * @param messageMetaData - Metadata containing agentName and time
 * @returns TemplateResult rendering the assistant message header
 */ const messageHeader = e => {
  if (e.role === "system" || e.role === "user") {
    return o;
 // TODO: Improve type safety in the ch-chat (nicolas-camera_globant)
    }
  const t = e.metadata?.agentName;
  const n = t?.toLowerCase().replace(/ /g, "-");
  const s = e.metadata?.time;
  return a`<div part="header assistant${n ? ` header-${n}` : ""}"><div part="header__start assistant"><div part="header__avatar-container assistant"><div part="header__avatar-border assistant"></div><div part="header__avatar-image assistant"></div></div><div part="header__role assistant">${t}</div>${e.role === "assistant" && e.status === "waiting" ? a`<mer-animated-dots></mer-animated-dots>` : o}</div>${s ? a`<time datetime="${s}" part="header__time assistant">${s}</time>` : o}</div>`;
};

// customzied in order to add the custom "messageHeader"
const customAssistantContentRender = (e, t, n) => {
  const o = getMessageContent(e);
  return e.status === "waiting" ? a`<div class="assistant-loading" part="${tokenMap({
    [`assistant content waiting ${e.id}`]: true,
    ...e.parts ? {
      [e.parts]: true
    } : {}
  })}">${o}</div>` : a`<ch-markdown-viewer part="${tokenMap({
    [`assistant content ${e.id} ${e.status ?? r}`]: true,
    ...e.parts ? {
      [e.parts]: true
    } : {}
  })}" .renderCode="${
  // WA: Define codeBlockRender as "never" to avoid types incompatibility:
  // codeBlockRender returns TemplateResult and renderCode expects TemplateResult | undefined
  // In Chameleon this type mismatch does not happens. TODO: Evaluate a solution in Chameleon.
  n(t)}" .showIndicator="${e.status === "streaming"}" .theme="${t.markdownTheme ?? undefined}" .value="${o}"></ch-markdown-viewer>`;
};

// Customized in order to add the custom "messageHeader"
const customErrorContentRender = (e, t, n) => {
  const o = getMessageContent(e);
  return a`<ch-markdown-viewer part="${tokenMap({
    [`error content ${e.id}`]: true,
    ...e.parts ? {
      [e.parts]: true
    } : {}
  })}" .renderCode="${
  // WA: Define codeBlockRender as "never" to avoid types incompatibility:
  // codeBlockRender returns TemplateResult and renderCode expects TemplateResult | undefined
  // In Chameleon this type mismatch does not happens. TODO: Evaluate a solution in Chameleon.
  n(t)}" .theme="${t.markdownTheme ?? undefined}" .value="${o}"></ch-markdown-viewer>`;
};

// No modification. It is required to be defined.
const defaultSystemContentRender = () => "string | TemplateResult"
// No modification. It is required to be defined.
;

const defaultUserContentRender = e => getMessageContent(e) ?? "";

const l = {
  // TODO: Check if each contentRender can be optional, since it may be not me required to implement
  // a custom render for each type of content. ie.: Mercury does not requres to customize "system" and "user"
  assistant: customAssistantContentRender,
  error: customErrorContentRender,
  system: defaultSystemContentRender,
  // No modification
  user: defaultUserContentRender
};

const customContentRender = (e, t, n) => l[e.role](e, t, n);

const u = {
  actions: customActionsRender,
  contentBefore: messageHeader,
  codeBlock: customCodeBlockRender,
  content: customContentRender,
  file: d
};

// 2) [Configuration for the ch-chat sendContainerLayout property]
const m = {
  sendInputAfter: [ "attach-files-button", "live-audio-button", "send-button", "chat-attached-files-viewer" ],
  sendContainerAfter: [ "live-audio-container" ]
};

const h = '\n### Code block {#code-block}\nTo create code blocks, you’ll use three backticks (` ``` `) or three tildes (`~~~`) on the lines before and after the code block.\n\n```json\n{\n  "firstName": "John",\n  "lastName": "Smith",\n  "age": 25\n}';

const p = "Nexa";

// - - - - - - - - - - - - - -
// Other messages
// - - - - - - - - - - - - - -
const f = `\n###### Code block {#code-block}\nTo create code blocks, you’ll use three backticks (\` \`\`\` \`) or three tildes (\`~~~\`) on the lines before and after the code block.\n\n\`\`\`\n{\n  "firstName": "John",\n  "lastName": "Smith",\n  "age": 25\n}\n\`\`\`\n\nAnother way to create code blocks is to indent every line of the block by at least four spaces or one tab.\n\n    <html>\n      <head>\n      </head>\n    </html>\n\n\n###### Syntax Highlighting {#syntax-highlighting}\nThis feature allows you to add color highlighting for whatever language your code was written in.\nTo add syntax highlighting, specify a language next to the backticks before the fenced code block.\n\n\`\`\`json\n{\n  "firstName": "John",\n  "lastName": "Smith",\n  "age": 25\n}\n\`\`\`\n\n\`\`\`javascript\nimport React from 'react'\nimport ReactDOM from 'react-dom'\nimport Markdown from 'react-markdown'\nimport rehypeHighlight from 'rehype-highlight'\n\nconst markdown = \`\n# Your markdown here\n\`\n\nReactDOM.render(\n  <Markdown rehypePlugins={[rehypeHighlight]}>{markdown}</Markdown>,\n  document.querySelector('#content')\n)\n\`\`\`\n\n###### Horizontal Rules {#horizontal-rules}\nTo create a horizontal rule, use three or more asterisks (\`***\`), dashes (\`---\`), or underscores (\`___\`) on a line by themselves.\n`;

Array.from({
  length: 40
}, ((e, t) => t % 2 === 0 ? {
  id: `index: ${t}`,
  role: "user",
  content: `index: ${t}` + `index: ${t}\n` + `index: ${t}\n` + `index: ${t}\n` + `index: ${t}\n` + `index: ${t}\n` + `index: ${t}\n`
} : {
  id: `index: ${t}`,
  role: "assistant",
  content: h + `\nindex: ${t}\n` + `index: ${t}\n` + `index: ${t}\n` + `index: ${t}\n` + `index: ${t}\n` + `index: ${t}\n` + `index: ${t}\n`
}));

const g = [ {
  id: "1",
  role: "user",
  content: "Please give me an example about...",
  metadata: "14:55"
}, {
  id: "2",
  role: "assistant",
  status: "complete",
  content: "Action required example. Action required example. Action required example.",
  metadata: {
    agentName: p,
    time: "14:25"
  }
}, {
  id: "3",
  role: "assistant",
  status: "complete",
  content: "Some fields contain missing or invalid data, which may prevent the process from completing correctly. Review your input carefully and make any necessary corrections before continuing.",
  metadata: {
    agentName: p,
    time: "14:25"
  },
  parts: "warning"
}, {
  id: "4",
  role: "error",
  content: "An unexpected error occurred while processing your request, and the operation couldn’t be completed.Please check your internet connection or try again later. If the problem persists, contact support.",
  metadata: {
    agentName: p,
    time: "14:25"
  }
}, {
  id: "5",
  role: "assistant",
  status: "complete",
  content: "Your information has been saved successfully, and all changes are now reflected in your account. You can continue with the next steps or return to the dashboard at any time.",
  metadata: {
    agentName: p,
    time: "14:25"
  },
  parts: "success"
}, {
  id: "6",
  role: "user",
  content: "Implement the function calculate_average_grade in grades.py that takes a list of grades as input and returns the average grade as a floating-point number",
  metadata: "15:00"
}, {
  id: "7",
  role: "assistant",
  status: "complete",
  content: "You can provide further details or updates regarding your support ticket and its associated code. Your input here helps us better understand and address your issue effectively.",
  metadata: {
    agentName: p,
    time: "14:25"
  }
}, {
  id: "8",
  role: "assistant",
  status: "waiting",
  content: "You can provide further details or updates",
  metadata: {
    agentName: p,
    time: "14:25"
  }
}, {
  id: "9",
  role: "assistant",
  status: "complete",
  content: h,
  metadata: {
    agentName: p,
    time: "14:25"
  }
} ];

const w = "{{ASSISTANT_NAME}}";

const sendChatMessages = e => () => {
  e.waitingResponse = true;
  e.addNewMessage({
    id: `${(new Date).getTime()}`,
    role: "assistant",
    content: "Analyzing",
    status: "waiting",
    metadata: {
      agentName: p,
      time: "14:25"
    }
  });
  setTimeout((() => {
    e.updateLastMessage({
      role: "assistant",
      content: "Processing with Chat with LLMs",
      status: "waiting",
      metadata: {
        agentName: p,
        time: "14:25"
      }
    }, "replace");
    setTimeout((() => {
      dummyStreaming(e, 20, f, "replace");
    }), 2e3);
  }), 2e3);
};

const stopResponseAnswer = () => {
  console.log("stop generating answer");
  return new Promise((e => {
    // Lógica asincrónica aquí si es necesario
    e();
  }));
};

const chatCallbacksWithChatRef = e => ({
  sendChatMessages: sendChatMessages(e),
  uploadFile: e => new Promise((() => {
    console.log("file", e);
    return Promise.resolve({
      url: "Error",
      mimeType: "application/javascript"
    });
  })),
  stopResponse: stopResponseAnswer
});

function dummyStreaming(e, t, n, a) {
  setTimeout((() => {
    const o = t >= n.length;
    e.updateLastMessage({
      role: "assistant",
      content: n.substring(t - 20, t),
      // {
      //   message: stringToDisplay.substring(counter - 20, counter),
      //   files: streamingCompleted
      //     ? [
      //         {
      //           url: "https://next.genexus.ai",
      //           caption: "Mars Exploration Contract"
      //         },
      //         {
      //           url: "https://gx-chameleon.netlify.app",
      //           caption: "Venus Exploration Contract"
      //         }
      //       ]
      //     : undefined
      // },
      status: o ? "complete" : "streaming",
      metadata: {
        agentName: p,
        time: "14:25"
      }
    }, a);
    if (!o) {
      dummyStreaming(e, t + 20, n, "concat");
    } else {
      e.waitingResponse = false;
    }
  }), t % 200 === 0 ? 50 : 40);
}

const b = {
  accessibleName: {
    clearChat: "Clear chat",
    copyMessageContent: "Copy message",
    downloadCodeButton: "Download code",
    sendButton: "Send",
    sendInput: "Message",
    stopResponseButton: "Stop generating answer"
  },
  placeholder: {
    sendInput: "Ask me a question..."
  },
  text: {
    copyCodeButton: "Copy code",
    copyMessageContent: "Copy message content",
    downloadCodeButton: "Download code",
    processing: `Processing with ${w}`,
    sourceFiles: "Source files:",
    stopResponseButton: ""
  }
};

const $ = ":host{block-size:100%;display:grid}";

var y = undefined && undefined.__classPrivateFieldGet || function(e, t, n, a) {
  if (n === "a" && !a) throw new TypeError("Private accessor was defined without a getter");
  if (typeof t === "function" ? e !== t || !a : !t.has(e)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
  return n === "m" ? a : n === "a" ? a.call(e) : a ? a.value : t.get(e);
};

var v = undefined && undefined.__classPrivateFieldSet || function(e, t, n, a, o) {
  if (a === "m") throw new TypeError("Private method is not writable");
  if (a === "a" && !o) throw new TypeError("Private accessor was defined without a setter");
  if (typeof t === "function" ? e !== t || !o : !t.has(e)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
  return a === "a" ? o.call(e, n) : o ? o.value = n : t.set(e, n), n;
};

var k, _, x, C, T, N, M;

const S = [ "resets/box-sizing", "utils/elevation", "components/chat", "components/markdown-viewer" ];

const A = class {
  constructor(t) {
    e(this, t);
    k.set(this, void 0);
    _.set(this, void 0);
    x.set(this, void 0);
    C.set(this, void 0);
    T.set(this, (() => {
      y(this, k, "f").showCopyConversationMessage();
    }));
    N.set(this, (() => {}));
    M.set(this, (async e => {
      let t;
      if (e.toLowerCase().includes("transaction")) {
        t = 'To create a transaction in GeneXus, start by opening your KB (Knowledge Base) and selecting "Transaction" from the "New Object" options. Give it a name and define its attributes, starting with a primary key followed by the related data fields. GeneXus will automatically infer the data structure and relationships based on how you define the attributes and their nesting. Once saved, it generates the necessary database tables and forms for inserting, updating, and deleting records. You can then run the application to test the transaction directly in your browser.';
      } else if (e.toLowerCase().includes("entity")) {
        t = 'In GeneXus, creating an entity usually means defining a Transaction object that represents a real-world concept like "Customer" or "Product." To do this, create a new Transaction, name it after the entity, and define its attributes—starting with a unique identifier (like CustomerId) and then adding other fields (like CustomerName, CustomerEmail). GeneXus treats this Transaction as an entity and uses it to generate the corresponding table and interface automatically.';
      } else {
        t = "Sorry, I didn’t catch that—mind rephrasing it? 😅";
      }
      const n = {
        id: "1",
        role: "user",
        content: e
      };
      y(this, x, "f").addNewMessage(n);
      setTimeout((() => {
        y(this, x, "f").addNewMessage({
          id: `${(new Date).getTime()}`,
          role: "assistant",
          content: "Analyzing",
          status: "waiting"
        });
        setTimeout((() => {
          y(this, x, "f").updateLastMessage({
            role: "assistant",
            content: "Processing with Chat with LLMs",
            status: "waiting"
          }, "replace");
          setTimeout((() => {
            y(this, x, "f").updateLastMessage({
              role: "assistant",
              content: "Getting information",
              status: "waiting"
            }, "replace");
            y(this, x, "f").updateLastMessage({
              role: "assistant",
              content: t,
              status: "complete"
            }, "replace");
          }), 1500);
        }), 1500);
      }), 100);
    }));
    this.mode = "messages-sample";
    this.generatingResponse = false;
    this.loadingState = "all-records-loaded";
    this.showAdditionalContent = false;
    this.conversationCopied = false;
    this.assistantStatus = "Getting Data";
    this.chatItems = [];
  }
  /**
     * It will exit the wellcome screen and remove it from the dom.
     */  async exitWelcome() {
    // hand exitWelcome to gx-ide-chat-welcome
    y(this, _, "f").exitWelcome();
  }
  componentDidLoad() {
    setTimeout((() => {
      this.assistantStatus = "Creating Data Base..";
    }), 1e3);
  }
  componentDidRender() {
    if (!y(this, C, "f") && y(this, x, "f")) {
      v(this, C, chatCallbacksWithChatRef(y(this, x, "f")), "f");
    }
  }
  async componentWillLoad() {
    if (this.mode === "messages-sample") {
      this.chatItems = g;
    } else if (this.mode === "welcome") {
      this.chatItems = [];
    } else if (this.mode === "empty") {
      this.chatItems = [ {
        id: "1",
        role: "assistant",
        status: "complete",
        content: "Hello! I am your assistant.",
        metadata: "14:56"
      } ];
    }
  }
  render() {
    return t(n, null, t("ch-theme", {
      model: S
    }), t("gx-ide-chat-container", {
      chatTitle: "GeneXus Assistant",
      copyConversationCallback: y(this, T, "f"),
      deleteConversationCallback: y(this, N, "f"),
      ref: e => v(this, k, e, "f"),
      class: "elevation-1"
    }, t("ch-chat", {
      callbacks: y(this, C, "f"),
      class: "chat",
      waitingResponse: this.generatingResponse,
      loadingState: this.loadingState,
      renderItem: u,
      items: this.chatItems,
      showAdditionalContent: false,
      sendContainerLayout: m,
      translations: b,
      ref: e => v(this, x, e, "f"),
      markdownTheme: "components/markdown-viewer"
    }, t("gx-ide-chat-welcome", {
      ref: e => v(this, _, e, "f"),
      slot: "empty-chat",
      suggestedPrompRequestedCallback: y(this, M, "f")
    }), t("div", {
      slot: "additional-content"
    }, "Custom content that is rendered when the chat renders content"))));
  }
};

k = new WeakMap, _ = new WeakMap, x = new WeakMap, C = new WeakMap, T = new WeakMap, 
N = new WeakMap, M = new WeakMap;

A.style = $;

export { A as gx_ide_sc_chat_container };
//# sourceMappingURL=p-1043534b.entry.js.map