-
🌐 admin_panel.phpWeb, 1.63 kB⬇
-
🌐 api.jsWeb, 3.06 kB⬇
-
🌐 api.phpWeb, 6.18 kB⬇
-
🌐 app.jsWeb, 58.50 kB⬇
-
🌐 base.cssWeb, 2.23 kB⬇
-
🌐 context.jsWeb, 8.71 kB⬇
-
🌐 conversation-index.jsWeb, 11.46 kB⬇
-
🌐 conversation.jsWeb, 9.87 kB⬇
-
🌐 conversations.jsWeb, 14.49 kB⬇
-
🌐 diction.jsWeb, 384 B⬇
-
🌐 document.jsWeb, 391 B⬇
-
🌐 dynamic.phpWeb, 430 B⬇
-
📷 favicon-lg.pngImage, 9.11 kB⬇
-
📷 favicon.pngImage, 3.12 kB⬇
-
🌐 index.phpWeb, 11.54 kB⬇
-
🌐 indexjs.jsWeb, 544 B⬇
-
🌐 login.phpWeb, 619 B⬇
-
🌐 manifest.jsonWeb, 256 B⬇
-
❓ manifest.webmanifestUnknown, 262 B⬇
-
🌐 memory.jsWeb, 407 B⬇
-
🌐 models.jsonWeb, 1.70 kB⬇
-
🌐 notebook-index.jsWeb, 527 B⬇
-
⚠️ php.iniOS File, 356 B⬇
-
🌐 storage.jsWeb, 12.57 kB⬇
-
🌐 style.cssWeb, 16.16 kB⬇
-
🌐 theme_dark.jsonWeb, 266 B⬇
-
🌐 theme_light.jsonWeb, 267 B⬇
-
🌐 users.jsWeb, 12.40 kB⬇
/**
* class Conversation
* Handles the formatting and rendering of conversation history items into HTML.
* Converts various API response content types (text, code, tables, diagrams, etc.) into styled DOM elements.
*/
class Conversation {
//region Initialization
/**
* Initializes a new instance of the Conversation class.
*/
constructor() {
}
//endregion
//region Formatting Helpers
/**
* Formats a header item.
* @param {Object} item - The content item object.
* @returns {string} HTML string for the header.
*/
format_header(item) {
return '<h4>' + item.value + '</h4>';
}
/**
* Formats a text paragraph.
* @param {Object} item - The content item object.
* @returns {string} HTML string for the paragraph.
*/
format_text(item) {
return '<p>' + item.value + '</p>';
}
/**
* Formats a code block with syntax highlighting support and escaping.
* @param {Object} item - The content item object containing code and language.
* @returns {string} HTML string for the code block.
*/
format_code(item) {
let escaped = item.value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
let lang_class = item.language ? ' class="code-block language-' + item.language + '"' : '';
let html = '';
if (item.caption) html += '<h7>' + item.caption + '</h7>';
html += '<code' + lang_class + '><pre>' + escaped + '</pre></code>';
return html;
}
/**
* Formats a blockquote.
* @param {Object} item - The content item object.
* @returns {string} HTML string for the blockquote.
*/
format_quote(item) {
let html = '';
if (item.caption) html += '<h7>' + item.caption + '</h7>';
html += '<blockquote>' + item.value + '</blockquote>';
return html;
}
/**
* Formats a hyperlink, using source metadata if available.
* @param {Object} item - The content item object.
* @returns {string} HTML string for the link.
*/
format_link(item) {
const link_title = item.source?.[0]?.title;
const link_href = item.source?.[0]?.url;
if(link_title && link_href){
return '<a target="_blank" href="' + link_href + '">' + link_title + '↗</a>';
}
return '<a>' + item.value + '</a>';
}
/**
* Formats a color preview.
* @param {Object} item - The content item object containing a hex color.
* @returns {string} HTML string for the color span.
*/
format_color(item) {
let html = '';
if (item.caption) html += '<h7>' + item.caption + '</h7>';
html += '<span style="color: ' + item.value + '">' + item.value + '</span>';
return html;
}
/**
* Formats a list item (ordered or unordered).
* @param {Object} item - The content item object.
* @returns {string} HTML string for the list item.
*/
format_list(item) {
if(item.ordered){
return '<ol><li value="' + item.index + '">' + item.value + '</li></ol>';
}
return '<ul><li>' + item.value + '</li></ul>';
}
/**
* Formats a Mermaid diagram container.
* @param {Object} item - The content item object containing Mermaid syntax.
* @returns {string} HTML string for the diagram.
*/
format_mermaid(item) {
let html = '';
if (item.caption) html += '<h7>' + item.caption + '</h7><br/>';
html += '<pre class="div-diagram-mermaid">' + item.value + '</pre>';
return html;
}
/**
* Formats a data table.
* @param {Object} item - The content item object containing table rows and configuration.
* @returns {string} HTML string for the table.
*/
format_table(item) {
let html = '';
if(item.caption) html += '<h7>' + item.caption + '</h7>';
const has_th = item['has-header'];
const rows = [...item['table-rows']];
html += '<table>';
if(has_th){
const row = rows.shift();
html += '<thead><tr>';
for(const title of row) html += '<th>' + title + '</th>';
html += '</tr></thead>';
}
html += '<tbody>';
for(const row of rows){
html += '<tr>';
for(const cell of row) html += '<td>' + cell + '</td>';
html += '</tr>';
}
html += '</tbody></table>';
return html;
}
/**
* Formats a TeX Equation container.
* @param {Object} item - The content item object containing TeX syntax.
* @returns {string} HTML string for the equation.
*/
format_equation(item) {
let html = '';
if (item.caption) html += '<h7>' + item.caption + '</h7>';
html += '$$ ' + item.value + ' $$';
return html;
}
/**
* Fallback formatter for unknown content types.
* @param {Object} item - The content item object.
* @returns {string} HTML string for the preformatted value.
*/
format_default(item) {
return '<pre>' + item.value + '</pre>';
}
//endregion
//region Core Routing
/**
* Routes a content item to its specific formatter based on its type.
* @param {Object} item - The content item object.
* @returns {string} The formatted HTML string.
*/
format_item(item) {
switch (item.type) {
case 'header':
return this.format_header(item);
case 'text':
return this.format_text(item);
case 'code':
return this.format_code(item);
case 'quote':
return this.format_quote(item);
case 'link':
return this.format_link(item);
case 'color-hex':
return this.format_color(item);
case 'list-step':
return this.format_list(item);
case 'diagram-mermaid':
return this.format_mermaid(item);
case 'table':
return this.format_table(item);
case 'equation':
return this.format_equation(item);
default:
return this.format_default(item);
}
}
//endregion
//region Response Metadata & Layout
/**
* Returns a standard horizontal divider for chat history.
* @param {string|number} [id] - Optional ID to assign to the divider.
* @returns {string} HTML string for the divider.
*/
format_divider(id = null) {
const id_attr = id !== null ? ' id="chat-item-' + id + '"' : '';
return '<hr class="hr-chat-response-divider"' + id_attr + '/>';
}
/**
* Formats the related topics and suggested follow-up prompts.
* @param {Object} data - The response data object.
* @param {Object} conversation_settings - Object containing settings for the current conversation (e.g., showRelatedQueries, showSuggestedQueries).
* @returns {string} HTML string for the related/suggestions section.
*/
format_suggestions(data, conversation_settings = {}) {
let html = '';
let has_content = false;
const show_related = conversation_settings.showRelatedQueries;
const show_suggestions = conversation_settings.showSuggestedQueries;
if (show_related && data.related && data.related.length > 0) {
html += this._get_related_html(data.related);
has_content = true;
}
if (show_suggestions && data.suggestions && data.suggestions.length > 0) {
html += this._get_suggestions_html(data.suggestions);
has_content = true;
}
if (has_content) {
html += this.format_divider();
}
return html;
}
/**
* Generates the HTML string for related topics.
* @param {Array<string>} related_topics - An array of related topic strings.
* @returns {string} The HTML string for related topics.
*/
_get_related_html(related_topics) {
const related_spans = related_topics.map(topic => `<span class="span-query-chip span-related-query span-clickable-query">${topic}</span>`).join(' ');
return `<p><strong>Related:</strong> <i>${related_spans}</i></p>`;
}
/**
* Generates the HTML string for suggested follow-up prompts.
* @param {Array<string>} suggestions - An array of suggested prompt strings.
* @returns {string} The HTML string for suggested prompts.
*/
_get_suggestions_html(suggestions) {
const suggestion_spans = suggestions.map(suggestion => `<span class="span-query-chip span-suggested-query span-clickable-query">${suggestion}</span>`).join(' ');
return `<p><strong>Suggestions:</strong> <i>${suggestion_spans}</i></p>`;
}
/**
* Formats the cost and token usage summary for a response.
* @param {Object} data - The response data containing model, tokens, and costs.
* @returns {string} HTML string for the cost summary.
*/
format_cost_summary(data) {
if (!data.costs || !data.tokens) {
return '';
}
const total_cost = data.costs.total.toFixed(6);
const op = data.costs.op !== undefined ? data.costs.op.toFixed(6) : '?';
return `<p style="opacity: 0.5;"><strong>${data.model}:</strong> Input ${data.tokens.prompt}, replied ${data.tokens.reply}, thought ${data.tokens.thought}, totalling ${data.tokens.total}, costing ≈ $${total_cost} (op: $${op}).</p>`;
}
/**
* Formats an entire history item from the API, including the query, response content,
* suggestions, and token/cost metadata.
* @param {Object} data - The complete response object for a single turn.
* @param {number} [index=0] - The index of the item in the conversation history.
* @param {Object} conversation_settings - Object containing settings for the current conversation (e.g., showRelatedQueries, showSuggestedQueries).
* @returns {string} The complete HTML representation of the history item.
*/
format_history_item(data, index = 0, conversation_settings = {}) {
let html = '';
let related_to_text = data.chain ? 'As related to the previous query.' : 'As a new conversational direction.';
html += this.format_divider(index);
html += this._get_history_item_header_html(data.query, related_to_text);
html += this.format_divider();
if(data.content){
Object.values(data.content).forEach(item => {
html += this.format_item(item);
html += this.format_divider();
});
}
html += this.format_suggestions(data, conversation_settings);
html += this.format_cost_summary(data);
return html;
}
/**
* Generates the HTML string for the history item header (query and related text).
* @param {string} query The user's query.
* @param {string} related_to_text Text indicating if the query is related or new.
* @returns {string} The HTML string for the history item header.
*/
_get_history_item_header_html(query, related_to_text) {
return `<h5><strong>Query:</strong> ${query}</h5><h6>${related_to_text}</h6>`;
}
//endregion
}
export default Conversation;
conversation.js
×
Type: Web, text/plain
9.87 Kilobytes
Last Modified 2026-05-04 01:35:56
⬇ Download File
Type: Web, text/plain
9.87 Kilobytes
Last Modified 2026-05-04 01:35:56
⬇ Download File