"use strict"; import { Fieldset, Section, Form, Div, Nav, UL, LI, Span, Pre } from "../Utils/HTMLDSL.ecma.js"; import {MarkDown} from "../Utils/MarkDown.ecma.js"; import {Common} from "../Utils/Common.ecma.js"; /** * @typedef {import("../Application/AnP.ecma.js").AnP} AnP */ /** * @class AIChatComponent * @constructor * @param {!AnP} anp * @returns {void} * @access private * @static */ export const AIChatComponent = (function(){ /** * @constructs AIChatComponent * @param {!AnP} anp * @returns {void} * @access private * @static */ const AIChatComponent = function(anp){ /** @type {AIChatComponent} */ const self = this; /** @type {string|null} */ let web_socket_id = null; /** * @returns {void} * @access private */ const constructor = () => {}; this.build = (inputs = null) => { const name = Common.get_value("name", inputs, "aichat"); return Fieldset({class : "aichat"}, [ anp.components.i18n(name, "legend"), Section({class : "messages"}), Form({ method : "post", action : "#", on_submit : send, on_key_down : check_keys }, [ anp.components.text("message", { multiline : true }), anp.components.button("send", "submit") ]) ]); }; const build_data_icon = (name, value) => LI({ data_name : name, data_i18n : value, data_i18n_without : true, title : anp.i18n.get(value) }, [ anp.components.icon(value), anp.components.i18n(value) ]); const build_data_item = (name, value = null) => LI({ data_name : name, data_i18n : name, data_i18n_without : true, title : anp.i18n.get(name) }, [ anp.components.icon(name), anp.components.i18n(name), value === null ? null : Span({class : "value"}, "" + value) ]); const get_message_box = item => { while((!item.classList || !item.classList.contains("message")) && (item = item.parentElement)); return item; }; const set_view = (item, event) => { const box = get_message_box(item), mode = item.getAttribute("data-i18n"); box.getAttribute("data-mode") != mode && box.setAttribute("data-mode", mode); }; const format = content => { const html = MarkDown.to_html(content); return [html, html.replace(//g, ">"), content]; }; const build_message = (id, type, content = "", mode = "waiting") => { const [html, raw_html, md] = format(content), date = Date.now(); return Fieldset({ class : "message", data_id : id, data_type : type, data_ok : true, data_status : mode, data_done : mode == "done", data_mode : "html" }, [ anp.components.i18n(type, "legend"), Div({class : "message-box html-content"}, html), Pre({class : "message-box raw-html-content"}, raw_html), Pre({class : "message-box md-content"}, md), Nav({class : "view buttons"}, [ anp.components.button("html", set_view), anp.components.button("raw_html", set_view), anp.components.button("md", set_view), ]), UL({class : "data"}, [ build_data_icon("status", mode), build_data_item("ok"), build_data_item("done"), build_data_item("date_from", date), build_data_item("date_to", date), build_data_item("time", 0), build_data_item("length", content.length), build_data_item("response_tokens", content.replace(/(?:[^a-z0-9]+|[\r\n]+)+/gi, " ").trim().split(" ").length) ]) ]); }; const send = (item, event) => { const text_box = item.querySelector("[name=message]"), text = text_box.value.trim(); event.preventDefault(); if(text){ const data_id = anp.unique_keys.get(); Common.HTML( ".aichat .messages", build_message(data_id, "user", text, "done"), build_message(data_id, "bot") ); text_box.value = ""; anp.web_sockets_clients.send("anp", "ai", "message", { message_id : data_id, message : text }); }; return false; }; const check_keys = (item, event) => { event.key == "Enter" && !event.shiftKey && send(item, event); }; this.write_response = (id, fragment, ok, done) => { console.log([id, fragment]); const box = document.querySelector(".aichat .messages>[data-type=bot][data-id='" + id + "']"), status = ( !ok ? "error" : done ? "done" : "loading"), status_text = anp.i18n.get(status), status_box = box.querySelector("[data-name=status]"), status_i18n_box = status_box.querySelector("[data-i18n]"), date = Date.now(), tokens_box = box.querySelector("[data-name=response_tokens] .value"), [html, raw_html, md] = format(box.querySelector(".md-content").textContent += fragment); box.querySelector(".html-content").innerHTML = html; box.querySelector(".raw-html-content").innerHTML = raw_html; box.querySelector("[data-name=length] .value").innerText = md.length; box.setAttribute("data-ok", ok); box.setAttribute("data-done", done); box.setAttribute("data-status", status); status_box.setAttribute("data-i18n", status); status_box.setAttribute("title", status_text); status_box.querySelector("[data-icon]").setAttribute("data-icon", status); status_i18n_box.setAttribute("data-i18n", status_text); status_i18n_box.innerHTML = status_text; box.querySelector("[data-name=date_to]").querySelector(".value").innerHTML = date; box.querySelector("[data-name=time]").querySelector(".value").innerHTML = date - Number(box.querySelector("[data-name=date_from] .value").innerText); tokens_box.innerText = Number(tokens_box.innerText) + 1; }; constructor(); }; return AIChatComponent; })();