baibot icon indicating copy to clipboard operation
baibot copied to clipboard

FR: Configuration to disable threads and use room history

Open nesretep-anp1 opened this issue 1 year ago • 4 comments

I do know many, many users which are not using threads in Matrix. (Me too).

Additionally it is confusing and makes not really sence for some contexts to have AI reply within structures which are not shown/displayed directly within an appropriate room. (Specially on mobiles).

I understood that threads are used to build the context.

Like already requested here ...

#20 #24

... it would be great to have a configuration to switch off using threads and therefore switch to using chat history as the cointext and reply directly into the room.

This should be configurable for/within that room.

nesretep-anp1 avatar Jan 09 '25 12:01 nesretep-anp1

Again, ... that would be really great; I have to admit, that I even within our dev env already lost the overview between the threads.

;)

nesretep-anp1 avatar Jan 14 '25 19:01 nesretep-anp1

It was funny to watch baibot trying to agree with the antithread bot 😂

rda0 avatar Feb 21 '25 12:02 rda0

Looks like maybe it is not too difficult to patch it in the meantime. Only tested for text-generation.

no threads patch for v1.4.1
diff --git a/src/controller/agent/create/mod.rs b/src/controller/agent/create/mod.rs
index d02e148..8217814 100644
--- a/src/controller/agent/create/mod.rs
+++ b/src/controller/agent/create/mod.rs
@@ -73,7 +73,7 @@ pub async fn handle_room_local(
             .send_error_markdown_no_fail(
                 message_context.room(),
                 &strings::agent::already_exists_see_help(agent_id_prefixless, bot.command_prefix()),
-                MessageResponseType::InThread(message_context.thread_info().clone()),
+                MessageResponseType::Reply(message_context.thread_info().root_event_id.clone()),
             )
             .await;
 
@@ -186,7 +186,7 @@ pub async fn handle_global(
             .send_error_markdown_no_fail(
                 message_context.room(),
                 &strings::agent::already_exists_see_help(agent_id_prefixless, bot.command_prefix()),
-                MessageResponseType::InThread(message_context.thread_info().clone()),
+                MessageResponseType::Reply(message_context.thread_info().root_event_id.clone()),
             )
             .await;
 
@@ -256,7 +256,7 @@ async fn send_guide(
         .send_text_markdown_no_fail(
             message_context.room(),
             strings::agent::creation_guide(agent_identifier, provider, &sample_config_pretty_yaml),
-            MessageResponseType::InThread(message_context.thread_info().clone()),
+            MessageResponseType::Reply(message_context.thread_info().root_event_id.clone()),
         )
         .await;
 
@@ -302,7 +302,7 @@ async fn parse_agent_config_from_message_or_complain(
                 .send_error_markdown_no_fail(
                     message_context.room(),
                     &strings::agent::configuration_not_a_valid_yaml_hashmap(err),
-                    MessageResponseType::InThread(message_context.thread_info().clone()),
+                    MessageResponseType::Reply(message_context.thread_info().root_event_id.clone()),
                 )
                 .await;
 
@@ -326,7 +326,7 @@ async fn parse_agent_config_from_message_or_complain(
                 .send_error_markdown_no_fail(
                     message_context.room(),
                     &strings::provider::invalid_configuration_for_provider(provider, err),
-                    MessageResponseType::InThread(message_context.thread_info().clone()),
+                    MessageResponseType::Reply(message_context.thread_info().root_event_id.clone()),
                 )
                 .await;
 
@@ -346,7 +346,7 @@ async fn try_to_ping_agent_or_complain(
         .send_notice_markdown_no_fail(
             message_context.room(),
             format!("⏳ {}", strings::agent::configuration_agent_will_ping()),
-            MessageResponseType::InThread(message_context.thread_info().clone()),
+            MessageResponseType::Reply(message_context.thread_info().root_event_id.clone()),
         )
         .await;
 
@@ -366,7 +366,7 @@ async fn try_to_ping_agent_or_complain(
                 .send_notice_markdown_no_fail(
                     message_context.room(),
                     message,
-                    MessageResponseType::InThread(message_context.thread_info().clone()),
+                    MessageResponseType::Reply(message_context.thread_info().root_event_id.clone()),
                 )
                 .await;
 
@@ -377,7 +377,7 @@ async fn try_to_ping_agent_or_complain(
                 .send_error_markdown_no_fail(
                     message_context.room(),
                     &strings::agent::configuration_does_not_result_in_a_working_agent(err),
-                    MessageResponseType::InThread(message_context.thread_info().clone()),
+                    MessageResponseType::Reply(message_context.thread_info().root_event_id.clone()),
                 )
                 .await;
 
@@ -396,7 +396,7 @@ async fn send_completion_wrap_up(
         .send_success_markdown_no_fail(
             message_context.room(),
             &strings::agent::created(agent_identifier),
-            MessageResponseType::InThread(message_context.thread_info().clone()),
+            MessageResponseType::Reply(message_context.thread_info().root_event_id.clone()),
         )
         .await;
 
@@ -408,7 +408,7 @@ async fn send_completion_wrap_up(
                 agent_instance,
                 bot.command_prefix(),
             ),
-            MessageResponseType::InThread(message_context.thread_info().clone()),
+            MessageResponseType::Reply(message_context.thread_info().root_event_id.clone()),
         )
         .await;
 }
diff --git a/src/controller/chat_completion/mod.rs b/src/controller/chat_completion/mod.rs
index 5c2b307..1d18988 100644
--- a/src/controller/chat_completion/mod.rs
+++ b/src/controller/chat_completion/mod.rs
@@ -78,14 +78,14 @@ pub async fn handle(
             }
             SpeechToTextFlowType::TranscribeAndGenerateText => {
                 tracing::debug!("Will be transcribing and possibly generating text..");
-                MessageResponseType::InThread(message_context.thread_info().clone())
+                MessageResponseType::Reply(message_context.thread_info().root_event_id.clone())
             }
             SpeechToTextFlowType::OnlyTranscribe => {
                 tracing::debug!("Will only be transcribing audio to text..");
                 if message_context.thread_info().is_thread_root_only() {
                     MessageResponseType::Reply(message_context.thread_info().root_event_id.clone())
                 } else {
-                    MessageResponseType::InThread(message_context.thread_info().clone())
+                    MessageResponseType::Reply(message_context.thread_info().root_event_id.clone())
                 }
             }
         };
@@ -147,7 +147,7 @@ pub async fn handle(
             }
 
             // In all other cases, we're dealing with a threaded conversation, so we reply in the thread.
-            _ => MessageResponseType::InThread(message_context.thread_info().clone()),
+            _ => MessageResponseType::Reply(message_context.thread_info().root_event_id.clone()),
         };
 
         let text_to_speech_eligible_payload = handle_stage_text_generation(
@@ -413,7 +413,8 @@ async fn handle_stage_text_generation(
 
     let conversation = match controller_type {
         // When we're triggered via a reply mention, the context is the whole reply chain upward of the message that triggered us.
-        ChatCompletionControllerType::ReplyMention => {
+        //ChatCompletionControllerType::ReplyMention => {
+        _ => {
             create_llm_conversation_for_matrix_reply_chain(
                 &bot.room_event_fetcher().clone(),
                 message_context.room(),
@@ -424,15 +425,15 @@ async fn handle_stage_text_generation(
         }
 
         // Everything else is happening in a thread, so the context is the whole thread.
-        _ => {
-            create_llm_conversation_for_matrix_thread(
-                matrix_link.clone(),
-                message_context.room(),
-                message_context.thread_info().root_event_id.clone(),
-                &params,
-            )
-            .await
-        }
+        //_ => {
+        //    create_llm_conversation_for_matrix_thread(
+        //        matrix_link.clone(),
+        //        message_context.room(),
+        //        message_context.thread_info().root_event_id.clone(),
+        //        &params,
+        //    )
+        //    .await
+        //}
     };
 
     let conversation = match conversation {
@@ -630,7 +631,7 @@ async fn handle_stage_speech_to_text_actual_transcribing(
     // Regardless of how we post this message, it will be posted as a notice,
     // which can indicate to the bot (for potential future text-generation purposes) that this message is not a bot message.
     let (transcribed_text, annotate_message_with_reaction) =
-        if let MessageResponseType::InThread(_) = response_type {
+        if let MessageResponseType::Reply(_) = response_type {
             (
                 create_transcribed_message_text(&speech_to_text_result.text),
                 false,
diff --git a/src/controller/determination/mod.rs b/src/controller/determination/mod.rs
index 7fdd117..319763d 100644
--- a/src/controller/determination/mod.rs
+++ b/src/controller/determination/mod.rs
@@ -19,7 +19,7 @@ pub fn determine_controller(
 ) -> ControllerType {
     match &first_thread_message.payload {
         MessagePayload::SynthethicChatCompletionTriggerInThread => {
-            ControllerType::ChatCompletion(ChatCompletionControllerType::ThreadMention)
+            ControllerType::ChatCompletion(ChatCompletionControllerType::ReplyMention)
         }
         MessagePayload::SynthethicChatCompletionTriggerForReply => {
             ControllerType::ChatCompletion(ChatCompletionControllerType::ReplyMention)
diff --git a/src/controller/dispatching.rs b/src/controller/dispatching.rs
index e73c362..3166dfc 100644
--- a/src/controller/dispatching.rs
+++ b/src/controller/dispatching.rs
@@ -58,7 +58,7 @@ pub async fn dispatch_controller(
                 .send_error_markdown_no_fail(
                     message_context.room(),
                     message,
-                    MessageResponseType::InThread(thread_info.clone()),
+                    MessageResponseType::Reply(thread_info.root_event_id.clone()),
                 )
                 .await;
 
diff --git a/src/controller/image/generation.rs b/src/controller/image/generation.rs
index 823593b..edd5918 100644
--- a/src/controller/image/generation.rs
+++ b/src/controller/image/generation.rs
@@ -20,7 +20,7 @@ pub async fn handle_image(
     message_context: &MessageContext,
     original_prompt: &str,
 ) -> anyhow::Result<()> {
-    let response_type = MessageResponseType::InThread(message_context.thread_info().clone());
+    let response_type = MessageResponseType::Reply(message_context.thread_info().root_event_id.clone());
 
     let Some(agent) = get_effective_agent_for_purpose_or_complain(
         bot,
diff --git a/src/controller/reaction/text_to_speech.rs b/src/controller/reaction/text_to_speech.rs
index b9c3205..d747ed1 100644
--- a/src/controller/reaction/text_to_speech.rs
+++ b/src/controller/reaction/text_to_speech.rs
@@ -26,7 +26,7 @@ pub(super) async fn handle(
     let response_type = if message_context.thread_info().is_thread_root_only() {
         MessageResponseType::Reply(reacted_to_event_id.clone())
     } else {
-        MessageResponseType::InThread(message_context.thread_info().clone())
+        MessageResponseType::Reply(message_context.thread_info().root_event_id.clone())
     };
 
     if !is_allowed_to_tts_for_event(
diff --git a/src/controller/utils/mod.rs b/src/controller/utils/mod.rs
index 9f493c1..69fcd62 100644
--- a/src/controller/utils/mod.rs
+++ b/src/controller/utils/mod.rs
@@ -19,7 +19,7 @@ pub async fn get_text_body_or_complain<'a>(
                 .send_text_markdown_no_fail(
                     message_context.room(),
                     "This command only works with text messages.".to_owned(),
-                    MessageResponseType::InThread(message_context.thread_info().clone()),
+                    MessageResponseType::Reply(message_context.thread_info().root_event_id.clone()),
                 )
                 .await;

rda0 avatar Feb 21 '25 13:02 rda0

Your idea is to get a reply to your message, and to then continue the conversation by sending your own reply to the bot's message?

Since v1.2.0, baibot supports On-demand involvement, so it can follow reply chains like this.

I suppose this could work to solve this issue. It's not really sending clean top-level messages, since everything will be a reply in a long reply-chain, but.. It's a feasible solution.

As long as the bot sends its first response to the in-room trigger message as a reply (not a thread), then one could avoid threads by sticking to reply chains.

spantaleev avatar Feb 21 '25 13:02 spantaleev