Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/chrome/src/agent/agent.js
Original file line number Diff line number Diff line change
Expand Up @@ -18172,7 +18172,7 @@ Rules: no prose intro, no conclusion, no "this screenshot shows...", no layout d
const key = args.key;
const repeatRaw = Number(args.repeat ?? 1);
const repeat = Math.max(1, Math.min(3, Number.isFinite(repeatRaw) ? Math.floor(repeatRaw) : 1));
const SUPPORTED_KEYS = ['Escape', 'Tab', 'Enter', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'];
const SUPPORTED_KEYS = ['Escape', 'Tab', 'Enter', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', ';'];
if (!SUPPORTED_KEYS.includes(key)) {
return {
success: false,
Expand All @@ -18196,6 +18196,7 @@ Rules: no prose intro, no conclusion, no "this screenshot shows...", no layout d
ArrowUp: { code: 'ArrowUp', windowsVirtualKeyCode: 38 },
ArrowRight: { code: 'ArrowRight', windowsVirtualKeyCode: 39 },
ArrowDown: { code: 'ArrowDown', windowsVirtualKeyCode: 40 },
';': { code: 'Semicolon', windowsVirtualKeyCode: 186 },
}[key];

for (let i = 0; i < repeat; i++) {
Expand Down
3 changes: 2 additions & 1 deletion src/chrome/src/agent/permission-gate.js
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,8 @@ const TOOL_CAPABILITY = {
* via chrome.downloads → DOWNLOAD. These are not model-exposed tools.
* - set_field: TYPE normally, but CLICK when submit:true (pressing Enter
* submits the form — a TYPE grant must not authorize a submit).
* - press_keys: Enter can submit/activate → CLICK; Tab/Escape are benign.
* - press_keys: Enter and page shortcuts such as ; can mutate → CLICK;
* Tab/Escape are benign.
*/
export function capabilityFor(name, args) {
args = args || {};
Expand Down
4 changes: 2 additions & 2 deletions src/chrome/src/agent/planner.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ Rules:
memory: scratchpad_write, progress_update, progress_read
schedule: schedule_task (future/recurring work the user explicitly asked for), schedule_resume (pause CURRENT run blocked on external event)
finish: done
- press_keys supports only unmodified Escape, Tab, Enter, and arrow keys. Never plan Ctrl/Cmd/Alt/Shift combinations or browser UI shortcuts. To select one literal page-text match, plan find_text instead of Ctrl/Cmd+F. Each find_text call replaces the previous selection and does not open browser Find UI; never plan sequential calls as simultaneous highlights.
- press_keys supports only unmodified Escape, Tab, Enter, arrow keys, and ; (semicolon, for page shortcuts such as Gmail Expand all). Never plan Ctrl/Cmd/Alt/Shift combinations or browser UI shortcuts. To select one literal page-text match, plan find_text instead of Ctrl/Cmd+F. Each find_text call replaces the previous selection and does not open browser Find UI; never plan sequential calls as simultaneous highlights.
- For repeated same-kind UI mutations (for example following many users), plan visible UI first with bounded batches, verification, progress_update, and wait_for_stable pacing; do not plan one huge same-shape click/tool batch.
- Do not invent a prerequisite to discover a raw identifier (email address, account ID, username, or similar) when the target UI provides a name-based contact/entity picker and the user already supplied a human-readable name. Plan to use the picker first. Inspect surrounding pages or messages for the raw identifier only if the picker fails, returns multiple ambiguous matches, or the user explicitly asked for the identifier itself.
- Set confidence from 0.0 to 1.0 for how clear and safe this plan is. Use 0.90+ only when the task, page state, and next steps are straightforward; use lower scores for ambiguity, destructive changes, payments, credentials, bulk mutations, or uncertain page state.
Expand Down Expand Up @@ -128,7 +128,7 @@ Rules:
- schedule_task supports one-shot times and fixed-minute intervals only. Calendar/cron recurrence such as monthly is unsupported: classify it as clarify, explain the limitation in localized.summary, and ask for a one-shot time or fixed interval. Never convert calendar recurrence into an approximate interval.
- Canonical summary, steps, and risks must be English. localized fields must use the requested wbLocale.
- For execute, keep the compact plan to 1–4 steps. For plan_only, provide 2–8 useful steps. For respond and clarify, steps may be empty.
- press_keys supports only unmodified Escape, Tab, Enter, and arrow keys. Never plan modifier combinations or browser UI shortcuts; use find_text to select one page-text match instead of Ctrl/Cmd+F. Each call replaces the previous selection and cannot create simultaneous highlights or browser Find UI.
- press_keys supports only unmodified Escape, Tab, Enter, arrow keys, and ; (semicolon, for page shortcuts such as Gmail Expand all). Never plan modifier combinations or browser UI shortcuts; use find_text to select one page-text match instead of Ctrl/Cmd+F. Each call replaces the previous selection and cannot create simultaneous highlights or browser Find UI.
- Do not invent URLs, credentials, tool names, or facts.`;

export function normalizePlannerLocale(value) {
Expand Down
8 changes: 4 additions & 4 deletions src/chrome/src/agent/tools.js
Original file line number Diff line number Diff line change
Expand Up @@ -306,11 +306,11 @@ export const AGENT_TOOLS = [
type: 'function',
function: {
name: 'press_keys',
description: 'Press one unmodified keyboard key. Supports only Escape, Tab, Enter, ArrowUp, ArrowDown, ArrowLeft, and ArrowRight. Ctrl/Cmd/Alt/Shift combinations and browser shortcuts such as Ctrl+F are not supported. Use find_text to select one page-text match.',
description: 'Press one unmodified keyboard key. Supports Escape, Tab, Enter, ArrowUp, ArrowDown, ArrowLeft, ArrowRight, and ; (semicolon, for page shortcuts such as Gmail Expand all). Ctrl/Cmd/Alt/Shift combinations and browser shortcuts such as Ctrl+F are not supported. Use find_text to select one page-text match.',
parameters: {
type: 'object',
properties: {
key: { type: 'string', enum: ['Escape', 'Tab', 'Enter', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'], description: 'Key to press.' },
key: { type: 'string', enum: ['Escape', 'Tab', 'Enter', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', ';'], description: 'Key to press.' },
repeat: { type: 'number', description: 'How many times to press the key (default: 1, max: 3).' },
},
required: ['key'],
Expand Down Expand Up @@ -1469,7 +1469,7 @@ Available tools:
- schedule_task: Create a one-shot or fixed-minute-interval task only when the user explicitly asks for future scheduled work. It does not support calendar/cron recurrence; never approximate monthly recurrence. Prefer URL targets for repeatable automations; current_tab is strict and fails if the tab changes.
- get_selection: Get highlighted text
- find_text: Select one literal page-text match instead of Ctrl/Cmd+F. Each call replaces the previous selection; it does not open browser Find UI or keep multiple terms highlighted.
- press_keys: Press only unmodified Escape/Tab/Enter/arrows. Modifier combinations and browser shortcuts are unsupported.
- press_keys: Press only unmodified Escape/Tab/Enter/arrows or ; (semicolon). Modifier combinations and browser shortcuts are unsupported.
- new_tab: Open a background reference tab; the current run stays on its original tab
- clarify: Pause and ask the user a question. Use ONLY for material ambiguity that you cannot resolve by reading the page (e.g. "my API key" on a site with multiple plugins that each have one). Unanswered clarifies auto-select options[0] after the timeout (default 60s) with source=timeout (not high-risk approval); Settings Instant yields source=auto (intentional auto-approve — continue). Put the safe/default first. Do NOT use to confirm correct actions; do NOT call before every step. Budget 1-2 per run, max.
- done: Signal task completion
Expand Down Expand Up @@ -1809,7 +1809,7 @@ TOOLS — use only these:
- get_accessibility_tree: PREFERRED read. Flat-text tree with roles, names, and stable ref_ids. Use filter:"visible" by default.
- click_ax({ref_id}) / set_checked({ref_id, checked}) / type_ax({ref_id, text}) / set_field({ref_id, text, submit}): act on nodes by ref_id. set_field is preferred for text fields; set_checked is required for native checkboxes.
- read_page: prose fallback for long articles. get_window_info: inspect browser window/viewport size. scroll, navigate({url}), go_back()/go_forward(): walk the run tab's history. new_tab({url}) only opens a background reference tab and never retargets the run.
- get_interactive_elements: legacy indexed element list (use when the tree misses elements). click({text}) / type_text({text}) / press_keys({key}): legacy fallbacks. press_keys supports only unmodified Escape/Tab/Enter/arrows, never Ctrl/Cmd/Alt/Shift combinations or browser shortcuts.
- get_interactive_elements: legacy indexed element list (use when the tree misses elements). click({text}) / type_text({text}) / press_keys({key}): legacy fallbacks. press_keys supports only unmodified Escape/Tab/Enter/arrows or ; (semicolon), never Ctrl/Cmd/Alt/Shift combinations or browser shortcuts.
- extract_data: tables/headings/images/links. get_selection: read highlighted text. find_text({text}): select one literal page-text match; each call replaces the previous selection and never creates simultaneous highlights or browser Find UI. read_pdf: read a PDF.
- wait_for_element({selector}) / wait_for_stable({quietMs}): wait for an element / for the page to go quiet after an action.
- schedule_resume({after_seconds|run_at, reason, resume_instruction}): terminal durable pause for this current task.
Expand Down
3 changes: 2 additions & 1 deletion src/chrome/src/content/content.js
Original file line number Diff line number Diff line change
Expand Up @@ -1935,7 +1935,7 @@
const key = params?.key;
const repeatRaw = Number(params?.repeat ?? 1);
const repeat = Math.max(1, Math.min(3, Number.isFinite(repeatRaw) ? Math.floor(repeatRaw) : 1));
const SUPPORTED_KEYS = ['Escape', 'Tab', 'Enter', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'];
const SUPPORTED_KEYS = ['Escape', 'Tab', 'Enter', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', ';'];
if (!SUPPORTED_KEYS.includes(key)) {
return {
success: false,
Expand All @@ -1959,6 +1959,7 @@
ArrowUp: { code: 'ArrowUp', keyCode: 38 },
ArrowRight: { code: 'ArrowRight', keyCode: 39 },
ArrowDown: { code: 'ArrowDown', keyCode: 40 },
';': { code: 'Semicolon', keyCode: 186 },
}[key];
const target = (document.activeElement && document.activeElement !== document.body)
? document.activeElement
Expand Down
3 changes: 2 additions & 1 deletion src/firefox/src/agent/permission-gate.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,8 @@ const TOOL_CAPABILITY = {
* via downloads → DOWNLOAD. These are not model-exposed tools.
* - set_field: TYPE normally, but CLICK when submit:true (pressing Enter
* submits the form — a TYPE grant must not authorize a submit).
* - press_keys: Enter can submit/activate → CLICK; Tab/Escape are benign.
* - press_keys: Enter and page shortcuts such as ; can mutate → CLICK;
* Tab/Escape are benign.
*/
export function capabilityFor(name, args) {
args = args || {};
Expand Down
4 changes: 2 additions & 2 deletions src/firefox/src/agent/planner.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ Rules:
memory: scratchpad_write, progress_update, progress_read
schedule: schedule_task (future/recurring work the user explicitly asked for), schedule_resume (pause CURRENT run blocked on external event)
finish: done
- press_keys supports only unmodified Escape, Tab, Enter, and arrow keys. Never plan Ctrl/Cmd/Alt/Shift combinations or browser UI shortcuts. To select one literal page-text match, plan find_text instead of Ctrl/Cmd+F. Each find_text call replaces the previous selection and does not open browser Find UI; never plan sequential calls as simultaneous highlights.
- press_keys supports only unmodified Escape, Tab, Enter, arrow keys, and ; (semicolon, for page shortcuts such as Gmail Expand all). Never plan Ctrl/Cmd/Alt/Shift combinations or browser UI shortcuts. To select one literal page-text match, plan find_text instead of Ctrl/Cmd+F. Each find_text call replaces the previous selection and does not open browser Find UI; never plan sequential calls as simultaneous highlights.
- For repeated same-kind UI mutations (for example following many users), plan visible UI first with bounded batches, verification, progress_update, and wait_for_stable pacing; do not plan one huge same-shape click/tool batch.
- Do not invent a prerequisite to discover a raw identifier (email address, account ID, username, or similar) when the target UI provides a name-based contact/entity picker and the user already supplied a human-readable name. Plan to use the picker first. Inspect surrounding pages or messages for the raw identifier only if the picker fails, returns multiple ambiguous matches, or the user explicitly asked for the identifier itself.
- Set confidence from 0.0 to 1.0 for how clear and safe this plan is. Use 0.90+ only when the task, page state, and next steps are straightforward; use lower scores for ambiguity, destructive changes, payments, credentials, bulk mutations, or uncertain page state.
Expand Down Expand Up @@ -128,7 +128,7 @@ Rules:
- schedule_task supports one-shot times and fixed-minute intervals only. Calendar/cron recurrence such as monthly is unsupported: classify it as clarify, explain the limitation in localized.summary, and ask for a one-shot time or fixed interval. Never convert calendar recurrence into an approximate interval.
- Canonical summary, steps, and risks must be English. localized fields must use the requested wbLocale.
- For execute, keep the compact plan to 1–4 steps. For plan_only, provide 2–8 useful steps. For respond and clarify, steps may be empty.
- press_keys supports only unmodified Escape, Tab, Enter, and arrow keys. Never plan modifier combinations or browser UI shortcuts; use find_text to select one page-text match instead of Ctrl/Cmd+F. Each call replaces the previous selection and cannot create simultaneous highlights or browser Find UI.
- press_keys supports only unmodified Escape, Tab, Enter, arrow keys, and ; (semicolon, for page shortcuts such as Gmail Expand all). Never plan modifier combinations or browser UI shortcuts; use find_text to select one page-text match instead of Ctrl/Cmd+F. Each call replaces the previous selection and cannot create simultaneous highlights or browser Find UI.
- Do not invent URLs, credentials, tool names, or facts.`;

export function normalizePlannerLocale(value) {
Expand Down
8 changes: 4 additions & 4 deletions src/firefox/src/agent/tools.js
Original file line number Diff line number Diff line change
Expand Up @@ -306,11 +306,11 @@ export const AGENT_TOOLS = [
type: 'function',
function: {
name: 'press_keys',
description: 'Press one unmodified keyboard key. Supports only Escape, Tab, Enter, ArrowUp, ArrowDown, ArrowLeft, and ArrowRight. Ctrl/Cmd/Alt/Shift combinations and browser shortcuts such as Ctrl+F are not supported. Use find_text to select one page-text match. Firefox dispatches synthetic events, so native controls may not react on every site.',
description: 'Press one unmodified keyboard key. Supports Escape, Tab, Enter, ArrowUp, ArrowDown, ArrowLeft, ArrowRight, and ; (semicolon, for page shortcuts such as Gmail Expand all). Ctrl/Cmd/Alt/Shift combinations and browser shortcuts such as Ctrl+F are not supported. Use find_text to select one page-text match. Firefox dispatches synthetic events, so native controls may not react on every site.',
parameters: {
type: 'object',
properties: {
key: { type: 'string', enum: ['Escape', 'Tab', 'Enter', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'], description: 'Key to press.' },
key: { type: 'string', enum: ['Escape', 'Tab', 'Enter', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', ';'], description: 'Key to press.' },
repeat: { type: 'number', description: 'How many times to press the key (default: 1, max: 3).' },
},
required: ['key'],
Expand Down Expand Up @@ -1340,7 +1340,7 @@ Available tools:
- schedule_task: Create a one-shot or fixed-minute-interval task only when the user explicitly asks for future scheduled work. It does not support calendar/cron recurrence; never approximate monthly recurrence. Prefer URL targets for repeatable automations; current_tab is strict and fails if the tab changes.
- get_selection: Get highlighted text
- find_text: Select one literal page-text match instead of Ctrl/Cmd+F. Each call replaces the previous selection; it does not open browser Find UI or keep multiple terms highlighted.
- press_keys: Press only unmodified Escape/Tab/Enter/arrows. Modifier combinations and browser shortcuts are unsupported.
- press_keys: Press only unmodified Escape/Tab/Enter/arrows or ; (semicolon). Modifier combinations and browser shortcuts are unsupported.
- new_tab: Open a background reference tab; the current run stays on its original tab
- clarify: Pause and ask the user a question. Use ONLY for material ambiguity that you cannot resolve by reading the page (e.g. "my API key" on a site with multiple plugins that each have one). Unanswered clarifies auto-select options[0] after the timeout (default 60s) with source=timeout (not high-risk approval); Settings Instant yields source=auto (intentional auto-approve — continue). Put the safe/default first. Do NOT use to confirm correct actions; do NOT call before every step. Budget 1-2 per run, max.
- done: Signal task completion
Expand Down Expand Up @@ -1564,7 +1564,7 @@ TOOLS — use only these:
- get_accessibility_tree: PREFERRED read. Flat-text tree with roles, names, and stable ref_ids. Use filter:"visible" by default.
- click_ax({ref_id}) / set_checked({ref_id, checked}) / type_ax({ref_id, text}) / set_field({ref_id, text, submit}): act on nodes by ref_id. set_field is preferred for text fields; set_checked is required for native checkboxes.
- read_page: prose fallback for long articles. get_window_info: inspect browser window/viewport size. scroll, navigate({url}), go_back()/go_forward(): walk the run tab's history. new_tab({url}) only opens a background reference tab and never retargets the run.
- get_interactive_elements: legacy indexed element list (use when the tree misses elements). click({text}) / type_text({text}) / press_keys({key}): legacy fallbacks. press_keys supports only unmodified Escape/Tab/Enter/arrows, never Ctrl/Cmd/Alt/Shift combinations or browser shortcuts.
- get_interactive_elements: legacy indexed element list (use when the tree misses elements). click({text}) / type_text({text}) / press_keys({key}): legacy fallbacks. press_keys supports only unmodified Escape/Tab/Enter/arrows or ; (semicolon), never Ctrl/Cmd/Alt/Shift combinations or browser shortcuts.
- extract_data: tables/headings/images/links. get_selection: read highlighted text. find_text({text}): select one literal page-text match; each call replaces the previous selection and never creates simultaneous highlights or browser Find UI. read_pdf: read a PDF.
- wait_for_element({selector}) / wait_for_stable({quietMs}): wait for an element / for the page to go quiet after an action.
- schedule_resume({after_seconds|run_at, reason, resume_instruction}): terminal durable pause for this current task.
Expand Down
3 changes: 2 additions & 1 deletion src/firefox/src/content/content.js
Original file line number Diff line number Diff line change
Expand Up @@ -2129,7 +2129,7 @@
const key = params?.key;
const repeatRaw = Number(params?.repeat ?? 1);
const repeat = Math.max(1, Math.min(3, Number.isFinite(repeatRaw) ? Math.floor(repeatRaw) : 1));
const SUPPORTED_KEYS = ['Escape', 'Tab', 'Enter', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'];
const SUPPORTED_KEYS = ['Escape', 'Tab', 'Enter', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', ';'];
if (!SUPPORTED_KEYS.includes(key)) {
return {
success: false,
Expand All @@ -2154,6 +2154,7 @@
ArrowUp: { code: 'ArrowUp', keyCode: 38 },
ArrowRight: { code: 'ArrowRight', keyCode: 39 },
ArrowDown: { code: 'ArrowDown', keyCode: 40 },
';': { code: 'Semicolon', keyCode: 59 },
}[key];
const target = (document.activeElement && document.activeElement !== document.body)
? document.activeElement
Expand Down
2 changes: 1 addition & 1 deletion test/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Three layers, each with a different scope, speed, and cost profile.

```bash
npm install
npx playwright install chromium
npx playwright install chromium firefox
```

## 1. Unit — `npm test`
Expand Down
Loading
Loading