fix: prevent typing indicator leak on agent run exceptions and follow-up race
Two leak paths caused Discord typing indicators to persist indefinitely: 1. If runAgent() threw before turnController.finish(), setTyping(false) was never called. Wrap the agent run in try/finally to guarantee cleanup. 2. Follow-up message piping called setTyping(true) fire-and-forget. If the Promise resolved after finish()'s setTyping(false), the typing interval was recreated with nobody to clear it. Await the call to serialize the on/off sequence. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -345,6 +345,7 @@ export function createMessageRuntime(deps: MessageRuntimeDeps): {
|
|||||||
|
|
||||||
await turnController.start();
|
await turnController.start();
|
||||||
|
|
||||||
|
try {
|
||||||
const output = await runAgent(group, prompt, chatJid, runId, (result) =>
|
const output = await runAgent(group, prompt, chatJid, runId, (result) =>
|
||||||
turnController.handleOutput(result),
|
turnController.handleOutput(result),
|
||||||
);
|
);
|
||||||
@@ -372,6 +373,12 @@ export function createMessageRuntime(deps: MessageRuntimeDeps): {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
} finally {
|
||||||
|
// Safety net: always clear typing even if runAgent() or finish() throws.
|
||||||
|
// Prevents stuck typing indicators when exceptions bypass the normal
|
||||||
|
// turnController.finish() → setTyping(false) path.
|
||||||
|
await channel.setTyping?.(chatJid, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -523,7 +530,7 @@ export function createMessageRuntime(deps: MessageRuntimeDeps): {
|
|||||||
endSeq,
|
endSeq,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
channel
|
await channel
|
||||||
.setTyping?.(chatJid, true)
|
.setTyping?.(chatJid, true)
|
||||||
?.catch((err) =>
|
?.catch((err) =>
|
||||||
logger.warn(
|
logger.warn(
|
||||||
|
|||||||
Reference in New Issue
Block a user