agtrace_engine/session/
assembler.rs

1use 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}