tor-browser

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

commit 46dda4f4969e1e4bd1a32308b5fd6ec04e9db4e7
parent 5ccaf7fa2d7ee2bd28d433f8a7346902f6e2d733
Author: Nick Grato <ngrato@gmail.com>
Date:   Mon,  6 Oct 2025 23:24:58 +0000

Bug 1990881 - basic intent ask vs search vs navigate heuristic r=Mardak,firefox-ai-ml-reviewers

building on bug 1989035 doing chat, sometimes we want it to search instead. we can do some very basic heuristic to set up an async api for it to be likely replaced by a engine/model

to start, this could reflect text of the submit button based on the typed text. eventually this might be reused for classifying quick prompts and suggestions

Differential Revision: https://phabricator.services.mozilla.com/D267500

Diffstat:
Mbrowser/components/genai/SmartAssistEngine.sys.mjs | 27+++++++++++++++++++++++++++
Mbrowser/components/genai/content/smart-assist.mjs | 42+++++++++++++++++++++++++++++++++++++-----
Mbrowser/components/genai/tests/xpcshell/test_smart_assist_engine.js | 19+++++++++++++++++++
3 files changed, 83 insertions(+), 5 deletions(-)

diff --git a/browser/components/genai/SmartAssistEngine.sys.mjs b/browser/components/genai/SmartAssistEngine.sys.mjs @@ -210,4 +210,31 @@ export const SmartAssistEngine = { convo = [...convo, assistantToolMsg, ...toolResultMessages]; } }, + + /** + * + * @param {string} prompt + * @returns {string} "search" | "chat" + */ + async getPromptIntent(prompt) { + // TODO : this is mock logic to determine if the user wants to search or chat + // We will eventually want to use a model to determine this intent + const searchKeywords = [ + "search", + "find", + "look", + "query", + "locate", + "explore", + ]; + const formattedPrompt = prompt.toLowerCase(); + + const intent = searchKeywords.some(keyword => + formattedPrompt.includes(keyword) + ) + ? "search" + : "chat"; + + return intent; + }, }; diff --git a/browser/components/genai/content/smart-assist.mjs b/browser/components/genai/content/smart-assist.mjs @@ -29,6 +29,7 @@ export class SmartAssist extends MozLitElement { mode: { type: String }, // "tab" | "sidebar" overrideNewTab: { type: Boolean }, showLog: { type: Boolean }, + actionKey: { type: String }, // "chat" | "search" }; constructor() { @@ -45,6 +46,20 @@ export class SmartAssist extends MozLitElement { this.overrideNewTab = Services.prefs.getBoolPref( "browser.ml.smartAssist.overrideNewTab" ); + this.actionKey = "chat"; + + this._actions = { + chat: { + label: "Submit", + icon: "chrome://global/skin/icons/arrow-right.svg", + run: this._actionChat, + }, + search: { + label: "Search", + icon: "chrome://global/skin/icons/search-glass.svg", + run: this._actionSearch, + }, + }; } connectedCallback() { @@ -70,12 +85,27 @@ export class SmartAssist extends MozLitElement { this.logState = [...this.logState, entryWithDate]; }; - _handlePromptInput = e => { + _handlePromptInput = async e => { const value = e.target.value; this.userPrompt = value; + + // Determine intent based on keywords in the prompt + this.actionKey = await lazy.SmartAssistEngine.getPromptIntent(value); + }; + + /** + * Returns the current action object based on the actionKey + */ + + get inputAction() { + return this._actions[this.actionKey]; + } + + _actionSearch = () => { + // TODO: Implement search functionality }; - _handleSubmit = async () => { + _actionChat = async () => { const formattedPrompt = (this.userPrompt || "").trim(); if (!formattedPrompt) { return; @@ -126,7 +156,7 @@ export class SmartAssist extends MozLitElement { * Mock Functionality to open full page UX * * @param {boolean} enable - * Whether or not to override the new tab page. + * Whether or not to override the new tab page. */ _applyNewTabOverride(enable) { try { @@ -223,12 +253,14 @@ export class SmartAssist extends MozLitElement { @input=${e => this._handlePromptInput(e)} ></textarea> <moz-button + iconSrc=${this.inputAction.icon} id="submit-user-prompt-btn" type="primary" size="small" - @click=${this._handleSubmit} + @click=${this.inputAction.run} + iconPosition="end" > - Submit + ${this.inputAction.label} </moz-button> <!-- Footer - New Tab Override --> diff --git a/browser/components/genai/tests/xpcshell/test_smart_assist_engine.js b/browser/components/genai/tests/xpcshell/test_smart_assist_engine.js @@ -177,3 +177,22 @@ add_task(async function test_fetchWithHistory_propagates_stream_error() { sb.restore(); } }); + +add_task(async function test_getPromptIntent_basic() { + const cases = [ + { prompt: "please search for news on firefox", expected: "search" }, + { prompt: "Can you FIND me the docs for PageAssist?", expected: "search" }, // case-insensitive + { prompt: "look up the best pizza in SF", expected: "search" }, + { prompt: "hello there, how are you?", expected: "chat" }, + { prompt: "tell me a joke", expected: "chat" }, + ]; + + for (const { prompt, expected } of cases) { + const intent = await SmartAssistEngine.getPromptIntent(prompt); + Assert.equal( + intent, + expected, + `getPromptIntent("${prompt}") should return "${expected}"` + ); + } +});