1use super::{ProtocolEvent, ProtocolEventMeta};
2use crate::message::TranscriptMessage;
3
4macro_rules! match_event_meta {
5 ($event:expr, |$session_id:ident, $seq:ident, $created_at:ident| $body:expr) => {
6 match $event {
7 ProtocolEvent::SessionStarted {
8 session_id: $session_id,
9 seq: $seq,
10 created_at: $created_at,
11 ..
12 }
13 | ProtocolEvent::SessionTitleUpdated {
14 session_id: $session_id,
15 seq: $seq,
16 created_at: $created_at,
17 ..
18 }
19 | ProtocolEvent::AssistantDelta {
20 session_id: $session_id,
21 seq: $seq,
22 created_at: $created_at,
23 ..
24 }
25 | ProtocolEvent::AssistantMessageCompleted {
26 session_id: $session_id,
27 seq: $seq,
28 created_at: $created_at,
29 ..
30 }
31 | ProtocolEvent::ToolCallStarted {
32 session_id: $session_id,
33 seq: $seq,
34 created_at: $created_at,
35 ..
36 }
37 | ProtocolEvent::ToolApprovalRequested {
38 session_id: $session_id,
39 seq: $seq,
40 created_at: $created_at,
41 ..
42 }
43 | ProtocolEvent::ToolApprovalResolved {
44 session_id: $session_id,
45 seq: $seq,
46 created_at: $created_at,
47 ..
48 }
49 | ProtocolEvent::ToolResultAdded {
50 session_id: $session_id,
51 seq: $seq,
52 created_at: $created_at,
53 ..
54 }
55 | ProtocolEvent::SessionTurnFinished {
56 session_id: $session_id,
57 seq: $seq,
58 created_at: $created_at,
59 ..
60 }
61 | ProtocolEvent::StreamResyncRequired {
62 session_id: $session_id,
63 seq: $seq,
64 created_at: $created_at,
65 ..
66 }
67 | ProtocolEvent::Overloaded {
68 session_id: $session_id,
69 seq: $seq,
70 created_at: $created_at,
71 ..
72 }
73 | ProtocolEvent::PersistenceFailed {
74 session_id: $session_id,
75 seq: $seq,
76 created_at: $created_at,
77 ..
78 }
79 | ProtocolEvent::ProviderRetrying {
80 session_id: $session_id,
81 seq: $seq,
82 created_at: $created_at,
83 ..
84 }
85 | ProtocolEvent::SessionCompactionStarted {
86 session_id: $session_id,
87 seq: $seq,
88 created_at: $created_at,
89 ..
90 }
91 | ProtocolEvent::VerificationFinished {
92 session_id: $session_id,
93 seq: $seq,
94 created_at: $created_at,
95 ..
96 }
97 | ProtocolEvent::TaskGraphUpdated {
98 session_id: $session_id,
99 seq: $seq,
100 created_at: $created_at,
101 ..
102 }
103 | ProtocolEvent::TaskStatusUpdated {
104 session_id: $session_id,
105 seq: $seq,
106 created_at: $created_at,
107 ..
108 }
109 | ProtocolEvent::TaskArtifactUpdated {
110 session_id: $session_id,
111 seq: $seq,
112 created_at: $created_at,
113 ..
114 }
115 | ProtocolEvent::ArtifactLineageUpdated {
116 session_id: $session_id,
117 seq: $seq,
118 created_at: $created_at,
119 ..
120 }
121 | ProtocolEvent::RunInterrupted {
122 session_id: $session_id,
123 seq: $seq,
124 created_at: $created_at,
125 ..
126 }
127 | ProtocolEvent::RunFailed {
128 session_id: $session_id,
129 seq: $seq,
130 created_at: $created_at,
131 ..
132 }
133 | ProtocolEvent::SessionCompacted {
134 session_id: $session_id,
135 seq: $seq,
136 created_at: $created_at,
137 ..
138 }
139 | ProtocolEvent::SessionContextFolded {
140 session_id: $session_id,
141 seq: $seq,
142 created_at: $created_at,
143 ..
144 }
145 | ProtocolEvent::UsageUpdated {
146 session_id: $session_id,
147 seq: $seq,
148 created_at: $created_at,
149 ..
150 }
151 | ProtocolEvent::TurnUsage {
152 session_id: $session_id,
153 seq: $seq,
154 created_at: $created_at,
155 ..
156 }
157 | ProtocolEvent::PromptCacheBreak {
158 session_id: $session_id,
159 seq: $seq,
160 created_at: $created_at,
161 ..
162 }
163 | ProtocolEvent::ToolOutputDelta {
164 session_id: $session_id,
165 seq: $seq,
166 created_at: $created_at,
167 ..
168 }
169 | ProtocolEvent::BackgroundShellExited {
170 session_id: $session_id,
171 seq: $seq,
172 created_at: $created_at,
173 ..
174 }
175 | ProtocolEvent::BudgetExceeded {
176 session_id: $session_id,
177 seq: $seq,
178 created_at: $created_at,
179 ..
180 }
181 | ProtocolEvent::ProviderRouteUpdated {
182 session_id: $session_id,
183 seq: $seq,
184 created_at: $created_at,
185 ..
186 }
187 | ProtocolEvent::AccountRateLimited {
188 session_id: $session_id,
189 seq: $seq,
190 created_at: $created_at,
191 ..
192 }
193 | ProtocolEvent::AccountUsageReported {
194 session_id: $session_id,
195 seq: $seq,
196 created_at: $created_at,
197 ..
198 }
199 | ProtocolEvent::DispatchDecided {
200 session_id: $session_id,
201 seq: $seq,
202 created_at: $created_at,
203 ..
204 }
205 | ProtocolEvent::OrchestrationObservationRecorded {
206 session_id: $session_id,
207 seq: $seq,
208 created_at: $created_at,
209 ..
210 }
211 | ProtocolEvent::AgentQueryIssued {
212 session_id: $session_id,
213 seq: $seq,
214 created_at: $created_at,
215 ..
216 }
217 | ProtocolEvent::AgentQueryResponded {
218 session_id: $session_id,
219 seq: $seq,
220 created_at: $created_at,
221 ..
222 }
223 | ProtocolEvent::HumanSteeringInjected {
224 session_id: $session_id,
225 seq: $seq,
226 created_at: $created_at,
227 ..
228 }
229 | ProtocolEvent::SubAgentSpawned {
230 session_id: $session_id,
231 seq: $seq,
232 created_at: $created_at,
233 ..
234 }
235 | ProtocolEvent::SubAgentCompleted {
236 session_id: $session_id,
237 seq: $seq,
238 created_at: $created_at,
239 ..
240 }
241 | ProtocolEvent::SubAgentCancelled {
242 session_id: $session_id,
243 seq: $seq,
244 created_at: $created_at,
245 ..
246 }
247 | ProtocolEvent::UserMessageSubmitted {
248 session_id: $session_id,
249 seq: $seq,
250 created_at: $created_at,
251 ..
252 }
253 | ProtocolEvent::UserQuestionAsked {
254 session_id: $session_id,
255 seq: $seq,
256 created_at: $created_at,
257 ..
258 }
259 | ProtocolEvent::McpElicitationRequested {
260 session_id: $session_id,
261 seq: $seq,
262 created_at: $created_at,
263 ..
264 }
265 | ProtocolEvent::CredentialRequested {
266 session_id: $session_id,
267 seq: $seq,
268 created_at: $created_at,
269 ..
270 }
271 | ProtocolEvent::CredentialResolved {
272 session_id: $session_id,
273 seq: $seq,
274 created_at: $created_at,
275 ..
276 }
277 | ProtocolEvent::UserQuestionAnswered {
278 session_id: $session_id,
279 seq: $seq,
280 created_at: $created_at,
281 ..
282 }
283 | ProtocolEvent::PlanPresented {
284 session_id: $session_id,
285 seq: $seq,
286 created_at: $created_at,
287 ..
288 }
289 | ProtocolEvent::AgentRosterUpdated {
290 session_id: $session_id,
291 seq: $seq,
292 created_at: $created_at,
293 ..
294 }
295 | ProtocolEvent::CheckRunCompleted {
296 session_id: $session_id,
297 seq: $seq,
298 created_at: $created_at,
299 ..
300 }
301 | ProtocolEvent::GoalProgressUpdated {
302 session_id: $session_id,
303 seq: $seq,
304 created_at: $created_at,
305 ..
306 }
307 | ProtocolEvent::SelfReviewProposalReceived {
308 session_id: $session_id,
309 seq: $seq,
310 created_at: $created_at,
311 ..
312 }
313 | ProtocolEvent::ToolApprovalReviewed {
314 session_id: $session_id,
315 seq: $seq,
316 created_at: $created_at,
317 ..
318 }
319 | ProtocolEvent::ModelRouteDecision {
320 session_id: $session_id,
321 seq: $seq,
322 created_at: $created_at,
323 ..
324 }
325 | ProtocolEvent::RunGovernanceRejected {
326 session_id: $session_id,
327 seq: $seq,
328 created_at: $created_at,
329 ..
330 } => $body,
331 }
332 };
333}
334
335fn assign_seq(event: &mut ProtocolEvent, new_seq: i64) {
341 match event {
342 ProtocolEvent::SessionStarted { seq, .. }
343 | ProtocolEvent::SessionTitleUpdated { seq, .. }
344 | ProtocolEvent::AssistantDelta { seq, .. }
345 | ProtocolEvent::AssistantMessageCompleted { seq, .. }
346 | ProtocolEvent::ToolCallStarted { seq, .. }
347 | ProtocolEvent::ToolApprovalRequested { seq, .. }
348 | ProtocolEvent::ToolApprovalResolved { seq, .. }
349 | ProtocolEvent::ToolResultAdded { seq, .. }
350 | ProtocolEvent::SessionTurnFinished { seq, .. }
351 | ProtocolEvent::StreamResyncRequired { seq, .. }
352 | ProtocolEvent::Overloaded { seq, .. }
353 | ProtocolEvent::PersistenceFailed { seq, .. }
354 | ProtocolEvent::ProviderRetrying { seq, .. }
355 | ProtocolEvent::SessionCompactionStarted { seq, .. }
356 | ProtocolEvent::VerificationFinished { seq, .. }
357 | ProtocolEvent::TaskGraphUpdated { seq, .. }
358 | ProtocolEvent::TaskStatusUpdated { seq, .. }
359 | ProtocolEvent::TaskArtifactUpdated { seq, .. }
360 | ProtocolEvent::ArtifactLineageUpdated { seq, .. }
361 | ProtocolEvent::RunInterrupted { seq, .. }
362 | ProtocolEvent::RunFailed { seq, .. }
363 | ProtocolEvent::SessionCompacted { seq, .. }
364 | ProtocolEvent::SessionContextFolded { seq, .. }
365 | ProtocolEvent::UsageUpdated { seq, .. }
366 | ProtocolEvent::TurnUsage { seq, .. }
367 | ProtocolEvent::PromptCacheBreak { seq, .. }
368 | ProtocolEvent::ToolOutputDelta { seq, .. }
369 | ProtocolEvent::BackgroundShellExited { seq, .. }
370 | ProtocolEvent::BudgetExceeded { seq, .. }
371 | ProtocolEvent::ProviderRouteUpdated { seq, .. }
372 | ProtocolEvent::AccountRateLimited { seq, .. }
373 | ProtocolEvent::AccountUsageReported { seq, .. }
374 | ProtocolEvent::DispatchDecided { seq, .. }
375 | ProtocolEvent::OrchestrationObservationRecorded { seq, .. }
376 | ProtocolEvent::AgentQueryIssued { seq, .. }
377 | ProtocolEvent::AgentQueryResponded { seq, .. }
378 | ProtocolEvent::HumanSteeringInjected { seq, .. }
379 | ProtocolEvent::SubAgentSpawned { seq, .. }
380 | ProtocolEvent::SubAgentCompleted { seq, .. }
381 | ProtocolEvent::SubAgentCancelled { seq, .. }
382 | ProtocolEvent::UserMessageSubmitted { seq, .. }
383 | ProtocolEvent::UserQuestionAsked { seq, .. }
384 | ProtocolEvent::McpElicitationRequested { seq, .. }
385 | ProtocolEvent::CredentialRequested { seq, .. }
386 | ProtocolEvent::CredentialResolved { seq, .. }
387 | ProtocolEvent::UserQuestionAnswered { seq, .. }
388 | ProtocolEvent::PlanPresented { seq, .. }
389 | ProtocolEvent::AgentRosterUpdated { seq, .. }
390 | ProtocolEvent::CheckRunCompleted { seq, .. }
391 | ProtocolEvent::GoalProgressUpdated { seq, .. }
392 | ProtocolEvent::SelfReviewProposalReceived { seq, .. }
393 | ProtocolEvent::ModelRouteDecision { seq, .. }
394 | ProtocolEvent::ToolApprovalReviewed { seq, .. }
395 | ProtocolEvent::RunGovernanceRejected { seq, .. } => *seq = new_seq,
396 }
397}
398
399fn rewrite_message_id<F: FnOnce(&mut TranscriptMessage)>(event: &mut ProtocolEvent, rewrite: F) {
403 match event {
404 ProtocolEvent::AssistantMessageCompleted { message, .. } => rewrite(message),
405 ProtocolEvent::ToolResultAdded { result, .. } => rewrite(result),
406 ProtocolEvent::SessionContextFolded { fold, .. } => rewrite(fold),
407 _ => {}
408 }
409}
410
411impl ProtocolEvent {
412 pub fn meta(&self) -> ProtocolEventMeta {
413 match_event_meta!(self, |session_id, seq, created_at| ProtocolEventMeta {
414 session_id: session_id.clone(),
415 seq: *seq,
416 created_at: created_at.clone(),
417 })
418 }
419
420 pub fn session_id(&self) -> &str {
421 match_event_meta!(self, |session_id, _seq, _created_at| session_id.as_str())
422 }
423
424 pub fn seq(&self) -> i64 {
425 match_event_meta!(self, |_session_id, seq, _created_at| *seq)
426 }
427
428 pub fn created_at(&self) -> &str {
429 match_event_meta!(self, |_session_id, _seq, created_at| created_at.as_str())
430 }
431
432 pub fn set_seq(&mut self, new_seq: i64) {
435 assign_seq(self, new_seq);
436 }
437
438 pub fn canonicalize_identity(&mut self, authoritative_seq: i64) {
443 assign_seq(self, authoritative_seq);
444 let outer = authoritative_seq;
445 rewrite_message_id(self, |message| {
446 message.set_id(derive_message_id(message, outer));
447 });
448 }
449}
450
451fn derive_message_id(message: &TranscriptMessage, row_seq: i64) -> String {
453 use TranscriptMessage::*;
454 match message {
455 System { .. } => crate::ids::message_id(row_seq),
456 User { .. } => crate::ids::message_id(row_seq),
457 Assistant { .. } => crate::ids::assistant_message_id(row_seq),
458 Tool { tool_call_id, .. } => crate::ids::tool_result_id(tool_call_id, row_seq),
459 Compact { .. } => crate::ids::message_id(row_seq),
460 Fold { .. } => crate::ids::message_id(row_seq),
461 }
462}