# tool-router

## Назначение

`tool-router` переключает active tool presets внутри Pi runtime. Его задача — держать редкие или high-risk tools выключенными по умолчанию и включать их только тогда, когда выбран соответствующий preset.

Текущая версия — disabled `compat-wrapper`: она использует OMP-style inspect-first `/tools` boundary и Pi extension API `setActiveTools`, но сама preset-модель остается локальной и не считается default product.

## Почему он есть в проекте

OMP уже имеет native `/tools` для просмотра доступных и активных tools, а runtime API умеет менять active tool set. Поэтому локальный `tool-router` может быть только тонкой preset-упаковкой поверх OMP/Pi active-tool boundary, а не отдельным владельцем tool discovery или permission model.

## Пользовательская поверхность

Пользователь вызывает `/tools`, `/tools status` или `/tools list`, чтобы посмотреть текущий локальный preset и доступные preset names. Эта команда больше не переключает tools без явного намерения.

Для переключения пользователь вызывает `/tools use <preset>` или legacy shorthand `/tools <preset>`. После переключения extension обновляет widget `tools`, где видно выбранный preset и список активных tools.

Агент вызывает tool `toolRouter`, когда ему нужно программно переключить tool preset. Обязательный параметр `preset` принимает значения `minimal`, `dev` или `agentic-dev`.

## Как работает по коду

Entrypoint содержит константу `PRESETS`, где каждому preset соответствует список tool names. Функция `presetTools` возвращает список для known preset и fallback на `minimal` для неизвестной строки.

Tool `toolRouter` валидирует preset через TypeBox, записывает выбранное значение в `sharedState.toolPreset`, вызывает `pi.setActiveTools(tools)` и возвращает summary. Команда `/tools` читает текст аргументов через `getCommandText`: без аргументов она показывает status, а `use`/`switch` или legacy preset shorthand выполняют переключение через `setActiveTools`.

- Entrypoint: `./extensions/tool-router/index.ts`
- Manifest: `extensions/tool-router/manifest.json`
- Commands: `tools`
- Tools: `toolRouter`
- Hooks: none
- Permissions: fs.read=none, fs.write=none, subprocess=none, network=none, browser=false, models=false, ui=`setWidget`
- State: Текущий preset хранится в `sharedState.toolPreset` только в памяти процесса.
- Review: status=reviewed, source=copy-after-audit, reviewedBy=miloc-pi, reviewedAt=2026-06-01, risk=medium

## OMP source evidence

- `/tmp/oh-my-pi-review/packages/coding-agent/src/slash-commands/builtin-registry.ts`
- `/tmp/oh-my-pi-review/packages/coding-agent/src/session/agent-session.ts`
- `/tmp/oh-my-pi-review/packages/coding-agent/src/extensibility/extensions/types.ts`
- `/tmp/oh-my-pi-review/docs/custom-tools.md`
- `/tmp/oh-my-pi-review/LICENSE`

## Ограничения и риски

Extension сам не реализует permission enforcement, tool discovery или approval policy: он просит runtime заменить active tools через `pi.setActiveTools`. Поэтому product correctness зависит от OMP/Pi runtime behavior и не должна подменять native `/tools`, `--tools`, `--no-tools`, `search_tool_bm25` или approval settings.

Команда `/tools` принимает произвольный текст только для explicit switch path и для неизвестного preset включает `minimal`; widget явно показывает fallback. Tool `toolRouter` строже: его schema допускает только известные preset values.

## Решение

Решение: `compat-wrapper`, disabled by default. Его можно оставить как Miloc preset layer только если он остается поверх OMP/Pi active-tool API и не конфликтует с native `/tools` inspection behavior. Default enable требует runtime proof.
