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