From 106b39e46bdf17c705479d8510e6aaed78b88347 Mon Sep 17 00:00:00 2001 From: Edward Funnekotter Date: Sun, 20 Oct 2024 16:04:15 -0400 Subject: [PATCH] feat: AI-179: Add handling for status messages and add a Response Complete status when the response complete event arrives --- .../components/slack_input.py | 19 ++++- .../components/slack_output.py | 70 +++++++++++++------ 2 files changed, 63 insertions(+), 26 deletions(-) diff --git a/src/solace_ai_connector_slack/components/slack_input.py b/src/solace_ai_connector_slack/components/slack_input.py index 48da4f7..2f33db2 100644 --- a/src/solace_ai_connector_slack/components/slack_input.py +++ b/src/solace_ai_connector_slack/components/slack_input.py @@ -271,7 +271,10 @@ def handle_event(self, event): (text, mention_emails) = self.process_text_for_mentions(event["text"]) # Determine the reply_to thread to put in the message - if event.get("channel_type") == "im" and event.get("subtype", event.get("type")) == "app_mention": + if ( + event.get("channel_type") == "im" + and event.get("subtype", event.get("type")) == "app_mention" + ): # First message uses ts, subsequent messages use thread_ts reply_to = event.get("thread_ts") or event.get("ts") else: @@ -298,7 +301,7 @@ def handle_event(self, event): "channel_name": event.get("channel_name", ""), "subtype": event.get("subtype"), "event_ts": event.get("event_ts"), - "thread_ts": event.get("thread_ts"), + "thread_ts": event.get("thread_ts"), "channel_type": event.get("channel_type"), "user_id": event.get("user"), "thread_id": thread_id, @@ -325,6 +328,17 @@ def handle_event(self, event): ack_msg_ts = self.app.client.chat_postMessage( channel=event["channel"], text=self.acknowledgement_message, + blocks=[ + { + "type": "context", + "elements": [ + { + "type": "mrkdwn", + "text": self.acknowledgement_message, + } + ], + } + ], thread_ts=reply_to, ).get("ts") user_properties["ack_msg_ts"] = ack_msg_ts @@ -444,7 +458,6 @@ def handle_new_channel_join(self, event): def register_handlers(self): @self.app.event("message") def handle_chat_message(event): - print("Got message event: ", event, event.get("channel_type")) if event.get("channel_type") == "im": self.handle_event(event) elif event.get("channel_type") == "channel": diff --git a/src/solace_ai_connector_slack/components/slack_output.py b/src/solace_ai_connector_slack/components/slack_output.py index ccebf4b..93fdb37 100644 --- a/src/solace_ai_connector_slack/components/slack_output.py +++ b/src/solace_ai_connector_slack/components/slack_output.py @@ -119,32 +119,44 @@ def __init__(self, **kwargs): self.streaming_state = {} def invoke(self, message, data): - message_info = data.get("message_info") content = data.get("content") + message_info = data.get("message_info") + text = content.get("text") + uuid = content.get("uuid") + files = content.get("files") stream = content.get("stream") - first_streamed_chunk = content.get("first_streamed_chunk") + status_update = content.get("status_update") + response_complete = content.get("response_complete") last_streamed_chunk = content.get("last_streamed_chunk") - uuid = content.get("uuid") - channel = message_info.get("channel") + first_streamed_chunk = content.get("first_streamed_chunk") + thread_ts = message_info.get("ts") + channel = message_info.get("channel") ack_msg_ts = message_info.get("ack_msg_ts") + if response_complete: + status_update = True + text = ":checkered_flag: Response complete" + elif status_update: + text = ":thinking_face: " + text + if not channel: log.error("slack_output: No channel specified in message") self.discard_current_message() return None return { - "channel": channel, "text": text, - "files": content.get("files"), + "uuid": uuid, + "files": files, + "stream": stream, + "channel": channel, "thread_ts": thread_ts, "ack_msg_ts": ack_msg_ts, - "stream": stream, - "first_streamed_chunk": first_streamed_chunk, + "status_update": status_update, "last_streamed_chunk": last_streamed_chunk, - "uuid": uuid, + "first_streamed_chunk": first_streamed_chunk, } def send_message(self, message): @@ -153,11 +165,14 @@ def send_message(self, message): messages = message.get_data("previous:text") stream = message.get_data("previous:stream") files = message.get_data("previous:files") or [] - thread_ts = message.get_data("previous:reply_to_thread", message.get_data("previous:thread_ts")) + thread_ts = message.get_data( + "previous:reply_to_thread", message.get_data("previous:thread_ts") + ) ack_msg_ts = message.get_data("previous:ack_msg_ts") first_streamed_chunk = message.get_data("previous:first_streamed_chunk") last_streamed_chunk = message.get_data("previous:last_streamed_chunk") uuid = message.get_data("previous:uuid") + status_update = message.get_data("previous:status_update") if not isinstance(messages, list): if messages is not None: @@ -189,7 +204,28 @@ def send_message(self, message): streaming_state["completed"] = last_streamed_chunk ts = streaming_state.get("ts") - if ts: + if status_update: + blocks = [ + { + "type": "context", + "elements": [ + { + "type": "mrkdwn", + "text": text, + } + ], + }, + ] + + if not ts: + ts = ack_msg_ts + try: + self.app.client.chat_update( + channel=channel, ts=ts, text="test", blocks=blocks + ) + except Exception: + pass + elif ts: try: self.app.client.chat_update( channel=channel, ts=ts, text=text @@ -212,12 +248,6 @@ def send_message(self, message): self.app.client.chat_postMessage( channel=channel, text=text, thread_ts=thread_ts ) - # if ts: - # self.app.client.chat_update(channel=channel, ts=ts, text=text) - # else: - # self.app.client.chat_postMessage( - # channel=channel, text=text, thread_ts=thread_ts - # ) for file in files: file_content = base64.b64decode(file["content"]) @@ -232,12 +262,6 @@ def send_message(self, message): super().send_message(message) - try: - if ack_msg_ts: - self.app.client.chat_delete(channel=channel, ts=ack_msg_ts) - except Exception: - pass - def fix_markdown(self, message): # Fix links - the LLM is very stubborn about giving markdown links # Find [text](http...) and replace with