fix: address AI patrol concurrency and streaming issues

- HIGH: Create per-request AgenticLoop instead of sharing one across
  concurrent sessions. This prevents race conditions where ExecuteStream
  calls would overwrite each other's FSM, knowledge accumulator, and
  other session-specific state.

- MEDIUM: TriggerManager.GetStatus now recomputes adaptive interval after
  pruning old events. Previously, currentInterval could remain stuck in
  busy/quiet mode after events aged out of the window.

- MEDIUM: Patrol stream phases are now broadcast to subscribers. Fixed
  setStreamPhase() to emit phase events and SubscribeToStream() to send
  phase events to late joiners. UI was stuck on 'Starting patrol...'
  because phase events were never emitted.

- LOW: Fixed TriggerStatus.CurrentInterval JSON serialization. Changed
  from time.Duration (serializes as nanoseconds) to int64 milliseconds
  to match the 'current_interval_ms' tag.
This commit is contained in:
rcourtman 2026-02-03 14:39:00 +00:00
parent 565b2ef51d
commit 8720708e70
6 changed files with 71 additions and 28 deletions

View file

@ -60,6 +60,7 @@ func TestService_ExecuteStream_Success(t *testing.T) {
sessions: store,
executor: executor,
agenticLoop: loop,
provider: provider, // Required: per-request loops need a provider to create new instances
started: true,
}