0.167.10
Fixed
- Сохранность полей сообщений на round-trip + фиксы Anthropic-провайдера (#278 — оба P0; #281 — P1 round-trip часть; #290 — P1). Батч из аудита контекстного слоя 2026-08 (
audit:2026-08-context). (1) #277 — thinking-блоки не возвращались в истории → HTTP 400 приthinking_level=deepс инструментами. Anthropic требует эхо-возвратаthinking/redacted_thinking-блоков с криптографической подписью вместе сtool_useтого же assistant-хода. Раньше: стрим вычитывал только текст thinking (signatureигнорировался), non-streaming путь вообще не обрабатывал эти типы блоков, аproviders.Messageне имел полей для их переноса. Фикс: новый типproviders.ReasoningBlock{Type, Thinking, Signature, Data}; поляReasoningBlocksвMessageиLLMResponse; в стриме блоки собираются по индексу content-блока изcontent_block_start+thinking_delta+signature_delta(накопление черезstrings.Builder, O(n); strict-by-construction: блок эмитится только если наблюдался егоcontent_block_start, у thinking непусты и текст и подпись, у redacted — data;signature_deltaприкрепляется только к существующему thinking-блоку); non-streaming парсер обрабатываетthinking/redacted_thinking;convertRequestэмитит блоки перед text/tool_use, гейтится на включённость thinking в текущем запросе (эхо при выключенном thinking — тоже 400);runner.goпереноситresp.ReasoningBlocksв assistant-сообщение хода. (2) #278 —cache_control: до 5 breakpoint’ов при лимите Anthropic 4;CacheLevelтерялся в конвертерах.ContextBuilderразмечал 3 system-секции, ноtoProviderMessages/fromProviderMessagesне переносилиCacheLevel— все приходили как zero valueCacheStableи каждая получала breakpoint (3 system + tools + last message = 5 > 4 → 400). Фикс: конвертеры (и сборка истории вcontext.go) переносятCacheLevel(а такжеIsError,ReasoningBlocks); breakpoint-бюджет централизован вconvertRequest(≤ 4, с приоритетом system → tools → last message): system — ровно один на последнем кэшируемом блоке (CacheStable всегда; для коротких CacheSemiStable-секций — порог минимальной кэшируемой длины, fallback на более ранний блок), tools — на последнем определении, последнее сообщение — на последнем кэшируемом блоке (раньше — на первом: при N параллельныхtool_resultхвост выпадал из кэшируемого префикса). (3) #281 (round-trip) —IsErrorтерялся в конвертерах:toProviderMessages/fromProviderMessagesпереносят флаг →NewToolResultBlock(..., is_error)и extra-полеis_errorдля OpenAI-пути теперь реальные;<tool_error>для провайдеров без нативного tool-calling заработал. БД-колонкаis_error— вне этого батча (миграция 106, трекается в #280). (4) #290 — описания инструментов не отправлялись на Anthropic:ToolParam.Descriptionзаполняется изToolDefinition.Description; JSON-схема инструментов передаётся целиком черезToolInputSchemaParam.ExtraFields($defs,enum,oneOf/anyOf,additionalProperties), а не толькоproperties/required;required— строго строки; ошибки marshal схемы логируются. Тесты:anthropic_test.go— сборка thinking+подписи в стриме, redacted, drop неподписанных/пустых/без-start блоков, non-streaming parse, эхо перед tool_use, гейт по thinking-флагу запроса, кэш-лимиты (1 system breakpoint, breakpoint на последнем tool_result, ≤ 4 суммарно, порог SemiStable, fallback), description/$defs-passthrough, nil-properties;p3_infra_test.go— тавтологические тесты переписаны на реальный round-trip через конвертеры (IsError/CacheLevel/ReasoningBlocks);runner_test.go— блоки доезжают доspec.Messagesследующей итерации. Проверки:go test ./...— все зелёные;go vet— 0;golangci-lint— 0;make build-cross— 6/6 бинарников;ocr review— 0 замечаний после 7 итераций (устранены: эхо при выключенном thinking, асимметрия фильтров, O(n²)-накопление, orphan signature_delta, дубли breakpoints и др.).