Skip to content

Honor preemption token in DreamService LLM calls#341

Merged
rockfordlhotka merged 2 commits intomainfrom
issue-333/dreamservice-preempt-token
May 5, 2026
Merged

Honor preemption token in DreamService LLM calls#341
rockfordlhotka merged 2 commits intomainfrom
issue-333/dreamservice-preempt-token

Conversation

@rockfordlhotka
Copy link
Copy Markdown
Member

Summary

  • Adds a single InvokeDreamPassAsync<TResult> helper that builds messages, calls the Balanced-tier LLM with the supplied CancellationToken, extracts JSON, logs warnings on parse failure, and deserializes to the target DTO.
  • Replaces 15 near-identical inline LLM call blocks across DreamAsync and 14 pass methods with calls to the helper, threading slot.Token through every site.
  • Net -179 lines; behavior preserved.

Why

Previously 14 of 15 _llmClient.GetResponseAsync call sites in DreamService omitted the slot's cancellation token. When a user message preempted an in-flight dream cycle, the cooperative cancel signal never reached the LLM call, and the dream loop kept running pass after pass while the user waited (observed user-perceived latency: 3 min 36 s in production). Threading the token through one helper plugs all sites and prevents future passes from reintroducing the leak.

Test plan

  • dotnet build RockBot.slnx — clean compile
  • dotnet test RockBot.slnx — all suites pass (RockBot.Host.Tests: 601 passed)
  • No remaining _llmClient.GetResponseAsync call sites outside the helper
  • Optional manual: deploy and confirm logs show "dream cycle preempted by user request" followed by a fast user reply when a user message arrives during a dream cycle

Closes #333

🤖 Generated with Claude Code

rockfordlhotka and others added 2 commits May 5, 2026 16:26
Consolidate 15 near-identical LLM call sites in DreamService into a
single InvokeDreamPassAsync<T> helper that builds messages, calls the
Balanced-tier LLM with the slot's cancellation token, extracts JSON,
logs warnings on parse failure, and deserializes to the target DTO.

Previously 14 of 15 sites omitted the slot.Token, so when a user message
preempted an in-flight dream cycle the cooperative cancel never reached
the LLM call — observed user-perceived latency of 3 min 36 s in
production. Threading the token through one helper plugs all sites and
prevents future passes from reintroducing the leak.

Net -179 lines; behavior preserved.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds RunPassAsync(passName, body) which runs the supplied body inside
a try/catch that rethrows OperationCanceledException and converts other
exceptions into a per-pass error log. The 10 dream-pass methods that
previously hand-rolled the same try/catch wrapper now call into this
helper, eliminating ~80 lines of duplicated boilerplate.

This also fixes a noisy log line surfaced during k8s validation: when
preemption fired, each pass's catch (Exception ex) was catching the
OperationCanceledException and logging it as "<pass> pass failed" with
a stack trace before the OCE rethrew at the next ThrowIfCancellationRequested
between passes. The helper has an explicit catch (OperationCanceledException)
that rethrows, so OCE flows cleanly to DreamAsync's outer handler and
only the single "dream cycle preempted by user request" line is logged.

Also bumps Directory.Build.props from 0.10.28 to 0.10.29 for the
deploy used to validate the original fix.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@rockfordlhotka rockfordlhotka merged commit 3c71323 into main May 5, 2026
2 checks passed
@rockfordlhotka rockfordlhotka deleted the issue-333/dreamservice-preempt-token branch May 5, 2026 22:14
@rockfordlhotka rockfordlhotka mentioned this pull request May 5, 2026
1 task
rockfordlhotka added a commit that referenced this pull request May 5, 2026
Tracks the agent image already running in the cluster (deployed during
PR #341 validation).

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

DreamService blocks user messages because LLM calls ignore preemption token

1 participant