Skip to content

feat(discord): show typing indicator while processing an LLM call#1288

Open
CumpsD wants to merge 1 commit into
netclaw-dev:devfrom
CumpsD:feature/discord-typing-indicator
Open

feat(discord): show typing indicator while processing an LLM call#1288
CumpsD wants to merge 1 commit into
netclaw-dev:devfrom
CumpsD:feature/discord-typing-indicator

Conversation

@CumpsD
Copy link
Copy Markdown
Contributor

@CumpsD CumpsD commented Jun 1, 2026

What

Adds a cross-channel processing signal that brackets each LLM model call and renders it as Discord's native typing indicator. The agent now gives live feedback while it is thinking, instead of staying silent until the turn finishes.

Why

Discord currently posts once when a turn completes — no feedback during long model calls. A typing indicator signals the agent is working.

How

Core (channel-agnostic)

  • New ProcessingStateOutput(bool IsProcessing) SessionOutput and an opt-in OutputFilter.Processing flag.
  • LlmSessionActor emits IsProcessing=true at the start of each model call (FireLlmCall) and false when it ends:
    • response received (HandleLlmResponseReceived),
    • call failed (emitted early, so retry/compaction paths re-bracket with a fresh true),
    • LLM-call watchdog timeout.
  • Because the stop fires when the response lands, the indicator is naturally off during tool execution and tool-approval waits, and resumes on the next model call.

Discord

  • DiscordSessionBindingActor subscribes to the new filter and drives typing via TriggerTypingAsync + an 8s periodic timer (Discord typing auto-expires ~10s). Stops on the processing-off signal and on TurnCompleted (backstop). Best-effort — never fails or retries a turn.
  • New IDiscordReplyClient.TriggerTypingAsync, implemented in DiscordNetReplyClient (reuses existing channel resolution), stubbed in the unconfigured client.

The flag is excluded from OutputFilter.Full, so existing subscribers are unaffected. Slack can adopt the same signal later by adding the flag and a case ProcessingStateOutput.

Tests

  • LlmSessionProcessingStateTests — started→stopped on success and on failure.
  • DiscordFileFlowIntegrationTests — typing triggered during a turn.
  • Test doubles updated for the new interface method.

Verification

  • Full solution build: 29 projects, 0 errors, 0 warnings.
  • Affected + adjacent suites pass (40 tests).
  • dotnet slopwatch analyze: 0 issues.
  • Copyright headers verified.

🤖 Generated with Claude Code

Add a cross-channel processing signal that brackets each LLM model call and
render it as Discord's native typing indicator. The agent now gives live
feedback while it is thinking instead of staying silent until the turn ends.

Core:
- New ProcessingStateOutput(bool IsProcessing) SessionOutput and an opt-in
  OutputFilter.Processing flag.
- LlmSessionActor emits IsProcessing=true at the start of each model call
  (FireLlmCall) and false when it ends: response received, call failed (emitted
  early so retries re-bracket), or LLM-call watchdog timeout. Because the stop
  fires when the response lands, the indicator is naturally off during tool
  execution and tool-approval waits, and resumes on the next model call.

Discord:
- DiscordSessionBindingActor subscribes to the new filter and drives the typing
  indicator via TriggerTypingAsync plus an 8s periodic timer (Discord typing
  auto-expires ~10s); it stops on the processing-off signal and on TurnCompleted.
  Typing is best-effort and never fails or retries a turn.
- New IDiscordReplyClient.TriggerTypingAsync, implemented in DiscordNetReplyClient
  (reuses the existing channel resolution) and stubbed in the unconfigured client.

The flag is opt-in and excluded from OutputFilter.Full, so existing subscribers
are unaffected. Slack can adopt the same signal later.

Tests:
- LlmSessionProcessingStateTests: started->stopped on success and on failure.
- DiscordFileFlowIntegrationTests: typing triggered during a turn.

Co-Authored-By: Claude Opus 4.8 <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.

1 participant