From f42a98b887300bac6ee37d409dcbf855f28f902a Mon Sep 17 00:00:00 2001 From: AIOSAI Date: Thu, 2 Jul 2026 20:19:14 -0700 Subject: [PATCH] fix(hooks): TG replies no longer overwrite the previous message _advance_pending kept the pending file with a frozen processing_message_id, so any Stop firing without a fresh placeholder (remote/mirror input or multi-Stop turns) re-edited the same Telegram message instead of posting a new one. Clear processing_message_id after the first delivery so subsequent Stops fall through to send a new message. Live-proven on the devpulse bot; +2 regression tests in TestAdvancePending (114/114). --- .../notification/telegram_response.py | 1 + .../hooks/tests/test_telegram_response.py | 49 +++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/src/aipass/hooks/apps/handlers/notification/telegram_response.py b/src/aipass/hooks/apps/handlers/notification/telegram_response.py index 8ea70900..9617caec 100644 --- a/src/aipass/hooks/apps/handlers/notification/telegram_response.py +++ b/src/aipass/hooks/apps/handlers/notification/telegram_response.py @@ -701,6 +701,7 @@ def _advance_pending(pending_file: Path, pending_data: dict, transcript_path: st line_count += 1 pending_data["transcript_line_after"] = line_count pending_data["delivered"] = True + pending_data["processing_message_id"] = None pending_file.write_text(json.dumps(pending_data, indent=2), encoding="utf-8") logger.info("[HOOKS] telegram: cursor advanced to line %d", line_count) except OSError as e: diff --git a/src/aipass/hooks/tests/test_telegram_response.py b/src/aipass/hooks/tests/test_telegram_response.py index 3ca3ff9d..a9992c6b 100644 --- a/src/aipass/hooks/tests/test_telegram_response.py +++ b/src/aipass/hooks/tests/test_telegram_response.py @@ -1358,6 +1358,55 @@ class TestAdvancePending: assert not pending_file.exists() + def test_clears_processing_message_id_after_advance(self, tmp_path): + """After advance, processing_message_id is None so next Stop sends new msg, not edit.""" + from aipass.hooks.apps.handlers.notification.telegram_response import _advance_pending + + transcript = tmp_path / "transcript.jsonl" + transcript.write_text("line1\nline2\n", encoding="utf-8") + + pending_file = tmp_path / "pending.json" + pending_data = {"chat_id": 1, "bot_token": "tok", "processing_message_id": 42} + pending_file.write_text(json.dumps(pending_data), encoding="utf-8") + + with patch(LOGGER_PATCH): + _advance_pending(pending_file, pending_data, str(transcript)) + + updated = json.loads(pending_file.read_text(encoding="utf-8")) + assert updated["processing_message_id"] is None + + def test_second_delivery_sends_new_message_after_advance(self, tmp_path): + """Two consecutive deliver->advance cycles: 2nd must send, not edit.""" + from aipass.hooks.apps.handlers.notification.telegram_response import _advance_pending + + transcript = tmp_path / "transcript.jsonl" + transcript.write_text("line1\nline2\n", encoding="utf-8") + + pending_file = tmp_path / "pending.json" + pending_data = { + "chat_id": 1, + "bot_token": "tok", + "processing_message_id": 42, + } + pending_file.write_text(json.dumps(pending_data), encoding="utf-8") + + with patch(LOGGER_PATCH): + _advance_pending(pending_file, pending_data, str(transcript)) + + after_first = json.loads(pending_file.read_text(encoding="utf-8")) + assert after_first["processing_message_id"] is None + assert after_first["delivered"] is True + + transcript.write_text("line1\nline2\nline3\nline4\n", encoding="utf-8") + after_first["delivered"] = False + + with patch(LOGGER_PATCH): + _advance_pending(pending_file, after_first, str(transcript)) + + after_second = json.loads(pending_file.read_text(encoding="utf-8")) + assert after_second["processing_message_id"] is None + assert after_second["transcript_line_after"] == 4 + # =========================================================================== # _write_delivery_log