feat(room): add attachment_ids to messages, pass AppConfig, increase max_tool_depth to 1000

This commit is contained in:
ZhenYi 2026-04-20 19:32:22 +08:00
parent dee79f3f7f
commit b23c6a03c3
5 changed files with 59 additions and 3 deletions

View File

@ -74,6 +74,7 @@ impl From<room_message::Model> for super::RoomMessageResponse {
revoked_by: value.revoked_by,
in_reply_to: value.in_reply_to,
highlighted_content: None,
attachment_ids: Vec::new(),
}
}
}
@ -431,6 +432,7 @@ impl RoomService {
revoked_by: msg.revoked_by,
in_reply_to: msg.in_reply_to,
highlighted_content: None,
attachment_ids: Vec::new(),
}
}
}

View File

@ -2,10 +2,10 @@ use crate::error::RoomError;
use crate::service::RoomService;
use crate::ws_context::WsUserContext;
use chrono::Utc;
use models::rooms::{room, room_message, room_thread};
use models::rooms::{room, room_attachment, room_message, room_thread};
use models::users::user as user_model;
use queue::RoomMessageEnvelope;
use sea_orm::*;
use sea_orm::{sea_query::Expr, *};
use serde_json;
use uuid::Uuid;
@ -97,11 +97,34 @@ impl RoomService {
revoked: msg.revoked,
revoked_by: msg.revoked_by,
highlighted_content: None,
attachment_ids: Vec::new(),
}
})
.collect();
messages.reverse();
// Batch-load attachment IDs for all returned messages
if !messages.is_empty() {
let msg_ids: Vec<Uuid> = messages.iter().map(|m| m.id).collect();
let attachments = room_attachment::Entity::find()
.filter(room_attachment::Column::Message.is_in(msg_ids))
.all(&self.db)
.await
.unwrap_or_default();
let mut attachment_map: std::collections::HashMap<Uuid, Vec<Uuid>> =
std::collections::HashMap::new();
for att in attachments {
attachment_map.entry(att.message).or_default().push(att.id);
}
for msg in &mut messages {
if let Some(ids) = attachment_map.remove(&msg.id) {
msg.attachment_ids = ids;
}
}
}
Ok(super::RoomMessageListResponse { messages, total })
}
@ -198,6 +221,27 @@ impl RoomService {
txn.commit().await?;
// Link uploaded attachments to this message
let attachment_ids = request.attachment_ids.clone();
if !attachment_ids.is_empty() {
if let Err(e) = room_attachment::Entity::update_many()
.col_expr(
room_attachment::Column::Message,
Expr::value(Some(id)),
)
.filter(room_attachment::Column::Id.is_in(attachment_ids.clone()))
.exec(&self.db)
.await
{
slog::warn!(
self.log,
"Failed to link attachments to message {}: {}",
id,
e
);
}
}
self.publish_room_event(
project_id,
super::RoomEventType::NewMessage,
@ -278,6 +322,7 @@ impl RoomService {
revoked: None,
revoked_by: None,
highlighted_content: None,
attachment_ids,
})
}

View File

@ -326,6 +326,7 @@ impl RoomService {
revoked: msg.revoked,
revoked_by: msg.revoked_by,
highlighted_content: None,
attachment_ids: Vec::new(),
}
})
.collect()

View File

@ -53,6 +53,7 @@ static MENTION_BRACKET_RE: LazyLock<regex_lite::Regex, fn() -> regex_lite::Regex
pub struct RoomService {
pub db: AppDatabase,
pub cache: AppCache,
pub config: config::AppConfig,
pub room_manager: Arc<RoomConnectionManager>,
pub queue: MessageProducer,
pub redis_url: String,
@ -68,6 +69,7 @@ impl RoomService {
pub fn new(
db: AppDatabase,
cache: AppCache,
config: config::AppConfig,
queue: MessageProducer,
room_manager: Arc<RoomConnectionManager>,
redis_url: String,
@ -82,6 +84,7 @@ impl RoomService {
Self {
db,
cache,
config,
room_manager,
queue,
redis_url,
@ -898,6 +901,7 @@ impl RoomService {
let request = AiRequest {
db: self.db.clone(),
cache: self.cache.clone(),
config: self.config.clone(),
model,
project: project.clone(),
sender,
@ -913,7 +917,7 @@ impl RoomService {
presence_penalty: 0.0,
think: ai_config.think,
tools: Some(chat_service.tools()),
max_tool_depth: 3,
max_tool_depth: 1000,
};
let use_streaming = ai_config.stream;

View File

@ -185,6 +185,8 @@ pub struct RoomMessageCreateRequest {
#[serde(rename = "thread_id")]
pub thread: Option<Uuid>,
pub in_reply_to: Option<Uuid>,
#[serde(default)]
pub attachment_ids: Vec<Uuid>,
}
#[derive(Debug, Clone, Deserialize, Serialize, utoipa::ToSchema)]
@ -222,6 +224,8 @@ pub struct RoomMessageResponse {
/// Highlighted content with <mark> tags around matched terms (for search results)
#[serde(skip_serializing_if = "Option::is_none")]
pub highlighted_content: Option<String>,
#[serde(default)]
pub attachment_ids: Vec<Uuid>,
}
/// Search result wrapper (keeps API compatibility)