Действия страницы через run_js
Основной Chat Agent 2.3.0 предоставляет модели один инструмент страницы:
run_js({code}). code — тело async-функции с явным JSON-возвратом.
История остаётся общей для сайта, выполнение привязано к исходной вкладке и документу.
Исходный Mermaid
flowchart LR
Model[Модель] -->|"run_js: code"| Agent
Agent -->|"существующая доставка NATS"| LocalMcp
LocalMcp --> Background
Background -->|"Chrome userScripts.execute / documentId"| Script[USER_SCRIPT]
Script <-->|"Chrome messages: dom.find/get/set/act"| DOM[Общий DOM runtime / collector]
Script -->|"JSON: ok, value / error"| Background
Background --> LocalMcp
LocalMcp -->|"browser_tool_result"| Agent
Agent --> ModelВключение
Нужен Chrome 138+. Обновите основной пакет по прежнему пути и включите «Разрешить пользовательские скрипты» в настройках расширения. Нажатие значка на HTTP/HTTPS-странице выдаёт временный activeTab доступ именно этой странице. Объявленные optional host permissions не выдают доступ всем сайтам. Смена CSP страницы не нужна. Проверка доступности — «Проверить JavaScript» в шестерёнке панели; она не вызывает модель и не меняет страницу.
DOM API
Все четыре метода асинхронные. Ссылки выдаёт общий ограниченный реестр collector; удалённая ссылка никогда не назначается другому узлу.
| Метод | Назначение |
|---|---|
dom.find({selector,text,role,scope,limit,offset,include_hidden}) |
Порция элементов и признак продолжения; условия соединяются И |
dom.get([ref], [property], {limit,offset}) |
Нужные свойства, constraints, контекст и порции options |
dom.set([{ref,property,value}]) |
Предварительная проверка, native setters, события и фактический результат |
dom.act(ref, 'click' / 'scroll') |
Ограниченное действие над найденным элементом |
Например, изменить единственный h1, сохранив заголовок вкладки:
const found = await dom.find({selector: 'h1', limit: 2});
if (found.items.length !== 1 || found.has_more) {
return {ok: false, reason: 'Нужен один однозначный заголовок'};
}
return await dom.set([{ref: found.items[0].ref, property: 'textContent', value: 'Новый заголовок'}]);
Формы используют value, checked, selected_values; заголовок вкладки —
{ref:'@document', property:'title'}. Метаданные доступны через attr:name,
attr:property, attr:content, стили — style:<property> и computed:<property>.
Helper обходит доступные iframe и открытый/закрытый Shadow DOM. Новая поддержка
кросс-доменных iframe в этот выпуск не входит. Ручной «Собрать поля» сохранён.
Инструменты приложения
await pageTools.list() возвращает JSON-каталог текущего документа с name,
description, inputSchema. await pageTools.call(name, args) вызывает
инструмент с JSON-объектом аргументов. Сначала читайте каталог, затем используйте
имя и схему из него; не разбирайте имя на модуль и метод самостоятельно.
const tools = await pageTools.list();
if (!tools.some(tool => tool.name === 'Measure.GetActive')) return {available: false};
return {active: await pageTools.call('Measure.GetActive', {})};
Непустой каталог document.modelContext текущего документа имеет приоритет.
Нативный вызов выполняется в USER_SCRIPT; формат аргументов выбирается до вызова:
Chrome до 155 получает JSON-строку, 155+ — объект. Строковая схема каталога
преобразуется в JSON-объект. Инструменты дочерних документов не включаются.
Если нативный каталог пуст или API отсутствует, фиксированная операция читает
window.webMcp в MAIN. Используется существующий chrome.userScripts.execute
и тот же валидатор JSON, без eval/Function, изменения CSP и новых разрешений.
В MAIN передаются только операция, имя и JSON-аргументы; код модели остаётся
в USER_SCRIPT. moduleName/apiName берутся из актуального каталога страницы.
Поддерживаются JSON, Promise и void (возвращается null). Observable выдаёт
явную ошибку: автоматические подписки не создаются. Ошибка вызова не приводит
к повтору через другой API или DOM. Каталог и результаты не кэшируются между
вызовами. Действуют существующие deadline и привязка к исходному документу;
отмена прекращает ожидание, но не обещает остановку уже запущенной функции.
На SPPI API включается штатно: «Настройки карты → Feature flags → webMcpEnabled». Дождитесь загрузки каталога. Это настройка SPPI в браузере, расширение не включает её автоматически.
Результаты и пределы
Исполнитель возвращает {ok:true,value} либо {ok:false,error,message,effect}.
Нужно проверить также внутренние value.ok и value.errors: выполненный JS
сам по себе не означает успешное изменение поля. JSON и код раскрываются в панели;
просмотр истории и Monitor ничего не исполняет.
Пределы: код 16 000 символов, поиск 20 элементов по умолчанию / максимум 100, запись 100 изменений, реестр 1000 ссылок. Результат клиента ограничен 96 000 байт с запасом под серверный конверт 98 304 байта. На вопрос: 12 вызовов модели, 10 инструментов, 120 секунд. Ожидание JS — 4,5 секунды, серверное — 5 секунд.
Один незавершённый запуск на документ. Повторная доставка того же tool_call_id возвращает прежний исход. Отметка chrome.storage.session переживает остановку background. При неизвестном исходе нужна перезагрузка документа. Тайм-аут и отмена прекращают ожидание и дальнейшие шаги Agent; произвольный JS принудительно не останавливается, уже сделанные изменения не откатываются автоматически.
Каталог сервера принимает только run_js; локальные message/cancel остаются служебными командами. Результаты доступны внутри вопроса и не сохраняются между независимыми вопросами. Таблица widget_cache хранит каталог по (session_id, context_id); старый столбец results и история физически сохранены.
Источники реализации: extensions/chrome/src/runJs.ts, domRuntime.ts,
form-collector.js, src_agent/widget_requests.py, src_shared/browser_tools.py.
Отдельный аудит и измерения: RUN_JS_AUDIT_2026-10-28.