Source code

Revision control

Copy as Markdown

Other Tools

/*
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<ChatMessage>} 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<object>} rows - The database rows to parse.
* @returns {Array<ChatHistoryResult>} 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 "";
}