agtrace_engine/session/
assembler.rs1use super::stats::calculate_session_stats;
2use super::turn_builder::TurnBuilder;
3use super::types::*;
4use agtrace_types::{AgentEvent, EventPayload};
5
6pub fn assemble_session(events: &[AgentEvent]) -> Option<AgentSession> {
7 if events.is_empty() {
8 return None;
9 }
10
11 let session_id = events.first()?.session_id;
12 let start_time = events.first()?.timestamp;
13 let end_time = events.last().map(|e| e.timestamp);
14
15 let turns = build_turns(events);
16 let stats = calculate_session_stats(&turns, start_time, end_time);
17
18 Some(AgentSession {
19 session_id,
20 start_time,
21 end_time,
22 turns,
23 stats,
24 })
25}
26
27fn build_turns(events: &[AgentEvent]) -> Vec<AgentTurn> {
28 let mut turns = Vec::new();
29 let mut current_turn: Option<TurnBuilder> = None;
30
31 for event in events {
32 match &event.payload {
33 EventPayload::User(user) => {
34 if let Some(builder) = current_turn.take()
35 && let Some(turn) = builder.build()
36 {
37 turns.push(turn);
38 }
39
40 current_turn = Some(TurnBuilder::new(
41 event.id,
42 event.timestamp,
43 UserMessage {
44 event_id: event.id,
45 content: user.clone(),
46 },
47 ));
48 }
49 _ => {
50 if let Some(ref mut builder) = current_turn {
51 builder.add_event(event);
52 }
53 }
54 }
55 }
56
57 if let Some(builder) = current_turn
58 && let Some(turn) = builder.build()
59 {
60 turns.push(turn);
61 }
62
63 turns
64}