gitdataai/libs/transport/handler/dispatch.rs
ZhenYi 14f6e1e500 feat(core): initialize project with access control and AI integration
- Add gitignore and prettier configuration files for project scaffolding
- Implement room access control service with project member verification
- Create user access key management with CRUD operations and activity logging
- Add accordion UI component for frontend expandable sections
- Implement room AI configuration with list, upsert, and delete operations
- Add AI event types for agent join/leave/status change tracking
- Create streaming AI processing services for mode and react patterns
- Build room AI service with model detection and idempotency handling
- Integrate chat service orchestration for AI message processing
- Add typing indicators and stream cancellation for AI interactions
- Implement mention parsing and context extraction for AI agents
2026-05-03 06:04:31 +08:00

128 lines
4.9 KiB
Rust

use models::RoomId;
use queue::{ReactionGroup, RoomMessageEvent, RoomMessageStreamChunkEvent, TypingEvent};
use room::types::NotificationEvent;
use crate::event::{member, message, reaction, notify};
use super::types::WsOutEvent;
pub struct EventDispatcher;
impl EventDispatcher {
pub fn dispatch_message(event: &RoomMessageEvent) -> WsOutEvent {
WsOutEvent::MessageNew {
room_id: event.room_id,
data: message::MessageNewService {
id: event.id,
seq: event.seq,
room: event.room_id,
sender_type: event.sender_type.clone(),
sender_id: event.sender_id,
display_name: event.display_name.clone(),
thread: event.thread_id,
in_reply_to: event.in_reply_to,
content: event.content.clone(),
content_type: event.content_type.clone(),
thinking_content: event.thinking_content.clone(),
thinking_is_chunked: false,
send_at: event.send_at,
},
}
}
/// Dispatch MessageStreamStart — WS only sends message_id + SSE URL.
/// Full chunk content is delivered via dedicated SSE endpoint.
pub fn dispatch_stream_start(event: &RoomMessageStreamChunkEvent) -> WsOutEvent {
WsOutEvent::MessageStreamStart {
room_id: event.room_id,
data: message::MessageStreamStartService {
message_id: event.message_id,
room: event.room_id,
sse_url: String::new(),
display_name: event.display_name.clone(),
},
}
}
/// Dispatch MessageStreamDone — WS notifies client that SSE stream ended.
pub fn dispatch_stream_done(event: &RoomMessageStreamChunkEvent) -> WsOutEvent {
WsOutEvent::MessageStreamDone {
room_id: event.room_id,
data: message::MessageStreamDoneService {
message_id: event.message_id,
room: event.room_id,
content: String::new(),
thinking_content: None,
display_name: event.display_name.clone(),
error: event.error.clone(),
},
}
}
pub fn dispatch_typing(event: &TypingEvent) -> WsOutEvent {
match event.action.as_str() {
"start" => WsOutEvent::TypingStart {
room_id: event.room_id,
data: member::TypingStartService {
room: event.room_id,
user: event.user_id,
username: event.username.clone(),
avatar_url: event.avatar_url.clone(),
sender_type: event.sender_type.clone(),
},
},
_ => WsOutEvent::TypingStop {
room_id: event.room_id,
data: member::TypingStopService {
room: event.room_id,
user: event.user_id,
username: event.username.clone(),
avatar_url: event.avatar_url.clone(),
sender_type: event.sender_type.clone(),
},
},
}
}
pub fn dispatch_notification(event: &NotificationEvent) -> WsOutEvent {
WsOutEvent::NotifyCreated {
data: notify::NotifyCreatedService {
id: event.notification.id,
room: event.notification.room,
project: event.notification.project,
user_id: event.notification.user_id,
notification_type: event.event_type.clone(),
title: event.notification.title.clone(),
content: event.notification.content.clone(),
related_message_id: event.notification.related_message_id,
related_user_id: event.notification.related_user_id,
related_room_id: event.notification.related_room_id,
metadata: event.notification.metadata.clone(),
created_at: event.timestamp,
deep_link_url: event.deep_link_url.clone(),
},
}
}
pub fn dispatch_reactions(
room_id: RoomId,
message_id: uuid::Uuid,
reactions: &[ReactionGroup],
) -> WsOutEvent {
WsOutEvent::ReactionBatchUpdated {
room_id,
data: reaction::ReactionBatchUpdatedService {
room: room_id,
message: message_id,
reactions: reactions
.iter()
.map(|g| reaction::ReactionGroup {
emoji: g.emoji.clone(),
count: g.count as i64,
reacted_by_me: g.reacted_by_me,
users: g.users.iter().filter_map(|u| u.parse::<uuid::Uuid>().ok()).collect(),
})
.collect(),
},
}
}
}