fix: buffer progress to prevent final-like text from showing

Progress updates are now buffered: each new progress flushes the
previous one. The latest pending progress is discarded when final
arrives with matching text, preventing duplicate display in Discord.
This commit is contained in:
Eyejoker
2026-03-23 18:23:46 +09:00
parent 08a560f144
commit bf1453541f
2 changed files with 158 additions and 65 deletions

View File

@@ -27,6 +27,7 @@ export class MessageTurnController {
private producedDeliverySucceeded = true;
private latestProgressText: string | null = null;
private previousProgressText: string | null = null;
private pendingProgressText: string | null = null;
private latestProgressRendered: string | null = null;
private progressMessageId: string | null = null;
private progressStartedAt: number | null = null;
@@ -104,7 +105,7 @@ export class MessageTurnController {
if (result.phase === 'progress') {
if (text) {
await this.sendProgressMessage(text);
this.bufferProgress(text);
}
if (!this.poisonedSessionDetected) {
this.resetIdleTimer();
@@ -115,8 +116,11 @@ export class MessageTurnController {
return;
}
// Final arrived — flush any buffered progress that isn't the same text,
// then discard the pending buffer so it never shows up.
if (text) {
await this.finalizeProgressMessage(text);
await this.flushPendingProgress(text);
await this.finalizeProgressMessage();
await this.deliverFinalText(text);
} else if (raw) {
logger.info(
@@ -228,6 +232,7 @@ export class MessageTurnController {
private resetProgressState(): void {
this.clearProgressTicker();
this.pendingProgressText = null;
this.latestProgressText = null;
this.previousProgressText = null;
this.latestProgressRendered = null;
@@ -236,6 +241,30 @@ export class MessageTurnController {
this.progressEditFailCount = 0;
}
/**
* Buffer a progress update. The previous pending text gets flushed
* immediately, and the new text waits until the next event arrives.
* If a final result arrives before another progress, the pending
* text is discarded — so it never shows up in Discord.
*/
private bufferProgress(text: string): void {
if (this.pendingProgressText) {
void this.sendProgressMessage(this.pendingProgressText);
}
this.pendingProgressText = text;
}
/**
* Flush pending progress before a final result, but only if the
* pending text differs from the final text.
*/
private async flushPendingProgress(finalText: string): Promise<void> {
if (this.pendingProgressText && this.pendingProgressText !== finalText) {
await this.sendProgressMessage(this.pendingProgressText);
}
this.pendingProgressText = null;
}
private async syncTrackedProgressMessage(): Promise<void> {
if (
!this.progressMessageId ||
@@ -293,7 +322,7 @@ export class MessageTurnController {
}, 10_000);
}
private async finalizeProgressMessage(finalText?: string): Promise<void> {
private async finalizeProgressMessage(): Promise<void> {
logger.info(
{
chatJid: this.options.chatJid,
@@ -305,28 +334,7 @@ export class MessageTurnController {
},
'Finalizing tracked progress message',
);
// If the last progress text matches the final result, revert to the
// previous progress so the same text doesn't appear twice in chat.
if (
finalText &&
this.latestProgressText === finalText &&
this.previousProgressText &&
this.progressMessageId &&
this.options.channel.editMessage
) {
try {
const rendered = this.renderProgressMessage(this.previousProgressText);
await this.options.channel.editMessage(
this.options.chatJid,
this.progressMessageId,
rendered,
);
} catch {
// Best effort
}
} else {
await this.syncTrackedProgressMessage();
}
await this.syncTrackedProgressMessage();
this.resetProgressState();
}