From fa7b2615e094fcecf34b11d8c85fcbf5f292b1c0 Mon Sep 17 00:00:00 2001 From: Adam Moussa Date: Wed, 8 Jul 2026 16:42:34 -0400 Subject: [PATCH] fix(slack): persist trace_message_ts so web-handoff updates the trace reply Re-land upstream #1630 onto the modular structure. The first-mention store_slack_run_mapping call did not pass trace_message_ts, so it was never persisted (nothing to preserve from on first mention) and _notify_slack_web_handoff always skipped the trace-reply update on web handoff. Pass it through and cover it with a test. Refs #80, upstream #1630 --- agent/webhooks/slack.py | 1 + tests/test_slack_context.py | 38 +++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/agent/webhooks/slack.py b/agent/webhooks/slack.py index 4e3021ff..4c3658f8 100644 --- a/agent/webhooks/slack.py +++ b/agent/webhooks/slack.py @@ -258,6 +258,7 @@ async def process_slack_mention(event_data: dict[str, Any], repo_config: dict[st run_id, message_ts=trace_message_ts, triggering_user_id=user_id, + trace_message_ts=trace_message_ts, ) else: webapp.logger.info( diff --git a/tests/test_slack_context.py b/tests/test_slack_context.py index b045f866..c56d7d71 100644 --- a/tests/test_slack_context.py +++ b/tests/test_slack_context.py @@ -638,6 +638,44 @@ def test_process_slack_mention_uses_vision_fallback_for_image_thread( assert "does not support image input" not in content[0]["text"] +def test_process_slack_mention_persists_trace_message_ts_on_first_mention( + monkeypatch: pytest.MonkeyPatch, +) -> None: + captured: dict[str, object] = {} + _setup_slack_mention_fakes(monkeypatch, captured) + + async def fake_thread_exists(thread_id: str) -> bool: + return False + + async def fake_post_slack_trace_reply(channel_id: str, thread_ts: str, thread_id: str) -> str: + return "1700000000.999999" + + async def fake_store_slack_run_mapping(*args, **kwargs) -> None: + captured["run_mapping"] = {"args": args, "kwargs": kwargs} + + monkeypatch.setattr(webapp, "_thread_exists", fake_thread_exists) + monkeypatch.setattr(webapp, "post_slack_trace_reply", fake_post_slack_trace_reply) + monkeypatch.setattr(webapp, "store_slack_run_mapping", fake_store_slack_run_mapping) + + asyncio.run( + webapp.process_slack_mention( + { + "channel_id": "C123", + "thread_ts": "1700000000.000100", + "event_ts": "1700000000.000200", + "user_id": "U123", + "text": "<@UBOT> continue on the branch", + "bot_user_id": "UBOT", + }, + {"owner": "langchain-ai", "name": "open-swe"}, + ) + ) + + run_mapping = captured["run_mapping"] + assert isinstance(run_mapping, dict) + assert run_mapping["kwargs"]["trace_message_ts"] == "1700000000.999999" + + def test_process_slack_mention_skips_trace_reply_on_followup_mention( monkeypatch: pytest.MonkeyPatch, ) -> None: