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
/**
* This module exports a provider that offers search history suggestions
* based on embeddings and semantic search techniques using semantic
* history
*/
import {
UrlbarProvider,
UrlbarUtils,
} from "resource:///modules/UrlbarUtils.sys.mjs";
import { PlacesSemanticHistoryManager } from "resource://gre/modules/PlacesSemanticHistoryManager.sys.mjs";
const lazy = {};
ChromeUtils.defineESModuleGetters(lazy, {
UrlbarResult: "resource:///modules/UrlbarResult.sys.mjs",
UrlbarPrefs: "resource:///modules/UrlbarPrefs.sys.mjs",
});
/**
* Class representing the Semantic History Search provider for the URL bar.
*
* This provider queries a semantic database created using history.
* It performs semantic search using embeddings generated
* by an ML model and retrieves results ranked by cosine similarity to the
* query's embedding.
*
* @class
*/
class ProviderSemanticHistorySearch extends UrlbarProvider {
#semanticManager;
/**
* Lazily creates (on first call) and returns the
* {@link PlacesSemanticHistoryManager} instance backing this provider.
*
* The manager is instantiated only once and cached in the private
* `#semanticManager` field. It is configured with sensible defaults for
* semantic history search:
* • `embeddingSize`: 384 – dimensionality of vector embeddings
* • `rowLimit`: 10000 – maximum rows pulled from Places
* • `samplingAttrib`: "frecency" – column used when down-sampling
* • `changeThresholdCount`: 3 – restart inference after this many DB changes
* • `distanceThreshold`: 0.75 – cosine-distance cut-off for matches
*
* @returns {PlacesSemanticHistoryManager}
* The shared, initialized semantic-history manager instance.
*/
ensureSemanticManagerInitialized() {
if (!this.#semanticManager) {
this.#semanticManager = new PlacesSemanticHistoryManager({
embeddingSize: 384,
rowLimit: 10000,
samplingAttrib: "frecency",
changeThresholdCount: 3,
distanceThreshold: 0.75,
});
}
return this.#semanticManager;
}
get name() {
return "SemanticHistorySearch";
}
get type() {
return UrlbarUtils.PROVIDER_TYPE.PROFILE;
}
/**
* Determines if the provider is active for the given query context.
*
* @param {object} queryContext
* The context of the query, including the search string.
* @returns {boolean}
* `true` if the provider is active; `false` otherwise.
*/
isActive(queryContext) {
const semanticHistoryFlag = lazy.UrlbarPrefs.get("suggest.semanticHistory");
const minSearchStringLength = lazy.UrlbarPrefs.get(
"suggest.semanticHistory.minLength"
);
if (
semanticHistoryFlag &&
queryContext.searchString.length >= minSearchStringLength
) {
const semanticManager = this.ensureSemanticManagerInitialized();
return semanticManager?.canUseSemanticSearch ?? false;
}
return false;
}
/**
* Starts a semantic search query.
*
* @param {object} queryContext
* The query context, including the search string.
* @param {Function} addCallback
* Callback to add results to the URL bar.
*/
async startQuery(queryContext, addCallback) {
let instance = this.queryInstance;
if (!this.#semanticManager) {
throw new Error(
"SemanticManager must be initialized via isActive() before calling startQuery()"
);
}
let resultObject = await this.#semanticManager.infer(queryContext);
let results = resultObject.results;
if (!results || instance != this.queryInstance) {
return;
}
for (let res of results) {
const result = new lazy.UrlbarResult(
UrlbarUtils.RESULT_TYPE.URL,
UrlbarUtils.RESULT_SOURCE.HISTORY,
...lazy.UrlbarResult.payloadAndSimpleHighlights(queryContext.tokens, {
title: [res.title, UrlbarUtils.HIGHLIGHT.NONE],
url: [res.url, UrlbarUtils.HIGHLIGHT.NONE],
icon: UrlbarUtils.getIconForUrl(res.url),
})
);
result.resultGroup = UrlbarUtils.RESULT_GROUP.HISTORY_SEMANTIC;
addCallback(this, result);
}
}
/**
* Gets the priority of this provider relative to other providers.
*
* @returns {number} The priority of this provider.
*/
getPriority() {
return 0;
}
}
export var UrlbarProviderSemanticHistorySearch =
new ProviderSemanticHistorySearch();