1use serde::{Deserialize, Serialize};
2use time::OffsetDateTime;
3
4use crate::artifacts::{ContextArtifact, ContextArtifactId};
5use crate::automations::{
6 AutomationCompleted, AutomationCreated, AutomationDeleted, AutomationDue, AutomationFailed,
7 AutomationLeaseExpired, AutomationLeased, AutomationQueued, AutomationSkipped,
8 AutomationStarted, AutomationUpdated,
9};
10use crate::code_index::{
11 CodeIndexChunked, CodeIndexEmbedded, CodeIndexFailed, CodeIndexProofFilteredResultDropped,
12 CodeIndexReady, CodeIndexStale, CodeIndexingStarted,
13};
14use crate::discovery::{
15 DiscoveryAuthRequired, DiscoveryCatalogBuilt, DiscoveryItemPromoted, DiscoveryItemRead,
16 DiscoveryItemUpdated, DiscoveryPromotionExpired, DiscoveryPromotionReused,
17 DiscoveryWarmCacheHit,
18};
19use crate::dynamic_workflows::{
20 WorkflowAgentCompleted, WorkflowAgentFailed, WorkflowAgentQueued, WorkflowAgentStarted,
21 WorkflowApprovalRequested, WorkflowCheckpointRecorded, WorkflowOutputRecorded,
22 WorkflowPhaseCompleted, WorkflowPhaseStarted, WorkflowRunApproved, WorkflowRunCompleted,
23 WorkflowRunDenied, WorkflowRunDrafted, WorkflowRunFailed, WorkflowRunPaused, WorkflowRunQueued,
24 WorkflowRunResumed, WorkflowRunStarted, WorkflowRunStopped,
25};
26use crate::extension::{ExtensionId, InferenceEngineId};
27use crate::goals::{ThreadGoalCleared, ThreadGoalUpdated};
28use crate::inference::{
29 InferenceEvent, ModelSelection, ReasoningConfig, RuntimeProfile, SpeedPolicyDecision,
30 TokenUsage,
31};
32use crate::inference_routing::InferenceRoutingDecision;
33use crate::knowledge::{KnowledgeDocId, KnowledgeDocSummary, KnowledgeLinkType};
34use crate::lifecycle::TurnLifecycleRecord;
35use crate::media::{MediaArtifact, MediaArtifactId, MediaPreview};
36use crate::memory::{MemoryCitation, MemoryId, MemoryProviderSelection, MemoryRecord, MemoryScope};
37use crate::plan_review::{
38 HunkId, HunkRecord, PlanComment, PlanReview, PlanReviewId, PlanReviewStatus, PlanRewrite,
39};
40use crate::processes::{
41 ProcessExited, ProcessFailed, ProcessOutput, ProcessStarted, ProcessStopped, ProcessStopping,
42};
43use crate::reliability::{
44 ReliabilityFailureRecorded, ReliabilityLimitRecorded, ReliabilityMetricRecorded,
45 ReliabilityRetryRecorded,
46};
47use crate::retrieval::{
48 RetrievalDiscoveryItemPromoted, RetrievalPromotionSkipped, RetrievalResultUsed,
49 RetrievalRouteAccepted, RetrievalRouteFailed, RetrievalRouteIgnored, RetrievalRoutePlanned,
50};
51use crate::review::{ReviewId, ReviewOutput, ReviewPublishSkip, ReviewPublisherId, ReviewTarget};
52use crate::skills::{
53 SkillActivationResolved, SkillAutoActivated, SkillConfigApplied, SkillIndexRendered,
54 SkillInvoked, SkillSkipped, SkillsCatalogLoaded,
55};
56use crate::subagents::{
57 AgentSwarmCompleted, AgentSwarmModeChanged, AgentSwarmProgress, AgentSwarmStarted,
58 SubagentExitReason, UltraModeChanged,
59};
60use crate::task_ledger::TaskLedgerItem;
61use crate::teams::{
62 AgentTeamDisplayMode, TeamId, TeamMemberDescriptor, TeamMemberId, TeamMemberStatus,
63 TeamTaskDescriptor,
64};
65use crate::trace::{
66 ParentTurnRef, SubagentTraceDelta, SubagentTraceId, SubagentTraceStatus, SubagentTraceSummary,
67};
68use crate::transcript::TranscriptItem;
69use crate::workflow::{WorkflowImportDecision, WorkflowImportError, WorkflowImportItem};
70use crate::workspace_changes::WorkspaceChangeObservation;
71
72pub use crate::policy_mode::{
73 PolicyBypassActive, PolicyDecisionRecorded, PolicyExitPlanRequested, PolicyExitPlanResolved,
74 PolicyModeChanged,
75};
76pub use crate::tasks::{TaskCancelled, TaskCompleted, TaskFailed, TaskOutput, TaskStarted};
77
78pub type ThreadId = String;
79pub type TurnId = String;
80pub type EventId = String;
81
82#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
83pub enum EventSource {
84 Runtime,
85 Core,
86 Provider,
87 Tool,
88 AppServer,
89 Tui,
90 Extension,
91 System,
92}
93
94#[derive(Debug, Clone, Serialize, Deserialize)]
95pub struct RuntimeStarted {
96 #[serde(with = "time::serde::rfc3339")]
97 pub timestamp: OffsetDateTime,
98}
99
100#[derive(Debug, Clone, Serialize, Deserialize)]
102pub struct HookRunRecorded {
103 pub thread_id: ThreadId,
104 pub turn_id: TurnId,
105 pub tool_id: String,
106 pub tool_name: String,
107 pub hook_event_name: String,
108 pub handler_type: String,
109 pub status: String,
110 pub detail: String,
111 #[serde(default, skip_serializing_if = "Option::is_none")]
112 pub output: Option<String>,
113 #[serde(with = "time::serde::rfc3339")]
114 pub timestamp: OffsetDateTime,
115}
116
117#[derive(Debug, Clone, Serialize, Deserialize)]
118pub struct ExtensionRegistered {
119 pub extension_id: ExtensionId,
120 #[serde(with = "time::serde::rfc3339")]
121 pub timestamp: OffsetDateTime,
122}
123
124#[derive(Debug, Clone, Serialize, Deserialize)]
125pub struct ThreadCreated {
126 pub thread_id: ThreadId,
127 #[serde(with = "time::serde::rfc3339")]
128 pub timestamp: OffsetDateTime,
129}
130
131#[derive(Debug, Clone, Serialize, Deserialize)]
133pub struct ThreadForkRequested {
134 pub parent_thread_id: ThreadId,
135 pub name: String,
136 #[serde(with = "time::serde::rfc3339")]
137 pub timestamp: OffsetDateTime,
138}
139
140#[derive(Debug, Clone, Serialize, Deserialize)]
142pub struct ThreadForked {
143 pub parent_thread_id: ThreadId,
144 pub child_thread_id: ThreadId,
145 pub fork: crate::forks::WorkspaceFork,
146 #[serde(with = "time::serde::rfc3339")]
147 pub timestamp: OffsetDateTime,
148}
149
150#[derive(Debug, Clone, Serialize, Deserialize)]
152pub struct ThreadForkFailed {
153 pub parent_thread_id: ThreadId,
154 pub name: String,
155 pub message: String,
156 #[serde(with = "time::serde::rfc3339")]
157 pub timestamp: OffsetDateTime,
158}
159
160#[derive(Debug, Clone, Serialize, Deserialize)]
162pub struct ThreadForkRemoved {
163 pub thread_id: ThreadId,
164 pub fork_id: String,
165 pub worktree_path: String,
166 #[serde(with = "time::serde::rfc3339")]
167 pub timestamp: OffsetDateTime,
168}
169
170#[derive(Debug, Clone, Serialize, Deserialize)]
174pub struct ExtensionEventEmitted {
175 pub extension_id: String,
176 pub event_kind: String,
177 pub schema_version: u32,
178 pub payload: serde_json::Value,
179 #[serde(with = "time::serde::rfc3339")]
180 pub timestamp: OffsetDateTime,
181}
182
183#[derive(Debug, Clone, Serialize, Deserialize)]
187pub struct EventSinkFailed {
188 pub sink_id: String,
189 pub event_kind: String,
190 pub message: String,
191 #[serde(with = "time::serde::rfc3339")]
192 pub timestamp: OffsetDateTime,
193}
194
195#[derive(Debug, Clone, Serialize, Deserialize)]
196pub struct ThreadLoaded {
197 pub thread_id: ThreadId,
198 #[serde(with = "time::serde::rfc3339")]
199 pub timestamp: OffsetDateTime,
200}
201
202#[derive(Debug, Clone, Serialize, Deserialize)]
203pub struct TurnStarted {
204 pub thread_id: ThreadId,
205 pub turn_id: TurnId,
206 #[serde(default)]
207 pub runtime_profile: RuntimeProfile,
208 #[serde(with = "time::serde::rfc3339")]
209 pub timestamp: OffsetDateTime,
210}
211
212#[derive(Debug, Clone, Serialize, Deserialize)]
213pub struct ContextAssemblyStarted {
214 pub thread_id: ThreadId,
215 pub turn_id: TurnId,
216 #[serde(with = "time::serde::rfc3339")]
217 pub timestamp: OffsetDateTime,
218}
219
220#[derive(Debug, Clone, Serialize, Deserialize)]
221pub struct ContextBlockAdded {
222 pub thread_id: ThreadId,
223 pub turn_id: TurnId,
224 pub block_type: String,
225 #[serde(default)]
226 pub byte_count: u64,
227 #[serde(default)]
228 pub estimated_tokens: u32,
229 #[serde(default)]
230 pub priority: i32,
231 #[serde(with = "time::serde::rfc3339")]
232 pub timestamp: OffsetDateTime,
233}
234
235#[derive(Debug, Clone, Serialize, Deserialize)]
236pub struct ContextAssemblyCompleted {
237 pub thread_id: ThreadId,
238 pub turn_id: TurnId,
239 #[serde(default)]
240 pub block_count: u64,
241 #[serde(default)]
242 pub total_byte_count: u64,
243 #[serde(default)]
244 pub estimated_tokens: u32,
245 #[serde(default)]
246 pub prompt_estimated_tokens: u32,
247 #[serde(default, skip_serializing_if = "Option::is_none")]
248 pub token_budget: Option<u32>,
249 #[serde(with = "time::serde::rfc3339")]
250 pub timestamp: OffsetDateTime,
251}
252
253#[derive(Debug, Clone, Serialize, Deserialize)]
254pub struct ContextEntrypointCandidatesInjected {
255 pub thread_id: ThreadId,
256 pub turn_id: TurnId,
257 pub candidate_count: u64,
258 pub block_byte_count: u64,
259 pub estimated_tokens: u32,
260 #[serde(with = "time::serde::rfc3339")]
261 pub timestamp: OffsetDateTime,
262}
263
264#[derive(Debug, Clone, Serialize, Deserialize)]
265pub struct ContextCompactionStarted {
266 pub thread_id: ThreadId,
267 pub turn_id: TurnId,
268 pub original_item_count: u64,
269 pub original_estimated_tokens: u32,
270 #[serde(with = "time::serde::rfc3339")]
271 pub timestamp: OffsetDateTime,
272}
273
274#[derive(Debug, Clone, Serialize, Deserialize)]
275pub struct ContextCompactionRecorded {
276 pub thread_id: ThreadId,
277 pub turn_id: TurnId,
278 pub original_item_count: u64,
279 pub original_estimated_tokens: u32,
280 pub compacted_item_count: u64,
281 pub compacted_estimated_tokens: u32,
282 pub file_backed: bool,
283 #[serde(default, skip_serializing_if = "Option::is_none")]
284 pub strategy: Option<String>,
285 #[serde(default, skip_serializing_if = "Option::is_none")]
286 pub pruned_tool_count: Option<u32>,
287 #[serde(default, skip_serializing_if = "Option::is_none")]
289 pub duration_ms: Option<u64>,
290 #[serde(with = "time::serde::rfc3339")]
291 pub timestamp: OffsetDateTime,
292}
293
294#[derive(Debug, Clone, Serialize, Deserialize)]
295pub struct ContextCompactionSkipped {
296 pub thread_id: ThreadId,
297 pub turn_id: TurnId,
298 pub reason: String,
299 pub estimated_tokens: u32,
300 #[serde(default, skip_serializing_if = "Option::is_none")]
301 pub threshold: Option<u32>,
302 #[serde(default, skip_serializing_if = "Option::is_none")]
303 pub pruned_tool_count: Option<u32>,
304 #[serde(with = "time::serde::rfc3339")]
305 pub timestamp: OffsetDateTime,
306}
307
308#[derive(Debug, Clone, Serialize, Deserialize)]
309pub struct InferenceStarted {
310 pub thread_id: ThreadId,
311 pub turn_id: TurnId,
312 pub engine_id: InferenceEngineId,
313 #[serde(default = "default_model_selection")]
314 pub model: ModelSelection,
315 #[serde(default)]
316 pub reasoning: ReasoningConfig,
317 #[serde(default, skip_serializing_if = "Option::is_none")]
318 pub speed_policy: Option<SpeedPolicyDecision>,
319 #[serde(default, skip_serializing_if = "Option::is_none")]
320 pub deadline_remaining_seconds: Option<u64>,
321 #[serde(with = "time::serde::rfc3339")]
322 pub timestamp: OffsetDateTime,
323}
324
325fn default_model_selection() -> ModelSelection {
326 ModelSelection {
327 provider: String::new(),
328 model: String::new(),
329 }
330}
331
332#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
333pub struct InferenceRoutingDecisionEvent {
334 pub thread_id: ThreadId,
335 pub turn_id: TurnId,
336 #[serde(default)]
337 pub round_index: u32,
338 pub default_selection: ModelSelection,
339 pub selected_selection: ModelSelection,
340 pub decision: InferenceRoutingDecision,
341 #[serde(with = "time::serde::rfc3339")]
342 pub timestamp: OffsetDateTime,
343}
344
345#[derive(Debug, Clone, Serialize, Deserialize)]
346pub struct InferenceEventReceived {
347 pub thread_id: ThreadId,
348 pub turn_id: TurnId,
349 pub event: InferenceEvent,
350 #[serde(with = "time::serde::rfc3339")]
351 pub timestamp: OffsetDateTime,
352}
353
354#[derive(Debug, Clone, Serialize, Deserialize)]
355pub struct ToolCallRequested {
356 pub thread_id: ThreadId,
357 pub turn_id: TurnId,
358 pub tool_id: String,
359 pub tool_name: String,
360 #[serde(default, skip_serializing_if = "Option::is_none")]
361 pub display_payload: Option<serde_json::Value>,
362 #[serde(with = "time::serde::rfc3339")]
363 pub timestamp: OffsetDateTime,
364}
365
366#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
367#[serde(rename_all = "snake_case")]
368pub enum ToolCallValidationFailureClass {
369 InvalidJson,
370 UnknownTool,
371 MissingRequired,
372 UnexpectedProperty,
373 WrongType,
374 EmptyRequiredString,
375 SchemaRepairApplied,
376 SchemaRepairRejected,
377}
378
379#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
380#[serde(rename_all = "snake_case")]
381pub enum ToolCallValidationRepairStatus {
382 NotNeeded,
383 Applied,
384 Rejected,
385}
386
387#[derive(Debug, Clone, Serialize, Deserialize)]
388pub struct ToolCallValidationRecorded {
389 pub thread_id: ThreadId,
390 pub turn_id: TurnId,
391 pub tool_id: String,
392 pub tool_name: String,
393 pub failure_class: ToolCallValidationFailureClass,
394 pub repair_status: ToolCallValidationRepairStatus,
395 pub message: String,
396 #[serde(with = "time::serde::rfc3339")]
397 pub timestamp: OffsetDateTime,
398}
399
400#[derive(Debug, Clone, Serialize, Deserialize)]
401pub struct ApprovalRequested {
402 pub thread_id: ThreadId,
403 pub turn_id: TurnId,
404 pub approval_id: String,
405 pub tool_id: String,
406 pub tool_name: String,
407 pub reason: Option<String>,
408 #[serde(with = "time::serde::rfc3339")]
409 pub timestamp: OffsetDateTime,
410}
411
412#[derive(Debug, Clone, Serialize, Deserialize)]
413pub struct ApprovalResolved {
414 pub thread_id: ThreadId,
415 pub turn_id: TurnId,
416 pub approval_id: String,
417 pub tool_id: String,
418 pub tool_name: String,
419 pub approved: bool,
420 #[serde(with = "time::serde::rfc3339")]
421 pub timestamp: OffsetDateTime,
422}
423
424#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
425#[serde(rename_all = "camelCase")]
426pub enum ExternalToolCallOutcome {
427 Resolved,
428 TimedOut,
429 Cancelled,
430}
431
432#[derive(Debug, Clone, Serialize, Deserialize)]
433pub struct ExternalToolCallRequested {
434 pub thread_id: ThreadId,
435 pub turn_id: TurnId,
436 pub request_id: String,
437 pub tool_id: String,
438 pub tool_name: String,
439 pub arguments: serde_json::Value,
440 #[serde(with = "time::serde::rfc3339")]
441 pub timestamp: OffsetDateTime,
442}
443
444#[derive(Debug, Clone, Serialize, Deserialize)]
445pub struct ExternalToolCallResolved {
446 pub thread_id: ThreadId,
447 pub turn_id: TurnId,
448 pub request_id: String,
449 pub tool_id: String,
450 pub tool_name: String,
451 pub outcome: ExternalToolCallOutcome,
452 pub is_error: bool,
453 #[serde(with = "time::serde::rfc3339")]
454 pub timestamp: OffsetDateTime,
455}
456
457#[derive(Debug, Clone, Serialize, Deserialize)]
458pub struct UserInputRequested {
459 pub thread_id: ThreadId,
460 pub turn_id: TurnId,
461 pub request_id: String,
462 pub questions: serde_json::Value,
463 #[serde(with = "time::serde::rfc3339")]
464 pub timestamp: OffsetDateTime,
465}
466
467#[derive(Debug, Clone, Serialize, Deserialize)]
468pub struct UserInputResolved {
469 pub thread_id: ThreadId,
470 pub turn_id: TurnId,
471 pub request_id: String,
472 pub answers: serde_json::Value,
473 #[serde(with = "time::serde::rfc3339")]
474 pub timestamp: OffsetDateTime,
475}
476
477#[derive(Debug, Clone, Serialize, Deserialize)]
478pub struct TaskLedgerUpdated {
479 pub thread_id: ThreadId,
480 pub turn_id: TurnId,
481 pub tasks: Vec<TaskLedgerItem>,
482 pub completed_count: u64,
483 #[serde(with = "time::serde::rfc3339")]
484 pub timestamp: OffsetDateTime,
485}
486
487#[derive(Debug, Clone, Serialize, Deserialize)]
488pub struct VerificationRequired {
489 pub thread_id: ThreadId,
490 pub turn_id: TurnId,
491 pub reason: String,
492 pub changed_files: Vec<String>,
493 pub tool_evidence: Vec<String>,
494 pub tests_run: Vec<String>,
495 pub open_gaps: Vec<String>,
496 #[serde(with = "time::serde::rfc3339")]
497 pub timestamp: OffsetDateTime,
498}
499
500#[derive(Debug, Clone, Serialize, Deserialize)]
501pub struct VerificationCompleted {
502 pub thread_id: ThreadId,
503 pub turn_id: TurnId,
504 pub passed: bool,
505 pub changed_files: Vec<String>,
506 pub tool_evidence: Vec<String>,
507 pub tests_run: Vec<String>,
508 pub open_gaps: Vec<String>,
509 #[serde(with = "time::serde::rfc3339")]
510 pub timestamp: OffsetDateTime,
511}
512
513#[derive(Debug, Clone, Serialize, Deserialize)]
514pub struct VerificationSkipped {
515 pub thread_id: ThreadId,
516 pub turn_id: TurnId,
517 pub reason: String,
518 #[serde(with = "time::serde::rfc3339")]
519 pub timestamp: OffsetDateTime,
520}
521
522#[derive(Debug, Clone, Serialize, Deserialize)]
523pub struct ToolCallStarted {
524 pub thread_id: ThreadId,
525 pub turn_id: TurnId,
526 pub tool_id: String,
527 #[serde(default, skip_serializing_if = "Option::is_none")]
528 pub tool_name: Option<String>,
529 #[serde(default, skip_serializing_if = "Option::is_none")]
530 pub display_payload: Option<serde_json::Value>,
531 #[serde(with = "time::serde::rfc3339")]
532 pub timestamp: OffsetDateTime,
533}
534
535#[derive(Debug, Clone, Serialize, Deserialize)]
536pub struct ToolCallCompleted {
537 pub thread_id: ThreadId,
538 pub turn_id: TurnId,
539 pub tool_id: String,
540 #[serde(default, skip_serializing_if = "Option::is_none")]
541 pub tool_name: Option<String>,
542 #[serde(default, skip_serializing_if = "Option::is_none")]
543 pub display_payload: Option<serde_json::Value>,
544 #[serde(default)]
545 pub is_error: bool,
546 #[serde(default)]
547 pub output: Option<String>,
548 #[serde(with = "time::serde::rfc3339")]
549 pub timestamp: OffsetDateTime,
550}
551
552#[derive(Debug, Clone, Serialize, Deserialize)]
553pub struct ToolOutputDelta {
554 pub thread_id: ThreadId,
555 pub turn_id: TurnId,
556 pub tool_id: String,
557 pub delta: String,
558 #[serde(with = "time::serde::rfc3339")]
559 pub timestamp: OffsetDateTime,
560}
561
562#[derive(Debug, Clone, Serialize, Deserialize)]
563pub struct ToolOutputTruncated {
564 pub thread_id: ThreadId,
565 pub turn_id: TurnId,
566 pub tool_id: String,
567 #[serde(default, skip_serializing_if = "Option::is_none")]
568 pub tool_name: Option<String>,
569 pub original_line_count: u64,
570 pub original_char_count: u64,
571 pub inline_char_count: u64,
572 pub artifact_backed: bool,
573 #[serde(with = "time::serde::rfc3339")]
574 pub timestamp: OffsetDateTime,
575}
576
577#[derive(Debug, Clone, Serialize, Deserialize)]
578pub struct SubagentStarted {
579 pub thread_id: ThreadId,
580 pub turn_id: TurnId,
581 pub parent_thread_id: ThreadId,
582 pub parent_turn_id: TurnId,
583 pub agent_type: String,
584 pub description: String,
585 pub model: Option<String>,
586 #[serde(with = "time::serde::rfc3339")]
587 pub timestamp: OffsetDateTime,
588}
589
590#[derive(Debug, Clone, Serialize, Deserialize)]
591pub struct SubagentMessage {
592 pub thread_id: ThreadId,
593 pub turn_id: TurnId,
594 pub parent_thread_id: ThreadId,
595 pub parent_turn_id: TurnId,
596 pub agent_type: String,
597 pub text: String,
598 #[serde(with = "time::serde::rfc3339")]
599 pub timestamp: OffsetDateTime,
600}
601
602#[derive(Debug, Clone, Serialize, Deserialize)]
603pub struct SubagentToolCall {
604 pub thread_id: ThreadId,
605 pub turn_id: TurnId,
606 pub parent_thread_id: ThreadId,
607 pub parent_turn_id: TurnId,
608 pub agent_type: String,
609 pub tool_id: String,
610 pub tool_name: String,
611 #[serde(with = "time::serde::rfc3339")]
612 pub timestamp: OffsetDateTime,
613}
614
615#[derive(Debug, Clone, Serialize, Deserialize)]
616pub struct SubagentCompleted {
617 pub thread_id: ThreadId,
618 pub turn_id: TurnId,
619 pub parent_thread_id: ThreadId,
620 pub parent_turn_id: TurnId,
621 pub agent_type: String,
622 pub exit_reason: SubagentExitReason,
623 #[serde(with = "time::serde::rfc3339")]
624 pub timestamp: OffsetDateTime,
625}
626
627#[derive(Debug, Clone, Serialize, Deserialize)]
628pub struct SubagentFailed {
629 pub thread_id: ThreadId,
630 pub turn_id: TurnId,
631 pub parent_thread_id: ThreadId,
632 pub parent_turn_id: TurnId,
633 pub agent_type: String,
634 pub error: String,
635 #[serde(with = "time::serde::rfc3339")]
636 pub timestamp: OffsetDateTime,
637}
638
639#[derive(Debug, Clone, Serialize, Deserialize)]
640pub struct SubagentTraceCreated {
641 pub summary: SubagentTraceSummary,
642 #[serde(with = "time::serde::rfc3339")]
643 pub timestamp: OffsetDateTime,
644}
645
646#[derive(Debug, Clone, Serialize, Deserialize)]
647pub struct SubagentTraceDeltaEvent {
648 pub delta: SubagentTraceDelta,
649 #[serde(with = "time::serde::rfc3339")]
650 pub timestamp: OffsetDateTime,
651}
652
653#[derive(Debug, Clone, Serialize, Deserialize)]
654pub struct SubagentTraceStatusChanged {
655 pub trace_id: SubagentTraceId,
656 pub parent: ParentTurnRef,
657 pub status: SubagentTraceStatus,
658 #[serde(default, skip_serializing_if = "Option::is_none")]
659 pub detail: Option<String>,
660 #[serde(with = "time::serde::rfc3339")]
661 pub timestamp: OffsetDateTime,
662}
663
664#[derive(Debug, Clone, Serialize, Deserialize)]
665pub struct SubagentTraceCompleted {
666 pub summary: SubagentTraceSummary,
667 #[serde(with = "time::serde::rfc3339")]
668 pub timestamp: OffsetDateTime,
669}
670
671#[derive(Debug, Clone, Serialize, Deserialize)]
672pub struct SubagentTraceFailed {
673 pub summary: SubagentTraceSummary,
674 pub error: String,
675 #[serde(with = "time::serde::rfc3339")]
676 pub timestamp: OffsetDateTime,
677}
678
679#[derive(Debug, Clone, Serialize, Deserialize)]
680#[serde(rename_all = "camelCase")]
681pub struct PlanReviewCreated {
682 pub review: PlanReview,
683 #[serde(with = "time::serde::rfc3339")]
684 pub timestamp: OffsetDateTime,
685}
686
687#[derive(Debug, Clone, Serialize, Deserialize)]
688#[serde(rename_all = "camelCase")]
689pub struct PlanReviewStatusChanged {
690 pub thread_id: ThreadId,
691 pub turn_id: TurnId,
692 pub review_id: PlanReviewId,
693 pub status: PlanReviewStatus,
694 #[serde(default, skip_serializing_if = "Option::is_none")]
695 pub detail: Option<String>,
696 #[serde(with = "time::serde::rfc3339")]
697 pub timestamp: OffsetDateTime,
698}
699
700#[derive(Debug, Clone, Serialize, Deserialize)]
701#[serde(rename_all = "camelCase")]
702pub struct PlanReviewCommentAdded {
703 pub thread_id: ThreadId,
704 pub turn_id: TurnId,
705 pub review_id: PlanReviewId,
706 pub comment: PlanComment,
707 #[serde(with = "time::serde::rfc3339")]
708 pub timestamp: OffsetDateTime,
709}
710
711#[derive(Debug, Clone, Serialize, Deserialize)]
712#[serde(rename_all = "camelCase")]
713pub struct PlanReviewRewritten {
714 pub thread_id: ThreadId,
715 pub turn_id: TurnId,
716 pub review_id: PlanReviewId,
717 pub rewrite: PlanRewrite,
718 #[serde(with = "time::serde::rfc3339")]
719 pub timestamp: OffsetDateTime,
720}
721
722#[derive(Debug, Clone, Serialize, Deserialize)]
723#[serde(rename_all = "camelCase")]
724pub struct PlanReviewApproved {
725 pub thread_id: ThreadId,
726 pub turn_id: TurnId,
727 pub review_id: PlanReviewId,
728 #[serde(with = "time::serde::rfc3339")]
729 pub timestamp: OffsetDateTime,
730}
731
732#[derive(Debug, Clone, Serialize, Deserialize)]
733#[serde(rename_all = "camelCase")]
734pub struct PlanReviewRejected {
735 pub thread_id: ThreadId,
736 pub turn_id: TurnId,
737 pub review_id: PlanReviewId,
738 #[serde(default, skip_serializing_if = "Option::is_none")]
739 pub reason: Option<String>,
740 #[serde(with = "time::serde::rfc3339")]
741 pub timestamp: OffsetDateTime,
742}
743
744#[derive(Debug, Clone, Serialize, Deserialize)]
745#[serde(rename_all = "camelCase")]
746pub struct HunkRecorded {
747 pub hunk: HunkRecord,
748 #[serde(with = "time::serde::rfc3339")]
749 pub timestamp: OffsetDateTime,
750}
751
752#[derive(Debug, Clone, Serialize, Deserialize)]
753#[serde(rename_all = "camelCase")]
754pub struct WorkspaceChangeObserved {
755 pub change: WorkspaceChangeObservation,
756 #[serde(with = "time::serde::rfc3339")]
757 pub timestamp: OffsetDateTime,
758}
759
760#[derive(Debug, Clone, Serialize, Deserialize)]
761#[serde(rename_all = "camelCase")]
762pub struct HunkRollbackRequested {
763 pub thread_id: ThreadId,
764 pub turn_id: TurnId,
765 pub hunk_id: HunkId,
766 #[serde(with = "time::serde::rfc3339")]
767 pub timestamp: OffsetDateTime,
768}
769
770#[derive(Debug, Clone, Serialize, Deserialize)]
771#[serde(rename_all = "camelCase")]
772pub struct HunkRollbackCompleted {
773 pub thread_id: ThreadId,
774 pub turn_id: TurnId,
775 pub hunk_id: HunkId,
776 #[serde(default, skip_serializing_if = "Option::is_none")]
777 pub error: Option<String>,
778 #[serde(with = "time::serde::rfc3339")]
779 pub timestamp: OffsetDateTime,
780}
781
782#[derive(Debug, Clone, Serialize, Deserialize)]
783#[serde(rename_all = "camelCase")]
784pub struct WorkflowImportsDetected {
785 pub workspace: String,
786 pub items: Vec<WorkflowImportItem>,
787 #[serde(default, skip_serializing_if = "Vec::is_empty")]
788 pub errors: Vec<WorkflowImportError>,
789 #[serde(with = "time::serde::rfc3339")]
790 pub timestamp: OffsetDateTime,
791}
792
793#[derive(Debug, Clone, Serialize, Deserialize)]
794#[serde(rename_all = "camelCase")]
795pub struct WorkflowImportPreviewed {
796 pub item: WorkflowImportItem,
797 #[serde(with = "time::serde::rfc3339")]
798 pub timestamp: OffsetDateTime,
799}
800
801#[derive(Debug, Clone, Serialize, Deserialize)]
802#[serde(rename_all = "camelCase")]
803pub struct WorkflowImportEnabled {
804 pub item: WorkflowImportItem,
805 pub decision: WorkflowImportDecision,
806 #[serde(with = "time::serde::rfc3339")]
807 pub timestamp: OffsetDateTime,
808}
809
810#[derive(Debug, Clone, Serialize, Deserialize)]
811#[serde(rename_all = "camelCase")]
812pub struct WorkflowImportDisabled {
813 pub item_id: String,
814 pub decision: WorkflowImportDecision,
815 #[serde(with = "time::serde::rfc3339")]
816 pub timestamp: OffsetDateTime,
817}
818
819#[derive(Debug, Clone, Serialize, Deserialize)]
820#[serde(rename_all = "camelCase")]
821pub struct WorkflowImportStale {
822 pub item: WorkflowImportItem,
823 pub previous_hash: String,
824 #[serde(with = "time::serde::rfc3339")]
825 pub timestamp: OffsetDateTime,
826}
827
828#[derive(Debug, Clone, Serialize, Deserialize)]
829#[serde(rename_all = "camelCase")]
830pub struct WorkflowImportFailed {
831 pub item_id: Option<String>,
832 pub error: WorkflowImportError,
833 #[serde(with = "time::serde::rfc3339")]
834 pub timestamp: OffsetDateTime,
835}
836
837#[derive(Debug, Clone, Serialize, Deserialize)]
838#[serde(rename_all = "camelCase")]
839pub struct MediaArtifactCreated {
840 pub thread_id: ThreadId,
841 pub turn_id: TurnId,
842 pub artifact: MediaArtifact,
843 #[serde(with = "time::serde::rfc3339")]
844 pub timestamp: OffsetDateTime,
845}
846
847#[derive(Debug, Clone, Serialize, Deserialize)]
848#[serde(rename_all = "camelCase")]
849pub struct MediaArtifactUpdated {
850 pub thread_id: ThreadId,
851 pub turn_id: TurnId,
852 pub artifact: MediaArtifact,
853 #[serde(with = "time::serde::rfc3339")]
854 pub timestamp: OffsetDateTime,
855}
856
857#[derive(Debug, Clone, Serialize, Deserialize)]
858#[serde(rename_all = "camelCase")]
859pub struct MediaArtifactDeleted {
860 pub artifact_id: MediaArtifactId,
861 #[serde(with = "time::serde::rfc3339")]
862 pub timestamp: OffsetDateTime,
863}
864
865#[derive(Debug, Clone, Serialize, Deserialize)]
866#[serde(rename_all = "camelCase")]
867pub struct MediaPreviewReady {
868 pub thread_id: ThreadId,
869 pub turn_id: TurnId,
870 pub preview: MediaPreview,
871 #[serde(with = "time::serde::rfc3339")]
872 pub timestamp: OffsetDateTime,
873}
874
875#[derive(Debug, Clone, Serialize, Deserialize)]
876#[serde(rename_all = "camelCase")]
877pub struct ContextArtifactCreated {
878 pub thread_id: ThreadId,
879 pub turn_id: TurnId,
880 pub artifact: ContextArtifact,
881 #[serde(with = "time::serde::rfc3339")]
882 pub timestamp: OffsetDateTime,
883}
884
885#[derive(Debug, Clone, Serialize, Deserialize)]
886#[serde(rename_all = "camelCase")]
887pub struct ContextArtifactAppended {
888 pub thread_id: ThreadId,
889 pub turn_id: TurnId,
890 pub artifact_id: ContextArtifactId,
891 pub appended_bytes: u64,
892 pub byte_count: u64,
893 pub line_count: u64,
894 #[serde(with = "time::serde::rfc3339")]
895 pub timestamp: OffsetDateTime,
896}
897
898#[derive(Debug, Clone, Serialize, Deserialize)]
899#[serde(rename_all = "camelCase")]
900pub struct ContextArtifactCapped {
901 pub thread_id: ThreadId,
902 pub turn_id: TurnId,
903 pub artifact_id: ContextArtifactId,
904 pub inline_byte_count: u64,
905 pub original_byte_count: u64,
906 #[serde(with = "time::serde::rfc3339")]
907 pub timestamp: OffsetDateTime,
908}
909
910#[derive(Debug, Clone, Serialize, Deserialize)]
911#[serde(rename_all = "camelCase")]
912pub struct ContextArtifactDeleted {
913 pub thread_id: ThreadId,
914 pub artifact_id: ContextArtifactId,
915 #[serde(with = "time::serde::rfc3339")]
916 pub timestamp: OffsetDateTime,
917}
918
919#[derive(Debug, Clone, Serialize, Deserialize)]
920#[serde(rename_all = "camelCase")]
921pub struct ContextArtifactRetentionExpired {
922 pub thread_id: ThreadId,
923 pub artifact_id: ContextArtifactId,
924 #[serde(with = "time::serde::rfc3339")]
925 pub timestamp: OffsetDateTime,
926}
927
928#[derive(Debug, Clone, Serialize, Deserialize)]
929pub struct FileChanged {
930 pub thread_id: ThreadId,
931 pub turn_id: TurnId,
932 pub path: String,
933 pub change_type: String,
934 #[serde(with = "time::serde::rfc3339")]
935 pub timestamp: OffsetDateTime,
936}
937
938#[derive(Debug, Clone, Serialize, Deserialize)]
939pub struct FileChangePreviewReady {
940 pub thread_id: ThreadId,
941 pub turn_id: TurnId,
942 pub tool_id: String,
943 pub tool_name: String,
944 pub path: String,
945 pub change_type: String,
946 pub before: Option<String>,
947 pub after: String,
948 pub supports_partial: bool,
949 #[serde(with = "time::serde::rfc3339")]
950 pub timestamp: OffsetDateTime,
951}
952
953#[derive(Debug, Clone, Serialize, Deserialize)]
954pub struct TranscriptItemAppended {
955 pub thread_id: ThreadId,
956 pub turn_id: TurnId,
957 pub item_type: String,
958 #[serde(default, skip_serializing_if = "Option::is_none")]
959 pub item_index: Option<usize>,
960 #[serde(default, skip_serializing_if = "Option::is_none")]
963 pub item: Option<TranscriptItem>,
964 #[serde(with = "time::serde::rfc3339")]
965 pub timestamp: OffsetDateTime,
966}
967
968#[derive(Debug, Clone, Serialize, Deserialize)]
969pub struct TurnCompleted {
970 pub thread_id: ThreadId,
971 pub turn_id: TurnId,
972 #[serde(default, skip_serializing_if = "Option::is_none")]
973 pub usage: Option<TokenUsage>,
974 #[serde(default, skip_serializing_if = "Option::is_none")]
979 pub finish_reason: Option<String>,
980 #[serde(with = "time::serde::rfc3339")]
981 pub timestamp: OffsetDateTime,
982}
983
984#[derive(Debug, Clone, Serialize, Deserialize)]
985pub struct TurnFailed {
986 pub thread_id: ThreadId,
987 pub turn_id: TurnId,
988 pub error: String,
989 #[serde(default, skip_serializing_if = "Option::is_none")]
990 pub error_kind: Option<String>,
991 #[serde(default, skip_serializing_if = "Option::is_none")]
992 pub usage: Option<TokenUsage>,
993 #[serde(with = "time::serde::rfc3339")]
994 pub timestamp: OffsetDateTime,
995}
996
997#[derive(Debug, Clone, Serialize, Deserialize)]
998pub struct TurnPartialResult {
999 pub thread_id: ThreadId,
1000 pub turn_id: TurnId,
1001 pub summary: String,
1002 #[serde(with = "time::serde::rfc3339")]
1003 pub timestamp: OffsetDateTime,
1004}
1005
1006#[derive(Debug, Clone, Serialize, Deserialize)]
1007pub struct TurnDeadlineExceeded {
1008 pub thread_id: ThreadId,
1009 pub turn_id: TurnId,
1010 #[serde(with = "time::serde::rfc3339")]
1011 pub deadline: OffsetDateTime,
1012 pub partial_result: String,
1013 #[serde(with = "time::serde::rfc3339")]
1014 pub timestamp: OffsetDateTime,
1015}
1016
1017#[derive(Debug, Clone, Serialize, Deserialize)]
1018pub struct TurnInterrupted {
1019 pub thread_id: ThreadId,
1020 pub turn_id: TurnId,
1021 #[serde(default, skip_serializing_if = "Option::is_none")]
1023 pub usage: Option<TokenUsage>,
1024 #[serde(with = "time::serde::rfc3339")]
1025 pub timestamp: OffsetDateTime,
1026}
1027
1028#[derive(Debug, Clone, Serialize, Deserialize)]
1029pub struct TurnSteered {
1030 pub thread_id: ThreadId,
1031 pub turn_id: TurnId,
1032 pub message: String,
1033 #[serde(with = "time::serde::rfc3339")]
1034 pub timestamp: OffsetDateTime,
1035}
1036
1037#[derive(Debug, Clone, Serialize, Deserialize)]
1038pub struct RunnerLifecycle {
1039 pub destination_id: String,
1040 pub provider_id: String,
1041 pub state: String,
1042 #[serde(default, skip_serializing_if = "Option::is_none")]
1043 pub session_id: Option<String>,
1044 #[serde(with = "time::serde::rfc3339")]
1045 pub timestamp: OffsetDateTime,
1046}
1047
1048#[derive(Debug, Clone, Serialize, Deserialize)]
1049pub struct TeamStarted {
1050 pub team_id: TeamId,
1051 pub lead_thread_id: ThreadId,
1052 pub display_mode: AgentTeamDisplayMode,
1053 pub members: Vec<TeamMemberDescriptor>,
1054 pub tasks: Vec<TeamTaskDescriptor>,
1055 #[serde(with = "time::serde::rfc3339")]
1056 pub timestamp: OffsetDateTime,
1057}
1058
1059#[derive(Debug, Clone, Serialize, Deserialize)]
1060pub struct TeamMemberStarted {
1061 pub team_id: TeamId,
1062 pub member: TeamMemberDescriptor,
1063 #[serde(with = "time::serde::rfc3339")]
1064 pub timestamp: OffsetDateTime,
1065}
1066
1067#[derive(Debug, Clone, Serialize, Deserialize)]
1068pub struct TeamMemberStatusChanged {
1069 pub team_id: TeamId,
1070 pub member_id: TeamMemberId,
1071 pub member_thread_id: ThreadId,
1072 pub status: TeamMemberStatus,
1073 #[serde(with = "time::serde::rfc3339")]
1074 pub timestamp: OffsetDateTime,
1075}
1076
1077#[derive(Debug, Clone, Serialize, Deserialize)]
1078pub struct TeamMemberMessageDelta {
1079 pub team_id: TeamId,
1080 pub member_id: TeamMemberId,
1081 pub member_thread_id: ThreadId,
1082 pub turn_id: TurnId,
1083 pub delta: String,
1084 #[serde(with = "time::serde::rfc3339")]
1085 pub timestamp: OffsetDateTime,
1086}
1087
1088#[derive(Debug, Clone, Serialize, Deserialize)]
1089pub struct TeamMemberCompleted {
1090 pub team_id: TeamId,
1091 pub member_id: TeamMemberId,
1092 pub member_thread_id: ThreadId,
1093 pub turn_id: Option<TurnId>,
1094 pub status: TeamMemberStatus,
1095 #[serde(default, skip_serializing_if = "Option::is_none")]
1096 pub final_message: Option<String>,
1097 #[serde(default, skip_serializing_if = "Option::is_none")]
1098 pub error: Option<String>,
1099 #[serde(with = "time::serde::rfc3339")]
1100 pub timestamp: OffsetDateTime,
1101}
1102
1103#[derive(Debug, Clone, Serialize, Deserialize)]
1104pub struct TeamDisplayModeChanged {
1105 pub team_id: TeamId,
1106 pub display_mode: AgentTeamDisplayMode,
1107 #[serde(with = "time::serde::rfc3339")]
1108 pub timestamp: OffsetDateTime,
1109}
1110
1111#[derive(Debug, Clone, Serialize, Deserialize)]
1112pub struct TeamTaskChanged {
1113 pub team_id: TeamId,
1114 pub task: TeamTaskDescriptor,
1115 #[serde(with = "time::serde::rfc3339")]
1116 pub timestamp: OffsetDateTime,
1117}
1118
1119#[derive(Debug, Clone, Serialize, Deserialize)]
1120pub struct TeamCleanupCompleted {
1121 pub team_id: TeamId,
1122 pub forced: bool,
1123 #[serde(with = "time::serde::rfc3339")]
1124 pub timestamp: OffsetDateTime,
1125}
1126
1127#[derive(Debug, Clone, Serialize, Deserialize)]
1128pub struct MemorySaved {
1129 pub memory: MemoryRecord,
1130 #[serde(with = "time::serde::rfc3339")]
1131 pub timestamp: OffsetDateTime,
1132}
1133
1134#[derive(Debug, Clone, Serialize, Deserialize)]
1135pub struct MemoryUpdated {
1136 pub memory: MemoryRecord,
1137 #[serde(with = "time::serde::rfc3339")]
1138 pub timestamp: OffsetDateTime,
1139}
1140
1141#[derive(Debug, Clone, Serialize, Deserialize)]
1142pub struct MemoryDeleted {
1143 pub memory_id: MemoryId,
1144 #[serde(with = "time::serde::rfc3339")]
1145 pub timestamp: OffsetDateTime,
1146}
1147
1148#[derive(Debug, Clone, Serialize, Deserialize)]
1149pub struct MemoryQueried {
1150 pub scope: Option<MemoryScope>,
1151 pub query: String,
1152 pub result_count: usize,
1153 #[serde(with = "time::serde::rfc3339")]
1154 pub timestamp: OffsetDateTime,
1155}
1156
1157#[derive(Debug, Clone, Serialize, Deserialize)]
1158pub struct MemoryRecallReady {
1159 pub thread_id: ThreadId,
1160 pub turn_id: TurnId,
1161 pub citations: Vec<MemoryCitation>,
1162 #[serde(with = "time::serde::rfc3339")]
1163 pub timestamp: OffsetDateTime,
1164}
1165
1166#[derive(Debug, Clone, Serialize, Deserialize)]
1167pub struct MemoryReembedQueued {
1168 pub scope: Option<MemoryScope>,
1169 pub provider: MemoryProviderSelection,
1170 #[serde(with = "time::serde::rfc3339")]
1171 pub timestamp: OffsetDateTime,
1172}
1173
1174#[derive(Debug, Clone, Serialize, Deserialize)]
1175pub struct MemoryProviderChanged {
1176 pub provider: MemoryProviderSelection,
1177 #[serde(with = "time::serde::rfc3339")]
1178 pub timestamp: OffsetDateTime,
1179}
1180
1181#[derive(Debug, Clone, Serialize, Deserialize)]
1182pub struct MemoryObservationRecorded {
1183 pub thread_id: ThreadId,
1184 pub turn_id: TurnId,
1185 pub memory_id: MemoryId,
1186 #[serde(with = "time::serde::rfc3339")]
1187 pub timestamp: OffsetDateTime,
1188}
1189
1190#[derive(Debug, Clone, Serialize, Deserialize)]
1191pub struct KnowledgeSaved {
1192 pub document: KnowledgeDocSummary,
1193 #[serde(with = "time::serde::rfc3339")]
1194 pub timestamp: OffsetDateTime,
1195}
1196
1197#[derive(Debug, Clone, Serialize, Deserialize)]
1198pub struct KnowledgeUpdated {
1199 pub document: KnowledgeDocSummary,
1200 #[serde(with = "time::serde::rfc3339")]
1201 pub timestamp: OffsetDateTime,
1202}
1203
1204#[derive(Debug, Clone, Serialize, Deserialize)]
1205pub struct KnowledgeArchived {
1206 pub doc_id: KnowledgeDocId,
1207 #[serde(with = "time::serde::rfc3339")]
1208 pub timestamp: OffsetDateTime,
1209}
1210
1211#[derive(Debug, Clone, Serialize, Deserialize)]
1212pub struct KnowledgeLinked {
1213 pub from: KnowledgeDocId,
1214 pub to: KnowledgeDocId,
1215 pub link_type: KnowledgeLinkType,
1216 pub removed: bool,
1217 #[serde(with = "time::serde::rfc3339")]
1218 pub timestamp: OffsetDateTime,
1219}
1220
1221#[derive(Debug, Clone, Serialize, Deserialize)]
1222pub struct RemoteServerStarted {
1223 pub listen_addr: String,
1224 pub connect_urls: Vec<String>,
1225 pub token_preview: String,
1226 #[serde(with = "time::serde::rfc3339")]
1227 pub timestamp: OffsetDateTime,
1228}
1229
1230#[derive(Debug, Clone, Serialize, Deserialize)]
1231pub struct RemoteServerStopped {
1232 pub listen_addr: String,
1233 #[serde(with = "time::serde::rfc3339")]
1234 pub timestamp: OffsetDateTime,
1235}
1236
1237#[derive(Debug, Clone, Serialize, Deserialize)]
1238pub struct RemoteAuthFailed {
1239 pub remote_addr: Option<String>,
1240 #[serde(with = "time::serde::rfc3339")]
1241 pub timestamp: OffsetDateTime,
1242}
1243
1244#[derive(Debug, Clone, Serialize, Deserialize)]
1245pub struct RemoteClientConnected {
1246 pub remote_addr: Option<String>,
1247 #[serde(with = "time::serde::rfc3339")]
1248 pub timestamp: OffsetDateTime,
1249}
1250
1251#[derive(Debug, Clone, Serialize, Deserialize)]
1252pub struct RemoteClientDisconnected {
1253 pub remote_addr: Option<String>,
1254 #[serde(with = "time::serde::rfc3339")]
1255 pub timestamp: OffsetDateTime,
1256}
1257
1258#[derive(Debug, Clone, Serialize, Deserialize)]
1259pub struct RoadmapChanged {
1260 pub event_kind: String,
1261 pub path: String,
1262 pub task_id: Option<String>,
1263 pub thread_id: Option<String>,
1264 #[serde(with = "time::serde::rfc3339")]
1265 pub timestamp: OffsetDateTime,
1266}
1267
1268#[derive(Debug, Clone, Serialize, Deserialize)]
1272#[serde(rename_all = "camelCase")]
1273pub struct ReviewStarted {
1274 pub thread_id: ThreadId,
1275 pub turn_id: TurnId,
1276 pub review_id: ReviewId,
1277 pub review_thread_id: ThreadId,
1278 pub target: ReviewTarget,
1279 pub label: String,
1280 #[serde(with = "time::serde::rfc3339")]
1281 pub timestamp: OffsetDateTime,
1282}
1283
1284#[derive(Debug, Clone, Serialize, Deserialize)]
1285#[serde(rename_all = "camelCase")]
1286pub struct ReviewCompleted {
1287 pub thread_id: ThreadId,
1288 pub turn_id: TurnId,
1289 pub review_id: ReviewId,
1290 pub review_thread_id: ThreadId,
1291 pub output: ReviewOutput,
1292 #[serde(with = "time::serde::rfc3339")]
1293 pub timestamp: OffsetDateTime,
1294}
1295
1296#[derive(Debug, Clone, Serialize, Deserialize)]
1297#[serde(rename_all = "camelCase")]
1298pub struct ReviewFailed {
1299 pub thread_id: ThreadId,
1300 #[serde(default, skip_serializing_if = "Option::is_none")]
1302 pub turn_id: Option<TurnId>,
1303 pub review_id: ReviewId,
1304 #[serde(default, skip_serializing_if = "Option::is_none")]
1305 pub review_thread_id: Option<ThreadId>,
1306 pub error: String,
1307 #[serde(with = "time::serde::rfc3339")]
1308 pub timestamp: OffsetDateTime,
1309}
1310
1311#[derive(Debug, Clone, Serialize, Deserialize)]
1312#[serde(rename_all = "camelCase")]
1313pub struct ReviewPublished {
1314 #[serde(default, skip_serializing_if = "Option::is_none")]
1315 pub thread_id: Option<ThreadId>,
1316 pub review_id: ReviewId,
1317 pub publisher_id: ReviewPublisherId,
1318 #[serde(default, skip_serializing_if = "Option::is_none")]
1319 pub url: Option<String>,
1320 pub published_findings: usize,
1321 #[serde(default)]
1322 pub skipped: Vec<ReviewPublishSkip>,
1323 pub dry_run: bool,
1324 #[serde(with = "time::serde::rfc3339")]
1325 pub timestamp: OffsetDateTime,
1326}
1327
1328#[derive(Debug, Clone, Serialize, Deserialize)]
1329pub enum RoderEvent {
1330 RuntimeStarted(RuntimeStarted),
1331 ExtensionRegistered(ExtensionRegistered),
1332 ExtensionEventEmitted(ExtensionEventEmitted),
1333 EventSinkFailed(EventSinkFailed),
1334 ThreadCreated(ThreadCreated),
1335 ThreadLoaded(ThreadLoaded),
1336 ThreadForkRequested(ThreadForkRequested),
1337 ThreadForked(ThreadForked),
1338 ThreadForkFailed(ThreadForkFailed),
1339 ThreadForkRemoved(ThreadForkRemoved),
1340 TurnStarted(TurnStarted),
1341 ContextAssemblyStarted(ContextAssemblyStarted),
1342 ContextBlockAdded(ContextBlockAdded),
1343 ContextAssemblyCompleted(ContextAssemblyCompleted),
1344 ContextEntrypointCandidatesInjected(ContextEntrypointCandidatesInjected),
1345 ContextCompactionStarted(ContextCompactionStarted),
1346 ContextCompactionRecorded(ContextCompactionRecorded),
1347 ContextCompactionSkipped(ContextCompactionSkipped),
1348 InferenceRoutingDecision(InferenceRoutingDecisionEvent),
1349 InferenceStarted(InferenceStarted),
1350 InferenceEventReceived(InferenceEventReceived),
1351 ToolCallRequested(ToolCallRequested),
1352 HookRunRecorded(HookRunRecorded),
1353 ToolCallValidationRecorded(ToolCallValidationRecorded),
1354 ReliabilityFailureRecorded(ReliabilityFailureRecorded),
1355 ReliabilityRetryRecorded(ReliabilityRetryRecorded),
1356 ReliabilityLimitRecorded(ReliabilityLimitRecorded),
1357 ReliabilityMetricRecorded(ReliabilityMetricRecorded),
1358 CodeIndexingStarted(CodeIndexingStarted),
1359 CodeIndexChunked(CodeIndexChunked),
1360 CodeIndexEmbedded(CodeIndexEmbedded),
1361 CodeIndexReady(CodeIndexReady),
1362 CodeIndexStale(CodeIndexStale),
1363 CodeIndexFailed(CodeIndexFailed),
1364 CodeIndexProofFilteredResultDropped(CodeIndexProofFilteredResultDropped),
1365 ApprovalRequested(ApprovalRequested),
1366 ApprovalResolved(ApprovalResolved),
1367 ExternalToolCallRequested(ExternalToolCallRequested),
1368 ExternalToolCallResolved(ExternalToolCallResolved),
1369 UserInputRequested(UserInputRequested),
1370 UserInputResolved(UserInputResolved),
1371 TaskLedgerUpdated(TaskLedgerUpdated),
1372 VerificationRequired(VerificationRequired),
1373 VerificationCompleted(VerificationCompleted),
1374 VerificationSkipped(VerificationSkipped),
1375 PolicyDecisionRecorded(PolicyDecisionRecorded),
1376 PolicyBypassActive(PolicyBypassActive),
1377 PolicyModeChanged(PolicyModeChanged),
1378 AgentSwarmModeChanged(AgentSwarmModeChanged),
1379 AgentSwarmStarted(AgentSwarmStarted),
1380 AgentSwarmProgress(AgentSwarmProgress),
1381 AgentSwarmCompleted(AgentSwarmCompleted),
1382 UltraModeChanged(UltraModeChanged),
1383 PolicyExitPlanRequested(PolicyExitPlanRequested),
1384 PolicyExitPlanResolved(PolicyExitPlanResolved),
1385 ToolCallStarted(ToolCallStarted),
1386 ToolCallCompleted(ToolCallCompleted),
1387 ToolOutputDelta(ToolOutputDelta),
1388 ToolOutputTruncated(ToolOutputTruncated),
1389 SubagentStarted(SubagentStarted),
1390 SubagentMessage(SubagentMessage),
1391 SubagentToolCall(SubagentToolCall),
1392 SubagentCompleted(SubagentCompleted),
1393 SubagentFailed(SubagentFailed),
1394 SubagentTraceCreated(SubagentTraceCreated),
1395 SubagentTraceDelta(SubagentTraceDeltaEvent),
1396 SubagentTraceStatusChanged(SubagentTraceStatusChanged),
1397 SubagentTraceCompleted(SubagentTraceCompleted),
1398 SubagentTraceFailed(SubagentTraceFailed),
1399 PlanReviewCreated(PlanReviewCreated),
1400 PlanReviewStatusChanged(PlanReviewStatusChanged),
1401 PlanReviewCommentAdded(PlanReviewCommentAdded),
1402 PlanReviewRewritten(PlanReviewRewritten),
1403 PlanReviewApproved(PlanReviewApproved),
1404 PlanReviewRejected(PlanReviewRejected),
1405 HunkRecorded(HunkRecorded),
1406 WorkspaceChangeObserved(WorkspaceChangeObserved),
1407 HunkRollbackRequested(HunkRollbackRequested),
1408 HunkRollbackCompleted(HunkRollbackCompleted),
1409 WorkflowImportsDetected(WorkflowImportsDetected),
1410 WorkflowImportPreviewed(WorkflowImportPreviewed),
1411 WorkflowImportEnabled(WorkflowImportEnabled),
1412 WorkflowImportDisabled(WorkflowImportDisabled),
1413 WorkflowImportStale(WorkflowImportStale),
1414 WorkflowImportFailed(WorkflowImportFailed),
1415 WorkflowRunDrafted(WorkflowRunDrafted),
1416 WorkflowApprovalRequested(WorkflowApprovalRequested),
1417 WorkflowRunApproved(WorkflowRunApproved),
1418 WorkflowRunDenied(WorkflowRunDenied),
1419 WorkflowRunQueued(WorkflowRunQueued),
1420 WorkflowRunStarted(WorkflowRunStarted),
1421 WorkflowPhaseStarted(WorkflowPhaseStarted),
1422 WorkflowPhaseCompleted(WorkflowPhaseCompleted),
1423 WorkflowAgentQueued(WorkflowAgentQueued),
1424 WorkflowAgentStarted(WorkflowAgentStarted),
1425 WorkflowAgentCompleted(WorkflowAgentCompleted),
1426 WorkflowAgentFailed(WorkflowAgentFailed),
1427 WorkflowOutputRecorded(WorkflowOutputRecorded),
1428 WorkflowCheckpointRecorded(WorkflowCheckpointRecorded),
1429 WorkflowRunPaused(WorkflowRunPaused),
1430 WorkflowRunResumed(WorkflowRunResumed),
1431 WorkflowRunStopped(WorkflowRunStopped),
1432 WorkflowRunCompleted(WorkflowRunCompleted),
1433 WorkflowRunFailed(WorkflowRunFailed),
1434 MediaArtifactCreated(MediaArtifactCreated),
1435 MediaArtifactUpdated(MediaArtifactUpdated),
1436 MediaArtifactDeleted(MediaArtifactDeleted),
1437 MediaPreviewReady(MediaPreviewReady),
1438 ContextArtifactCreated(ContextArtifactCreated),
1439 ContextArtifactAppended(ContextArtifactAppended),
1440 ContextArtifactCapped(ContextArtifactCapped),
1441 ContextArtifactDeleted(ContextArtifactDeleted),
1442 ContextArtifactRetentionExpired(ContextArtifactRetentionExpired),
1443 DiscoveryCatalogBuilt(DiscoveryCatalogBuilt),
1444 DiscoveryItemUpdated(DiscoveryItemUpdated),
1445 DiscoveryAuthRequired(DiscoveryAuthRequired),
1446 DiscoveryItemRead(DiscoveryItemRead),
1447 DiscoveryItemPromoted(DiscoveryItemPromoted),
1448 DiscoveryPromotionReused(DiscoveryPromotionReused),
1449 DiscoveryWarmCacheHit(DiscoveryWarmCacheHit),
1450 DiscoveryPromotionExpired(DiscoveryPromotionExpired),
1451 RetrievalRoutePlanned(RetrievalRoutePlanned),
1452 RetrievalRouteAccepted(RetrievalRouteAccepted),
1453 RetrievalRouteIgnored(RetrievalRouteIgnored),
1454 RetrievalRouteFailed(RetrievalRouteFailed),
1455 RetrievalResultUsed(RetrievalResultUsed),
1456 RetrievalDiscoveryItemPromoted(RetrievalDiscoveryItemPromoted),
1457 RetrievalPromotionSkipped(RetrievalPromotionSkipped),
1458 MemorySaved(MemorySaved),
1459 MemoryUpdated(MemoryUpdated),
1460 MemoryDeleted(MemoryDeleted),
1461 MemoryQueried(MemoryQueried),
1462 MemoryRecallReady(MemoryRecallReady),
1463 MemoryReembedQueued(MemoryReembedQueued),
1464 MemoryProviderChanged(MemoryProviderChanged),
1465 MemoryObservationRecorded(MemoryObservationRecorded),
1466 KnowledgeSaved(KnowledgeSaved),
1467 KnowledgeUpdated(KnowledgeUpdated),
1468 KnowledgeArchived(KnowledgeArchived),
1469 KnowledgeLinked(KnowledgeLinked),
1470 RemoteServerStarted(RemoteServerStarted),
1471 RemoteServerStopped(RemoteServerStopped),
1472 RemoteAuthFailed(RemoteAuthFailed),
1473 RemoteClientConnected(RemoteClientConnected),
1474 RemoteClientDisconnected(RemoteClientDisconnected),
1475 ThreadGoalUpdated(ThreadGoalUpdated),
1476 ThreadGoalCleared(ThreadGoalCleared),
1477 RoadmapChanged(RoadmapChanged),
1478 AutomationCreated(AutomationCreated),
1479 AutomationUpdated(AutomationUpdated),
1480 AutomationDeleted(AutomationDeleted),
1481 AutomationDue(AutomationDue),
1482 AutomationLeased(AutomationLeased),
1483 AutomationQueued(AutomationQueued),
1484 AutomationStarted(AutomationStarted),
1485 AutomationCompleted(AutomationCompleted),
1486 AutomationFailed(AutomationFailed),
1487 AutomationSkipped(AutomationSkipped),
1488 AutomationLeaseExpired(AutomationLeaseExpired),
1489 SkillsCatalogLoaded(SkillsCatalogLoaded),
1490 SkillConfigApplied(SkillConfigApplied),
1491 SkillActivationResolved(SkillActivationResolved),
1492 SkillIndexRendered(SkillIndexRendered),
1493 SkillInvoked(SkillInvoked),
1494 SkillAutoActivated(SkillAutoActivated),
1495 SkillSkipped(SkillSkipped),
1496 TaskStarted(TaskStarted),
1497 TaskOutput(TaskOutput),
1498 TaskCompleted(TaskCompleted),
1499 TaskFailed(TaskFailed),
1500 TaskCancelled(TaskCancelled),
1501 ProcessStarted(ProcessStarted),
1502 ProcessOutput(ProcessOutput),
1503 ProcessExited(ProcessExited),
1504 ProcessStopping(ProcessStopping),
1505 ProcessStopped(ProcessStopped),
1506 ProcessFailed(ProcessFailed),
1507 FileChangePreviewReady(FileChangePreviewReady),
1508 PatchProgress(crate::patch_progress::PatchProgress),
1509 FileChanged(FileChanged),
1510 TranscriptItemAppended(TranscriptItemAppended),
1511 TurnCompleted(TurnCompleted),
1512 TurnFailed(TurnFailed),
1513 TurnPartialResult(TurnPartialResult),
1514 TurnDeadlineExceeded(TurnDeadlineExceeded),
1515 TurnLifecycleUpdated(TurnLifecycleRecord),
1516 TurnInterrupted(TurnInterrupted),
1517 TurnSteered(TurnSteered),
1518 RunnerLifecycle(RunnerLifecycle),
1519 TeamStarted(TeamStarted),
1520 TeamMemberStarted(TeamMemberStarted),
1521 TeamMemberStatusChanged(TeamMemberStatusChanged),
1522 TeamMemberMessageDelta(TeamMemberMessageDelta),
1523 TeamMemberCompleted(TeamMemberCompleted),
1524 TeamDisplayModeChanged(TeamDisplayModeChanged),
1525 TeamTaskChanged(TeamTaskChanged),
1526 TeamCleanupCompleted(TeamCleanupCompleted),
1527 ReviewStarted(ReviewStarted),
1528 ReviewCompleted(ReviewCompleted),
1529 ReviewFailed(ReviewFailed),
1530 ReviewPublished(ReviewPublished),
1531}
1532
1533impl RoderEvent {
1534 pub fn kind(&self) -> &'static str {
1535 match self {
1536 RoderEvent::RuntimeStarted(_) => "runtime.started",
1537 RoderEvent::ExtensionRegistered(_) => "extension.registered",
1538 RoderEvent::ExtensionEventEmitted(_) => "extension.event",
1539 RoderEvent::EventSinkFailed(_) => "extension.event_sink_failed",
1540 RoderEvent::ThreadCreated(_) => "thread.created",
1541 RoderEvent::ThreadLoaded(_) => "thread.loaded",
1542 RoderEvent::ThreadForkRequested(_) => "thread.fork_requested",
1543 RoderEvent::ThreadForked(_) => "thread.forked",
1544 RoderEvent::ThreadForkFailed(_) => "thread.fork_failed",
1545 RoderEvent::ThreadForkRemoved(_) => "thread.fork_removed",
1546 RoderEvent::TurnStarted(_) => "turn.started",
1547 RoderEvent::ContextAssemblyStarted(_) => "context.assembly_started",
1548 RoderEvent::ContextBlockAdded(_) => "context.block_added",
1549 RoderEvent::ContextAssemblyCompleted(_) => "context.assembly_completed",
1550 RoderEvent::ContextEntrypointCandidatesInjected(_) => {
1551 "context.entrypoint_candidates_injected"
1552 }
1553 RoderEvent::ContextCompactionStarted(_) => "context.compaction_started",
1554 RoderEvent::ContextCompactionRecorded(_) => "context.compaction_recorded",
1555 RoderEvent::ContextCompactionSkipped(_) => "context.compaction_skipped",
1556 RoderEvent::InferenceRoutingDecision(_) => "inference.routing_decision",
1557 RoderEvent::InferenceStarted(_) => "inference.started",
1558 RoderEvent::InferenceEventReceived(_) => "inference.event_received",
1559 RoderEvent::ToolCallRequested(_) => "tool.call_requested",
1560 RoderEvent::HookRunRecorded(_) => "hook.run_recorded",
1561 RoderEvent::ToolCallValidationRecorded(_) => "tool.call_validation",
1562 RoderEvent::ReliabilityFailureRecorded(_) => "reliability.failure",
1563 RoderEvent::ReliabilityRetryRecorded(_) => "reliability.retry",
1564 RoderEvent::ReliabilityLimitRecorded(_) => "reliability.limit",
1565 RoderEvent::ReliabilityMetricRecorded(_) => "reliability.metric",
1566 RoderEvent::CodeIndexingStarted(_) => "code_index.started",
1567 RoderEvent::CodeIndexChunked(_) => "code_index.chunked",
1568 RoderEvent::CodeIndexEmbedded(_) => "code_index.embedded",
1569 RoderEvent::CodeIndexReady(_) => "code_index.ready",
1570 RoderEvent::CodeIndexStale(_) => "code_index.stale",
1571 RoderEvent::CodeIndexFailed(_) => "code_index.failed",
1572 RoderEvent::CodeIndexProofFilteredResultDropped(_) => {
1573 "code_index.proof_filtered_result_dropped"
1574 }
1575 RoderEvent::ApprovalRequested(_) => "approval.requested",
1576 RoderEvent::ApprovalResolved(_) => "approval.resolved",
1577 RoderEvent::ExternalToolCallRequested(_) => "external_tool.requested",
1578 RoderEvent::ExternalToolCallResolved(_) => "external_tool.resolved",
1579 RoderEvent::UserInputRequested(_) => "user_input.requested",
1580 RoderEvent::UserInputResolved(_) => "user_input.resolved",
1581 RoderEvent::TaskLedgerUpdated(_) => "task_ledger.updated",
1582 RoderEvent::VerificationRequired(_) => "verification.required",
1583 RoderEvent::VerificationCompleted(_) => "verification.completed",
1584 RoderEvent::VerificationSkipped(_) => "verification.skipped",
1585 RoderEvent::PolicyDecisionRecorded(_) => "policy.decision",
1586 RoderEvent::PolicyBypassActive(_) => "policy.bypass_active",
1587 RoderEvent::PolicyModeChanged(_) => "policy.mode_changed",
1588 RoderEvent::AgentSwarmModeChanged(_) => "agent_swarm.mode_changed",
1589 RoderEvent::AgentSwarmStarted(_) => "agent_swarm.started",
1590 RoderEvent::AgentSwarmProgress(_) => "agent_swarm.progress",
1591 RoderEvent::AgentSwarmCompleted(_) => "agent_swarm.completed",
1592 RoderEvent::UltraModeChanged(_) => "ultra.mode_changed",
1593 RoderEvent::PolicyExitPlanRequested(_) => "policy.exit_plan_requested",
1594 RoderEvent::PolicyExitPlanResolved(_) => "policy.exit_plan_resolved",
1595 RoderEvent::ToolCallStarted(_) => "tool.call_started",
1596 RoderEvent::ToolCallCompleted(_) => "tool.call_completed",
1597 RoderEvent::ToolOutputDelta(_) => "tool.output_delta",
1598 RoderEvent::ToolOutputTruncated(_) => "tool.output_truncated",
1599 RoderEvent::SubagentStarted(_) => "subagent.started",
1600 RoderEvent::SubagentMessage(_) => "subagent.message",
1601 RoderEvent::SubagentToolCall(_) => "subagent.tool_call",
1602 RoderEvent::SubagentCompleted(_) => "subagent.completed",
1603 RoderEvent::SubagentFailed(_) => "subagent.failed",
1604 RoderEvent::SubagentTraceCreated(_) => "turn/subagentTraceCreated",
1605 RoderEvent::SubagentTraceDelta(_) => "turn/subagentTraceDelta",
1606 RoderEvent::SubagentTraceStatusChanged(_) => "turn/subagentTraceStatusChanged",
1607 RoderEvent::SubagentTraceCompleted(_) => "turn/subagentTraceCompleted",
1608 RoderEvent::SubagentTraceFailed(_) => "turn/subagentTraceFailed",
1609 RoderEvent::PlanReviewCreated(_) => "plan/reviewCreated",
1610 RoderEvent::PlanReviewStatusChanged(_) => "plan/reviewStatusChanged",
1611 RoderEvent::PlanReviewCommentAdded(_) => "plan/reviewCommentAdded",
1612 RoderEvent::PlanReviewRewritten(_) => "plan/reviewRewritten",
1613 RoderEvent::PlanReviewApproved(_) => "plan/reviewApproved",
1614 RoderEvent::PlanReviewRejected(_) => "plan/reviewRejected",
1615 RoderEvent::HunkRecorded(_) => "hunk/recorded",
1616 RoderEvent::WorkspaceChangeObserved(_) => "workspace/changeObserved",
1617 RoderEvent::HunkRollbackRequested(_) => "hunk/rollbackRequested",
1618 RoderEvent::HunkRollbackCompleted(_) => "hunk/rollbackCompleted",
1619 RoderEvent::WorkflowImportsDetected(_) => "workflow/importsDetected",
1620 RoderEvent::WorkflowImportPreviewed(_) => "workflow/importPreviewed",
1621 RoderEvent::WorkflowImportEnabled(_) => "workflow/importEnabled",
1622 RoderEvent::WorkflowImportDisabled(_) => "workflow/importDisabled",
1623 RoderEvent::WorkflowImportStale(_) => "workflow/importStale",
1624 RoderEvent::WorkflowImportFailed(_) => "workflow/importFailed",
1625 RoderEvent::WorkflowRunDrafted(_) => "workflows/drafted",
1626 RoderEvent::WorkflowApprovalRequested(_) => "workflows/approvalRequested",
1627 RoderEvent::WorkflowRunApproved(_) => "workflows/approved",
1628 RoderEvent::WorkflowRunDenied(_) => "workflows/denied",
1629 RoderEvent::WorkflowRunQueued(_) => "workflows/queued",
1630 RoderEvent::WorkflowRunStarted(_) => "workflows/started",
1631 RoderEvent::WorkflowPhaseStarted(_) => "workflows/phaseStarted",
1632 RoderEvent::WorkflowPhaseCompleted(_) => "workflows/phaseCompleted",
1633 RoderEvent::WorkflowAgentQueued(_) => "workflows/agentQueued",
1634 RoderEvent::WorkflowAgentStarted(_) => "workflows/agentStarted",
1635 RoderEvent::WorkflowAgentCompleted(_) => "workflows/agentCompleted",
1636 RoderEvent::WorkflowAgentFailed(_) => "workflows/agentFailed",
1637 RoderEvent::WorkflowOutputRecorded(_) => "workflows/outputRecorded",
1638 RoderEvent::WorkflowCheckpointRecorded(_) => "workflows/checkpointRecorded",
1639 RoderEvent::WorkflowRunPaused(_) => "workflows/paused",
1640 RoderEvent::WorkflowRunResumed(_) => "workflows/resumed",
1641 RoderEvent::WorkflowRunStopped(_) => "workflows/stopped",
1642 RoderEvent::WorkflowRunCompleted(_) => "workflows/completed",
1643 RoderEvent::WorkflowRunFailed(_) => "workflows/failed",
1644 RoderEvent::MediaArtifactCreated(_) => "media/artifactCreated",
1645 RoderEvent::MediaArtifactUpdated(_) => "media/artifactUpdated",
1646 RoderEvent::MediaArtifactDeleted(_) => "media/artifactDeleted",
1647 RoderEvent::MediaPreviewReady(_) => "media/previewReady",
1648 RoderEvent::ContextArtifactCreated(_) => "artifact/created",
1649 RoderEvent::ContextArtifactAppended(_) => "artifact/appended",
1650 RoderEvent::ContextArtifactCapped(_) => "artifact/capped",
1651 RoderEvent::ContextArtifactDeleted(_) => "artifact/deleted",
1652 RoderEvent::ContextArtifactRetentionExpired(_) => "artifact/retentionExpired",
1653 RoderEvent::DiscoveryCatalogBuilt(_) => "discovery/catalogBuilt",
1654 RoderEvent::DiscoveryItemUpdated(_) => "discovery/itemUpdated",
1655 RoderEvent::DiscoveryAuthRequired(_) => "discovery/authRequired",
1656 RoderEvent::DiscoveryItemRead(_) => "discovery/itemRead",
1657 RoderEvent::DiscoveryItemPromoted(_) => "discovery/itemPromoted",
1658 RoderEvent::DiscoveryPromotionReused(_) => "discovery/promotionReused",
1659 RoderEvent::DiscoveryWarmCacheHit(_) => "discovery/warmCacheHit",
1660 RoderEvent::DiscoveryPromotionExpired(_) => "discovery/promotionExpired",
1661 RoderEvent::RetrievalRoutePlanned(_) => "retrieval/routePlanned",
1662 RoderEvent::RetrievalRouteAccepted(_) => "retrieval/routeAccepted",
1663 RoderEvent::RetrievalRouteIgnored(_) => "retrieval/routeIgnored",
1664 RoderEvent::RetrievalRouteFailed(_) => "retrieval/routeFailed",
1665 RoderEvent::RetrievalResultUsed(_) => "retrieval/resultUsed",
1666 RoderEvent::RetrievalDiscoveryItemPromoted(_) => "retrieval/discoveryItemPromoted",
1667 RoderEvent::RetrievalPromotionSkipped(_) => "retrieval/promotionSkipped",
1668 RoderEvent::MemorySaved(_) => "memory/saved",
1669 RoderEvent::MemoryUpdated(_) => "memory/updated",
1670 RoderEvent::MemoryDeleted(_) => "memory/deleted",
1671 RoderEvent::MemoryQueried(_) => "memory/queried",
1672 RoderEvent::MemoryRecallReady(_) => "memory/recallReady",
1673 RoderEvent::MemoryReembedQueued(_) => "memory/reembedQueued",
1674 RoderEvent::MemoryProviderChanged(_) => "memory/providerChanged",
1675 RoderEvent::MemoryObservationRecorded(_) => "memory/observationRecorded",
1676 RoderEvent::KnowledgeSaved(_) => "knowledge/saved",
1677 RoderEvent::KnowledgeUpdated(_) => "knowledge/updated",
1678 RoderEvent::KnowledgeArchived(_) => "knowledge/archived",
1679 RoderEvent::KnowledgeLinked(_) => "knowledge/linked",
1680 RoderEvent::RemoteServerStarted(_) => "remote/serverStarted",
1681 RoderEvent::RemoteServerStopped(_) => "remote/serverStopped",
1682 RoderEvent::RemoteAuthFailed(_) => "remote/authFailed",
1683 RoderEvent::RemoteClientConnected(_) => "remote/clientConnected",
1684 RoderEvent::RemoteClientDisconnected(_) => "remote/clientDisconnected",
1685 RoderEvent::ThreadGoalUpdated(_) => "thread/goal/updated",
1686 RoderEvent::ThreadGoalCleared(_) => "thread/goal/cleared",
1687 RoderEvent::RoadmapChanged(_) => "roadmap.changed",
1688 RoderEvent::AutomationCreated(_) => "automations/created",
1689 RoderEvent::AutomationUpdated(_) => "automations/updated",
1690 RoderEvent::AutomationDeleted(_) => "automations/deleted",
1691 RoderEvent::AutomationDue(_) => "automations/due",
1692 RoderEvent::AutomationLeased(_) => "automations/leased",
1693 RoderEvent::AutomationQueued(_) => "automations/queued",
1694 RoderEvent::AutomationStarted(_) => "automations/started",
1695 RoderEvent::AutomationCompleted(_) => "automations/completed",
1696 RoderEvent::AutomationFailed(_) => "automations/failed",
1697 RoderEvent::AutomationSkipped(_) => "automations/skipped",
1698 RoderEvent::AutomationLeaseExpired(_) => "automations/leaseExpired",
1699 RoderEvent::SkillsCatalogLoaded(_) => "skills/catalogLoaded",
1700 RoderEvent::SkillConfigApplied(_) => "skills/configApplied",
1701 RoderEvent::SkillActivationResolved(_) => "skills/activationResolved",
1702 RoderEvent::SkillIndexRendered(_) => "skills/indexRendered",
1703 RoderEvent::SkillInvoked(_) => "skills/invoked",
1704 RoderEvent::SkillAutoActivated(_) => "skills/autoActivated",
1705 RoderEvent::SkillSkipped(_) => "skills/skipped",
1706 RoderEvent::TaskStarted(_) => "task.started",
1707 RoderEvent::TaskOutput(_) => "task.output",
1708 RoderEvent::TaskCompleted(_) => "task.completed",
1709 RoderEvent::TaskFailed(_) => "task.failed",
1710 RoderEvent::TaskCancelled(_) => "task.cancelled",
1711 RoderEvent::ProcessStarted(_) => "process.started",
1712 RoderEvent::ProcessOutput(_) => "process.output",
1713 RoderEvent::ProcessExited(_) => "process.exited",
1714 RoderEvent::ProcessStopping(_) => "process.stopping",
1715 RoderEvent::ProcessStopped(_) => "process.stopped",
1716 RoderEvent::ProcessFailed(_) => "process.failed",
1717 RoderEvent::FileChangePreviewReady(_) => "file.change_preview_ready",
1718 RoderEvent::PatchProgress(_) => "patch/progress",
1719 RoderEvent::FileChanged(_) => "file.changed",
1720 RoderEvent::TranscriptItemAppended(_) => "turn.transcript_item_appended",
1721 RoderEvent::TurnCompleted(_) => "turn.completed",
1722 RoderEvent::TurnFailed(_) => "turn.failed",
1723 RoderEvent::TurnPartialResult(_) => "turn.partial_result",
1724 RoderEvent::TurnDeadlineExceeded(_) => "turn.deadline_exceeded",
1725 RoderEvent::TurnLifecycleUpdated(_) => "turn.lifecycle_updated",
1726 RoderEvent::TurnInterrupted(_) => "turn.interrupted",
1727 RoderEvent::TurnSteered(_) => "turn.steered",
1728 RoderEvent::RunnerLifecycle(_) => "runner.lifecycle",
1729 RoderEvent::TeamStarted(_) => "team.started",
1730 RoderEvent::TeamMemberStarted(_) => "team.member_started",
1731 RoderEvent::TeamMemberStatusChanged(_) => "team.member_status_changed",
1732 RoderEvent::TeamMemberMessageDelta(_) => "team.member_message_delta",
1733 RoderEvent::TeamMemberCompleted(_) => "team.member_completed",
1734 RoderEvent::TeamDisplayModeChanged(_) => "team.display_mode_changed",
1735 RoderEvent::TeamTaskChanged(_) => "team.task_changed",
1736 RoderEvent::TeamCleanupCompleted(_) => "team.cleanup_completed",
1737 RoderEvent::ReviewStarted(_) => "review.started",
1738 RoderEvent::ReviewCompleted(_) => "review.completed",
1739 RoderEvent::ReviewFailed(_) => "review.failed",
1740 RoderEvent::ReviewPublished(_) => "review.published",
1741 }
1742 }
1743
1744 pub fn source(&self) -> EventSource {
1745 match self {
1746 RoderEvent::InferenceEventReceived(_) | RoderEvent::InferenceStarted(_) => {
1747 EventSource::Provider
1748 }
1749 RoderEvent::InferenceRoutingDecision(_) => EventSource::Core,
1750 RoderEvent::ReliabilityRetryRecorded(_) => EventSource::Provider,
1751 RoderEvent::ReliabilityFailureRecorded(_)
1752 | RoderEvent::ReliabilityLimitRecorded(_)
1753 | RoderEvent::ReliabilityMetricRecorded(_) => EventSource::Core,
1754 RoderEvent::ToolCallRequested(_)
1755 | RoderEvent::ToolCallValidationRecorded(_)
1756 | RoderEvent::ToolCallStarted(_)
1757 | RoderEvent::ToolCallCompleted(_) => EventSource::Tool,
1758 RoderEvent::ToolOutputDelta(_) => EventSource::Tool,
1759 RoderEvent::SubagentStarted(_)
1760 | RoderEvent::SubagentMessage(_)
1761 | RoderEvent::SubagentToolCall(_)
1762 | RoderEvent::SubagentCompleted(_)
1763 | RoderEvent::SubagentFailed(_)
1764 | RoderEvent::SubagentTraceCreated(_)
1765 | RoderEvent::SubagentTraceDelta(_)
1766 | RoderEvent::SubagentTraceStatusChanged(_)
1767 | RoderEvent::SubagentTraceCompleted(_)
1768 | RoderEvent::SubagentTraceFailed(_)
1769 | RoderEvent::PlanReviewCreated(_)
1770 | RoderEvent::PlanReviewStatusChanged(_)
1771 | RoderEvent::PlanReviewCommentAdded(_)
1772 | RoderEvent::PlanReviewRewritten(_)
1773 | RoderEvent::PlanReviewApproved(_)
1774 | RoderEvent::PlanReviewRejected(_)
1775 | RoderEvent::HunkRecorded(_)
1776 | RoderEvent::WorkspaceChangeObserved(_)
1777 | RoderEvent::HunkRollbackRequested(_)
1778 | RoderEvent::HunkRollbackCompleted(_)
1779 | RoderEvent::WorkflowImportsDetected(_)
1780 | RoderEvent::WorkflowImportPreviewed(_)
1781 | RoderEvent::WorkflowImportEnabled(_)
1782 | RoderEvent::WorkflowImportDisabled(_)
1783 | RoderEvent::WorkflowImportStale(_)
1784 | RoderEvent::WorkflowImportFailed(_)
1785 | RoderEvent::MediaArtifactCreated(_)
1786 | RoderEvent::MediaArtifactUpdated(_)
1787 | RoderEvent::MediaArtifactDeleted(_)
1788 | RoderEvent::MediaPreviewReady(_)
1789 | RoderEvent::ContextArtifactCreated(_)
1790 | RoderEvent::ContextArtifactAppended(_)
1791 | RoderEvent::ContextArtifactCapped(_)
1792 | RoderEvent::ContextArtifactDeleted(_)
1793 | RoderEvent::ContextArtifactRetentionExpired(_)
1794 | RoderEvent::DiscoveryCatalogBuilt(_)
1795 | RoderEvent::DiscoveryItemUpdated(_)
1796 | RoderEvent::DiscoveryAuthRequired(_)
1797 | RoderEvent::DiscoveryItemRead(_)
1798 | RoderEvent::DiscoveryItemPromoted(_)
1799 | RoderEvent::DiscoveryPromotionReused(_)
1800 | RoderEvent::DiscoveryWarmCacheHit(_)
1801 | RoderEvent::DiscoveryPromotionExpired(_)
1802 | RoderEvent::RetrievalRoutePlanned(_)
1803 | RoderEvent::RetrievalRouteAccepted(_)
1804 | RoderEvent::RetrievalRouteIgnored(_)
1805 | RoderEvent::RetrievalRouteFailed(_)
1806 | RoderEvent::RetrievalResultUsed(_)
1807 | RoderEvent::RetrievalDiscoveryItemPromoted(_)
1808 | RoderEvent::RetrievalPromotionSkipped(_)
1809 | RoderEvent::MemorySaved(_)
1810 | RoderEvent::MemoryUpdated(_)
1811 | RoderEvent::MemoryDeleted(_)
1812 | RoderEvent::MemoryQueried(_)
1813 | RoderEvent::MemoryRecallReady(_)
1814 | RoderEvent::MemoryReembedQueued(_)
1815 | RoderEvent::MemoryProviderChanged(_)
1816 | RoderEvent::MemoryObservationRecorded(_)
1817 | RoderEvent::TaskStarted(_)
1818 | RoderEvent::TaskOutput(_)
1819 | RoderEvent::TaskCompleted(_)
1820 | RoderEvent::TaskFailed(_)
1821 | RoderEvent::TaskCancelled(_)
1822 | RoderEvent::ProcessStarted(_)
1823 | RoderEvent::ProcessOutput(_)
1824 | RoderEvent::ProcessExited(_)
1825 | RoderEvent::ProcessStopping(_)
1826 | RoderEvent::ProcessStopped(_)
1827 | RoderEvent::ProcessFailed(_) => EventSource::Extension,
1828 RoderEvent::RemoteServerStarted(_)
1829 | RoderEvent::RemoteServerStopped(_)
1830 | RoderEvent::RemoteAuthFailed(_)
1831 | RoderEvent::RemoteClientConnected(_)
1832 | RoderEvent::RemoteClientDisconnected(_) => EventSource::AppServer,
1833 RoderEvent::RoadmapChanged(_)
1834 | RoderEvent::ThreadGoalUpdated(_)
1835 | RoderEvent::ThreadGoalCleared(_)
1836 | RoderEvent::AutomationCreated(_)
1837 | RoderEvent::AutomationUpdated(_)
1838 | RoderEvent::AutomationDeleted(_)
1839 | RoderEvent::AutomationDue(_)
1840 | RoderEvent::AutomationLeased(_)
1841 | RoderEvent::AutomationQueued(_)
1842 | RoderEvent::AutomationStarted(_)
1843 | RoderEvent::AutomationCompleted(_)
1844 | RoderEvent::AutomationFailed(_)
1845 | RoderEvent::AutomationSkipped(_)
1846 | RoderEvent::AutomationLeaseExpired(_)
1847 | RoderEvent::SkillsCatalogLoaded(_)
1848 | RoderEvent::SkillConfigApplied(_)
1849 | RoderEvent::SkillActivationResolved(_)
1850 | RoderEvent::SkillIndexRendered(_)
1851 | RoderEvent::SkillInvoked(_)
1852 | RoderEvent::SkillAutoActivated(_)
1853 | RoderEvent::SkillSkipped(_) => EventSource::Core,
1854 RoderEvent::FileChangePreviewReady(_) | RoderEvent::PatchProgress(_) => {
1855 EventSource::Tool
1856 }
1857 RoderEvent::UserInputRequested(_)
1858 | RoderEvent::UserInputResolved(_)
1859 | RoderEvent::TaskLedgerUpdated(_)
1860 | RoderEvent::TurnPartialResult(_)
1861 | RoderEvent::TurnDeadlineExceeded(_)
1862 | RoderEvent::TurnLifecycleUpdated(_)
1863 | RoderEvent::VerificationRequired(_)
1864 | RoderEvent::VerificationCompleted(_)
1865 | RoderEvent::VerificationSkipped(_) => EventSource::Core,
1866 RoderEvent::ExtensionRegistered(_) => EventSource::Extension,
1867 RoderEvent::RunnerLifecycle(_) => EventSource::Extension,
1868 RoderEvent::TeamStarted(_)
1869 | RoderEvent::TeamMemberStarted(_)
1870 | RoderEvent::TeamMemberStatusChanged(_)
1871 | RoderEvent::TeamMemberMessageDelta(_)
1872 | RoderEvent::TeamMemberCompleted(_)
1873 | RoderEvent::TeamDisplayModeChanged(_)
1874 | RoderEvent::TeamTaskChanged(_)
1875 | RoderEvent::TeamCleanupCompleted(_) => EventSource::Core,
1876 RoderEvent::ReviewStarted(_)
1877 | RoderEvent::ReviewCompleted(_)
1878 | RoderEvent::ReviewFailed(_) => EventSource::Core,
1879 RoderEvent::ReviewPublished(_) => EventSource::Extension,
1880 _ => EventSource::Core,
1881 }
1882 }
1883
1884 pub fn thread_id(&self) -> Option<&ThreadId> {
1885 match self {
1886 RoderEvent::ExtensionEventEmitted(_) | RoderEvent::EventSinkFailed(_) => None,
1887 RoderEvent::ThreadCreated(e) => Some(&e.thread_id),
1888 RoderEvent::ThreadLoaded(e) => Some(&e.thread_id),
1889 RoderEvent::ThreadForkRequested(e) => Some(&e.parent_thread_id),
1890 RoderEvent::ThreadForked(e) => Some(&e.child_thread_id),
1891 RoderEvent::ThreadForkFailed(e) => Some(&e.parent_thread_id),
1892 RoderEvent::ThreadForkRemoved(e) => Some(&e.thread_id),
1893 RoderEvent::TurnStarted(e) => Some(&e.thread_id),
1894 RoderEvent::ContextAssemblyStarted(e) => Some(&e.thread_id),
1895 RoderEvent::ContextBlockAdded(e) => Some(&e.thread_id),
1896 RoderEvent::ContextAssemblyCompleted(e) => Some(&e.thread_id),
1897 RoderEvent::ContextEntrypointCandidatesInjected(e) => Some(&e.thread_id),
1898 RoderEvent::ContextCompactionStarted(e) => Some(&e.thread_id),
1899 RoderEvent::ContextCompactionRecorded(e) => Some(&e.thread_id),
1900 RoderEvent::ContextCompactionSkipped(e) => Some(&e.thread_id),
1901 RoderEvent::InferenceRoutingDecision(e) => Some(&e.thread_id),
1902 RoderEvent::InferenceStarted(e) => Some(&e.thread_id),
1903 RoderEvent::InferenceEventReceived(e) => Some(&e.thread_id),
1904 RoderEvent::ToolCallRequested(e) => Some(&e.thread_id),
1905 RoderEvent::HookRunRecorded(e) => Some(&e.thread_id),
1906 RoderEvent::ToolCallValidationRecorded(e) => Some(&e.thread_id),
1907 RoderEvent::ReliabilityFailureRecorded(e) => Some(&e.context.thread_id),
1908 RoderEvent::ReliabilityRetryRecorded(e) => Some(&e.context.thread_id),
1909 RoderEvent::ReliabilityLimitRecorded(e) => Some(&e.context.thread_id),
1910 RoderEvent::ReliabilityMetricRecorded(e) => Some(&e.context.thread_id),
1911 RoderEvent::CodeIndexingStarted(e) => e.context.thread_id.as_ref(),
1912 RoderEvent::CodeIndexChunked(e) => e.context.thread_id.as_ref(),
1913 RoderEvent::CodeIndexEmbedded(e) => e.context.thread_id.as_ref(),
1914 RoderEvent::CodeIndexReady(_) => None,
1915 RoderEvent::CodeIndexStale(e) => e.context.thread_id.as_ref(),
1916 RoderEvent::CodeIndexFailed(e) => e.context.thread_id.as_ref(),
1917 RoderEvent::CodeIndexProofFilteredResultDropped(e) => e.context.thread_id.as_ref(),
1918 RoderEvent::ApprovalRequested(e) => Some(&e.thread_id),
1919 RoderEvent::ApprovalResolved(e) => Some(&e.thread_id),
1920 RoderEvent::ExternalToolCallRequested(e) => Some(&e.thread_id),
1921 RoderEvent::ExternalToolCallResolved(e) => Some(&e.thread_id),
1922 RoderEvent::UserInputRequested(e) => Some(&e.thread_id),
1923 RoderEvent::UserInputResolved(e) => Some(&e.thread_id),
1924 RoderEvent::TaskLedgerUpdated(e) => Some(&e.thread_id),
1925 RoderEvent::VerificationRequired(e) => Some(&e.thread_id),
1926 RoderEvent::VerificationCompleted(e) => Some(&e.thread_id),
1927 RoderEvent::VerificationSkipped(e) => Some(&e.thread_id),
1928 RoderEvent::PolicyDecisionRecorded(e) => Some(&e.thread_id),
1929 RoderEvent::PolicyBypassActive(e) => Some(&e.thread_id),
1930 RoderEvent::PolicyModeChanged(e) => Some(&e.thread_id),
1931 RoderEvent::AgentSwarmModeChanged(e) => Some(&e.thread_id),
1932 RoderEvent::AgentSwarmStarted(e) => Some(&e.thread_id),
1933 RoderEvent::AgentSwarmProgress(e) => Some(&e.thread_id),
1934 RoderEvent::AgentSwarmCompleted(e) => Some(&e.thread_id),
1935 RoderEvent::UltraModeChanged(e) => Some(&e.thread_id),
1936 RoderEvent::PolicyExitPlanRequested(e) => Some(&e.thread_id),
1937 RoderEvent::PolicyExitPlanResolved(e) => Some(&e.thread_id),
1938 RoderEvent::ToolCallStarted(e) => Some(&e.thread_id),
1939 RoderEvent::ToolCallCompleted(e) => Some(&e.thread_id),
1940 RoderEvent::ToolOutputDelta(e) => Some(&e.thread_id),
1941 RoderEvent::ToolOutputTruncated(e) => Some(&e.thread_id),
1942 RoderEvent::SubagentStarted(e) => Some(&e.thread_id),
1943 RoderEvent::SubagentMessage(e) => Some(&e.thread_id),
1944 RoderEvent::SubagentToolCall(e) => Some(&e.thread_id),
1945 RoderEvent::SubagentCompleted(e) => Some(&e.thread_id),
1946 RoderEvent::SubagentFailed(e) => Some(&e.thread_id),
1947 RoderEvent::SubagentTraceCreated(e) => Some(&e.summary.parent.thread_id),
1948 RoderEvent::SubagentTraceDelta(e) => Some(&e.delta.parent.thread_id),
1949 RoderEvent::SubagentTraceStatusChanged(e) => Some(&e.parent.thread_id),
1950 RoderEvent::SubagentTraceCompleted(e) => Some(&e.summary.parent.thread_id),
1951 RoderEvent::SubagentTraceFailed(e) => Some(&e.summary.parent.thread_id),
1952 RoderEvent::PlanReviewCreated(e) => Some(&e.review.thread_id),
1953 RoderEvent::PlanReviewStatusChanged(e) => Some(&e.thread_id),
1954 RoderEvent::PlanReviewCommentAdded(e) => Some(&e.thread_id),
1955 RoderEvent::PlanReviewRewritten(e) => Some(&e.thread_id),
1956 RoderEvent::PlanReviewApproved(e) => Some(&e.thread_id),
1957 RoderEvent::PlanReviewRejected(e) => Some(&e.thread_id),
1958 RoderEvent::HunkRecorded(e) => Some(&e.hunk.thread_id),
1959 RoderEvent::WorkspaceChangeObserved(e) => Some(&e.change.thread_id),
1960 RoderEvent::HunkRollbackRequested(e) => Some(&e.thread_id),
1961 RoderEvent::HunkRollbackCompleted(e) => Some(&e.thread_id),
1962 RoderEvent::MediaArtifactCreated(e) => Some(&e.thread_id),
1963 RoderEvent::MediaArtifactUpdated(e) => Some(&e.thread_id),
1964 RoderEvent::MediaPreviewReady(e) => Some(&e.thread_id),
1965 RoderEvent::ContextArtifactCreated(e) => Some(&e.thread_id),
1966 RoderEvent::ContextArtifactAppended(e) => Some(&e.thread_id),
1967 RoderEvent::ContextArtifactCapped(e) => Some(&e.thread_id),
1968 RoderEvent::ContextArtifactDeleted(e) => Some(&e.thread_id),
1969 RoderEvent::ContextArtifactRetentionExpired(e) => Some(&e.thread_id),
1970 RoderEvent::DiscoveryItemRead(e) => Some(&e.thread_id),
1971 RoderEvent::DiscoveryItemPromoted(e) => Some(&e.record.thread_id),
1972 RoderEvent::DiscoveryPromotionReused(e) => Some(&e.record.thread_id),
1973 RoderEvent::DiscoveryWarmCacheHit(e) => Some(&e.record.thread_id),
1974 RoderEvent::DiscoveryPromotionExpired(e) => Some(&e.record.thread_id),
1975 RoderEvent::RetrievalRoutePlanned(e) => Some(&e.plan.thread_id),
1976 RoderEvent::RetrievalRouteAccepted(e) => Some(&e.thread_id),
1977 RoderEvent::RetrievalRouteIgnored(e) => Some(&e.thread_id),
1978 RoderEvent::RetrievalRouteFailed(e) => Some(&e.thread_id),
1979 RoderEvent::RetrievalResultUsed(e) => Some(&e.thread_id),
1980 RoderEvent::RetrievalDiscoveryItemPromoted(e) => Some(&e.thread_id),
1981 RoderEvent::RetrievalPromotionSkipped(e) => Some(&e.thread_id),
1982 RoderEvent::MemoryRecallReady(e) => Some(&e.thread_id),
1983 RoderEvent::MemoryObservationRecorded(e) => Some(&e.thread_id),
1984 RoderEvent::TaskStarted(e) => e.thread_id.as_ref(),
1985 RoderEvent::TaskOutput(e) => e.thread_id.as_ref(),
1986 RoderEvent::TaskCompleted(e) => e.thread_id.as_ref(),
1987 RoderEvent::TaskFailed(e) => e.thread_id.as_ref(),
1988 RoderEvent::TaskCancelled(e) => e.thread_id.as_ref(),
1989 RoderEvent::FileChangePreviewReady(e) => Some(&e.thread_id),
1990 RoderEvent::PatchProgress(e) => Some(&e.thread_id),
1991 RoderEvent::FileChanged(e) => Some(&e.thread_id),
1992 RoderEvent::TranscriptItemAppended(e) => Some(&e.thread_id),
1993 RoderEvent::TurnCompleted(e) => Some(&e.thread_id),
1994 RoderEvent::TurnFailed(e) => Some(&e.thread_id),
1995 RoderEvent::TurnPartialResult(e) => Some(&e.thread_id),
1996 RoderEvent::TurnDeadlineExceeded(e) => Some(&e.thread_id),
1997 RoderEvent::TurnLifecycleUpdated(e) => Some(&e.thread_id),
1998 RoderEvent::TurnInterrupted(e) => Some(&e.thread_id),
1999 RoderEvent::TurnSteered(e) => Some(&e.thread_id),
2000 RoderEvent::ThreadGoalUpdated(e) => Some(&e.thread_id),
2001 RoderEvent::ThreadGoalCleared(e) => Some(&e.thread_id),
2002 RoderEvent::TeamStarted(e) => Some(&e.lead_thread_id),
2003 RoderEvent::TeamMemberStarted(e) => Some(&e.member.thread_id),
2004 RoderEvent::TeamMemberStatusChanged(e) => Some(&e.member_thread_id),
2005 RoderEvent::TeamMemberMessageDelta(e) => Some(&e.member_thread_id),
2006 RoderEvent::TeamMemberCompleted(e) => Some(&e.member_thread_id),
2007 RoderEvent::SkillActivationResolved(e) => Some(&e.thread_id),
2008 RoderEvent::SkillIndexRendered(e) => Some(&e.thread_id),
2009 RoderEvent::SkillInvoked(e) => Some(&e.thread_id),
2010 RoderEvent::SkillAutoActivated(e) => Some(&e.thread_id),
2011 RoderEvent::SkillSkipped(e) => Some(&e.thread_id),
2012 RoderEvent::RuntimeStarted(_)
2013 | RoderEvent::ExtensionRegistered(_)
2014 | RoderEvent::WorkflowImportsDetected(_)
2015 | RoderEvent::WorkflowImportPreviewed(_)
2016 | RoderEvent::WorkflowImportEnabled(_)
2017 | RoderEvent::WorkflowImportDisabled(_)
2018 | RoderEvent::WorkflowImportStale(_)
2019 | RoderEvent::WorkflowImportFailed(_)
2020 | RoderEvent::MediaArtifactDeleted(_)
2021 | RoderEvent::DiscoveryCatalogBuilt(_)
2022 | RoderEvent::DiscoveryItemUpdated(_)
2023 | RoderEvent::DiscoveryAuthRequired(_)
2024 | RoderEvent::MemorySaved(_)
2025 | RoderEvent::MemoryUpdated(_)
2026 | RoderEvent::MemoryDeleted(_)
2027 | RoderEvent::MemoryQueried(_)
2028 | RoderEvent::MemoryReembedQueued(_)
2029 | RoderEvent::MemoryProviderChanged(_)
2030 | RoderEvent::KnowledgeSaved(_)
2031 | RoderEvent::KnowledgeUpdated(_)
2032 | RoderEvent::KnowledgeArchived(_)
2033 | RoderEvent::KnowledgeLinked(_)
2034 | RoderEvent::RemoteServerStarted(_)
2035 | RoderEvent::RemoteServerStopped(_)
2036 | RoderEvent::RemoteAuthFailed(_)
2037 | RoderEvent::RemoteClientConnected(_)
2038 | RoderEvent::RemoteClientDisconnected(_)
2039 | RoderEvent::RoadmapChanged(_)
2040 | RoderEvent::AutomationCreated(_)
2041 | RoderEvent::AutomationUpdated(_)
2042 | RoderEvent::AutomationDeleted(_)
2043 | RoderEvent::AutomationDue(_)
2044 | RoderEvent::AutomationLeased(_)
2045 | RoderEvent::AutomationQueued(_)
2046 | RoderEvent::AutomationSkipped(_)
2047 | RoderEvent::AutomationLeaseExpired(_)
2048 | RoderEvent::SkillsCatalogLoaded(_)
2049 | RoderEvent::SkillConfigApplied(_)
2050 | RoderEvent::RunnerLifecycle(_)
2051 | RoderEvent::TeamDisplayModeChanged(_)
2052 | RoderEvent::TeamTaskChanged(_)
2053 | RoderEvent::TeamCleanupCompleted(_) => None,
2054 RoderEvent::ProcessStarted(e) => e.process.thread_id.as_ref(),
2055 RoderEvent::ProcessOutput(e) => e.thread_id.as_ref(),
2056 RoderEvent::ProcessExited(e) => e.process.thread_id.as_ref(),
2057 RoderEvent::ProcessStopping(_) => None,
2058 RoderEvent::ProcessStopped(e) => e.process.thread_id.as_ref(),
2059 RoderEvent::ProcessFailed(e) => e.process.thread_id.as_ref(),
2060 RoderEvent::AutomationStarted(e) => e.run.thread_id.as_ref(),
2061 RoderEvent::AutomationCompleted(e) => e.run.thread_id.as_ref(),
2062 RoderEvent::AutomationFailed(e) => e.run.thread_id.as_ref(),
2063 RoderEvent::WorkflowRunDrafted(e) => e.thread_id.as_ref(),
2064 RoderEvent::WorkflowApprovalRequested(e) => e.thread_id.as_ref(),
2065 RoderEvent::WorkflowRunApproved(e) => e.thread_id.as_ref(),
2066 RoderEvent::WorkflowRunDenied(e) => e.thread_id.as_ref(),
2067 RoderEvent::WorkflowRunQueued(e) => e.thread_id.as_ref(),
2068 RoderEvent::WorkflowRunStarted(e) => e.thread_id.as_ref(),
2069 RoderEvent::WorkflowPhaseStarted(e) => e.thread_id.as_ref(),
2070 RoderEvent::WorkflowPhaseCompleted(e) => e.thread_id.as_ref(),
2071 RoderEvent::WorkflowAgentQueued(e) => e.thread_id.as_ref(),
2072 RoderEvent::WorkflowAgentStarted(e) => e.thread_id.as_ref(),
2073 RoderEvent::WorkflowAgentCompleted(e) => e.thread_id.as_ref(),
2074 RoderEvent::WorkflowAgentFailed(e) => e.thread_id.as_ref(),
2075 RoderEvent::WorkflowOutputRecorded(e) => e.thread_id.as_ref(),
2076 RoderEvent::WorkflowCheckpointRecorded(e) => e.thread_id.as_ref(),
2077 RoderEvent::WorkflowRunPaused(e) => e.thread_id.as_ref(),
2078 RoderEvent::WorkflowRunResumed(e) => e.thread_id.as_ref(),
2079 RoderEvent::WorkflowRunStopped(e) => e.thread_id.as_ref(),
2080 RoderEvent::WorkflowRunCompleted(e) => e.thread_id.as_ref(),
2081 RoderEvent::WorkflowRunFailed(e) => e.thread_id.as_ref(),
2082 RoderEvent::ReviewStarted(e) => Some(&e.thread_id),
2083 RoderEvent::ReviewCompleted(e) => Some(&e.thread_id),
2084 RoderEvent::ReviewFailed(e) => Some(&e.thread_id),
2085 RoderEvent::ReviewPublished(e) => e.thread_id.as_ref(),
2086 }
2087 }
2088
2089 pub fn turn_id(&self) -> Option<&TurnId> {
2090 match self {
2091 RoderEvent::ExtensionEventEmitted(_) | RoderEvent::EventSinkFailed(_) => None,
2092 RoderEvent::ThreadForkRequested(_)
2093 | RoderEvent::ThreadForked(_)
2094 | RoderEvent::ThreadForkFailed(_)
2095 | RoderEvent::ThreadForkRemoved(_) => None,
2096 RoderEvent::TurnStarted(e) => Some(&e.turn_id),
2097 RoderEvent::ContextAssemblyStarted(e) => Some(&e.turn_id),
2098 RoderEvent::ContextBlockAdded(e) => Some(&e.turn_id),
2099 RoderEvent::ContextAssemblyCompleted(e) => Some(&e.turn_id),
2100 RoderEvent::ContextEntrypointCandidatesInjected(e) => Some(&e.turn_id),
2101 RoderEvent::ContextCompactionStarted(e) => Some(&e.turn_id),
2102 RoderEvent::ContextCompactionRecorded(e) => Some(&e.turn_id),
2103 RoderEvent::ContextCompactionSkipped(e) => Some(&e.turn_id),
2104 RoderEvent::InferenceRoutingDecision(e) => Some(&e.turn_id),
2105 RoderEvent::InferenceStarted(e) => Some(&e.turn_id),
2106 RoderEvent::InferenceEventReceived(e) => Some(&e.turn_id),
2107 RoderEvent::ToolCallRequested(e) => Some(&e.turn_id),
2108 RoderEvent::HookRunRecorded(e) => Some(&e.turn_id),
2109 RoderEvent::ToolCallValidationRecorded(e) => Some(&e.turn_id),
2110 RoderEvent::ReliabilityFailureRecorded(e) => Some(&e.context.turn_id),
2111 RoderEvent::ReliabilityRetryRecorded(e) => Some(&e.context.turn_id),
2112 RoderEvent::ReliabilityLimitRecorded(e) => Some(&e.context.turn_id),
2113 RoderEvent::ReliabilityMetricRecorded(e) => Some(&e.context.turn_id),
2114 RoderEvent::CodeIndexingStarted(e) => e.context.turn_id.as_ref(),
2115 RoderEvent::CodeIndexChunked(e) => e.context.turn_id.as_ref(),
2116 RoderEvent::CodeIndexEmbedded(e) => e.context.turn_id.as_ref(),
2117 RoderEvent::CodeIndexReady(_) => None,
2118 RoderEvent::CodeIndexStale(e) => e.context.turn_id.as_ref(),
2119 RoderEvent::CodeIndexFailed(e) => e.context.turn_id.as_ref(),
2120 RoderEvent::CodeIndexProofFilteredResultDropped(e) => e.context.turn_id.as_ref(),
2121 RoderEvent::ApprovalRequested(e) => Some(&e.turn_id),
2122 RoderEvent::ApprovalResolved(e) => Some(&e.turn_id),
2123 RoderEvent::ExternalToolCallRequested(e) => Some(&e.turn_id),
2124 RoderEvent::ExternalToolCallResolved(e) => Some(&e.turn_id),
2125 RoderEvent::UserInputRequested(e) => Some(&e.turn_id),
2126 RoderEvent::UserInputResolved(e) => Some(&e.turn_id),
2127 RoderEvent::TaskLedgerUpdated(e) => Some(&e.turn_id),
2128 RoderEvent::VerificationRequired(e) => Some(&e.turn_id),
2129 RoderEvent::VerificationCompleted(e) => Some(&e.turn_id),
2130 RoderEvent::VerificationSkipped(e) => Some(&e.turn_id),
2131 RoderEvent::PolicyDecisionRecorded(e) => Some(&e.turn_id),
2132 RoderEvent::PolicyBypassActive(e) => Some(&e.turn_id),
2133 RoderEvent::PolicyModeChanged(e) => e.turn_id.as_ref(),
2134 RoderEvent::AgentSwarmModeChanged(e) => e.turn_id.as_ref(),
2135 RoderEvent::AgentSwarmStarted(e) => Some(&e.turn_id),
2136 RoderEvent::AgentSwarmProgress(e) => Some(&e.turn_id),
2137 RoderEvent::AgentSwarmCompleted(e) => Some(&e.turn_id),
2138 RoderEvent::UltraModeChanged(e) => e.turn_id.as_ref(),
2139 RoderEvent::PolicyExitPlanRequested(e) => Some(&e.turn_id),
2140 RoderEvent::PolicyExitPlanResolved(e) => Some(&e.turn_id),
2141 RoderEvent::ToolCallStarted(e) => Some(&e.turn_id),
2142 RoderEvent::ToolCallCompleted(e) => Some(&e.turn_id),
2143 RoderEvent::ToolOutputDelta(e) => Some(&e.turn_id),
2144 RoderEvent::ToolOutputTruncated(e) => Some(&e.turn_id),
2145 RoderEvent::SubagentStarted(e) => Some(&e.turn_id),
2146 RoderEvent::SubagentMessage(e) => Some(&e.turn_id),
2147 RoderEvent::SubagentToolCall(e) => Some(&e.turn_id),
2148 RoderEvent::SubagentCompleted(e) => Some(&e.turn_id),
2149 RoderEvent::SubagentFailed(e) => Some(&e.turn_id),
2150 RoderEvent::SubagentTraceCreated(e) => Some(&e.summary.parent.turn_id),
2151 RoderEvent::SubagentTraceDelta(e) => Some(&e.delta.parent.turn_id),
2152 RoderEvent::SubagentTraceStatusChanged(e) => Some(&e.parent.turn_id),
2153 RoderEvent::SubagentTraceCompleted(e) => Some(&e.summary.parent.turn_id),
2154 RoderEvent::SubagentTraceFailed(e) => Some(&e.summary.parent.turn_id),
2155 RoderEvent::PlanReviewCreated(e) => Some(&e.review.turn_id),
2156 RoderEvent::PlanReviewStatusChanged(e) => Some(&e.turn_id),
2157 RoderEvent::PlanReviewCommentAdded(e) => Some(&e.turn_id),
2158 RoderEvent::PlanReviewRewritten(e) => Some(&e.turn_id),
2159 RoderEvent::PlanReviewApproved(e) => Some(&e.turn_id),
2160 RoderEvent::PlanReviewRejected(e) => Some(&e.turn_id),
2161 RoderEvent::HunkRecorded(e) => Some(&e.hunk.turn_id),
2162 RoderEvent::WorkspaceChangeObserved(e) => Some(&e.change.turn_id),
2163 RoderEvent::HunkRollbackRequested(e) => Some(&e.turn_id),
2164 RoderEvent::HunkRollbackCompleted(e) => Some(&e.turn_id),
2165 RoderEvent::MediaArtifactCreated(e) => Some(&e.turn_id),
2166 RoderEvent::MediaArtifactUpdated(e) => Some(&e.turn_id),
2167 RoderEvent::MediaPreviewReady(e) => Some(&e.turn_id),
2168 RoderEvent::ContextArtifactCreated(e) => Some(&e.turn_id),
2169 RoderEvent::ContextArtifactAppended(e) => Some(&e.turn_id),
2170 RoderEvent::ContextArtifactCapped(e) => Some(&e.turn_id),
2171 RoderEvent::DiscoveryItemRead(e) => Some(&e.turn_id),
2172 RoderEvent::DiscoveryItemPromoted(e) => e.record.turn_id.as_ref(),
2173 RoderEvent::DiscoveryPromotionReused(e) => e.record.turn_id.as_ref(),
2174 RoderEvent::DiscoveryWarmCacheHit(e) => e.record.turn_id.as_ref(),
2175 RoderEvent::DiscoveryPromotionExpired(e) => e.record.turn_id.as_ref(),
2176 RoderEvent::RetrievalRoutePlanned(e) => Some(&e.plan.turn_id),
2177 RoderEvent::RetrievalRouteAccepted(e) => Some(&e.turn_id),
2178 RoderEvent::RetrievalRouteIgnored(e) => Some(&e.turn_id),
2179 RoderEvent::RetrievalRouteFailed(e) => Some(&e.turn_id),
2180 RoderEvent::RetrievalResultUsed(e) => Some(&e.turn_id),
2181 RoderEvent::RetrievalDiscoveryItemPromoted(e) => Some(&e.turn_id),
2182 RoderEvent::RetrievalPromotionSkipped(e) => Some(&e.turn_id),
2183 RoderEvent::MemoryRecallReady(e) => Some(&e.turn_id),
2184 RoderEvent::MemoryObservationRecorded(e) => Some(&e.turn_id),
2185 RoderEvent::TaskStarted(e) => e.turn_id.as_ref(),
2186 RoderEvent::TaskOutput(e) => e.turn_id.as_ref(),
2187 RoderEvent::TaskCompleted(e) => e.turn_id.as_ref(),
2188 RoderEvent::TaskFailed(e) => e.turn_id.as_ref(),
2189 RoderEvent::TaskCancelled(e) => e.turn_id.as_ref(),
2190 RoderEvent::FileChangePreviewReady(e) => Some(&e.turn_id),
2191 RoderEvent::PatchProgress(e) => Some(&e.turn_id),
2192 RoderEvent::FileChanged(e) => Some(&e.turn_id),
2193 RoderEvent::TranscriptItemAppended(e) => Some(&e.turn_id),
2194 RoderEvent::TurnCompleted(e) => Some(&e.turn_id),
2195 RoderEvent::TurnFailed(e) => Some(&e.turn_id),
2196 RoderEvent::TurnPartialResult(e) => Some(&e.turn_id),
2197 RoderEvent::TurnDeadlineExceeded(e) => Some(&e.turn_id),
2198 RoderEvent::TurnLifecycleUpdated(e) => Some(&e.turn_id),
2199 RoderEvent::TurnInterrupted(e) => Some(&e.turn_id),
2200 RoderEvent::TurnSteered(e) => Some(&e.turn_id),
2201 RoderEvent::TeamMemberMessageDelta(e) => Some(&e.turn_id),
2202 RoderEvent::TeamMemberCompleted(e) => e.turn_id.as_ref(),
2203 RoderEvent::SkillActivationResolved(e) => Some(&e.turn_id),
2204 RoderEvent::SkillIndexRendered(e) => Some(&e.turn_id),
2205 RoderEvent::SkillInvoked(e) => Some(&e.turn_id),
2206 RoderEvent::SkillAutoActivated(e) => Some(&e.turn_id),
2207 RoderEvent::SkillSkipped(e) => Some(&e.turn_id),
2208 RoderEvent::RuntimeStarted(_)
2209 | RoderEvent::ExtensionRegistered(_)
2210 | RoderEvent::ThreadCreated(_)
2211 | RoderEvent::ThreadLoaded(_)
2212 | RoderEvent::WorkflowImportsDetected(_)
2213 | RoderEvent::WorkflowImportPreviewed(_)
2214 | RoderEvent::WorkflowImportEnabled(_)
2215 | RoderEvent::WorkflowImportDisabled(_)
2216 | RoderEvent::WorkflowImportStale(_)
2217 | RoderEvent::WorkflowImportFailed(_)
2218 | RoderEvent::MediaArtifactDeleted(_)
2219 | RoderEvent::ContextArtifactDeleted(_)
2220 | RoderEvent::ContextArtifactRetentionExpired(_)
2221 | RoderEvent::DiscoveryCatalogBuilt(_)
2222 | RoderEvent::DiscoveryItemUpdated(_)
2223 | RoderEvent::DiscoveryAuthRequired(_)
2224 | RoderEvent::MemorySaved(_)
2225 | RoderEvent::MemoryUpdated(_)
2226 | RoderEvent::MemoryDeleted(_)
2227 | RoderEvent::MemoryQueried(_)
2228 | RoderEvent::MemoryReembedQueued(_)
2229 | RoderEvent::MemoryProviderChanged(_)
2230 | RoderEvent::KnowledgeSaved(_)
2231 | RoderEvent::KnowledgeUpdated(_)
2232 | RoderEvent::KnowledgeArchived(_)
2233 | RoderEvent::KnowledgeLinked(_)
2234 | RoderEvent::RemoteServerStarted(_)
2235 | RoderEvent::RemoteServerStopped(_)
2236 | RoderEvent::RemoteAuthFailed(_)
2237 | RoderEvent::RemoteClientConnected(_)
2238 | RoderEvent::RemoteClientDisconnected(_)
2239 | RoderEvent::ThreadGoalUpdated(_)
2240 | RoderEvent::ThreadGoalCleared(_)
2241 | RoderEvent::RoadmapChanged(_)
2242 | RoderEvent::AutomationCreated(_)
2243 | RoderEvent::AutomationUpdated(_)
2244 | RoderEvent::AutomationDeleted(_)
2245 | RoderEvent::AutomationDue(_)
2246 | RoderEvent::AutomationLeased(_)
2247 | RoderEvent::AutomationQueued(_)
2248 | RoderEvent::AutomationSkipped(_)
2249 | RoderEvent::AutomationLeaseExpired(_)
2250 | RoderEvent::SkillsCatalogLoaded(_)
2251 | RoderEvent::SkillConfigApplied(_)
2252 | RoderEvent::RunnerLifecycle(_)
2253 | RoderEvent::TeamStarted(_)
2254 | RoderEvent::TeamMemberStarted(_)
2255 | RoderEvent::TeamMemberStatusChanged(_)
2256 | RoderEvent::TeamDisplayModeChanged(_)
2257 | RoderEvent::TeamTaskChanged(_)
2258 | RoderEvent::TeamCleanupCompleted(_) => None,
2259 RoderEvent::ProcessStarted(e) => e.process.turn_id.as_ref(),
2260 RoderEvent::ProcessOutput(e) => e.turn_id.as_ref(),
2261 RoderEvent::ProcessExited(e) => e.process.turn_id.as_ref(),
2262 RoderEvent::ProcessStopping(_) => None,
2263 RoderEvent::ProcessStopped(e) => e.process.turn_id.as_ref(),
2264 RoderEvent::ProcessFailed(e) => e.process.turn_id.as_ref(),
2265 RoderEvent::AutomationStarted(e) => e.run.turn_id.as_ref(),
2266 RoderEvent::AutomationCompleted(e) => e.run.turn_id.as_ref(),
2267 RoderEvent::AutomationFailed(e) => e.run.turn_id.as_ref(),
2268 RoderEvent::WorkflowRunDrafted(e) => e.turn_id.as_ref(),
2269 RoderEvent::WorkflowApprovalRequested(e) => e.turn_id.as_ref(),
2270 RoderEvent::WorkflowRunApproved(e) => e.turn_id.as_ref(),
2271 RoderEvent::WorkflowRunDenied(e) => e.turn_id.as_ref(),
2272 RoderEvent::WorkflowRunQueued(e) => e.turn_id.as_ref(),
2273 RoderEvent::WorkflowRunStarted(e) => e.turn_id.as_ref(),
2274 RoderEvent::WorkflowPhaseStarted(e) => e.turn_id.as_ref(),
2275 RoderEvent::WorkflowPhaseCompleted(e) => e.turn_id.as_ref(),
2276 RoderEvent::WorkflowAgentQueued(e) => e.turn_id.as_ref(),
2277 RoderEvent::WorkflowAgentStarted(e) => e.turn_id.as_ref(),
2278 RoderEvent::WorkflowAgentCompleted(e) => e.turn_id.as_ref(),
2279 RoderEvent::WorkflowAgentFailed(e) => e.turn_id.as_ref(),
2280 RoderEvent::WorkflowOutputRecorded(e) => e.turn_id.as_ref(),
2281 RoderEvent::WorkflowCheckpointRecorded(e) => e.turn_id.as_ref(),
2282 RoderEvent::WorkflowRunPaused(e) => e.turn_id.as_ref(),
2283 RoderEvent::WorkflowRunResumed(e) => e.turn_id.as_ref(),
2284 RoderEvent::WorkflowRunStopped(e) => e.turn_id.as_ref(),
2285 RoderEvent::WorkflowRunCompleted(e) => e.turn_id.as_ref(),
2286 RoderEvent::WorkflowRunFailed(e) => e.turn_id.as_ref(),
2287 RoderEvent::ReviewStarted(e) => Some(&e.turn_id),
2288 RoderEvent::ReviewCompleted(e) => Some(&e.turn_id),
2289 RoderEvent::ReviewFailed(e) => e.turn_id.as_ref(),
2290 RoderEvent::ReviewPublished(_) => None,
2291 }
2292 }
2293}
2294
2295#[derive(Debug, Clone, Serialize, Deserialize)]
2296pub struct EventEnvelope {
2297 pub event_id: EventId,
2298 pub seq: u64,
2299 #[serde(with = "time::serde::rfc3339")]
2300 pub timestamp: OffsetDateTime,
2301 pub source: EventSource,
2302 pub kind: String,
2303 pub thread_id: Option<ThreadId>,
2304 pub turn_id: Option<TurnId>,
2305 pub event: RoderEvent,
2306}
2307
2308impl EventEnvelope {
2309 pub fn matches_filter(&self, filter: &EventFilter) -> bool {
2310 filter.matches(self)
2311 }
2312}
2313
2314#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
2315pub struct EventFilter {
2316 pub thread_id: Option<ThreadId>,
2317 pub turn_id: Option<TurnId>,
2318 pub source: Option<EventSource>,
2319 pub kinds: Vec<String>,
2320}
2321
2322impl EventFilter {
2323 pub fn for_thread(thread_id: impl Into<ThreadId>) -> Self {
2324 Self {
2325 thread_id: Some(thread_id.into()),
2326 ..Self::default()
2327 }
2328 }
2329
2330 pub fn for_turn(thread_id: impl Into<ThreadId>, turn_id: impl Into<TurnId>) -> Self {
2331 Self {
2332 thread_id: Some(thread_id.into()),
2333 turn_id: Some(turn_id.into()),
2334 ..Self::default()
2335 }
2336 }
2337
2338 pub fn with_source(mut self, source: EventSource) -> Self {
2339 self.source = Some(source);
2340 self
2341 }
2342
2343 pub fn with_kind(mut self, kind: impl Into<String>) -> Self {
2344 self.kinds.push(kind.into());
2345 self
2346 }
2347
2348 pub fn matches(&self, envelope: &EventEnvelope) -> bool {
2349 if self
2350 .thread_id
2351 .as_ref()
2352 .is_some_and(|thread_id| envelope.thread_id.as_ref() != Some(thread_id))
2353 {
2354 return false;
2355 }
2356 if self
2357 .turn_id
2358 .as_ref()
2359 .is_some_and(|turn_id| envelope.turn_id.as_ref() != Some(turn_id))
2360 {
2361 return false;
2362 }
2363 if self
2364 .source
2365 .as_ref()
2366 .is_some_and(|source| &envelope.source != source)
2367 {
2368 return false;
2369 }
2370 if !self.kinds.is_empty() && !self.kinds.iter().any(|kind| kind == &envelope.kind) {
2371 return false;
2372 }
2373 true
2374 }
2375}
2376
2377#[cfg(test)]
2378mod tests {
2379 use super::*;
2380
2381 fn envelope(thread_id: Option<&str>, turn_id: Option<&str>, kind: &str) -> EventEnvelope {
2382 EventEnvelope {
2383 event_id: "event-1".to_string(),
2384 seq: 1,
2385 timestamp: OffsetDateTime::UNIX_EPOCH,
2386 source: EventSource::Core,
2387 kind: kind.to_string(),
2388 thread_id: thread_id.map(str::to_string),
2389 turn_id: turn_id.map(str::to_string),
2390 event: RoderEvent::TurnStarted(TurnStarted {
2391 thread_id: thread_id.unwrap_or("thread-a").to_string(),
2392 turn_id: turn_id.unwrap_or("turn-a").to_string(),
2393 runtime_profile: RuntimeProfile::Interactive,
2394 timestamp: OffsetDateTime::UNIX_EPOCH,
2395 }),
2396 }
2397 }
2398
2399 #[test]
2400 fn event_filter_matches_thread_turn_source_and_kind() {
2401 let envelope = envelope(Some("thread-a"), Some("turn-a"), "turn.started");
2402 let filter = EventFilter::for_turn("thread-a", "turn-a")
2403 .with_source(EventSource::Core)
2404 .with_kind("turn.started");
2405
2406 assert!(filter.matches(&envelope));
2407 assert!(envelope.matches_filter(&filter));
2408 assert!(!EventFilter::for_thread("thread-b").matches(&envelope));
2409 assert!(!EventFilter::for_turn("thread-a", "turn-b").matches(&envelope));
2410 assert!(
2411 !EventFilter::default()
2412 .with_source(EventSource::Provider)
2413 .matches(&envelope)
2414 );
2415 assert!(
2416 !EventFilter::default()
2417 .with_kind("turn.completed")
2418 .matches(&envelope)
2419 );
2420 }
2421
2422 #[test]
2423 fn empty_event_filter_matches_everything() {
2424 assert!(EventFilter::default().matches(&envelope(None, None, "runtime.started")));
2425 }
2426
2427 #[test]
2428 fn code_index_event_kind_and_scope_are_visible() {
2429 let event = RoderEvent::CodeIndexProofFilteredResultDropped(
2430 crate::code_index::CodeIndexProofFilteredResultDropped {
2431 context: crate::code_index::CodeIndexEventContext {
2432 workspace_root: std::path::PathBuf::from("/repo"),
2433 generation_id: Some("gen-1".to_string()),
2434 thread_id: Some("thread-1".to_string()),
2435 turn_id: Some("turn-1".to_string()),
2436 },
2437 drop: crate::code_index::ProofFilteredDrop {
2438 query_id: "query-1".to_string(),
2439 path_hash: "path-hash".to_string(),
2440 content_hash: "content-hash".to_string(),
2441 reason: "proof missing".to_string(),
2442 },
2443 timestamp: OffsetDateTime::UNIX_EPOCH,
2444 },
2445 );
2446
2447 assert_eq!(event.kind(), "code_index.proof_filtered_result_dropped");
2448 assert_eq!(event.thread_id().map(String::as_str), Some("thread-1"));
2449 assert_eq!(event.turn_id().map(String::as_str), Some("turn-1"));
2450 assert_eq!(event.source(), EventSource::Core);
2451 }
2452
2453 #[test]
2454 fn workflow_event_kind_scope_and_agent_metadata_are_visible() {
2455 let agent = crate::dynamic_workflows::WorkflowAgentRun {
2456 agent_id: "agent-1".to_string(),
2457 phase_id: "phase-1".to_string(),
2458 description: "Review findings".to_string(),
2459 status: crate::dynamic_workflows::WorkflowAgentStatus::Completed,
2460 lane: Some(crate::subagents::SubagentLane::Reviewer),
2461 model: Some("mock-model".to_string()),
2462 thread_id: Some("child-thread".to_string()),
2463 turn_id: Some("child-turn".to_string()),
2464 usage: Some(crate::inference::TokenUsage::new(10, 5, 15)),
2465 exit_reason: None,
2466 error: None,
2467 started_at: Some(OffsetDateTime::UNIX_EPOCH),
2468 completed_at: Some(OffsetDateTime::UNIX_EPOCH),
2469 };
2470 let event = RoderEvent::WorkflowAgentCompleted(WorkflowAgentCompleted {
2471 run_id: "run-1".to_string(),
2472 thread_id: Some("thread-1".to_string()),
2473 turn_id: Some("turn-1".to_string()),
2474 agent,
2475 timestamp: OffsetDateTime::UNIX_EPOCH,
2476 });
2477
2478 assert_eq!(event.kind(), "workflows/agentCompleted");
2479 assert_eq!(event.source(), EventSource::Core);
2480 assert_eq!(event.thread_id().map(String::as_str), Some("thread-1"));
2481 assert_eq!(event.turn_id().map(String::as_str), Some("turn-1"));
2482
2483 let value = serde_json::to_value(&event).unwrap();
2484 let event_value = &value["WorkflowAgentCompleted"];
2485 assert_eq!(event_value["runId"], "run-1");
2486 assert_eq!(event_value["agent"]["phaseId"], "phase-1");
2487 assert_eq!(event_value["agent"]["agentId"], "agent-1");
2488 assert_eq!(event_value["agent"]["status"], "completed");
2489 assert_eq!(event_value["agent"]["usage"]["total_tokens"], 15);
2490 }
2491
2492 #[test]
2493 fn event_timestamps_serialize_as_rfc3339_strings() {
2494 let value =
2495 serde_json::to_value(envelope(Some("thread-a"), Some("turn-a"), "turn.started"))
2496 .unwrap();
2497
2498 assert_eq!(value["timestamp"], "1970-01-01T00:00:00Z");
2499 assert_eq!(
2500 value["event"]["TurnStarted"]["timestamp"],
2501 "1970-01-01T00:00:00Z"
2502 );
2503 }
2504
2505 #[test]
2506 fn subagent_event_envelope_round_trips_parent_ids() {
2507 let event = RoderEvent::SubagentStarted(SubagentStarted {
2508 thread_id: "child-thread".to_string(),
2509 turn_id: "child-turn".to_string(),
2510 parent_thread_id: "parent-thread".to_string(),
2511 parent_turn_id: "parent-turn".to_string(),
2512 agent_type: "explore".to_string(),
2513 description: "Inspect repository".to_string(),
2514 model: Some("test-model".to_string()),
2515 timestamp: OffsetDateTime::UNIX_EPOCH,
2516 });
2517 let envelope = EventEnvelope {
2518 event_id: "event-subagent-started".to_string(),
2519 seq: 7,
2520 timestamp: OffsetDateTime::UNIX_EPOCH,
2521 source: event.source(),
2522 kind: event.kind().to_string(),
2523 thread_id: event.thread_id().cloned(),
2524 turn_id: event.turn_id().cloned(),
2525 event,
2526 };
2527
2528 let serialized = serde_json::to_string(&envelope).unwrap();
2529 let round_trip: EventEnvelope = serde_json::from_str(&serialized).unwrap();
2530
2531 assert_eq!(round_trip.kind, "subagent.started");
2532 assert_eq!(round_trip.source, EventSource::Extension);
2533 assert_eq!(round_trip.thread_id.as_deref(), Some("child-thread"));
2534 assert_eq!(round_trip.turn_id.as_deref(), Some("child-turn"));
2535
2536 match round_trip.event {
2537 RoderEvent::SubagentStarted(started) => {
2538 assert_eq!(started.parent_thread_id, "parent-thread");
2539 assert_eq!(started.parent_turn_id, "parent-turn");
2540 }
2541 other => panic!("unexpected event: {other:?}"),
2542 }
2543 }
2544
2545 #[test]
2546 fn subagent_trace_event_uses_parent_turn_for_filtering() {
2547 let summary = SubagentTraceSummary {
2548 trace_id: "trace-1".to_string(),
2549 parent: ParentTurnRef {
2550 thread_id: "parent-thread".to_string(),
2551 turn_id: "parent-turn".to_string(),
2552 },
2553 child_thread_id: "child-thread".to_string(),
2554 child_turn_id: "child-turn".to_string(),
2555 title: "Inspect repository".to_string(),
2556 role: "explorer".to_string(),
2557 model: Some("test-model".to_string()),
2558 lane: None,
2559 status: SubagentTraceStatus::Running,
2560 elapsed_ms: 10,
2561 usage: None,
2562 destination: None,
2563 latest_activity: None,
2564 error_summary: None,
2565 exit_reason: None,
2566 };
2567 let event = RoderEvent::SubagentTraceCreated(SubagentTraceCreated {
2568 summary,
2569 timestamp: OffsetDateTime::UNIX_EPOCH,
2570 });
2571
2572 assert_eq!(event.kind(), "turn/subagentTraceCreated");
2573 assert_eq!(event.source(), EventSource::Extension);
2574 assert_eq!(event.thread_id().map(String::as_str), Some("parent-thread"));
2575 assert_eq!(event.turn_id().map(String::as_str), Some("parent-turn"));
2576 }
2577
2578 #[test]
2579 fn task_events_round_trip_with_replay_ids() {
2580 let event = RoderEvent::TaskOutput(TaskOutput {
2581 task_id: "task-1".to_string(),
2582 stream: crate::tasks::TaskOutputStream::Stdout,
2583 chunk: "building\n".to_string(),
2584 dropped_bytes: 0,
2585 thread_id: Some("thread-a".to_string()),
2586 turn_id: Some("turn-a".to_string()),
2587 timestamp: OffsetDateTime::UNIX_EPOCH,
2588 });
2589 let envelope = EventEnvelope {
2590 event_id: "event-task-output".to_string(),
2591 seq: 9,
2592 timestamp: OffsetDateTime::UNIX_EPOCH,
2593 source: event.source(),
2594 kind: event.kind().to_string(),
2595 thread_id: event.thread_id().cloned(),
2596 turn_id: event.turn_id().cloned(),
2597 event,
2598 };
2599
2600 let serialized = serde_json::to_string(&envelope).unwrap();
2601 let round_trip: EventEnvelope = serde_json::from_str(&serialized).unwrap();
2602
2603 assert_eq!(round_trip.kind, "task.output");
2604 assert_eq!(round_trip.source, EventSource::Extension);
2605 assert_eq!(round_trip.thread_id.as_deref(), Some("thread-a"));
2606 assert_eq!(round_trip.turn_id.as_deref(), Some("turn-a"));
2607 match round_trip.event {
2608 RoderEvent::TaskOutput(output) => {
2609 assert_eq!(output.task_id, "task-1");
2610 assert_eq!(output.stream, crate::tasks::TaskOutputStream::Stdout);
2611 assert_eq!(output.chunk, "building\n");
2612 }
2613 other => panic!("unexpected event: {other:?}"),
2614 }
2615 }
2616
2617 #[test]
2618 fn automations_event_exposes_kind_source_and_replay_scope() {
2619 let run = crate::automations::AutomationRunSummary {
2620 run_id: "run-1".to_string(),
2621 automation_id: "automation-1".to_string(),
2622 occurrence_key: "automation-1:1970-01-01T00:00:00Z".to_string(),
2623 state: crate::automations::AutomationRunState::Completed,
2624 scheduled_for: OffsetDateTime::UNIX_EPOCH,
2625 queued_at: Some(OffsetDateTime::UNIX_EPOCH),
2626 started_at: Some(OffsetDateTime::UNIX_EPOCH),
2627 finished_at: Some(OffsetDateTime::UNIX_EPOCH),
2628 thread_id: Some("thread-a".to_string()),
2629 turn_id: Some("turn-a".to_string()),
2630 task_id: Some("task-1".to_string()),
2631 server_id: Some("desktop-main".to_string()),
2632 server_role: Some("desktop".to_string()),
2633 exit_code: Some(0),
2634 error: None,
2635 skip_reason: None,
2636 };
2637 let event = RoderEvent::AutomationCompleted(crate::automations::AutomationCompleted {
2638 run,
2639 timestamp: OffsetDateTime::UNIX_EPOCH,
2640 });
2641
2642 assert_eq!(event.kind(), "automations/completed");
2643 assert_eq!(event.source(), EventSource::Core);
2644 assert_eq!(event.thread_id().map(String::as_str), Some("thread-a"));
2645 assert_eq!(event.turn_id().map(String::as_str), Some("turn-a"));
2646
2647 let value = serde_json::to_value(&event).unwrap();
2648 assert_eq!(
2649 value["AutomationCompleted"]["run"]["occurrenceKey"],
2650 "automation-1:1970-01-01T00:00:00Z"
2651 );
2652 assert_eq!(
2653 value["AutomationCompleted"]["run"]["serverId"],
2654 "desktop-main"
2655 );
2656 }
2657
2658 #[test]
2659 fn tool_call_completed_round_trips_error_status() {
2660 let event = RoderEvent::ToolCallCompleted(ToolCallCompleted {
2661 thread_id: "thread-a".to_string(),
2662 turn_id: "turn-a".to_string(),
2663 tool_id: "tool-a".to_string(),
2664 tool_name: Some("list_files".to_string()),
2665 display_payload: Some(serde_json::json!({ "path": "." })),
2666 is_error: true,
2667 output: Some("tool failed".to_string()),
2668 timestamp: OffsetDateTime::UNIX_EPOCH,
2669 });
2670 let envelope = EventEnvelope {
2671 event_id: "event-tool-completed".to_string(),
2672 seq: 10,
2673 timestamp: OffsetDateTime::UNIX_EPOCH,
2674 source: event.source(),
2675 kind: event.kind().to_string(),
2676 thread_id: event.thread_id().cloned(),
2677 turn_id: event.turn_id().cloned(),
2678 event,
2679 };
2680
2681 let serialized = serde_json::to_string(&envelope).unwrap();
2682 let round_trip: EventEnvelope = serde_json::from_str(&serialized).unwrap();
2683
2684 assert_eq!(round_trip.kind, "tool.call_completed");
2685 match round_trip.event {
2686 RoderEvent::ToolCallCompleted(completed) => {
2687 assert_eq!(completed.tool_id, "tool-a");
2688 assert!(completed.is_error);
2689 assert_eq!(completed.output.as_deref(), Some("tool failed"));
2690 }
2691 other => panic!("unexpected event: {other:?}"),
2692 }
2693 }
2694
2695 #[test]
2696 fn file_change_preview_event_round_trips_public_metadata() {
2697 let event = RoderEvent::FileChangePreviewReady(FileChangePreviewReady {
2698 thread_id: "thread-a".to_string(),
2699 turn_id: "turn-a".to_string(),
2700 tool_id: "tool-a".to_string(),
2701 tool_name: "edit".to_string(),
2702 path: "src/lib.rs".to_string(),
2703 change_type: "modify".to_string(),
2704 before: Some("old\n".to_string()),
2705 after: "new\n".to_string(),
2706 supports_partial: false,
2707 timestamp: OffsetDateTime::UNIX_EPOCH,
2708 });
2709 let envelope = EventEnvelope {
2710 event_id: "event-file-preview".to_string(),
2711 seq: 8,
2712 timestamp: OffsetDateTime::UNIX_EPOCH,
2713 source: event.source(),
2714 kind: event.kind().to_string(),
2715 thread_id: event.thread_id().cloned(),
2716 turn_id: event.turn_id().cloned(),
2717 event,
2718 };
2719
2720 let serialized = serde_json::to_string(&envelope).unwrap();
2721 let round_trip: EventEnvelope = serde_json::from_str(&serialized).unwrap();
2722
2723 assert_eq!(round_trip.kind, "file.change_preview_ready");
2724 assert_eq!(round_trip.source, EventSource::Tool);
2725 assert_eq!(round_trip.thread_id.as_deref(), Some("thread-a"));
2726 assert_eq!(round_trip.turn_id.as_deref(), Some("turn-a"));
2727 match round_trip.event {
2728 RoderEvent::FileChangePreviewReady(preview) => {
2729 assert_eq!(preview.tool_id, "tool-a");
2730 assert_eq!(preview.tool_name, "edit");
2731 assert_eq!(preview.path, "src/lib.rs");
2732 assert_eq!(preview.change_type, "modify");
2733 assert_eq!(preview.before.as_deref(), Some("old\n"));
2734 assert_eq!(preview.after, "new\n");
2735 assert!(!preview.supports_partial);
2736 }
2737 other => panic!("unexpected event: {other:?}"),
2738 }
2739 }
2740
2741 #[test]
2742 fn inference_started_deserializes_older_records_without_model_fields() {
2743 let value = serde_json::json!({
2744 "InferenceStarted": {
2745 "thread_id": "thread-a",
2746 "turn_id": "turn-a",
2747 "engine_id": "mock",
2748 "timestamp": "1970-01-01T00:00:00Z"
2749 }
2750 });
2751
2752 let event: RoderEvent = serde_json::from_value(value).unwrap();
2753
2754 match event {
2755 RoderEvent::InferenceStarted(started) => {
2756 assert_eq!(started.model.provider, "");
2757 assert_eq!(started.model.model, "");
2758 assert_eq!(started.reasoning, ReasoningConfig::default());
2759 }
2760 other => panic!("expected inference started, got {other:?}"),
2761 }
2762 }
2763
2764 #[test]
2765 fn team_member_completed_round_trips_optional_result_details() {
2766 let event = RoderEvent::TeamMemberCompleted(TeamMemberCompleted {
2767 team_id: "team-a".to_string(),
2768 member_id: "member-a".to_string(),
2769 member_thread_id: "thread-a".to_string(),
2770 turn_id: Some("turn-a".to_string()),
2771 status: TeamMemberStatus::Failed,
2772 final_message: Some("Partial review result.".to_string()),
2773 error: Some("provider request failed".to_string()),
2774 timestamp: OffsetDateTime::UNIX_EPOCH,
2775 });
2776
2777 let value = serde_json::to_value(&event).unwrap();
2778 assert_eq!(
2779 value["TeamMemberCompleted"]["final_message"],
2780 "Partial review result."
2781 );
2782 assert_eq!(
2783 value["TeamMemberCompleted"]["error"],
2784 "provider request failed"
2785 );
2786 let round_trip: RoderEvent = serde_json::from_value(value).unwrap();
2787 match round_trip {
2788 RoderEvent::TeamMemberCompleted(completed) => {
2789 assert_eq!(
2790 completed.final_message.as_deref(),
2791 Some("Partial review result.")
2792 );
2793 assert_eq!(completed.error.as_deref(), Some("provider request failed"));
2794 }
2795 other => panic!("expected team completion, got {other:?}"),
2796 }
2797
2798 let legacy: RoderEvent = serde_json::from_value(serde_json::json!({
2799 "TeamMemberCompleted": {
2800 "team_id": "team-a",
2801 "member_id": "member-a",
2802 "member_thread_id": "thread-a",
2803 "turn_id": "turn-a",
2804 "status": "completed",
2805 "timestamp": "1970-01-01T00:00:00Z"
2806 }
2807 }))
2808 .unwrap();
2809 match legacy {
2810 RoderEvent::TeamMemberCompleted(completed) => {
2811 assert!(completed.final_message.is_none());
2812 assert!(completed.error.is_none());
2813 }
2814 other => panic!("expected team completion, got {other:?}"),
2815 }
2816 }
2817
2818 #[test]
2819 fn processes_events_expose_kind_source_scope_and_round_trip() {
2820 let descriptor = crate::processes::ProcessDescriptor {
2821 process_id: "process-1".to_string(),
2822 origin: crate::processes::ProcessOrigin::CommandExec,
2823 state: crate::processes::ProcessState::Running,
2824 command: vec!["sleep".to_string(), "10".to_string()],
2825 command_summary: "sleep 10".to_string(),
2826 cwd: Some("/repo".to_string()),
2827 pid: Some(1234),
2828 task_id: Some("task-1".to_string()),
2829 thread_id: Some("thread-a".to_string()),
2830 turn_id: Some("turn-a".to_string()),
2831 runner_destination_id: None,
2832 runner_session_id: None,
2833 stoppable: true,
2834 started_at: OffsetDateTime::UNIX_EPOCH,
2835 updated_at: OffsetDateTime::UNIX_EPOCH,
2836 stdout_tail: None,
2837 stderr_tail: None,
2838 };
2839 let event = RoderEvent::ProcessStarted(crate::processes::ProcessStarted {
2840 process: descriptor,
2841 timestamp: OffsetDateTime::UNIX_EPOCH,
2842 });
2843 let envelope = EventEnvelope {
2844 event_id: "event-process-started".to_string(),
2845 seq: 11,
2846 timestamp: OffsetDateTime::UNIX_EPOCH,
2847 source: event.source(),
2848 kind: event.kind().to_string(),
2849 thread_id: event.thread_id().cloned(),
2850 turn_id: event.turn_id().cloned(),
2851 event,
2852 };
2853
2854 let serialized = serde_json::to_string(&envelope).unwrap();
2855 let round_trip: EventEnvelope = serde_json::from_str(&serialized).unwrap();
2856
2857 assert_eq!(round_trip.kind, "process.started");
2858 assert_eq!(round_trip.source, EventSource::Extension);
2859 assert_eq!(round_trip.thread_id.as_deref(), Some("thread-a"));
2860 assert_eq!(round_trip.turn_id.as_deref(), Some("turn-a"));
2861 match round_trip.event {
2862 RoderEvent::ProcessStarted(started) => {
2863 assert_eq!(started.process.process_id, "process-1");
2864 assert_eq!(started.process.pid, Some(1234));
2865 }
2866 other => panic!("unexpected event: {other:?}"),
2867 }
2868
2869 let output = RoderEvent::ProcessOutput(crate::processes::ProcessOutput {
2870 process_id: "process-1".to_string(),
2871 stream: crate::tasks::TaskOutputStream::Stdout,
2872 chunk: "ready\n".to_string(),
2873 dropped_bytes: 0,
2874 thread_id: Some("thread-a".to_string()),
2875 turn_id: Some("turn-a".to_string()),
2876 timestamp: OffsetDateTime::UNIX_EPOCH,
2877 });
2878 assert_eq!(output.kind(), "process.output");
2879 assert_eq!(output.thread_id().map(String::as_str), Some("thread-a"));
2880 assert_eq!(output.turn_id().map(String::as_str), Some("turn-a"));
2881 }
2882
2883 #[test]
2884 fn skill_activation_event_exposes_kind_source_and_turn_scope() {
2885 let descriptor = crate::skills::SkillDescriptor {
2886 id: "builtin:commit".to_string(),
2887 name: "commit".to_string(),
2888 canonical_path: "roder-builtin://commit/SKILL.md".to_string(),
2889 source: crate::skills::SkillSource::BuiltIn,
2890 exposure: crate::skills::SkillExposure::DirectOnly,
2891 activation: crate::skills::SkillActivationState::Enabled,
2892 description: "Commit staged changes safely.".to_string(),
2893 short_description: Some("Commit safely".to_string()),
2894 experimental: false,
2895 diagnostics: Vec::new(),
2896 agent_metadata: None,
2897 };
2898 let event = RoderEvent::SkillActivationResolved(crate::skills::SkillActivationResolved {
2899 thread_id: "thread-a".to_string(),
2900 turn_id: "turn-a".to_string(),
2901 selector: crate::skills::SkillSelector::Name {
2902 name: "commit".to_string(),
2903 },
2904 activation_reason: crate::skills::SkillActivationReason::FeatureBinding,
2905 activated: true,
2906 descriptor: Some(descriptor),
2907 diagnostic: None,
2908 timestamp: OffsetDateTime::UNIX_EPOCH,
2909 });
2910
2911 assert_eq!(event.kind(), "skills/activationResolved");
2912 assert_eq!(event.source(), EventSource::Core);
2913 assert_eq!(event.thread_id().map(String::as_str), Some("thread-a"));
2914 assert_eq!(event.turn_id().map(String::as_str), Some("turn-a"));
2915 }
2916}