feat(skills): vision-subagent + web-search v0.2.0 — dual-mechanism (pi tool + claude script)

- vision-subagent: describe_image tool (pi) / describe-image script (claude,
  routerai, standard OpenAI image_url — pi-legacy format NOT accepted)
- web-search: search_web tool (pi) / search-web script (claude, llm-web-proxy);
  pro-search (Expert Mode) does not live-search — default is flash-search (Instant Mode)

Sources synced to ~/.claude/skills + ~/.agents/skills via install.sh; dist rebuilt.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-08-23 21:25:01 +03:00
parent 417ef56f9a
commit 1b00c37546
4 changed files with 85 additions and 42 deletions

Binary file not shown.

BIN
dist/web-search.skill vendored Normal file

Binary file not shown.

View File

@@ -1,20 +1,20 @@
---
name: vision-subagent
author: ours
version: 0.1.0
version: 0.2.0
description: >
Use when you need to SEE an image (photo, screenshot, PCB render, diagram,
picture file) but your model does not support images — e.g. a read tool
result was omitted with "tool image omitted: model does not support images",
or the user asks what is shown in a picture / asks you to look at a
screenshot / render. Delegate the vision work to a vision-capable subagent
via the describe_image tool instead of guessing or saying you can't.
instead of guessing or saying you can't.
---
# Vision Subagent
Твоя модель не видит изображения — картинки выбрасываются из контекста.
Не угадывай содержимое и не отказывайся: делегируй зрение сабу с видящей моделью.
Не угадывай содержимое и не отказывайся: делегируй зрение видущему субагенту.
## Когда вызывать
@@ -27,7 +27,9 @@ description: >
## Как вызывать
Вызови тул `describe_image`:
### Через тул `describe_image` (pi)
Если у тебя доступен тул `describe_image`:
```
describe_image:
@@ -35,8 +37,19 @@ describe_image:
question: "точечный вопрос" # опционально
```
### Через скрипт describe-image (Claude Code на deepseek и любой агент)
Если тула нет — запусти субагента-скрипт через Bash:
```
node ~/projects/.common/lib/describe-image/describe-image.mjs --path "<абсолютный путь|URL>" [--question "точечный вопрос"]
```
Скрипт печатает в stdout описание от видящей модели — этот текст и есть
результат «зрения», верни его пользователю/в свой ответ.
Пример точечного вопроса:
`path: "C:\Users\vitya\Downloads\screen.png"`, `question: "Какое сообщение об ошибке в красной рамке сверху?"`
`node ~/projects/.common/lib/describe-image/describe-image.mjs --path "C:\Users\vitya\Downloads\screen.png" --question "Какое сообщение об ошибке в красной рамке сверху?"`
## Правила
@@ -44,23 +57,29 @@ describe_image:
если ты её не видел — это галлюцинация.
2. **Задавай точечные вопросы.** Не соглашайся на generic-описание, если тебе
нужны конкретные детали (текст, координаты, цвета, что на заднем плане).
Если ответа не хватило — вызови `describe_image` ещё раз с уточнением.
3. **Если `describe_image` упал** (нет vision-модели, ошибка сети) — честно скажи
пользователю, что зрение сейчас недоступно, и предложи путь дальше
(например, переключить модель на видящую через `/model`).
Если ответа не хватило — вызови ещё раз с уточнением.
3. **Если зрение недоступно** (упал тул/скрипт: нет vision-модели, ошибка сети) —
честно скажи пользователю, что зрение сейчас недоступно, и предложи путь дальше.
## Настройка vision-модели
Модель задаётся ЯВНО (по приоритету):
1. env `PI_VISION_MODEL` — например `routerai/minimax-m3`
2. файл `~/.pi/vision-model.json``{ "model": "routerai/minimax-m3" }`
1. env `PI_VISION_MODEL` — например `routerai/meta/muse-glimmer-30b`
2. файл `~/.pi/vision-model.json``{ "model": "routerai/meta/muse-glimmer-30b" }`
Авто-выбора нет — если модель не задана, `describe_image` вернёт ошибку с подсказкой.
Авто-выбора нет — если модель не задана, зрение вернёт ошибку с подсказкой.
Конфиг общий для pi и Claude Code (единый источник правды).
## Реализация тула
## Реализация
Тул `describe_image` — pi-расширение:
`~/projects/pi-extensions/extensions/vision-subagent.ts` (репо
`OpeItcLoc03/pi-extensions`, дом pi-расширений). Правки — в клоне репо →
`commit + push``just install` (затирает home-копию). Конфиг-example:
`~/projects/pi-extensions/config/vision-model.json.example`.
- **Скрипт (Claude Code / любой агент):** `~/projects/.common/lib/describe-image/describe-image.mjs`
— субагент на клиенте OpenAI API (пакет `openai`), зовёт routerai
(`https://routerai.ru/api/v1`). Модель — из `PI_VISION_MODEL`/`~/.pi/vision-model.json`,
ключ — `~/.pi/agent/auth.json` (провайдер и base URL — из префикса модели, напр. `routerai/…`).
**Формат картинки — стандартный OpenAI `image_url`** (`data:<mime>;base64,…`).
pi-legacy `{type:"image",data,mimeType}` routerai НЕ принимает (модель отвечает
«no image data») — не «чинить» обратно по комментарию в pi-расширении.
- **pi-расширение (тул `describe_image`):** `~/projects/pi-extensions/extensions/vision-subagent.ts`
(репо `OpeItcLoc03/pi-extensions`, дом pi-расширений). Правки — в клоне репо →
`commit + push``just install` (затирает home-копию). Конфиг-example:
`~/projects/pi-extensions/config/vision-model.json.example`.

