fix: prevent infinite message replay on container timeout (#164)
Container timeout and idle timeout both fire at 30min, racing the graceful shutdown. The hard kill returns error status, rolling back the message cursor even though output was already sent — causing duplicate messages indefinitely. - Grace period: hard timeout is now IDLE_TIMEOUT + 30s minimum - Timeout after output resolves as success (idle cleanup, not failure) - Don't roll back cursor if output was already sent to user - Remove src/telegram.ts and config vars (added to PR #156 by mistake) - Add typecheck step to CI workflow - Add container-runner timeout behavior tests Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -167,6 +167,7 @@ async function processGroupMessages(chatJid: string): Promise<boolean> {
|
||||
|
||||
await whatsapp.setTyping(chatJid, true);
|
||||
let hadError = false;
|
||||
let outputSentToUser = false;
|
||||
|
||||
const output = await runAgent(group, prompt, chatJid, async (result) => {
|
||||
// Streaming output callback — called for each agent result
|
||||
@@ -177,6 +178,7 @@ async function processGroupMessages(chatJid: string): Promise<boolean> {
|
||||
logger.info({ group: group.name }, `Agent output: ${raw.slice(0, 200)}`);
|
||||
if (text) {
|
||||
await whatsapp.sendMessage(chatJid, `${ASSISTANT_NAME}: ${text}`);
|
||||
outputSentToUser = true;
|
||||
}
|
||||
// Only reset idle timer on actual results, not session-update markers (result: null)
|
||||
resetIdleTimer();
|
||||
@@ -191,6 +193,12 @@ async function processGroupMessages(chatJid: string): Promise<boolean> {
|
||||
if (idleTimer) clearTimeout(idleTimer);
|
||||
|
||||
if (output === 'error' || hadError) {
|
||||
// If we already sent output to the user, don't roll back the cursor —
|
||||
// the user got their response and re-processing would send duplicates.
|
||||
if (outputSentToUser) {
|
||||
logger.warn({ group: group.name }, 'Agent error after output was sent, skipping cursor rollback to prevent duplicates');
|
||||
return true;
|
||||
}
|
||||
// Roll back cursor so retries can re-process these messages
|
||||
lastAgentTimestamp[chatJid] = previousCursor;
|
||||
saveState();
|
||||
|
||||
Reference in New Issue
Block a user