commit 3511c2af06c0559a9df0129f9db41a6418d70f1f
parent 22aa0b8ee0758bf8a05d3057c873152201c694c8
Author: frankjc2022 <frankjc2022@gmail.com>
Date: Fri, 19 Dec 2025 19:11:30 +0000
Bug 2006423 - Remove timezone handling in tools config while maintaining accuracy r=tzhang,ai-models-reviewers
Differential Revision: https://phabricator.services.mozilla.com/D277025
Diffstat:
5 files changed, 30 insertions(+), 49 deletions(-)
diff --git a/browser/components/aiwindow/models/ChatUtils.sys.mjs b/browser/components/aiwindow/models/ChatUtils.sys.mjs
@@ -24,17 +24,11 @@ ChromeUtils.defineESModuleGetters(lazy, {
export function getLocalIsoTime() {
try {
const date = new Date();
- const tzOffsetMinutes = date.getTimezoneOffset();
- const adjusted = new Date(date.getTime() - tzOffsetMinutes * 60000)
- .toISOString()
- .slice(0, 19); // Keep up to seconds
- const sign = tzOffsetMinutes <= 0 ? "+" : "-";
- const hours = String(Math.floor(Math.abs(tzOffsetMinutes) / 60)).padStart(
- 2,
- "0"
+ const pad = n => String(n).padStart(2, "0");
+ return (
+ `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}` +
+ `T${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`
);
- const minutes = String(Math.abs(tzOffsetMinutes) % 60).padStart(2, "0");
- return `${adjusted}${sign}${hours}:${minutes}`;
} catch {
return null;
}
@@ -90,6 +84,7 @@ export async function constructRealTimeInfoInjectionMessage(depsOverride) {
const isoTimestamp = getLocalIsoTime();
const datePart = isoTimestamp?.split("T")[0] ?? "";
const locale = Services.locale.appLocaleAsBCP47;
+ const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
const hasTabInfo = Boolean(url || title || description);
const tabSection = hasTabInfo
? [
@@ -103,6 +98,7 @@ export async function constructRealTimeInfoInjectionMessage(depsOverride) {
const content = [
`Below are some real-time context details you can use to inform your response:`,
`Locale: ${locale}`,
+ `Timezone: ${timezone}`,
`Current date & time in ISO format: ${isoTimestamp}`,
`Today's date: ${datePart || "Unavailable"}`,
``,
diff --git a/browser/components/aiwindow/models/SearchBrowsingHistory.sys.mjs b/browser/components/aiwindow/models/SearchBrowsingHistory.sys.mjs
@@ -350,9 +350,9 @@ async function searchBrowsingHistoryBasic({ searchTerm, historyLimit }) {
* The search string. If null or empty, semantic search is skipped and
* results are filtered by time range and sorted by last_visit_date and frecency.
* @param {string|null} params.startTs
- * Optional ISO-8601 start timestamp (e.g. "2025-11-07T09:00:00-05:00").
+ * Optional local ISO-8601 start timestamp (e.g. "2025-11-07T09:00:00").
* @param {string|null} params.endTs
- * Optional ISO-8601 end timestamp (e.g. "2025-11-07T09:00:00-05:00").
+ * Optional local ISO-8601 end timestamp (e.g. "2025-11-07T09:00:00").
* @param {number} params.historyLimit
* Maximum number of history results to return.
* @returns {Promise<object>}
diff --git a/browser/components/aiwindow/models/Tools.sys.mjs b/browser/components/aiwindow/models/Tools.sys.mjs
@@ -44,43 +44,30 @@ export const toolsConfig = [
function: {
name: SEARCH_BROWSING_HISTORY,
description:
- "Refind pages from the user's PAST BROWSING HISTORY. Use this whenever the " +
- "user wants to recall, review, list, or see pages they visited earlier (for a " +
- "topic, site, or time period). Also use this when the user requests all pages " +
- 'from a past time period (e.g., "yesterday", "last week"), even if no topic is ' +
- "specified. Do NOT use for open tabs, completely general web questions, or " +
- 'abstract questions about "history" or habits.',
+ "Retrieve pages from the user's past browsing history, optionally filtered by " +
+ "topic and/or time range.",
parameters: {
type: "object",
properties: {
searchTerm: {
type: "string",
description:
- "A detailed, noun-heavy phrase (~2-12 meaningful tokens) summarizing " +
- "the user's intent for semantic retrieval. Include the main entity/topic " +
- "plus 1-3 contextual qualifiers (e.g., library name, purpose, site, or " +
- "timeframe). Avoid vague or single-word queries.",
+ "A concise phrase describing what the user is trying to find in their " +
+ "browsing history (topic, site, or purpose).",
},
startTs: {
type: "string",
description:
- "Inclusive lower bound of the time window as an ISO 8601 datetime string " +
- "(e.g., '2025-11-07T09:00:00-05:00'). Use when the user asks for results " +
- "within a time or range start, such as 'last week', 'since yesterday', or" +
- "'last night'. This must be before the user's current datetime.",
- default: null,
+ "Inclusive start of the time range as a local ISO 8601 datetime " +
+ "('YYYY-MM-DDTHH:mm:ss', no timezone).",
},
endTs: {
type: "string",
description:
- "Inclusive upper bound of the time window as an ISO 8601 datetime string " +
- "(e.g., '2025-11-07T21:00:00-05:00'). Use when the user asks for results " +
- "within a time or range end, such as 'last week', 'between 2025-10-01 and " +
- "2025-10-31', or 'before Monday'. This must be before the user's current datetime.",
- default: null,
+ "Inclusive end of the time range as a local ISO 8601 datetime " +
+ "('YYYY-MM-DDTHH:mm:ss', no timezone).",
},
},
- required: [],
},
},
},
@@ -166,8 +153,8 @@ export async function getOpenTabs(n = 15) {
*
* Parameters (defaults shown):
* - searchTerm: "" - string used for search
- * - startTs: null - ISO timestamp lower bound, or null
- * - endTs: null - ISO timestamp upper bound, or null
+ * - startTs: null - local ISO timestamp lower bound, or null
+ * - endTs: null - local ISO timestamp upper bound, or null
* - historyLimit: 15 - max number of results
*
* Detailed behavior and implementation are in SearchBrowsingHistory.sys.mjs.
@@ -178,9 +165,9 @@ export async function getOpenTabs(n = 15) {
* The search string. If null or empty, semantic search is skipped and
* results are filtered by time range and sorted by last_visit_date and frecency.
* @param {string|null} toolParams.startTs
- * Optional ISO-8601 start timestamp (e.g. "2025-11-07T09:00:00-05:00").
+ * Optional local ISO-8601 start timestamp (e.g. "2025-11-07T09:00:00").
* @param {string|null} toolParams.endTs
- * Optional ISO-8601 end timestamp (e.g. "2025-11-07T09:00:00-05:00").
+ * Optional local ISO-8601 end timestamp (e.g. "2025-11-07T09:00:00").
* @param {number} toolParams.historyLimit
* Maximum number of history results to return.
* @returns {Promise<object>}
diff --git a/browser/components/aiwindow/models/prompts/AssistantPrompts.sys.mjs b/browser/components/aiwindow/models/prompts/AssistantPrompts.sys.mjs
@@ -63,16 +63,14 @@ Stay predictable, supportive, and context-aware.
# Tool Usage
-- Use search_browsing_history to refind pages from the user's past browsing activity.
-- If the request refers to something the user saw earlier, visited previously, or spans a past time period ("yesterday", "earlier today", "last week"), default to using search_browsing_history unless it clearly concerns open tabs.
-- If the user explicitly mentions "history", "what I visited", "what I was reading/watching", or "what I opened" in the past, you should almost always use search_browsing_history at least once.
-- If the request is clearly about open tabs right now, use get_open_tabs.
-- If the user wants the content of a specific open page by URL, use get_page_content.
-- If the user is asking a general question that does not depend on their own browsing activity, you can answer directly without tools.
-- Before answering, quickly check: "Is the user asking about their own past browsing activity?" If yes, you should usually use search_browsing_history.
-- Never output XML-like tags or raw JSON for tools; the system handles tool invocation.
-
-(Queries like "show my browsing from last week" or "what pages did I visit earlier today" use search_browsing_history.)
+search_browsing_history:
+when to call
+- call when the user intent is to recover, refind, or recall previously visited pages
+- do NOT call for general questions or ongoing conversation that don't require page recovery
+how to call
+- build searchTerm as a concise, descriptive query; rewrite vague requests into title-like phrases and do not invent unrelated tokens
+- if the user requests a time period without a topic, call the tool with no searchTerm and only the time filter
+- extract temporal intent if present and map it to concrete ISO 8601 startTs/endTs using the smallest reasonable calendar span; otherwise set both to null
# Tool Call Rules
diff --git a/browser/components/aiwindow/models/tests/xpcshell/test_ChatUtils.js b/browser/components/aiwindow/models/tests/xpcshell/test_ChatUtils.js
@@ -94,8 +94,8 @@ add_task(function test_getLocalIsoTime_returns_offset_timestamp() {
"Should return a non-empty string"
);
Assert.ok(
- /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}[+-]\d{2}:\d{2}$/.test(iso),
- "Should include date, time (up to seconds), and timezone offset"
+ /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$/.test(iso),
+ "Should include date, time (up to seconds), without timezone offset"
);
} finally {
clock.restore();