Skip to the content.

Task 75 — DI lifetime fixes: captive dependency and AgentCore singleton

Phase: 5 Initiative: 45 Status: done Owner: — Slug: di-lifetime-fixes

Goal

Два DI-бага ставят под угрозу correctness и HA:

  1. Captive dependency (H6): LayeredMemoryManager зарегистрирован как singleton (Program.cs:232, WebApi/Program.cs:261), но инжектит IWorkingMemory который зарегистрирован как scoped. В WebAPI scoped-сервис резолвится один раз для синглтона и разделяется между всеми HTTP-запросами — per-request изоляция теряется, происходит cross-request memory contamination.

  2. AgentCore singleton с mutable state (H7): AgentCore зарегистрирован как singleton (Program.cs:526, WebApi/Program.cs:425) но хранит per-session mutable state: _transcript (List), _currentToolTrace, _lastInput, SessionId (AgentCore.cs:105-111,161). Все HTTP-запросы делят один AgentCore и один transcript. WebApiAdapter.EnsureSessionStarted() (:499) стартует одну сессию на весь процесс.

Acceptance criteria

Sub-tasks

Scope / Likely files

src/agent/Agent/AgentCore.cs, src/agent/Agent/WebApiAdapter.cs, src/agent/Agent/ISessionStateStore.cs (new), src/agent/Agent/SessionStateStore.cs (new), src/agent/Memory/Layers/LayeredMemoryManager.cs, src/agent/Memory/IWorkingMemory.cs, src/agent/Memory/WorkingMemoryService.cs, src/agent/Program.cs, src/agent/Hercules.WebApi/Program.cs

Dependencies

Risks / Rollback

Externalization session state — большой refactor AgentCore. CLI single-session model должен сохраниться (один sessionId на процесс). Rollback: вернуть singleton AgentCore с mutable state (но баг останется). Тесты WebAPI с параллельными запросами — must-have.

Implementation notes

2026-08-14

Добавлено:

src/agent/Agent/SessionState.cs (new) — per-session mutable state, externalised from AgentCore:

src/agent/Agent/ISessionStateStore.cs (new) — интерфейс:

src/agent/Agent/InMemorySessionStateStore.cs (new) — реализация на ConcurrentDictionary<string, SessionState>, LRU-eviction при MaxSessions (default 1024).

src/agent/Agent/AgentCore.cs — refactor:

src/agent/Agent/WebApiAdapter.cs:

src/agent/Hercules.WebApi/Controllers/ChatController.cs — multi-tenant режим:

src/agent/Memory/Layers/LayeredMemoryManager.cs — два ctor:

src/agent/Agent/MemoryManager.cs — BuildContextBlock(string? sessionId) overload: пробрасывает sessionId в LayeredMemoryManager.BuildContextBlockAsync.

src/agent/Program.cs + src/agent/Hercules.WebApi/Program.cs — DI:

tests/Hercules.Agent.Tests/AgentCoreTests/DiLifetimeFixesTests.cs (new) — 11 unit-тестов:

Validation:

Back-compat guarantees: