diff --git a/README.md b/README.md index e8d530f..372a4e9 100644 --- a/README.md +++ b/README.md @@ -122,6 +122,7 @@ an explicit `adapted-from` marker in its frontmatter. | `code-review` | `adapted-from: mattpocock/skills @ 84fdeffd` (MIT) — two-axis + Fowler baseline; output: caveman-review format | | `writing-skills` | `adapted-from: obra/superpowers @ 6.2.0` (MIT) — TDD-for-skills core + ideya 8 self-skill-authoring | | `web-search` | `author: ours` — search_web tool (pi-extension) + policy: when to search, «без поиска» session-off | +| `ops-browser` | `author: ours` — свой **скрытый** браузер агента: отдельный профиль + CDP (`eval`/`fetch` из страницы/скриншоты), `handoff` человеку для пароля/капчи; свой замок `ops.lock` | | `browser-operator` | `author: ours` — браузер ОПЕРАТОРА (его Chrome/логины): канал по харнессу (Hermes `browser_exec` / pi тул `browser` / CC `chrome-devtools`), аренда «один водитель за раз», границы «человек vs агент», рецепты тяжёлых страниц. Закрывает провал базового прогона 2026-09-11 («куки из Chrome + curl + ввод пароля» мимо канала); анонимные прогоны — `browser-cdp` | | `review-subagent` | `author: ours` — review_subagent tool (pi-extension): clean-context review by your own model, optional `model` override | | `report-mappa-issue` | `author: ours` — TEMPORARY stopgap: mappa deviation reporting (mail to `mappa` + `.workshop`) while the service is unstable; retire when stabilized | diff --git a/README.ru.md b/README.ru.md index 8b10b84..04f730f 100644 --- a/README.ru.md +++ b/README.ru.md @@ -91,6 +91,7 @@ bash scripts/build.sh caveman # один | `code-search` | `author: ours` — rg-first код-поиск (замер: 15 мин → 0 сек; роутинг: rg / git grep / interns repo_read / grep_audit) | | `code-review` | `adapted-from: mattpocock/skills @ 84fdeffd` (MIT) — двухосевость + Fowler-база; формат вывода: caveman-review | | `writing-skills` | `adapted-from: obra/superpowers @ 6.2.0` (MIT) — TDD-for-skills ядро + идея 8 self-skill-authoring | +| `ops-browser` | `author: ours` — свой скрытый браузер агента (профиль + CDP + `handoff` человеку, замок `ops.lock`) | | `browser-operator` | `author: ours` — браузер ОПЕРАТОРА (его Chrome/логины): канал по харнессу (Hermes `browser_exec` / pi тул `browser` / CC `chrome-devtools`), аренда «один водитель за раз», границы «человек vs агент»; анонимные прогоны — `browser-cdp` | | остальные `skills/*` | `author: ours` | diff --git a/dist/ops-browser.skill b/dist/ops-browser.skill new file mode 100644 index 0000000..14a57ee Binary files /dev/null and b/dist/ops-browser.skill differ diff --git a/hermes/mapping.yaml b/hermes/mapping.yaml index 5ebbf4a..8f72524 100644 --- a/hermes/mapping.yaml +++ b/hermes/mapping.yaml @@ -59,6 +59,10 @@ skills: mode: auto category: software-development + ops-browser: + mode: auto + category: software-development + using-markitdown: mode: auto category: productivity diff --git a/skills/ops-browser/SKILL.md b/skills/ops-browser/SKILL.md new file mode 100644 index 0000000..4b8f6d8 --- /dev/null +++ b/skills/ops-browser/SKILL.md @@ -0,0 +1,90 @@ +--- +name: ops-browser +author: ours +version: 0.1.0 +description: > + Use when a task needs a real browser — личный кабинет, заказы, чеки, yt-digest, + скриншот живого сайта, «дёрни внутренний API». Свой СКРЫТЫЙ браузер агента: + отдельный профиль, CDP, `fetch()` ИЗ страницы, хендофф человеку для пароля/капчи. +--- + +# ops-browser — свой скрытый браузер агента + +**Есть задача, которой нужен браузер? Работай в своём браузере, скрыто, и не подсовывай куки.** +Профиль владеет сессией сам (куки продлеваются браузером, а не руками) — это и есть лечение +боли «куки протухли». + +## Когда ЭТОТ инструмент, а когда другой + +| Ситуация | Чем работать | +|---|---| +| Публичная страница без логина | `web_search` / `web_extract` / curl — браузер не нужен | +| Личный кабинет, заказы, чеки, внутренний API сайта, антибот | **`ops-browser.sh`** (этот скил) | +| Нужны ЕГО логины и ЕГО Chrome (Avito, кабинеты поставщиков) | канал оператора: Hermes `browser_exec` / pi тул `browser` / CC `chrome-devtools` — всё под арендой `driver.lock` | +| Посмотреть глазами, кликнуть по живому сайту, показать ему | панель предпросмотра (`desktop_preview` + `drive_preview`) — без JS, только текст/клики | + +`ops-browser` не заменяет канал оператора: там его сессии, здесь — **мой** профиль. +И то и другое живёт под правилом «один водитель» (у ops свой замок `ops.lock`). + +## Команды + +```bash +OB="$HOME/.config/browser-harness/bin/ops-browser.sh" +bash "$OB" start # headless + аренда (окон нет) +bash "$OB" open https://site/path # перейти +bash "$OB" read 2000 # видимый текст страницы +bash "$OB" eval 'fetch("/api/x",{credentials:"include"}).then(r=>r.json()).then(j=>JSON.stringify(j))' +bash "$OB" screenshot [path] # PNG, печатает путь +bash "$OB" cookies https://site # имена кук (без значений) +bash "$OB" status # аренда + CDP + текущая страница +bash "$OB" stop # ШТАТНО закрыть и отпустить +bash "$OB" handoff # человеку: пароль/2FA/капча (см. ниже) +``` + +`eval` выполняет JS **в контексте страницы** — значит `fetch()` идёт с её куками и заголовками: +так дёргают внутренние эндпоинты приложения (то, что недоступно извне и чего не умеет панель). + +## Хендофф человеку (пароль, 2FA, капча, согласие) + +Останавливаюсь и отдаю экран **сам**, без «скажи готово»: + +1. `bash "$OB" handoff ` — закрывает headless (профиль нельзя открыть дважды) и поднимает + **видимое** окно ТОГО ЖЕ профиля на нужной странице; +2. человек вводит, что нужно (пароль/2FA/капчу вводит только он); +3. признак успеха ловлю сам: URL ушёл со страницы логина/auth **или** выросли куки домена; +4. штатно закрываю окно и возвращаюсь в headless — логин остался в профиле. + +Скриншот делаю **до** шага (что от человека хотят) и **после** (что получилось); **во время ввода +пароля не снимаю**. Если признак успеха не увидел — окно остаётся открытым, а я говорю об этом прямо. + +## Границы (не двигаются) + +- Пароли, 2FA, капчу — **вводит человек**. Я к ним не подхожу. +- Деньги, оформление заказов, формы с перс.данными — только с явного согласия оператора. +- Куки не выгружаю и не расшифровываю; содержимое залогиненных страниц не уходит в логи/вику. +- Антибот-челленджи не обхожу; если сайт невзлюбил `headless` — это повод для `handoff`, а не для трюков. + +## Грабли (стоили времени, проверены живьём) + +- **Закрывать только штатно** (`stop` → `Browser.close`). Жёсткий kill может не сбросить профиль → + потеря логина. Сессионные куки (без срока) перезапуск не переживают по дизайну — настоящие логины живут. +- **MSYS-пути**: нативным программам нужен вид `C:/...` (`cygpath -m`), а `powershell -File` — + только `C:\...` (`cygpath -w`). Иначе «модуль не найден» / «файл .ps1 не найден». +- **Экранирование PowerShell внутри bash-строки тихо ломается** (`$_` подменяется) — PS-запросы + держим в отдельных `.ps1`. +- **Профиль нельзя открыть дважды** — перед видимым окном headless обязан остановиться (это делает `handoff`). +- **Профиль**: `~/.config/browser-harness/profiles/ops`; порт CDP: `OPS_CDP_PORT` (9346). + +## Аренда + +```bash +BL="$HOME/.config/browser-harness/bin/browser-lease.sh" +bash "$BL" --lock ops status # состояние ops-замка (у Chrome оператора — driver.lock) +``` + +Чужой держатель `ops.lock` → `start` честно отказывает (rc=1). Мёртвый держатель отпускается по PID/TTL. +Идёшь в браузер **сам** (в обход `ops-browser.sh`)? Возьми `ops.lock` так же, как любой другой харнесс. + +Контракт: mappa `concepts/ops-browser-contract` (проект `pi-extensions`), +требования `requirements:42`, план `plan:35`. Исходники: репо `pi-extensions/scripts/browser/` +(установка `just install-browser`).