From 29c5ed54b276e8e65e2e894d0d29cc5ccbbadddd Mon Sep 17 00:00:00 2001 From: Sash Catanzarite Date: Wed, 7 Jan 2026 20:34:56 -0800 Subject: [PATCH] feat(typing): trigger indicator on tool start events MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add signalToolStart to TypingSignaler and call it from onAgentEvent when tools begin executing. This keeps the typing indicator visible during long-running tool operations. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/auto-reply/reply/agent-runner.ts | 22 ++++++++++++++++------ src/auto-reply/reply/typing-mode.ts | 8 ++++++++ 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/auto-reply/reply/agent-runner.ts b/src/auto-reply/reply/agent-runner.ts index fb711ccdf..bd0b270ed 100644 --- a/src/auto-reply/reply/agent-runner.ts +++ b/src/auto-reply/reply/agent-runner.ts @@ -300,12 +300,22 @@ export async function runReplyAgent(params: { } : undefined, onAgentEvent: (evt) => { - if (evt.stream !== "compaction") return; - const phase = - typeof evt.data.phase === "string" ? evt.data.phase : ""; - const willRetry = Boolean(evt.data.willRetry); - if (phase === "end" && !willRetry) { - autoCompactionCompleted = true; + // Trigger typing when tools start executing + if (evt.stream === "tool") { + const phase = + typeof evt.data.phase === "string" ? evt.data.phase : ""; + if (phase === "start") { + void typingSignals.signalToolStart(); + } + } + // Track auto-compaction completion + if (evt.stream === "compaction") { + const phase = + typeof evt.data.phase === "string" ? evt.data.phase : ""; + const willRetry = Boolean(evt.data.willRetry); + if (phase === "end" && !willRetry) { + autoCompactionCompleted = true; + } } }, onBlockReply: diff --git a/src/auto-reply/reply/typing-mode.ts b/src/auto-reply/reply/typing-mode.ts index e5ac1671e..839659c06 100644 --- a/src/auto-reply/reply/typing-mode.ts +++ b/src/auto-reply/reply/typing-mode.ts @@ -30,6 +30,7 @@ export type TypingSignaler = { signalRunStart: () => Promise; signalTextDelta: (text?: string) => Promise; signalReasoningDelta: () => Promise; + signalToolStart: () => Promise; }; export function createTypingSignaler(params: { @@ -65,6 +66,12 @@ export function createTypingSignaler(params: { typing.refreshTypingTtl(); }; + const signalToolStart = async () => { + if (disabled) return; + // Keep typing indicator alive during tool execution + await typing.startTypingLoop(); + }; + return { mode, shouldStartImmediately, @@ -73,5 +80,6 @@ export function createTypingSignaler(params: { signalRunStart, signalTextDelta, signalReasoningDelta, + signalToolStart, }; }