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