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, }; }