Repository: TabbyML/tabby
File: ee/tabby-webserver/src/service/thread.rs (Rust)

Code before:
            .await?
            .into_iter()
            .next())
    }

    async fn get_thread_message(&self, id: &ID) -> Result<Message> {
        Ok(self
            .db
            .get_thread_message(id.as_rowid()?)
            .await?
            .ok_or_else(|| CoreError::NotFound("Message not found"))?
            .try_into()?)
    }

    async fn set_persisted(&self, id: &ID) -> Result<()> {
        self.db
            .update_thread_ephemeral(id.as_rowid()?, false)
            .await?;
        Ok(())
    }

    async fn update_thread_message(&self, input: &UpdateMessageInput) -> Result<()> {
        self.db
            .append_thread_message_content(input.id.as_rowid()?, &input.content)
            .await?;
        Ok(())
    }

    async fn create_run(
        &self,
        policy: &AccessPolicy,
        thread_id: &ID,
        options: &ThreadRunOptionsInput,
        attachment_input: Option<&MessageAttachmentInput>,
        yield_last_user_message: bool,
        yield_thread_created: bool,
    ) -> Result<ThreadRunStream> {
        let Some(answer) = self.answer.clone() else {
            bail!("Answer service is not available");
        };

        let messages = self.get_thread_messages(thread_id).await?;

        let Some(last_message) = messages.last() else {
            bail!("Thread has no messages");
        };

        if last_message.role != thread::Role::User {
            bail!("Last message in thread is not from user");
        }


Review comment (suggestion):
1. the db function need to take both thread_id and id to ensure id is part of thread_id.
2. update_thread_message_content, not append.

Code after:
            .await?
            .into_iter()
            .next())
    }

    async fn set_persisted(&self, id: &ID) -> Result<()> {
        self.db
            .update_thread_ephemeral(id.as_rowid()?, false)
            .await?;
        Ok(())
    }

    async fn update_thread_message(&self, input: &UpdateMessageInput) -> Result<()> {
        self.db
            .update_thread_message_content(
                input.thread_id.as_rowid()?,
                input.id.as_rowid()?,
                &input.content,
            )
            .await?;
        Ok(())
    }

    async fn create_run(
        &self,
        policy: &AccessPolicy,
        thread_id: &ID,
        options: &ThreadRunOptionsInput,
        attachment_input: Option<&MessageAttachmentInput>,
        yield_last_user_message: bool,
        yield_thread_created: bool,
    ) -> Result<ThreadRunStream> {
        let Some(answer) = self.answer.clone() else {
            bail!("Answer service is not available");
        };

        let messages = self.get_thread_messages(thread_id).await?;

        let Some(last_message) = messages.last() else {
            bail!("Thread has no messages");
        };

        if last_message.role != thread::Role::User {
            bail!("Last message in thread is not from user");
        }

        let user_message_id = last_message.id.clone();

        let assistant_message_id = self
            .db
            .create_thread_message(