use std::sync::Arc; use chrono::Utc; use db::cache::AppCache; use db::database::AppDatabase; use models::rooms::room_ai; use queue::MessageProducer; use sea_orm::{sea_query::Expr, ColumnTrait, EntityTrait, ExprTrait, QueryFilter}; use uuid::Uuid; use crate::connection::RoomConnectionManager; use agent::chat::{AiRequest, ChatService}; use agent::tool::registry::ToolRegistry; pub async fn process_message_ai_react_nonstreaming( chat_service: Arc, request: AiRequest, room_id: Uuid, _project_id: Uuid, model_id: Uuid, lock_guard: crate::room_ai_queue::RoomAiLockGuard, db: AppDatabase, _cache: AppCache, queue: MessageProducer, _room_manager: Arc, room_tools: ToolRegistry, room_preamble: String, ) { tokio::spawn(async move { let _lock_guard = lock_guard; let model_display_name = request.model.name.clone(); let final_answer = chat_service .process_react_room( &request, |_step| async move {}, room_tools, Some(&room_preamble), Some(queue.clone()), ) .await; match final_answer { Ok((_response, _input_tokens, _output_tokens)) => { // In room mode, the AI communicates via send_message tool calls. // Do not post the final answer as a room message — only update call stats. tracing::info!( room_id = %room_id, model = %model_display_name, "Room AI ReAct nonstreaming completed — messages sent via send_message tool" ); let now = Utc::now(); if let Err(e) = room_ai::Entity::update_many() .col_expr( room_ai::Column::CallCount, Expr::col(room_ai::Column::CallCount).add(1), ) .col_expr(room_ai::Column::LastCallAt, Expr::value(Some(now))) .filter(room_ai::Column::Room.eq(room_id)) .filter(room_ai::Column::Model.eq(model_id)) .exec(&db) .await { tracing::warn!(error = %e, "Failed to update room_ai call stats"); } } Err(e) => { tracing::error!(error = ?e, "ReAct agent failed"); // Even on failure, the AI may have sent partial messages via send_message. // We log the error but don't post it to the room (the AI can retry). } } }); }