1.7.0
Added (#372)
- Per-server deferred-режим MCP (#372): если один MCP-сервер отдаёт тулов больше лимита, inline регистрируются только первые N, хвост скрывается из промпта и доступен через мета-тул
tool_search— глобальный порогtool_search_threshold(=30) считается по всему каталогу и не спасал от одного «шумного» сервера на 50+ тулов при каталоге ниже порога. Лимит: глобальная настройкаmcp_inline_tools_limit(дефолт 40, 0 — выключено) + per-server колонкаmcp_servers.inline_tools_limit(миграция 118, SQLite+PG; 0 — наследовать глобальную, >0 — переопределить, -1 — без лимита; валидация -1..1000 в Create/Update/Import). Механика:registerMCPToolsпомечает тулы за лимитомregistry.MarkToolDeferred(разметка — только поверх активного tool_search: порог > 0 и store реализуетToolSearcher, условие зеркально актору; ресурсный тулmcp_<server>_resourcesв лимите не участвует);ToolSearchMiddlewareвBeforeAgentделит каталог по разметке — inline-часть остаётся видимой рядом с мета-тулом даже ниже глобального порога, deferred-хвост уходит вavailable/FTS-индекс; глобальный порог остаётся backstop (inline после сплита выше порога → весь каталог в поиск, прежний режим);BeforeModelRewriteStateтеперь сохраняет inline-дефы при forward selection; системный блок## Toolsфильтруется обёрткойtoolSummaryFilter(Summaries+Has) — иначе хвост продолжал бы занимать промпт; выдачаtool_searchфильтруется по available, чтобы не обещать тулы, которые forward selection не добавит. Поляinline_tools_limitдобавлены в API Create/Update (Update — pointer + копирование existing), JSON import/export конфига, WebUI (типы + поле в блоке TaigaClaw-расширений модалки импорта, валидация целого -1..1000). Удалён мёртвыйinternal/mcp/bm25_index.go(проект per-server deferred изначально задумывался с отдельнымmcp_tool_searchи in-memory BM25 — реализация переиспользует глобальныйtool_search+ FTS-индексtool_index, ADR 2026-07-02 обновлён). Известные ограничения (осознанно, вне скоупа): resume-путь и child-run субагентов не подключают toolsearch-middleware вовсе (пре-существующий пробел #329) — там deferral не действует и каталог остаётся полным; follow-up issue заведён.
Review (#372)
- ocr review — 18 находок, все разобраны (детали в комментарии ). Исправлены: [high] per-server override применялся при выключенном tool_search (разметка без потребителя) — весь лимитный путь загейчен на
toolSearchActive; [high] FTS-индекс в per-server режиме строился из всего каталога, inline-тулы возвращались поиском, но молча отбрасывались при forward selection (ответ обещал то, чего не делал) — индексируются и выдаются только deferred (в global-backstop режиме deferred==каталог, поведение прежнее); [medium] UI-инпут принимал дробные значения (step="1"+Number.isInteger), явный0в патче импорта теперь уходит явно, а не молча опускается; [medium]MarkToolDeferredпринимает только зарегистрированные имена,Registerсбрасывает разметку при перезаписи имени (инвариант deferred ⊆ tools — защита от stale-пометок при reconnect hot-swap); no-op-веткаBeforeAgentявно сбрасывает состояние middleware;effectiveMCPInlineLimit→resolvedMCPInlineLimitвозвращает(limit, apply)без sentinel-семантики нуля; контрактtoolSummaryFilterзадокументирован (блок ## Tools строится один раз за ход, forward-selected тулы в него не ререндерятся; в global-backstop режиме блок может листить ToolDefs-скрытые тулы — тот же quirk глобального режима #329). Проверки:go test ./... -count=1,golangci-lint run ./...(0),go vet,make build-cross(6 платформ),npm run check,npm test— зелёные. Тесты: per-server активация ниже порога, forward selection с сохранением inline, поиск выбирает только deferred, глобальный backstop, неизвестные deferred-имена,toolSummaryFilter,resolvedMCPInlineLimit(таблица), инварианты registry (ghost-пометка no-op, re-register сбрасывает), round-trip колонки через миграцию 118 (SQLite) + guard pgMCPCols.