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