MemoriesChatSource.sys.mjs (3408B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 /** 6 * This module handles the user message extraction from chat store 7 */ 8 9 import { 10 ChatStore, 11 MESSAGE_ROLE, 12 } from "moz-src:///browser/components/aiwindow/ui/modules/ChatStore.sys.mjs"; 13 14 // Chat fetch defaults 15 const DEFAULT_MAX_RESULTS = 50; 16 const DEFAULT_HALF_LIFE_DAYS = 7; 17 const MS_PER_SEC = 1_000; 18 const SEC_PER_MIN = 60; 19 const MINS_PER_HOUR = 60; 20 const HOURS_PER_DAY = 24; 21 22 /** 23 * Fetch recent user chat messages from the ChatStore and compute a freshness 24 * score for each one. 25 * 26 * Messages are fetched between `startTime` and "now" (Date.now()) and limited 27 * to the most recent `maxResults` entries. A per-message `freshness_score` 28 * in [0, 1] is computed using an exponential half-life decay over age in days. 29 * 30 * @param {number} [startTime=0] 31 * Inclusive start time in milliseconds since Unix epoch. 32 * @param {number} [maxResults=DEFAULT_MAX_RESULTS] 33 * Maximum number of most recent messages to return. 34 * @param {number} [halfLifeDays=DEFAULT_HALF_LIFE_DAYS] 35 * Half-life in days for the freshness decay function. 36 * @returns {Promise<Array<{ 37 * createdDate: number, 38 * role: string, 39 * content: any, 40 * pageUrl: string | null, 41 * freshness_score: number 42 * }>>} 43 * Promise resolving to an array of mapped chat message objects. 44 */ 45 export async function getRecentChats( 46 startTime = 0, 47 maxResults = DEFAULT_MAX_RESULTS, 48 halfLifeDays = DEFAULT_HALF_LIFE_DAYS 49 ) { 50 // Underlying Chatstore uses Date type but MemoriesStore maintains in TS 51 const startDate = new Date(startTime); 52 const endDate = new Date(); 53 const chatStore = new ChatStore(); 54 const messages = await chatStore.findMessagesByDate( 55 startDate, 56 endDate, 57 MESSAGE_ROLE.USER, 58 maxResults 59 ); 60 61 const chatMessages = messages.map(msg => { 62 const createdDate = msg.createdDate; 63 const freshness_score = computeFreshnessScore(createdDate, halfLifeDays); 64 return { 65 createdDate, 66 role: msg.role, 67 content: msg.content?.body ?? null, 68 pageUrl: msg.pageUrl, 69 freshness_score, 70 }; 71 }); 72 73 return chatMessages; 74 } 75 76 /** 77 * Compute a freshness score for a message based on its age, using an 78 * exponential decay with a configurable half-life. 79 * 80 * The score is: 81 * -> 1.0 for messages with ageDays <= 0 (now or in the future) 82 * -> exp(-ln(2) * (ageDays / halfLifeDays)) for older messages, 83 * clamped into the [0, 1] range. 84 * 85 * @param {number|Date} createdDate 86 * Message creation time, either as a millisecond timestamp or a Date. 87 * @param {number} [halfLifeDays=DEFAULT_HALF_LIFE_DAYS] 88 * Half-life in days; larger values decay more slowly. 89 * @returns {number} 90 * Freshness score in the range [0, 1]. 91 */ 92 export function computeFreshnessScore( 93 createdDate, 94 halfLifeDays = DEFAULT_HALF_LIFE_DAYS 95 ) { 96 const now = Date.now(); 97 const createdMs = 98 typeof createdDate === "number" ? createdDate : createdDate.getTime(); 99 const ageMs = now - createdMs; 100 const ageDays = 101 ageMs / (MS_PER_SEC * SEC_PER_MIN * MINS_PER_HOUR * HOURS_PER_DAY); 102 if (ageDays <= 0) { 103 return 1; 104 } 105 const raw = Math.exp(-Math.LN2 * (ageDays / halfLifeDays)); 106 return Math.max(0, Math.min(1, raw)); 107 }