tirea_contract/thread/
changeset.rs1use crate::thread::{Message, Thread};
4use serde::{Deserialize, Serialize};
5use serde_json::Value;
6use std::sync::Arc;
7use tirea_state::TrackedPatch;
8
9pub type Version = u64;
11
12#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
14pub enum CheckpointReason {
15 UserMessage,
16 AssistantTurnCommitted,
17 ToolResultsCommitted,
18 RunFinished,
19}
20
21#[derive(Debug, Clone, Serialize, Deserialize)]
23pub struct ThreadChangeSet {
24 pub run_id: String,
26 #[serde(skip_serializing_if = "Option::is_none")]
28 pub parent_run_id: Option<String>,
29 pub reason: CheckpointReason,
31 pub messages: Vec<Arc<Message>>,
33 pub patches: Vec<TrackedPatch>,
35 #[serde(skip_serializing_if = "Option::is_none")]
37 pub snapshot: Option<Value>,
38}
39
40impl ThreadChangeSet {
41 pub fn from_parts(
43 run_id: impl Into<String>,
44 parent_run_id: Option<String>,
45 reason: CheckpointReason,
46 messages: Vec<Arc<Message>>,
47 patches: Vec<TrackedPatch>,
48 snapshot: Option<Value>,
49 ) -> Self {
50 Self {
51 run_id: run_id.into(),
52 parent_run_id,
53 reason,
54 messages,
55 patches,
56 snapshot,
57 }
58 }
59
60 pub fn apply_to(&self, thread: &mut Thread) {
62 if let Some(ref snapshot) = self.snapshot {
63 thread.state = snapshot.clone();
64 thread.patches.clear();
65 }
66
67 thread.messages.extend(self.messages.iter().cloned());
68 thread.patches.extend(self.patches.iter().cloned());
69 }
70}