0.13.0

Итерации 5–9 плана аудита: continuation актора, deadlocks/recover, graceful shutdown, tool security, tool permissions.

Added

  • Гарантированный _turn_end через defer в actor.handleInbound — во всех ветках success/error/panic публикуется событие завершения хода
  • Continue-working pattern: 16 маркеров намерения (ru/en), до 3 continuation-циклов при обнаружении незавершённой задачи
  • max_iterations — при достижении лимита публиковается явное сообщение «Напишите продолжай»
  • isSystemChannel("cron"|"heartbeat") — системные сообщения не интерпретируются как ответ на pending ask_user
  • findPendingAskUser — поиск любого assistant-сообщения с ask_user tool_call, не только последнего
  • recover() во все долгоживущие горутины: actor.run, loop.run, runner.executeTools, cron/heartbeat, email poller, WSHub
  • Stream-loop с idle-timeout (120s) и ctx.Done в runner
  • Общий tool timeout (5 min) через context.WithTimeout в runTool
  • Shared appCtx в main.go: SIGINT/SIGTERM → cancel → производные контексты отменяются
  • Graceful shutdown-цепочка: HTTP → AgentLoop → ChannelManager → MCP → Cron → Heartbeat → Consolidator → Dream → AutoCompact → DB close
  • Idempotent Stop-методы (sync.Once/флаг stopped) для AgentLoop, MCP Manager, Consolidator, Dream
  • Per-component timeout 10s, общий 60s; логирование shutdown step с took_ms
  • SSRF-защита в web_search и web_fetch: ssrfGuard.SafeHTTPClient() вместо http.DefaultClient
  • resolveWorkDir() в exec: filepath.Join + Clean + isUnder — traversal ../etc заблокирован
  • BuildMinimalEnv: PATH фиксированный, HOME → temp, allowlist env-vars, секреты не утекают
  • Расширен isBlockedDevice: /sys/*, /proc/<pid>/mem|maps|environ|..., девайсы дисков
  • atomicWriteFile() (temp+rename) в write_file и edit_file — устранение TOCTOU
  • Поля Heartbeat bool и Skill bool в ToolsPermissions — дефолты false
  • Именованные пресеты инструментов: assistant, automation, minimal + API GET /api/v1/tool-presets
  • Тесты: actor_test (8), runner_test (6), autocompact_service_test (2), tool_security_test (8), sandbox_test (5)

Changed

  • loop.Stop неблокирующий: select-default + CancelFunc() при переполненном канале
  • Параллельные tools: ошибки из горутин не игнорируются, panic ловится через recover
  • Rate-limit fix: tool_result генерируется для каждого tool_call_id в батче
  • loop.providerCfg — запись под l.mu.Lock (раньше был race)
  • AutoCompactService.Stop — idempotent через флаг stopped
  • Cron/Heartbeat/Skill инструменты регистрируются только при включённом permission
  • UI: чекбоксы «Пульс» и «Навыки» в разделе «Инструменты» страницы permissions

Fixed

  • Work §1.1: отсутствие _turn_end при ошибке/панике актора
  • Work §1.3: max_iterations без уведомления пользователя
  • Work §4.2: busy-loop в actor.run при мёртвом parent ctx
  • Work §4.3: loop.Stop блокировался при переполненном канале актора
  • Work §4.4: panic в горутине tool убивал процесс
  • Work §4.5: stream-loop без таймаута зависал при молчащем провайдере
  • Work §4.6: rate-limit глотал tool_call_id для второго и последующего вызовов
  • Work §4.7: race на loop.providerCfg (чтение без блокировки)
  • Work §4.8: os.Exit(1) в server.Serve не давал graceful shutdown
  • Tools B4: cron/heartbeat/skill_manage регистрировались без проверки permission
  • Tools B8: SSRF через http.DefaultClient в web_search/web_fetch
  • Tools B18: path traversal в exec.workDir
  • Tools B19: утечка env-секретов в sandbox
  • Tools B20: неполный список заблокированных устройств