/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ const lazy = {}; ChromeUtils.defineESModuleGetters(lazy, { CryptoUtils: "moz-src:///services/crypto/modules/utils.sys.mjs", }); import { MESSAGE_ROLE } from "./ChatConstants.sys.mjs"; import { ChatConversation } from "./ChatConversation.sys.mjs"; import { ChatMessage, ChatHistoryResult } from "./ChatMessage.sys.mjs"; /** * Creates a 12 characters GUID with 72 bits of entropy. * * @returns {string} A base64url encoded GUID. */ export function makeGuid() { return ChromeUtils.base64URLEncode(lazy.CryptoUtils.generateRandomBytes(9), { pad: false, }); } /** * Parse a conversation row from the database into a ChatConversation * object. * * @param {object} row - The database row to parse. * @returns {ChatConversation} The parsed conversation object. */ export function parseConversationRow(row) { return new ChatConversation({ id: row.getResultByName("conv_id"), title: row.getResultByName("title"), description: row.getResultByName("description"), pageUrl: URL.parse(row.getResultByName("page_url")), pageMeta: parseJSONOrNull(row.getResultByName("page_meta")), createdDate: row.getResultByName("created_date"), updatedDate: row.getResultByName("updated_date"), status: row.getResultByName("status"), }); } /** * Parse message rows from the database into an array of ChatMessage * objects. * * @param {object} rows - The database rows to parse. * @returns {Array} The parsed message objects. */ export function parseMessageRows(rows) { return rows.map(row => { return new ChatMessage({ id: row.getResultByName("message_id"), createdDate: row.getResultByName("created_date"), parentMessageId: row.getResultByName("parent_message_id"), revisionRootMessageId: row.getResultByName("revision_root_message_id"), ordinal: row.getResultByName("ordinal"), isActiveBranch: !!row.getResultByName("is_active_branch"), role: row.getResultByName("role"), modelId: row.getResultByName("model_id"), params: parseJSONOrNull(row.getResultByName("params")), usage: parseJSONOrNull(row.getResultByName("usage")), content: parseJSONOrNull(row.getResultByName("content")), convId: row.getResultByName("conv_id"), pageUrl: URL.parse(row.getResultByName("page_url")), turnIndex: row.getResultByName("turn_index"), insightsEnabled: row.getResultByName("insights_enabled"), insightsFlagSource: row.getResultByName("insights_flag_source"), insightsApplied: parseJSONOrNull(row.getResultByName("insights_applied")), webSearchQueries: parseJSONOrNull( row.getResultByName("web_search_queries") ), }); }); } /** * Parse conversation rows from the database into an array of ChatHistoryResult * objects. * * @param {Array} rows - The database rows to parse. * @returns {Array} The parsed chat history result entries */ export function parseChatHistoryViewRows(rows) { return rows.map(row => { return new ChatHistoryResult({ convId: row.getResultByName("conv_id"), title: row.getResultByName("title"), createdDate: row.getResultByName("created_date"), updatedDate: row.getResultByName("updated_date"), urls: row .getResultByName("urls") .split(",") .map(url => new URL(url)), }); }); } /** * Try to parse a JSON string, returning null if it fails or the value is falsy. * * @param {string} value - The JSON string to parse. * @returns {object|null} The parsed object or null. */ export function parseJSONOrNull(value) { if (!value) { return null; } try { return JSON.parse(value); } catch (e) { return null; } } /** * Try to stringify a value if it is truthy, otherwise return null. * * @param {*} value - A value to JSON.stringify() * * @returns {string|null} - JSON string */ export function toJSONOrNull(value) { return value ? JSON.stringify(value) : null; } /** * Converts the different types of message roles from * the database numeric type to a string label * * @param {number} role - The database numeric role type * @returns {string} - A human readable role label */ export function getRoleLabel(role) { switch (role) { case MESSAGE_ROLE.USER: return "User"; case MESSAGE_ROLE.ASSISTANT: return "Assistant"; case MESSAGE_ROLE.SYSTEM: return "System"; case MESSAGE_ROLE.TOOL: return "Tool"; } return ""; }