tor-browser

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

commit 63c14b53caf82c72378d2974846127213068ba55
parent 92325e1fa4edd0ece34dc0ecbdf34536303ead1c
Author: Molly Shillabeer <mshillabeer@mozilla.com>
Date:   Tue, 23 Dec 2025 20:53:08 +0000

Bug 2003681 - Implement New Tab conversation starters r=tzhang,ai-models-reviewers

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

Diffstat:
Mbrowser/components/aiwindow/models/ConversationSuggestions.sys.mjs | 45+++++++++++++++++++++++++++++++++++++++++++++
Mbrowser/components/aiwindow/models/tests/xpcshell/test_ConversationSuggestions.js | 77+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 122 insertions(+), 0 deletions(-)

diff --git a/browser/components/aiwindow/models/ConversationSuggestions.sys.mjs b/browser/components/aiwindow/models/ConversationSuggestions.sys.mjs @@ -103,6 +103,51 @@ const formatJson = obj => { } }; +export const NewTabStarterGenerator = { + writingPrompts: [ + "Write a first draft", + "Improve writing", + "Proofread a message", + ], + + planningPrompts: ["Simplify a topic", "Brainstorm ideas", "Help make a plan"], + + // TODO: discuss with design about updating phrasing to "pages" instead of "tabs" + browsingPrompts: [ + { text: "Find tabs in history", minTabs: 0 }, + { text: "Summarize tabs", minTabs: 1 }, + { text: "Compare tabs", minTabs: 2 }, + ], + + getRandom(arr) { + return arr[Math.floor(Math.random() * arr.length)]; + }, + + /** + * Generate conversation starter prompts based on number of open tabs + * + * @param {number} tabCount - number of open tabs + * @returns {Promise<Array>} Array of {text, type} suggestion objects + */ + async getPrompts(tabCount) { + const validBrowsingPrompts = this.browsingPrompts.filter( + p => tabCount >= p.minTabs + ); + + const writingPrompt = this.getRandom(this.writingPrompts); + const planningPrompt = this.getRandom(this.planningPrompts); + const browsingPrompt = validBrowsingPrompts.length + ? this.getRandom(validBrowsingPrompts) + : this.browsingPrompts[0]; + + return [ + { text: writingPrompt, type: "chat" }, + { text: planningPrompt, type: "chat" }, + { text: browsingPrompt.text, type: "chat" }, + ]; + }, +}; + /** * Generates conversation starter prompts based on tab context + (optional) user insights * diff --git a/browser/components/aiwindow/models/tests/xpcshell/test_ConversationSuggestions.js b/browser/components/aiwindow/models/tests/xpcshell/test_ConversationSuggestions.js @@ -5,6 +5,7 @@ do_get_profile(); const { + NewTabStarterGenerator, trimConversation, addInsightsToPrompt, cleanInferenceOutput, @@ -254,6 +255,82 @@ add_task(function test_cleanInferenceOutput() { }); /** + * Tests for createNewTabPromptGenerator generating prompts based on tab count + */ +add_task(async function test_createNewTabPromptGenerator() { + const sb = sinon.createSandbox(); + const writingPrompts = [ + "Write a first draft", + "Improve writing", + "Proofread a message", + ]; + + const planningPrompts = [ + "Simplify a topic", + "Brainstorm ideas", + "Help make a plan", + ]; + try { + const cases = [ + { + input: { tabCount: -1 }, + expectedBrowsing: ["Find tabs in history"], + }, + { + input: { tabCount: 0 }, + expectedBrowsing: ["Find tabs in history"], + }, + { + input: { tabCount: 1 }, + expectedBrowsing: ["Find tabs in history", "Summarize tabs"], + }, + { + input: { tabCount: 2 }, + expectedBrowsing: [ + "Find tabs in history", + "Summarize tabs", + "Compare tabs", + ], + }, + { + input: { tabCount: 3 }, + expectedBrowsing: [ + "Find tabs in history", + "Summarize tabs", + "Compare tabs", + ], + }, + ]; + const promptGenerator = NewTabStarterGenerator; + for (const { input, expectedBrowsing } of cases) { + const results = await promptGenerator.getPrompts(input.tabCount); + Assert.equal(results.length, 3, "Should return 3 suggestions"); + for (const result of results) { + Assert.equal( + result.type, + "chat", + "Each result should have type 'chat'" + ); + } + Assert.ok( + writingPrompts.includes(results[0].text), + "Results should include a valid writing prompt" + ); + Assert.ok( + planningPrompts.includes(results[1].text), + "Results should include a valid planning prompt" + ); + Assert.ok( + expectedBrowsing.includes(results[2].text), + "Results should include a valid browsing prompt" + ); + } + } finally { + sb.restore(); + } +}); + +/** * Tests for generateConversationStartersSidebar successfully generating suggestions */ add_task(async function test_generateConversationStartersSidebar_happy_path() {