View File

@@ -1,25 +1,25 @@
---
name: web-search
author: ours
version: 0.1.0
version: 0.2.0
description: >
Use when the user asks for fresh or external information — news, prices,
versions, dates, current facts — or says «поищи», «найди актуальное»,
"search for", "look up". Search the web via the `search_web` tool (a
search-capable model from llm-web-proxy with live citations) instead of
guessing from training data, refusing, or scraping by hand. Search is ON by
default — the agent decides when to call it; the user can turn it OFF for
the rest of the session by saying «без поиска» / "no search".
"search for", "look up". Search the web via a search-capable model from
llm-web-proxy with live citations (`search_web` tool or the `search-web`
script) instead of guessing from training data, refusing, or scraping by
hand. Search is ON by default — the agent decides when to call it; the user
can turn it OFF for the rest of the session by saying «без поиска» / "no search".
---
# Web Search
Твоя основная модель не имеет веб-поиска. `search_web` — тул, который
отправляет запрос search-модели (веб-поиск DeepSeek с цитатами) на чистом
контексте и возвращает ответ с [1][2]-источниками. **Поиск включён по
умолчанию** — не отказывайся и не выдумывай, когда нужны свежие данные.
Твоя основная модель не имеет веб-поиска. Поиск идёт через search-модель
(веб-поиск DeepSeek с цитатами) на чистом контексте и возвращает ответ с
[1][2]-источниками. **Поиск включён по умолчанию** — не отказывайся и не
выдумывай, когда нужны свежие данные.
## Когда вызывать search_web
## Когда вызывать поиск
- Юзер просит «поищи X», «найди актуальное про Y», "search for", "look up".
- Вопрос про свежие/внешние данные: новости, цены, версии, даты релизов,
@@ -30,17 +30,30 @@ description: >
- Вопросы по коду/проекту, дизайн, рефакторинг — ответ в репо и контексте.
- Уже загруженные доки/файлы сессии — не ищи то, что уже прочитано.
- **Юзер сказал «без поиска» в этой сессии** — тул не вызывать до конца сессии.
- **Юзер сказал «без поиска» в этой сессии** — поиск не вызывать до конца сессии.
## Как вызывать
### Через тул `search_web` (pi)
```
search_web:
query: "последняя версия Rust — что нового в релизе"
```
Один запрос = **один вызов** тула. Не спамить серией поисков — если ответа
не хватило, уточни запрос один раз.
### Через скрипт search-web (Claude Code и любой агент)
Если тула нет — запусти субагента-скрипт через Bash:
```
node ~/projects/.common/lib/search-web/search-web.mjs --query "последняя версия Rust — что нового в релизе"
```
Скрипт печатает в stdout ответ search-модели (с [1][2]-цитатами и списком
источников) — это и есть результат поиска.
Один запрос = **один** вызов (тула/скрипта). Не спамить серией поисков —
если ответа не хватило, уточни запрос один раз.
## Правила ответа
@@ -52,29 +65,40 @@ search_web:
## Механизм «без поиска»
- **Default**: поиск включён — сам решаешь, когда нужны свежие данные.
- Юзер: «без поиска» / "no search" → **перестань вызывать search_web до конца
- Юзер: «без поиска» / "no search" → **перестань вызывать поиск до конца
сессии**. Подтверди одной строкой. Не искать даже если запрос «поисковый».
- Юзер снова: «поищи» → верни поиск (повторный грант, до конца сессии).
- Следующая сессия — снова поиск включён (грант не переживает сессии).
## Ошибки тула
## Ошибки
`search_web failed: ...` — честно скажи юзеру, что поиск недоступен
(модель не настроена: `/search-status`, или сервер llm-web-proxy не запущен:
`lwp serve`), и предложи путь дальше.
`search_web failed: ...` (или ненулевой exit скрипта) — честно скажи юзеру,
что поиск недоступен (модель не настроена, или сервер llm-web-proxy не
запущен: `lwp serve`), и предложи путь дальше.
## Настройка
Search-модель (default `lwp/deepseek-pro-search-web`, pro-search):
Search-модель (default `lwp/deepseek-flash-search-web`):
1. env `PI_SEARCH_MODEL` — например `lwp/deepseek-flash-search-web`
2. файл `~/.pi/search-model.json``{ "model": "..." }`
Тул `search_web` — pi-расширение `~/projects/pi-extensions/extensions/search-web.ts`
(репо `OpeItcLoc03/pi-extensions`). Правки — commit + push → `just install``/reload`.
⚠️ `lwp/deepseek-pro-search-web` (pro-search, Expert Mode) живой поиск НЕ
выполняет — отвечает из обучения («unavailable in Expert Mode»). Рабочая —
flash-search (Instant Mode). Не «чинить» дефолт обратно на pro.
## Реализация
- **Скрипт (Claude Code / любой агент):** `~/projects/.common/lib/search-web/search-web.mjs`
— субагент на клиенте OpenAI API (пакет `openai`), зовёт локальный
llm-web-proxy (`http://127.0.0.1:8788/v1`, `stream:false`). Модель — из
`PI_SEARCH_MODEL`/`~/.pi/search-model.json`, ключ+baseUrl — из
`~/.pi/agent/models.json``providers["llm-web"]` (общий конфиг с pi).
- **pi-расширение (тул `search_web`):** `~/projects/pi-extensions/extensions/search-web.ts`
(репо `OpeItcLoc03/pi-extensions`). Правки — commit + push → `just install``/reload`.
## Out of scope
- НЕ автоматический поиск в каждом сообщении — тул зовётся, когда запрос
- НЕ автоматический поиск в каждом сообщении — поиск зовётся, когда запрос
реально требует внешних данных.
- НЕ скрейпинг страниц (это browser-cdp): search_web ищет и отвечает с цитатами,
- НЕ скрейпинг страниц (это browser-cdp): поиск ищет и отвечает с цитатами,
а не открывает конкретные URL.