0.167.38
Added
- Anti-loop: детекция повторных идентичных tool-вызовов внутри хода ( — P2). Раньше единственным ограничителем зацикливания модели был
agent_max_iterations(при 0 — выключен вовсе): повторяя идентичныйread_file/exec, модель сжигала токены и время до конца хода. ВведёнtoolLoopDetector(internal/agent/loop_detector.go): подписьимя + канонический JSON аргументов(ключи map сортируются — разный порядок ключей даёт ту же подпись), счётчик серии ПОДРЯД идущих вызовов. На 3-м повторе инструмент не исполняется — модель получает[anti-loop]-предупреждение вместо результата (IsError=true, в метрики не попадает); на 5-м ход завершаетсяStopReason="loop_detected"с внятным сообщением пользователю (actor.go,_loop_detected). Исключения:RepeatableTool(ask_user, tool_log, chat_history — повторы осмыслены) и аргумент-зависимыйRepeatableCallChecker(self:check— поллинг, повторяем;set— детектируется, повторный идентичный set это как раз зацикливание). Параллельные батчи: loopStop-вердикт отменяет in-flight соседей (batchCancel) и прекращает исполнение следующих батчей; отмена контекста имеет приоритет над loop_detected (structural else-if);hook.AfterIteration— ровно один раз на итерацию с корректным StopReason. Документированные осознанные ограничения: порядок элементов массивов и числовое кодирование не канонизируются (сортировка массивов давала бы false positive на семантический порядок todo_write/exec); немаршалящиеся аргументы дают уникальные подписи (детекция для такого инструмента отключается — безопаснее ложного стопа). Метрикаloops_detected(JSON snapshot + Prometheustaigaclaw_actor_loops_detected_total+ карточка «Итерации» в UI). Тесты: warn на 3-м без исполнения, стоп на 5-м, разные аргументы ≠ повтор, интерливинг сбрасывает серию, repeatable/условная повторяемость, канонизация ключей, parallel-батч, конкурентные немаршалящиеся аргументы (race-safe nonce), реальные self/chat_history/ask_user/tool_log. - Интерфейс
RepeatableTool/RepeatableCallCheckerвinternal/agent/tools/tool.go— контракт исключения инструмента из anti-loop учёта.
Fixed
- Zero-value слоты parallel-batch больше не попадают в контекст. Guard
tr.CallID == ""в цикле результатов (раньше — только на персисте): пустые role=tool раздули бы контекст следующего LLM-вызова. Найдено в ходе ocr review.