clark_agent_compaction/
plain.rs1use crate::TranscriptMessage;
2
3#[derive(Clone, Debug, PartialEq, Eq)]
5pub enum PlainMessage {
6 System(String),
7 User(String),
8 Assistant {
9 text: String,
10 tool_calls: Vec<PlainToolCall>,
11 },
12 ToolResult {
13 tool_call_id: String,
14 tool_name: String,
15 content: String,
16 is_error: bool,
17 },
18 Custom {
19 kind: String,
20 payload: String,
21 },
22}
23
24impl PlainMessage {
25 pub fn system(text: impl Into<String>) -> Self {
26 Self::System(text.into())
27 }
28
29 pub fn user(text: impl Into<String>) -> Self {
30 Self::User(text.into())
31 }
32
33 pub fn assistant(text: impl Into<String>) -> Self {
34 Self::Assistant {
35 text: text.into(),
36 tool_calls: Vec::new(),
37 }
38 }
39
40 pub fn assistant_with_tool_calls(
41 text: impl Into<String>,
42 tool_calls: Vec<PlainToolCall>,
43 ) -> Self {
44 Self::Assistant {
45 text: text.into(),
46 tool_calls,
47 }
48 }
49
50 pub fn tool_result(
51 tool_call_id: impl Into<String>,
52 tool_name: impl Into<String>,
53 content: impl Into<String>,
54 is_error: bool,
55 ) -> Self {
56 Self::ToolResult {
57 tool_call_id: tool_call_id.into(),
58 tool_name: tool_name.into(),
59 content: content.into(),
60 is_error,
61 }
62 }
63}
64
65#[derive(Clone, Debug, PartialEq, Eq)]
67pub struct PlainToolCall {
68 pub name: String,
69 pub arguments: String,
70}
71
72impl PlainToolCall {
73 pub fn new(name: impl Into<String>, arguments: impl Into<String>) -> Self {
74 Self {
75 name: name.into(),
76 arguments: arguments.into(),
77 }
78 }
79}
80
81impl TranscriptMessage for PlainMessage {
82 fn render_for_compaction(&self, out: &mut String) {
83 match self {
84 PlainMessage::System(text) => {
85 out.push_str("[system]\n");
86 out.push_str(text);
87 }
88 PlainMessage::User(text) => {
89 out.push_str("[user]\n");
90 out.push_str(text);
91 }
92 PlainMessage::Assistant { text, tool_calls } => {
93 out.push_str("[assistant]\n");
94 let mut wrote = false;
95 if !text.is_empty() {
96 out.push_str(text);
97 wrote = true;
98 }
99 if !tool_calls.is_empty() {
100 if wrote {
101 out.push('\n');
102 }
103 out.push_str("tool calls: ");
104 for (idx, call) in tool_calls.iter().enumerate() {
105 if idx > 0 {
106 out.push_str(", ");
107 }
108 out.push_str(&call.name);
109 out.push('(');
110 out.push_str(&call.arguments);
111 out.push(')');
112 }
113 wrote = true;
114 }
115 if !wrote {
116 out.push_str("(empty)");
117 }
118 }
119 PlainMessage::ToolResult {
120 tool_call_id,
121 tool_name,
122 content,
123 is_error,
124 } => {
125 let status = if *is_error { "error" } else { "ok" };
126 out.push_str("[tool result ");
127 out.push_str(tool_call_id);
128 out.push(' ');
129 out.push_str(tool_name);
130 out.push(' ');
131 out.push_str(status);
132 out.push_str("]\n");
133 out.push_str(content);
134 }
135 PlainMessage::Custom { kind, payload } => {
136 out.push_str("[custom ");
137 out.push_str(kind);
138 out.push_str("]\n");
139 out.push_str(payload);
140 }
141 }
142 }
143
144 fn user_text_for_compaction(&self, out: &mut String) -> bool {
145 if let PlainMessage::User(text) = self {
146 out.push_str(text);
147 true
148 } else {
149 false
150 }
151 }
152}