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 name: vision-subagent
author: ours author: ours
version: 0.1.0 version: 0.2.0
description: > description: >
Use when you need to SEE an image (photo, screenshot, PCB render, diagram, 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 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", 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 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 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 # Vision Subagent
Твоя модель не видит изображения — картинки выбрасываются из контекста. Твоя модель не видит изображения — картинки выбрасываются из контекста.
Не угадывай содержимое и не отказывайся: делегируй зрение сабу с видящей моделью. Не угадывай содержимое и не отказывайся: делегируй зрение видущему субагенту.
## Когда вызывать ## Когда вызывать
@@ -27,7 +27,9 @@ description: >
## Как вызывать ## Как вызывать
Вызови тул `describe_image`: ### Через тул `describe_image` (pi)
Если у тебя доступен тул `describe_image`:
``` ```
describe_image: describe_image:
@@ -35,8 +37,19 @@ describe_image:
question: "точечный вопрос" # опционально 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-описание, если тебе 2. **Задавай точечные вопросы.** Не соглашайся на generic-описание, если тебе
нужны конкретные детали (текст, координаты, цвета, что на заднем плане). нужны конкретные детали (текст, координаты, цвета, что на заднем плане).
Если ответа не хватило — вызови `describe_image` ещё раз с уточнением. Если ответа не хватило — вызови ещё раз с уточнением.
3. **Если `describe_image` упал** (нет vision-модели, ошибка сети) — честно скажи 3. **Если зрение недоступно** (упал тул/скрипт: нет vision-модели, ошибка сети) —
пользователю, что зрение сейчас недоступно, и предложи путь дальше честно скажи пользователю, что зрение сейчас недоступно, и предложи путь дальше.
(например, переключить модель на видящую через `/model`).
## Настройка vision-модели ## Настройка vision-модели
Модель задаётся ЯВНО (по приоритету): Модель задаётся ЯВНО (по приоритету):
1. env `PI_VISION_MODEL` — например `routerai/minimax-m3` 1. env `PI_VISION_MODEL` — например `routerai/meta/muse-glimmer-30b`
2. файл `~/.pi/vision-model.json``{ "model": "routerai/minimax-m3" }` 2. файл `~/.pi/vision-model.json``{ "model": "routerai/meta/muse-glimmer-30b" }`
Авто-выбора нет — если модель не задана, `describe_image` вернёт ошибку с подсказкой. Авто-выбора нет — если модель не задана, зрение вернёт ошибку с подсказкой.
Конфиг общий для pi и Claude Code (единый источник правды).
## Реализация тула ## Реализация
Тул `describe_image` — pi-расширение: - **Скрипт (Claude Code / любой агент):** `~/projects/.common/lib/describe-image/describe-image.mjs`
`~/projects/pi-extensions/extensions/vision-subagent.ts` (репо — субагент на клиенте OpenAI API (пакет `openai`), зовёт routerai
`OpeItcLoc03/pi-extensions`, дом pi-расширений). Правки — в клоне репо → (`https://routerai.ru/api/v1`). Модель — из `PI_VISION_MODEL`/`~/.pi/vision-model.json`,
`commit + push``just install` (затирает home-копию). Конфиг-example: ключ — `~/.pi/agent/auth.json` (провайдер и base URL — из префикса модели, напр. `routerai/…`).
`~/projects/pi-extensions/config/vision-model.json.example`. **Формат картинки — стандартный 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 name: web-search
author: ours author: ours
version: 0.1.0 version: 0.2.0
description: > description: >
Use when the user asks for fresh or external information — news, prices, Use when the user asks for fresh or external information — news, prices,
versions, dates, current facts — or says «поищи», «найди актуальное», versions, dates, current facts — or says «поищи», «найди актуальное»,
"search for", "look up". Search the web via the `search_web` tool (a "search for", "look up". Search the web via a search-capable model from
search-capable model from llm-web-proxy with live citations) instead of llm-web-proxy with live citations (`search_web` tool or the `search-web`
guessing from training data, refusing, or scraping by hand. Search is ON by script) instead of guessing from training data, refusing, or scraping by
default — the agent decides when to call it; the user can turn it OFF for hand. Search is ON by default — the agent decides when to call it; the user
the rest of the session by saying «без поиска» / "no search". can turn it OFF for the rest of the session by saying «без поиска» / "no search".
--- ---
# Web Search # Web Search
Твоя основная модель не имеет веб-поиска. `search_web` — тул, который Твоя основная модель не имеет веб-поиска. Поиск идёт через search-модель
отправляет запрос search-модели (веб-поиск DeepSeek с цитатами) на чистом (веб-поиск DeepSeek с цитатами) на чистом контексте и возвращает ответ с
контексте и возвращает ответ с [1][2]-источниками. **Поиск включён по [1][2]-источниками. **Поиск включён по умолчанию** — не отказывайся и не
умолчанию** — не отказывайся и не выдумывай, когда нужны свежие данные. выдумывай, когда нужны свежие данные.
## Когда вызывать search_web ## Когда вызывать поиск
- Юзер просит «поищи X», «найди актуальное про Y», "search for", "look up". - Юзер просит «поищи X», «найди актуальное про Y», "search for", "look up".
- Вопрос про свежие/внешние данные: новости, цены, версии, даты релизов, - Вопрос про свежие/внешние данные: новости, цены, версии, даты релизов,
@@ -30,17 +30,30 @@ description: >
- Вопросы по коду/проекту, дизайн, рефакторинг — ответ в репо и контексте. - Вопросы по коду/проекту, дизайн, рефакторинг — ответ в репо и контексте.
- Уже загруженные доки/файлы сессии — не ищи то, что уже прочитано. - Уже загруженные доки/файлы сессии — не ищи то, что уже прочитано.
- **Юзер сказал «без поиска» в этой сессии** — тул не вызывать до конца сессии. - **Юзер сказал «без поиска» в этой сессии** — поиск не вызывать до конца сессии.
## Как вызывать ## Как вызывать
### Через тул `search_web` (pi)
``` ```
search_web: search_web:
query: "последняя версия Rust — что нового в релизе" 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**: поиск включён — сам решаешь, когда нужны свежие данные. - **Default**: поиск включён — сам решаешь, когда нужны свежие данные.
- Юзер: «без поиска» / "no search" → **перестань вызывать search_web до конца - Юзер: «без поиска» / "no search" → **перестань вызывать поиск до конца
сессии**. Подтверди одной строкой. Не искать даже если запрос «поисковый». сессии**. Подтверди одной строкой. Не искать даже если запрос «поисковый».
- Юзер снова: «поищи» → верни поиск (повторный грант, до конца сессии). - Юзер снова: «поищи» → верни поиск (повторный грант, до конца сессии).
- Следующая сессия — снова поиск включён (грант не переживает сессии). - Следующая сессия — снова поиск включён (грант не переживает сессии).
## Ошибки тула ## Ошибки
`search_web failed: ...` — честно скажи юзеру, что поиск недоступен `search_web failed: ...` (или ненулевой exit скрипта) — честно скажи юзеру,
(модель не настроена: `/search-status`, или сервер llm-web-proxy не запущен: что поиск недоступен (модель не настроена, или сервер llm-web-proxy не
`lwp serve`), и предложи путь дальше. запущен: `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` 1. env `PI_SEARCH_MODEL` — например `lwp/deepseek-flash-search-web`
2. файл `~/.pi/search-model.json``{ "model": "..." }` 2. файл `~/.pi/search-model.json``{ "model": "..." }`
Тул `search_web` — pi-расширение `~/projects/pi-extensions/extensions/search-web.ts` ⚠️ `lwp/deepseek-pro-search-web` (pro-search, Expert Mode) живой поиск НЕ
(репо `OpeItcLoc03/pi-extensions`). Правки — commit + push → `just install``/reload`. выполняет — отвечает из обучения («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 ## Out of scope
- НЕ автоматический поиск в каждом сообщении — тул зовётся, когда запрос - НЕ автоматический поиск в каждом сообщении — поиск зовётся, когда запрос
реально требует внешних данных. реально требует внешних данных.
- НЕ скрейпинг страниц (это browser-cdp): search_web ищет и отвечает с цитатами, - НЕ скрейпинг страниц (это browser-cdp): поиск ищет и отвечает с цитатами,
а не открывает конкретные URL. а не открывает конкретные URL.