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