tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

MemoriesConversationScheduler.sys.mjs (3968B)


      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 https://mozilla.org/MPL/2.0/. */
      4 
      5 const lazy = {};
      6 ChromeUtils.defineESModuleGetters(lazy, {
      7  setInterval: "resource://gre/modules/Timer.sys.mjs",
      8  clearInterval: "resource://gre/modules/Timer.sys.mjs",
      9  MemoriesManager:
     10    "moz-src:///browser/components/aiwindow/models/memories/MemoriesManager.sys.mjs",
     11  getRecentChats:
     12    "moz-src:///browser/components/aiwindow/models/memories/MemoriesChatSource.sys.mjs",
     13  PREF_GENERATE_MEMORIES:
     14    "moz-src:///browser/components/aiwindow/models/memories/MemoriesConstants.sys.mjs",
     15 });
     16 ChromeUtils.defineLazyGetter(lazy, "console", function () {
     17  return console.createInstance({
     18    prefix: "MemoriesConversationScheduler",
     19    maxLogLevelPref: "browser.aiwindow.memoriesLogLevel",
     20  });
     21 });
     22 
     23 // Generate memories if there have been at least 10 user messages since the last run
     24 const MEMORIES_SCHEDULER_MESSAGES_THRESHOLD = 10;
     25 
     26 // Memories conversation schedule every 4 hours
     27 const MEMORIES_SCHEDULER_INTERVAL_MS = 4 * 60 * 60 * 1000;
     28 
     29 /**
     30 * Schedules periodic generation of conversation-based memories.
     31 * Triggers memories generation when number of user messages exceeds the configured threshold ({@link MEMORIES_SCHEDULER_MESSAGES_THRESHOLD})
     32 *
     33 * E.g. Usage: MemoriesConversationScheduler.maybeInit()
     34 */
     35 export class MemoriesConversationScheduler {
     36  #intervalHandle = 0;
     37  #destroyed = false;
     38  #running = false;
     39 
     40  /** @type {MemoriesConversationScheduler | null} */
     41  static #instance = null;
     42 
     43  static maybeInit() {
     44    if (!Services.prefs.getBoolPref(lazy.PREF_GENERATE_MEMORIES, false)) {
     45      return null;
     46    }
     47    if (!this.#instance) {
     48      this.#instance = new MemoriesConversationScheduler();
     49    }
     50    return this.#instance;
     51  }
     52 
     53  constructor() {
     54    this.#startInterval();
     55    lazy.console.debug("Initialized");
     56  }
     57 
     58  /**
     59   * Starts the interval that periodically evaluates history drift and
     60   * potentially triggers memory generation.
     61   *
     62   * @throws {Error} If an interval is already running.
     63   */
     64  #startInterval() {
     65    if (this.#intervalHandle) {
     66      throw new Error(
     67        "Attempting to start an interval when one already existed"
     68      );
     69    }
     70    this.#intervalHandle = lazy.setInterval(
     71      this.#onInterval,
     72      MEMORIES_SCHEDULER_INTERVAL_MS
     73    );
     74  }
     75 
     76  /**
     77   * Stops the currently running interval, if any.
     78   */
     79  #stopInterval() {
     80    if (this.#intervalHandle) {
     81      lazy.clearInterval(this.#intervalHandle);
     82      this.#intervalHandle = 0;
     83    }
     84  }
     85 
     86  #onInterval = async () => {
     87    if (this.#destroyed) {
     88      lazy.console.warn("Interval fired after destroy; ignoring.");
     89      return;
     90    }
     91 
     92    if (this.#running) {
     93      lazy.console.debug(
     94        "Skipping run because a previous run is still in progress."
     95      );
     96      return;
     97    }
     98 
     99    this.#running = true;
    100    this.#stopInterval();
    101 
    102    try {
    103      // Detect whether conversation memories were generated before.
    104      const lastMemoryTs =
    105        (await lazy.MemoriesManager.getLastConversationMemoryTimestamp()) ?? 0;
    106 
    107      // Get user chat messages
    108      const chatMessagesSinceLastMemory =
    109        await lazy.getRecentChats(lastMemoryTs);
    110 
    111      // Not enough new messages
    112      if (
    113        chatMessagesSinceLastMemory.length <
    114        MEMORIES_SCHEDULER_MESSAGES_THRESHOLD
    115      ) {
    116        return;
    117      }
    118 
    119      // Generate memories
    120      await lazy.MemoriesManager.generateMemoriesFromConversationHistory();
    121    } catch (error) {
    122      lazy.console.error("Failed to generate conversation memories", error);
    123    } finally {
    124      if (!this.#destroyed) {
    125        this.#startInterval();
    126      }
    127      this.#running = false;
    128    }
    129  };
    130 
    131  destroy() {
    132    this.#stopInterval();
    133    this.#destroyed = true;
    134    lazy.console.debug("Destroyed");
    135  }
    136 
    137  async runNowForTesting() {
    138    await this.#onInterval();
    139  }
    140 }