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