1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3
4#[derive(Debug, Clone, Serialize, Deserialize)]
9#[serde(tag = "type")]
10pub enum Entry {
11 #[serde(rename = "user")]
13 User(UserEntry),
14
15 #[serde(rename = "assistant")]
16 Assistant(AssistantEntry),
17
18 #[serde(rename = "system")]
19 System(SystemEntry),
20
21 #[serde(rename = "attachment")]
22 Attachment(AttachmentEntry),
23
24 #[serde(rename = "progress")]
25 Progress(ProgressEntry),
26
27 #[serde(rename = "permission-mode")]
29 PermissionMode(PermissionModeEntry),
30
31 #[serde(rename = "last-prompt")]
32 LastPrompt(LastPromptEntry),
33
34 #[serde(rename = "ai-title")]
35 AiTitle(AiTitleEntry),
36
37 #[serde(rename = "custom-title")]
38 CustomTitle(CustomTitleEntry),
39
40 #[serde(rename = "agent-name")]
41 AgentName(AgentNameEntry),
42
43 #[serde(rename = "agent-color")]
44 AgentColor(AgentColorEntry),
45
46 #[serde(rename = "agent-setting")]
47 AgentSetting(AgentSettingEntry),
48
49 #[serde(rename = "tag")]
50 Tag(TagEntry),
51
52 #[serde(rename = "summary")]
53 Summary(SummaryEntry),
54
55 #[serde(rename = "task-summary")]
56 TaskSummary(TaskSummaryEntry),
57
58 #[serde(rename = "pr-link")]
59 PrLink(PrLinkEntry),
60
61 #[serde(rename = "mode")]
62 Mode(ModeEntry),
63
64 #[serde(rename = "worktree-state")]
65 WorktreeState(WorktreeStateEntry),
66
67 #[serde(rename = "content-replacement")]
68 ContentReplacement(ContentReplacementEntry),
69
70 #[serde(rename = "file-history-snapshot")]
71 FileHistorySnapshot(FileHistorySnapshotEntry),
72
73 #[serde(rename = "attribution-snapshot")]
74 AttributionSnapshot(AttributionSnapshotEntry),
75
76 #[serde(rename = "queue-operation")]
77 QueueOperation(QueueOperationEntry),
78
79 #[serde(rename = "marble-origami-commit")]
80 ContextCollapseCommit(ContextCollapseCommitEntry),
81
82 #[serde(rename = "marble-origami-snapshot")]
83 ContextCollapseSnapshot(ContextCollapseSnapshotEntry),
84
85 #[serde(rename = "speculation-accept")]
86 SpeculationAccept(SpeculationAcceptEntry),
87
88 #[serde(other)]
92 Unknown,
93}
94
95#[derive(Debug, Clone, Serialize, Deserialize)]
104#[serde(rename_all = "camelCase")]
105pub struct Envelope {
106 pub uuid: String,
107
108 pub parent_uuid: Option<String>,
110
111 #[serde(skip_serializing_if = "Option::is_none")]
114 pub logical_parent_uuid: Option<String>,
115
116 pub is_sidechain: bool,
117 pub session_id: String,
118 pub timestamp: String,
119
120 #[serde(skip_serializing_if = "Option::is_none")]
121 pub user_type: Option<String>,
122
123 #[serde(skip_serializing_if = "Option::is_none")]
124 pub entrypoint: Option<String>,
125
126 #[serde(skip_serializing_if = "Option::is_none")]
127 pub cwd: Option<String>,
128
129 #[serde(skip_serializing_if = "Option::is_none")]
130 pub version: Option<String>,
131
132 #[serde(skip_serializing_if = "Option::is_none")]
133 pub git_branch: Option<String>,
134
135 #[serde(skip_serializing_if = "Option::is_none")]
137 pub slug: Option<String>,
138
139 #[serde(skip_serializing_if = "Option::is_none")]
141 pub agent_id: Option<String>,
142
143 #[serde(skip_serializing_if = "Option::is_none")]
144 pub team_name: Option<String>,
145
146 #[serde(skip_serializing_if = "Option::is_none")]
147 pub agent_name: Option<String>,
148
149 #[serde(skip_serializing_if = "Option::is_none")]
150 pub agent_color: Option<String>,
151
152 #[serde(skip_serializing_if = "Option::is_none")]
154 pub prompt_id: Option<String>,
155
156 #[serde(rename = "isMeta", skip_serializing_if = "Option::is_none")]
158 pub is_meta: Option<bool>,
159
160 #[serde(rename = "forkedFrom", skip_serializing_if = "Option::is_none")]
162 pub forked_from: Option<ForkedFrom>,
163}
164
165#[derive(Debug, Clone, Serialize, Deserialize)]
166#[serde(rename_all = "camelCase")]
167pub struct ForkedFrom {
168 pub message_uuid: String,
169 pub session_id: String,
170}
171
172#[derive(Debug, Clone, Serialize, Deserialize)]
177pub struct UserEntry {
178 #[serde(flatten)]
179 pub envelope: Envelope,
180 pub message: UserMessage,
181
182 #[serde(rename = "toolUseResult", skip_serializing_if = "Option::is_none")]
185 pub tool_use_result: Option<Value>,
186
187 #[serde(
189 rename = "sourceToolAssistantUUID",
190 skip_serializing_if = "Option::is_none"
191 )]
192 pub source_tool_assistant_uuid: Option<String>,
193
194 #[serde(rename = "sourceToolUseID", skip_serializing_if = "Option::is_none")]
196 pub source_tool_use_id: Option<String>,
197
198 #[serde(rename = "permissionMode", skip_serializing_if = "Option::is_none")]
199 pub permission_mode: Option<String>,
200
201 #[serde(skip_serializing_if = "Option::is_none")]
202 pub origin: Option<Value>,
203
204 #[serde(rename = "isCompactSummary", skip_serializing_if = "Option::is_none")]
205 pub is_compact_summary: Option<bool>,
206
207 #[serde(
208 rename = "isVisibleInTranscriptOnly",
209 skip_serializing_if = "Option::is_none"
210 )]
211 pub is_visible_in_transcript_only: Option<bool>,
212
213 #[serde(rename = "imagePasteIds", skip_serializing_if = "Option::is_none")]
214 pub image_paste_ids: Option<Vec<u64>>,
215
216 #[serde(rename = "planContent", skip_serializing_if = "Option::is_none")]
217 pub plan_content: Option<String>,
218}
219
220#[derive(Debug, Clone, Serialize, Deserialize)]
221pub struct UserMessage {
222 pub role: UserRole,
223 pub content: UserContent,
224}
225
226#[derive(Debug, Clone, Serialize, Deserialize)]
227#[serde(rename_all = "lowercase")]
228pub enum UserRole {
229 User,
230}
231
232#[derive(Debug, Clone, Serialize, Deserialize)]
234#[serde(untagged)]
235pub enum UserContent {
236 Text(String),
237 Blocks(Vec<UserContentBlock>),
238}
239
240#[derive(Debug, Clone, Serialize, Deserialize)]
241#[serde(tag = "type", rename_all = "snake_case")]
242pub enum UserContentBlock {
243 Text {
244 text: String,
245 },
246
247 ToolResult {
248 tool_use_id: String,
249 content: Value,
253 #[serde(skip_serializing_if = "Option::is_none")]
254 is_error: Option<bool>,
255 },
256
257 Image {
258 source: ImageSource,
259 },
260
261 Document {
262 source: DocumentSource,
263 #[serde(skip_serializing_if = "Option::is_none")]
264 title: Option<String>,
265 },
266}
267
268#[derive(Debug, Clone, Serialize, Deserialize)]
269#[serde(tag = "type", rename_all = "snake_case")]
270pub enum ImageSource {
271 Base64 { media_type: String, data: String },
272 Url { url: String },
273}
274
275#[derive(Debug, Clone, Serialize, Deserialize)]
276#[serde(tag = "type", rename_all = "snake_case")]
277pub enum DocumentSource {
278 Base64 { media_type: String, data: String },
279 Text { data: String },
280 Url { url: String },
281}
282
283#[derive(Debug, Clone, Serialize, Deserialize)]
288#[serde(rename_all = "camelCase")]
289pub struct AssistantEntry {
290 #[serde(flatten)]
291 pub envelope: Envelope,
292 pub message: AssistantMessage,
293
294 #[serde(skip_serializing_if = "Option::is_none")]
295 pub request_id: Option<String>,
296
297 #[serde(rename = "isApiErrorMessage", skip_serializing_if = "Option::is_none")]
298 pub is_api_error_message: Option<bool>,
299
300 #[serde(skip_serializing_if = "Option::is_none")]
301 pub error: Option<String>,
302}
303
304#[derive(Debug, Clone, Serialize, Deserialize)]
305pub struct AssistantMessage {
306 pub id: String,
307 #[serde(rename = "type")]
309 pub msg_type: String,
310 pub role: AssistantRole,
311 pub model: String,
312
313 #[serde(
315 default,
316 skip_serializing_if = "Option::is_none",
317 with = "opt_nullable"
318 )]
319 pub container: Option<Option<Value>>,
320
321 pub content: Vec<AssistantContentBlock>,
322
323 pub stop_reason: Option<String>,
326
327 pub stop_sequence: Option<String>,
329
330 #[serde(
333 default,
334 skip_serializing_if = "Option::is_none",
335 with = "opt_nullable"
336 )]
337 pub stop_details: Option<Option<Value>>,
338
339 pub usage: AssistantUsage,
340
341 #[serde(
343 default,
344 skip_serializing_if = "Option::is_none",
345 with = "opt_nullable"
346 )]
347 pub context_management: Option<Option<Value>>,
348}
349
350#[derive(Debug, Clone, Serialize, Deserialize)]
351#[serde(rename_all = "lowercase")]
352pub enum AssistantRole {
353 Assistant,
354}
355
356#[derive(Debug, Clone, Serialize, Deserialize)]
357#[serde(tag = "type", rename_all = "snake_case")]
358pub enum AssistantContentBlock {
359 Text {
360 text: String,
361 },
362
363 Thinking {
367 thinking: String,
368 signature: String,
369 },
370
371 RedactedThinking {
372 data: String,
373 },
374
375 ToolUse {
376 id: String,
377 name: String,
378 input: Value,
379 #[serde(skip_serializing_if = "Option::is_none")]
381 caller: Option<ToolUseCaller>,
382 },
383}
384
385#[derive(Debug, Clone, Serialize, Deserialize)]
386pub struct ToolUseCaller {
387 #[serde(rename = "type")]
388 pub caller_type: String,
389}
390
391#[derive(Debug, Clone, Serialize, Deserialize)]
393pub struct AssistantUsage {
394 pub input_tokens: u64,
395 pub output_tokens: u64,
396
397 #[serde(skip_serializing_if = "Option::is_none")]
398 pub cache_creation_input_tokens: Option<u64>,
399
400 #[serde(skip_serializing_if = "Option::is_none")]
401 pub cache_read_input_tokens: Option<u64>,
402
403 #[serde(skip_serializing_if = "Option::is_none")]
404 pub server_tool_use: Option<ServerToolUse>,
405
406 #[serde(
408 default,
409 skip_serializing_if = "Option::is_none",
410 with = "opt_nullable"
411 )]
412 pub service_tier: Option<Option<Value>>,
413
414 #[serde(skip_serializing_if = "Option::is_none")]
415 pub cache_creation: Option<CacheCreation>,
416
417 #[serde(
419 default,
420 skip_serializing_if = "Option::is_none",
421 with = "opt_nullable"
422 )]
423 pub inference_geo: Option<Option<Value>>,
424
425 #[serde(
427 default,
428 skip_serializing_if = "Option::is_none",
429 with = "opt_nullable"
430 )]
431 pub iterations: Option<Option<Value>>,
432
433 #[serde(
435 default,
436 skip_serializing_if = "Option::is_none",
437 with = "opt_nullable"
438 )]
439 pub speed: Option<Option<Value>>,
440}
441
442#[derive(Debug, Clone, Serialize, Deserialize)]
443pub struct ServerToolUse {
444 pub web_search_requests: u64,
445 pub web_fetch_requests: u64,
446}
447
448#[derive(Debug, Clone, Serialize, Deserialize)]
449pub struct CacheCreation {
450 #[serde(skip_serializing_if = "Option::is_none")]
451 pub ephemeral_1h_input_tokens: Option<u64>,
452 #[serde(skip_serializing_if = "Option::is_none")]
453 pub ephemeral_5m_input_tokens: Option<u64>,
454}
455
456#[derive(Debug, Clone, Serialize, Deserialize)]
457pub struct UsageIteration {
458 pub input_tokens: u64,
459 pub output_tokens: u64,
460
461 #[serde(skip_serializing_if = "Option::is_none")]
462 pub cache_read_input_tokens: Option<u64>,
463
464 #[serde(skip_serializing_if = "Option::is_none")]
465 pub cache_creation_input_tokens: Option<u64>,
466
467 #[serde(skip_serializing_if = "Option::is_none")]
468 pub cache_creation: Option<CacheCreation>,
469
470 #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
472 pub iter_type: Option<String>,
473}
474
475#[derive(Debug, Clone, Serialize, Deserialize)]
484#[serde(rename_all = "camelCase")]
485pub struct SystemEntry {
486 #[serde(flatten)]
487 pub envelope: Envelope,
488
489 pub subtype: SystemSubtype,
490
491 #[serde(skip_serializing_if = "Option::is_none")]
493 pub content: Option<String>,
494
495 #[serde(skip_serializing_if = "Option::is_none")]
497 pub level: Option<String>,
498
499 #[serde(rename = "isMeta", skip_serializing_if = "Option::is_none")]
501 pub is_meta: Option<bool>,
502
503 #[serde(skip_serializing_if = "Option::is_none")]
505 pub cause: Option<Value>,
506
507 #[serde(skip_serializing_if = "Option::is_none")]
508 pub error: Option<Value>,
509
510 #[serde(rename = "retryInMs", skip_serializing_if = "Option::is_none")]
511 pub retry_in_ms: Option<f64>,
512
513 #[serde(rename = "retryAttempt", skip_serializing_if = "Option::is_none")]
514 pub retry_attempt: Option<u32>,
515
516 #[serde(rename = "maxRetries", skip_serializing_if = "Option::is_none")]
517 pub max_retries: Option<u32>,
518
519 #[serde(rename = "hookCount", skip_serializing_if = "Option::is_none")]
521 pub hook_count: Option<u32>,
522
523 #[serde(rename = "hookInfos", skip_serializing_if = "Option::is_none")]
524 pub hook_infos: Option<Vec<HookInfo>>,
525
526 #[serde(rename = "hookErrors", skip_serializing_if = "Option::is_none")]
527 pub hook_errors: Option<Vec<Value>>,
528
529 #[serde(
530 rename = "preventedContinuation",
531 skip_serializing_if = "Option::is_none"
532 )]
533 pub prevented_continuation: Option<bool>,
534
535 #[serde(rename = "stopReason", skip_serializing_if = "Option::is_none")]
536 pub stop_reason: Option<String>,
537
538 #[serde(rename = "hasOutput", skip_serializing_if = "Option::is_none")]
539 pub has_output: Option<bool>,
540
541 #[serde(rename = "toolUseID", skip_serializing_if = "Option::is_none")]
542 pub tool_use_id: Option<String>,
543
544 #[serde(rename = "durationMs", skip_serializing_if = "Option::is_none")]
546 pub duration_ms: Option<f64>,
547
548 #[serde(rename = "messageCount", skip_serializing_if = "Option::is_none")]
549 pub message_count: Option<u32>,
550
551 #[serde(skip_serializing_if = "Option::is_none")]
553 pub url: Option<String>,
554
555 #[serde(rename = "upgradeNudge", skip_serializing_if = "Option::is_none")]
556 pub upgrade_nudge: Option<String>,
557
558 #[serde(rename = "compactMetadata", skip_serializing_if = "Option::is_none")]
560 pub compact_metadata: Option<CompactMetadata>,
561}
562
563#[derive(Debug, Clone, Serialize, Deserialize)]
564#[serde(rename_all = "snake_case")]
565pub enum SystemSubtype {
566 ApiError,
567 AwaySummary,
568 BridgeStatus,
569 CompactBoundary,
570 Informational,
571 LocalCommand,
572 ScheduledTaskFire,
573 StopHookSummary,
574 TurnDuration,
575 MicrocompactBoundary,
576 PermissionRetry,
577 AgentsKilled,
578 #[serde(other)]
579 Unknown,
580}
581
582#[derive(Debug, Clone, Serialize, Deserialize)]
583#[serde(rename_all = "camelCase")]
584pub struct HookInfo {
585 pub command: String,
586 pub duration_ms: u64,
587}
588
589#[derive(Debug, Clone, Serialize, Deserialize)]
590#[serde(rename_all = "camelCase")]
591pub struct PreservedSegment {
592 pub head_uuid: String,
593 pub anchor_uuid: String,
594 pub tail_uuid: String,
595}
596
597#[derive(Debug, Clone, Serialize, Deserialize)]
598#[serde(rename_all = "camelCase")]
599pub struct CompactMetadata {
600 pub trigger: String,
601 #[serde(skip_serializing_if = "Option::is_none")]
602 pub pre_tokens: Option<u64>,
603 #[serde(skip_serializing_if = "Option::is_none")]
604 pub post_tokens: Option<u64>,
605 #[serde(skip_serializing_if = "Option::is_none")]
606 pub duration_ms: Option<u64>,
607 #[serde(skip_serializing_if = "Option::is_none")]
608 pub preserved_segment: Option<PreservedSegment>,
609 #[serde(
610 rename = "preCompactDiscoveredTools",
611 skip_serializing_if = "Option::is_none"
612 )]
613 pub pre_compact_discovered_tools: Option<Vec<String>>,
614}
615
616#[derive(Debug, Clone, Serialize, Deserialize)]
621pub struct AttachmentEntry {
622 #[serde(flatten)]
623 pub envelope: Envelope,
624 pub attachment: AttachmentData,
625}
626
627#[derive(Debug, Clone, Serialize, Deserialize)]
628#[serde(tag = "type", rename_all = "snake_case")]
629pub enum AttachmentData {
630 HookSuccess(HookResultAttachment),
632 HookNonBlockingError(HookResultAttachment),
633 HookBlockingError(HookResultAttachment),
634 HookCancelled(HookResultAttachment),
635
636 HookAdditionalContext {
637 content: Vec<String>,
638 #[serde(rename = "hookName", skip_serializing_if = "Option::is_none")]
639 hook_name: Option<String>,
640 #[serde(rename = "toolUseID", skip_serializing_if = "Option::is_none")]
641 tool_use_id: Option<String>,
642 #[serde(rename = "hookEvent", skip_serializing_if = "Option::is_none")]
643 hook_event: Option<String>,
644 },
645
646 HookPermissionDecision {
647 decision: String,
648 #[serde(rename = "hookName", skip_serializing_if = "Option::is_none")]
649 hook_name: Option<String>,
650 #[serde(rename = "toolUseID", skip_serializing_if = "Option::is_none")]
651 tool_use_id: Option<String>,
652 #[serde(rename = "hookEvent", skip_serializing_if = "Option::is_none")]
653 hook_event: Option<String>,
654 },
655
656 File {
658 filename: String,
659 content: FileAttachmentContent,
660 #[serde(rename = "displayPath", skip_serializing_if = "Option::is_none")]
661 display_path: Option<String>,
662 },
663
664 EditedTextFile {
665 filename: String,
666 snippet: String,
668 },
669
670 Directory {
671 path: String,
672 content: String,
673 #[serde(rename = "displayPath")]
674 display_path: String,
675 },
676
677 CompactFileReference {
678 filename: String,
679 #[serde(rename = "displayPath")]
680 display_path: String,
681 },
682
683 CommandPermissions {
685 #[serde(rename = "allowedTools")]
686 allowed_tools: Vec<String>,
687 },
688
689 PlanMode {
691 #[serde(rename = "reminderType")]
692 reminder_type: String,
693 #[serde(rename = "isSubAgent")]
694 is_sub_agent: bool,
695 #[serde(rename = "planFilePath", skip_serializing_if = "Option::is_none")]
696 plan_file_path: Option<String>,
697 #[serde(rename = "planExists")]
698 plan_exists: bool,
699 },
700
701 PlanModeExit {
702 #[serde(rename = "planFilePath", skip_serializing_if = "Option::is_none")]
703 plan_file_path: Option<String>,
704 #[serde(rename = "planExists")]
705 plan_exists: bool,
706 },
707
708 SkillListing {
710 content: String,
711 #[serde(rename = "isInitial", skip_serializing_if = "Option::is_none")]
713 is_initial: Option<bool>,
714 #[serde(rename = "skillCount", skip_serializing_if = "Option::is_none")]
716 skill_count: Option<u32>,
717 },
718
719 DynamicSkill {
720 #[serde(rename = "skillDir")]
721 skill_dir: String,
722 #[serde(rename = "skillNames")]
723 skill_names: Vec<String>,
724 #[serde(rename = "displayPath")]
725 display_path: String,
726 },
727
728 InvokedSkills {
729 skills: Vec<InvokedSkill>,
730 },
731
732 TaskReminder {
734 content: Vec<Value>,
735 #[serde(rename = "itemCount")]
736 item_count: u32,
737 },
738
739 Diagnostics {
741 files: Vec<DiagnosticsFile>,
742 #[serde(rename = "isNew")]
743 is_new: bool,
744 },
745
746 DateChange {
748 #[serde(rename = "newDate")]
749 new_date: String,
750 },
751
752 DeferredToolsDelta {
754 #[serde(rename = "addedNames")]
755 added_names: Vec<String>,
756 #[serde(rename = "addedLines", skip_serializing_if = "Option::is_none")]
759 added_lines: Option<Vec<String>>,
760 #[serde(rename = "removedNames", skip_serializing_if = "Option::is_none")]
761 removed_names: Option<Vec<String>>,
762 },
763
764 McpInstructionsDelta {
765 #[serde(rename = "addedNames")]
766 added_names: Vec<String>,
767 #[serde(rename = "addedBlocks")]
768 added_blocks: Vec<String>,
769 #[serde(rename = "removedNames", skip_serializing_if = "Option::is_none")]
770 removed_names: Option<Vec<String>>,
771 },
772
773 UltrathinkEffort {
775 level: String,
776 },
777
778 QueuedCommand {
780 prompt: String,
781 #[serde(rename = "commandMode", skip_serializing_if = "Option::is_none")]
782 command_mode: Option<String>,
783 },
784}
785
786#[derive(Debug, Clone, Serialize, Deserialize)]
787#[serde(rename_all = "camelCase")]
788pub struct HookResultAttachment {
789 #[serde(rename = "hookName", skip_serializing_if = "Option::is_none")]
790 pub hook_name: Option<String>,
791 #[serde(rename = "toolUseID", skip_serializing_if = "Option::is_none")]
792 pub tool_use_id: Option<String>,
793 #[serde(rename = "hookEvent", skip_serializing_if = "Option::is_none")]
794 pub hook_event: Option<String>,
795 #[serde(skip_serializing_if = "Option::is_none")]
796 pub content: Option<String>,
797 #[serde(skip_serializing_if = "Option::is_none")]
798 pub stdout: Option<String>,
799 #[serde(skip_serializing_if = "Option::is_none")]
800 pub stderr: Option<String>,
801 #[serde(skip_serializing_if = "Option::is_none")]
802 pub exit_code: Option<i32>,
803 #[serde(skip_serializing_if = "Option::is_none")]
804 pub command: Option<String>,
805 #[serde(skip_serializing_if = "Option::is_none")]
806 pub duration_ms: Option<u64>,
807 #[serde(rename = "blockingError", skip_serializing_if = "Option::is_none")]
808 pub blocking_error: Option<Value>,
809}
810
811#[derive(Debug, Clone, Serialize, Deserialize)]
813#[serde(rename_all = "camelCase")]
814pub struct FileAttachmentContent {
815 #[serde(rename = "type")]
816 pub content_type: String,
817 pub file: FileData,
818}
819
820#[derive(Debug, Clone, Serialize, Deserialize)]
821#[serde(rename_all = "camelCase")]
822pub struct FileData {
823 pub file_path: String,
824 #[serde(skip_serializing_if = "Option::is_none")]
825 pub content: Option<String>,
826 #[serde(rename = "numLines", skip_serializing_if = "Option::is_none")]
827 pub num_lines: Option<u64>,
828 #[serde(rename = "startLine", skip_serializing_if = "Option::is_none")]
829 pub start_line: Option<u64>,
830 #[serde(rename = "totalLines", skip_serializing_if = "Option::is_none")]
831 pub total_lines: Option<u64>,
832}
833
834#[derive(Debug, Clone, Serialize, Deserialize)]
835pub struct InvokedSkill {
836 pub name: String,
837 pub path: String,
838 pub content: String,
839}
840
841#[derive(Debug, Clone, Serialize, Deserialize)]
842pub struct DiagnosticsFile {
843 pub uri: String,
844 pub diagnostics: Vec<Diagnostic>,
845}
846
847#[derive(Debug, Clone, Serialize, Deserialize)]
848pub struct Diagnostic {
849 pub message: String,
850 pub severity: String,
851 pub range: DiagnosticRange,
852 #[serde(skip_serializing_if = "Option::is_none")]
853 pub source: Option<String>,
854 #[serde(skip_serializing_if = "Option::is_none")]
855 pub code: Option<Value>,
856}
857
858#[derive(Debug, Clone, Serialize, Deserialize)]
859pub struct DiagnosticRange {
860 pub start: DiagnosticPosition,
861 pub end: DiagnosticPosition,
862}
863
864#[derive(Debug, Clone, Serialize, Deserialize)]
865pub struct DiagnosticPosition {
866 pub line: u32,
867 pub character: u32,
868}
869
870#[derive(Debug, Clone, Serialize, Deserialize)]
875#[serde(rename_all = "camelCase")]
876pub struct ProgressEntry {
877 #[serde(flatten)]
878 pub envelope: Envelope,
879
880 pub data: ProgressData,
881
882 #[serde(rename = "parentToolUseID", skip_serializing_if = "Option::is_none")]
883 pub parent_tool_use_id: Option<String>,
884
885 #[serde(rename = "toolUseID", skip_serializing_if = "Option::is_none")]
886 pub tool_use_id: Option<String>,
887}
888
889#[derive(Debug, Clone, Serialize, Deserialize)]
890#[serde(rename_all = "camelCase")]
891pub struct ProgressData {
892 #[serde(rename = "type")]
893 pub data_type: String,
894 #[serde(rename = "hookEvent", skip_serializing_if = "Option::is_none")]
895 pub hook_event: Option<String>,
896 #[serde(rename = "hookName", skip_serializing_if = "Option::is_none")]
897 pub hook_name: Option<String>,
898 #[serde(skip_serializing_if = "Option::is_none")]
899 pub command: Option<String>,
900 #[serde(rename = "agentId", skip_serializing_if = "Option::is_none")]
902 pub agent_id: Option<String>,
903 #[serde(skip_serializing_if = "Option::is_none")]
904 pub prompt: Option<String>,
905 #[serde(skip_serializing_if = "Option::is_none")]
906 pub message: Option<Value>,
907 #[serde(skip_serializing_if = "Option::is_none")]
909 pub query: Option<String>,
910 #[serde(rename = "resultCount", skip_serializing_if = "Option::is_none")]
911 pub result_count: Option<u32>,
912 #[serde(rename = "elapsedTimeSeconds", skip_serializing_if = "Option::is_none")]
914 pub elapsed_time_seconds: Option<f64>,
915 #[serde(rename = "fullOutput", skip_serializing_if = "Option::is_none")]
916 pub full_output: Option<String>,
917 #[serde(rename = "output", skip_serializing_if = "Option::is_none")]
918 pub output: Option<String>,
919 #[serde(rename = "timeoutMs", skip_serializing_if = "Option::is_none")]
920 pub timeout_ms: Option<u64>,
921 #[serde(rename = "totalLines", skip_serializing_if = "Option::is_none")]
922 pub total_lines: Option<u64>,
923 #[serde(rename = "totalBytes", skip_serializing_if = "Option::is_none")]
924 pub total_bytes: Option<u64>,
925 #[serde(rename = "taskId", skip_serializing_if = "Option::is_none")]
926 pub task_id: Option<String>,
927 #[serde(rename = "serverName", skip_serializing_if = "Option::is_none")]
929 pub server_name: Option<String>,
930 #[serde(rename = "status", skip_serializing_if = "Option::is_none")]
931 pub status: Option<String>,
932 #[serde(rename = "toolName", skip_serializing_if = "Option::is_none")]
933 pub tool_name: Option<String>,
934 #[serde(rename = "elapsedTimeMs", skip_serializing_if = "Option::is_none")]
935 pub elapsed_time_ms: Option<f64>,
936 #[serde(rename = "taskDescription", skip_serializing_if = "Option::is_none")]
938 pub task_description: Option<String>,
939 #[serde(rename = "taskType", skip_serializing_if = "Option::is_none")]
940 pub task_type: Option<String>,
941}
942
943#[derive(Debug, Clone, Serialize, Deserialize)]
948#[serde(rename_all = "camelCase")]
949pub struct PermissionModeEntry {
950 pub permission_mode: String,
951 pub session_id: String,
952}
953
954#[derive(Debug, Clone, Serialize, Deserialize)]
955#[serde(rename_all = "camelCase")]
956pub struct LastPromptEntry {
957 pub last_prompt: String,
958 pub session_id: String,
959}
960
961#[derive(Debug, Clone, Serialize, Deserialize)]
962#[serde(rename_all = "camelCase")]
963pub struct AiTitleEntry {
964 pub ai_title: String,
965 pub session_id: String,
966}
967
968#[derive(Debug, Clone, Serialize, Deserialize)]
969#[serde(rename_all = "camelCase")]
970pub struct CustomTitleEntry {
971 pub custom_title: String,
972 pub session_id: String,
973}
974
975#[derive(Debug, Clone, Serialize, Deserialize)]
976#[serde(rename_all = "camelCase")]
977pub struct AgentNameEntry {
978 pub agent_name: String,
979 pub session_id: String,
980}
981
982#[derive(Debug, Clone, Serialize, Deserialize)]
983#[serde(rename_all = "camelCase")]
984pub struct AgentColorEntry {
985 pub agent_color: String,
986 pub session_id: String,
987}
988
989#[derive(Debug, Clone, Serialize, Deserialize)]
990#[serde(rename_all = "camelCase")]
991pub struct AgentSettingEntry {
992 pub agent_setting: String,
993 pub session_id: String,
994}
995
996#[derive(Debug, Clone, Serialize, Deserialize)]
997#[serde(rename_all = "camelCase")]
998pub struct TagEntry {
999 pub tag: String,
1000 pub session_id: String,
1001}
1002
1003#[derive(Debug, Clone, Serialize, Deserialize)]
1004#[serde(rename_all = "camelCase")]
1005pub struct SummaryEntry {
1006 pub leaf_uuid: String,
1007 pub summary: String,
1008 pub session_id: String,
1009}
1010
1011#[derive(Debug, Clone, Serialize, Deserialize)]
1012#[serde(rename_all = "camelCase")]
1013pub struct TaskSummaryEntry {
1014 pub summary: String,
1015 pub session_id: String,
1016 pub timestamp: String,
1017}
1018
1019#[derive(Debug, Clone, Serialize, Deserialize)]
1020#[serde(rename_all = "camelCase")]
1021pub struct PrLinkEntry {
1022 pub session_id: String,
1023 pub pr_number: u32,
1024 pub pr_url: String,
1025 pub pr_repository: String,
1026 pub timestamp: String,
1027}
1028
1029#[derive(Debug, Clone, Serialize, Deserialize)]
1030#[serde(rename_all = "camelCase")]
1031pub struct ModeEntry {
1032 pub mode: SessionMode,
1033 pub session_id: String,
1034}
1035
1036#[derive(Debug, Clone, Serialize, Deserialize)]
1037#[serde(rename_all = "lowercase")]
1038pub enum SessionMode {
1039 Coordinator,
1040 Normal,
1041}
1042
1043#[derive(Debug, Clone, Serialize, Deserialize)]
1045#[serde(rename_all = "camelCase")]
1046pub struct WorktreeStateEntry {
1047 pub session_id: String,
1048 pub worktree_session: Option<PersistedWorktreeSession>,
1050}
1051
1052#[derive(Debug, Clone, Serialize, Deserialize)]
1053#[serde(rename_all = "camelCase")]
1054pub struct PersistedWorktreeSession {
1055 pub original_cwd: String,
1056 pub worktree_path: String,
1057 pub worktree_name: String,
1058 pub session_id: String,
1059
1060 #[serde(skip_serializing_if = "Option::is_none")]
1061 pub worktree_branch: Option<String>,
1062
1063 #[serde(skip_serializing_if = "Option::is_none")]
1064 pub original_branch: Option<String>,
1065
1066 #[serde(skip_serializing_if = "Option::is_none")]
1067 pub original_head_commit: Option<String>,
1068
1069 #[serde(rename = "tmuxSessionName", skip_serializing_if = "Option::is_none")]
1070 pub tmux_session_name: Option<String>,
1071
1072 #[serde(skip_serializing_if = "Option::is_none")]
1073 pub hook_based: Option<bool>,
1074}
1075
1076#[derive(Debug, Clone, Serialize, Deserialize)]
1077#[serde(rename_all = "camelCase")]
1078pub struct ContentReplacementEntry {
1079 pub session_id: String,
1080 pub replacements: Vec<Value>,
1081 #[serde(skip_serializing_if = "Option::is_none")]
1082 pub agent_id: Option<String>,
1083}
1084
1085#[derive(Debug, Clone, Serialize, Deserialize)]
1086#[serde(rename_all = "camelCase")]
1087pub struct FileHistorySnapshotEntry {
1088 pub message_id: String,
1089 pub snapshot: FileHistorySnapshot,
1090 pub is_snapshot_update: bool,
1091}
1092
1093#[derive(Debug, Clone, Serialize, Deserialize)]
1094#[serde(rename_all = "camelCase")]
1095pub struct FileHistorySnapshot {
1096 pub message_id: String,
1097 pub tracked_file_backups: Value,
1098 pub timestamp: String,
1099}
1100
1101#[derive(Debug, Clone, Serialize, Deserialize)]
1102#[serde(rename_all = "camelCase")]
1103pub struct AttributionSnapshotEntry {
1104 pub message_id: String,
1105 pub surface: String,
1106 pub file_states: Value,
1107
1108 #[serde(skip_serializing_if = "Option::is_none")]
1109 pub prompt_count: Option<u32>,
1110
1111 #[serde(skip_serializing_if = "Option::is_none")]
1112 pub prompt_count_at_last_commit: Option<u32>,
1113
1114 #[serde(skip_serializing_if = "Option::is_none")]
1115 pub permission_prompt_count: Option<u32>,
1116
1117 #[serde(skip_serializing_if = "Option::is_none")]
1118 pub permission_prompt_count_at_last_commit: Option<u32>,
1119
1120 #[serde(skip_serializing_if = "Option::is_none")]
1121 pub escape_count: Option<u32>,
1122
1123 #[serde(skip_serializing_if = "Option::is_none")]
1124 pub escape_count_at_last_commit: Option<u32>,
1125}
1126
1127#[derive(Debug, Clone, Serialize, Deserialize)]
1128#[serde(rename_all = "camelCase")]
1129pub struct QueueOperationEntry {
1130 pub operation: String,
1131 pub timestamp: String,
1132 pub session_id: String,
1133 #[serde(skip_serializing_if = "Option::is_none")]
1134 pub content: Option<String>,
1135}
1136
1137#[derive(Debug, Clone, Serialize, Deserialize)]
1142#[serde(rename_all = "camelCase")]
1143pub struct ContextCollapseCommitEntry {
1144 pub session_id: String,
1145 pub collapse_id: String,
1146 pub summary_uuid: String,
1147 pub summary_content: String,
1148 pub summary: String,
1149 pub first_archived_uuid: String,
1150 pub last_archived_uuid: String,
1151}
1152
1153#[derive(Debug, Clone, Serialize, Deserialize)]
1154#[serde(rename_all = "camelCase")]
1155pub struct ContextCollapseSnapshotEntry {
1156 pub session_id: String,
1157 pub staged: Vec<StagedSpan>,
1158 pub armed: bool,
1159 pub last_spawn_tokens: u64,
1160}
1161
1162#[derive(Debug, Clone, Serialize, Deserialize)]
1163#[serde(rename_all = "camelCase")]
1164pub struct StagedSpan {
1165 pub start_uuid: String,
1166 pub end_uuid: String,
1167 pub summary: String,
1168 pub risk: f64,
1169 pub staged_at: u64,
1170}
1171
1172#[derive(Debug, Clone, Serialize, Deserialize)]
1173#[serde(rename_all = "camelCase")]
1174pub struct SpeculationAcceptEntry {
1175 pub timestamp: String,
1176 pub time_saved_ms: u64,
1177}
1178
1179mod opt_nullable {
1192 use serde::{Deserialize, Deserializer, Serialize, Serializer};
1193 use serde_json::Value;
1194
1195 pub fn serialize<S>(val: &Option<Option<Value>>, ser: S) -> Result<S::Ok, S::Error>
1196 where
1197 S: Serializer,
1198 {
1199 match val {
1200 None => unreachable!("skip_serializing_if = \"Option::is_none\" should prevent this"),
1201 Some(inner) => inner.serialize(ser),
1202 }
1203 }
1204
1205 pub fn deserialize<'de, D>(de: D) -> Result<Option<Option<Value>>, D::Error>
1206 where
1207 D: Deserializer<'de>,
1208 {
1209 Ok(Some(Option::<Value>::deserialize(de)?))
1210 }
1211}