@@ -118,6 +118,33 @@ async def run_agent(
118118 raise
119119
120120
121+ def _extract_message_context (event : Any ) -> tuple [bool , str | None , str | None , str ]:
122+ """Return (is_edit, message_ts, thread_ts, text) for Slack events.
123+
124+ - For `message_changed` events, Slack nests the edited message under `event.message`.
125+ - For normal app_mention events, fields are at the top level.
126+ """
127+ is_edit = getattr (event , "subtype" , None ) == "message_changed"
128+ msg = (getattr (event , "message" , None ) or {}) if is_edit else {}
129+
130+ # Prefer the message ts for idempotency; fall back to event_ts if needed
131+ message_ts = (
132+ msg .get ("ts" )
133+ if is_edit
134+ else (getattr (event , "ts" , None ) or getattr (event , "event_ts" , None ))
135+ )
136+ # Thread anchor where we should post replies
137+ thread_ts = (
138+ (msg .get ("thread_ts" ) or msg .get ("ts" ))
139+ if is_edit
140+ else (getattr (event , "thread_ts" , None ) or getattr (event , "ts" , None ))
141+ )
142+ # Text used for bot mention detection
143+ text = (msg .get ("text" ) if is_edit else (getattr (event , "text" , None ) or "" )) or ""
144+
145+ return is_edit , message_ts , thread_ts , text
146+
147+
121148@flow (name = "Handle Slack Message" , retries = 1 )
122149async def handle_message (payload : SlackPayload , db : Database ):
123150 logger = get_run_logger ()
@@ -128,21 +155,7 @@ async def handle_message(payload: SlackPayload, db: Database):
128155
129156 USER_MESSAGE_MAX_TOKENS = settings .user_message_max_tokens
130157 # Determine message context accommodating edit events
131- is_edit = event .subtype == "message_changed"
132- # The per-message idempotency key: prefer message ts; fallback to event_ts for robustness
133- message_ts = (
134- (event .message or {}).get ("ts" ) if is_edit else (event .ts or event .event_ts )
135- )
136- # Text to inspect for a bot mention
137- user_message = (
138- (event .message or {}).get ("text" ) if is_edit else (event .text or "" )
139- ) or ""
140- # Thread anchor where we should respond/append
141- thread_ts = (
142- ((event .message or {}).get ("thread_ts" ) or (event .message or {}).get ("ts" ))
143- if is_edit
144- else (event .thread_ts or event .ts )
145- )
158+ is_edit , message_ts , thread_ts , user_message = _extract_message_context (event )
146159 assert thread_ts is not None , "No thread_ts found"
147160 assert message_ts is not None , "No message_ts found"
148161 cleaned_message = re .sub (BOT_MENTION , "" , user_message ).strip ()
0 commit comments