orcs_runtime/channel/traits.rs
1//! Channel trait definitions.
2//!
3//! The [`ChannelCore`] trait defines the core interface for all channel types.
4//! This allows different channel implementations (e.g., `BaseChannel`) to share
5//! a common interface while having different internal structures.
6//!
7//! For Human-interactive channels, use [`ClientRunner`](super::ClientRunner) which
8//! combines `BaseChannel` with IO bridging capabilities.
9
10use super::{ChannelConfig, ChannelState};
11use orcs_types::{ChannelId, Principal};
12use std::collections::HashSet;
13
14/// Core channel interface.
15///
16/// This trait defines the essential operations that all channel types must support.
17/// It provides a common interface for state queries, tree navigation, and lifecycle
18/// management.
19///
20/// # Implementors
21///
22/// - [`BaseChannel`](super::BaseChannel): Basic channel with state and tree management
23///
24/// For Human-interactive channels, use [`ClientRunner`](super::ClientRunner) which
25/// owns a `BaseChannel` internally.
26///
27/// # Example
28///
29/// ```ignore
30/// use orcs_runtime::channel::ChannelCore;
31///
32/// fn process_channel(channel: &impl ChannelCore) {
33/// println!("Channel {} is running: {}", channel.id(), channel.is_running());
34/// println!("Principal: {:?}", channel.principal());
35/// }
36/// ```
37pub trait ChannelCore {
38 // === Identity ===
39
40 /// Returns the channel's unique identifier.
41 fn id(&self) -> ChannelId;
42
43 /// Returns the principal associated with this channel.
44 ///
45 /// The principal is used for scope resolution and permission checks.
46 fn principal(&self) -> &Principal;
47
48 // === State ===
49
50 /// Returns a reference to the current state.
51 fn state(&self) -> &ChannelState;
52
53 /// Returns `true` if the channel is in Running state.
54 fn is_running(&self) -> bool {
55 matches!(self.state(), ChannelState::Running)
56 }
57
58 /// Returns `true` if the channel is in Paused state.
59 fn is_paused(&self) -> bool {
60 matches!(self.state(), ChannelState::Paused)
61 }
62
63 /// Returns `true` if the channel is in AwaitingApproval state.
64 fn is_awaiting_approval(&self) -> bool {
65 matches!(self.state(), ChannelState::AwaitingApproval { .. })
66 }
67
68 /// Returns `true` if the channel is in a terminal state (Completed or Aborted).
69 fn is_terminal(&self) -> bool {
70 matches!(
71 self.state(),
72 ChannelState::Completed | ChannelState::Aborted { .. }
73 )
74 }
75
76 // === Configuration ===
77
78 /// Returns a reference to the channel's configuration.
79 fn config(&self) -> &ChannelConfig;
80
81 /// Returns the scheduling priority (0-255).
82 fn priority(&self) -> u8 {
83 self.config().priority()
84 }
85
86 /// Returns whether this channel can spawn children.
87 fn can_spawn(&self) -> bool {
88 self.config().can_spawn()
89 }
90
91 // === Tree Structure ===
92
93 /// Returns the parent channel's ID, if any.
94 fn parent(&self) -> Option<ChannelId>;
95
96 /// Returns a reference to the set of child channel IDs.
97 fn children(&self) -> &HashSet<ChannelId>;
98
99 /// Returns `true` if this channel has any children.
100 fn has_children(&self) -> bool {
101 !self.children().is_empty()
102 }
103
104 /// Returns the cached ancestor path.
105 ///
106 /// The path is ordered: `[parent, grandparent, ..., root]`.
107 fn ancestor_path(&self) -> &[ChannelId];
108
109 /// Returns the depth of this channel in the tree.
110 fn depth(&self) -> usize {
111 self.ancestor_path().len()
112 }
113
114 /// Returns `true` if this channel is a descendant of the given ancestor.
115 fn is_descendant_of(&self, ancestor: ChannelId) -> bool {
116 self.ancestor_path().contains(&ancestor)
117 }
118}
119
120/// Mutable channel operations.
121///
122/// This trait extends [`ChannelCore`] with state transition and tree modification
123/// operations. Separated from `ChannelCore` to allow read-only access patterns.
124pub trait ChannelMut: ChannelCore {
125 // === State Transitions ===
126
127 /// Transitions to Completed state.
128 ///
129 /// Returns `true` if transition succeeded, `false` if not in Running state.
130 fn complete(&mut self) -> bool;
131
132 /// Transitions to Aborted state.
133 ///
134 /// Returns `true` if transition succeeded, `false` if already terminal.
135 fn abort(&mut self, reason: String) -> bool;
136
137 /// Transitions to Paused state.
138 ///
139 /// Returns `true` if transition succeeded, `false` if not in Running state.
140 fn pause(&mut self) -> bool;
141
142 /// Transitions from Paused to Running state.
143 ///
144 /// Returns `true` if transition succeeded, `false` if not in Paused state.
145 fn resume(&mut self) -> bool;
146
147 /// Transitions to AwaitingApproval state.
148 ///
149 /// Returns `true` if transition succeeded, `false` if not in Running state.
150 fn await_approval(&mut self, request_id: String) -> bool;
151
152 /// Resolves approval and transitions to Running state.
153 ///
154 /// Only succeeds if the channel is in AwaitingApproval state AND
155 /// the stored `request_id` matches the given `approval_id`.
156 /// Returns the request_id if matched, None otherwise.
157 fn resolve_approval(&mut self, approval_id: &str) -> Option<String>;
158
159 // === Tree Modification ===
160
161 /// Registers a child channel.
162 fn add_child(&mut self, id: ChannelId);
163
164 /// Unregisters a child channel.
165 fn remove_child(&mut self, id: &ChannelId);
166}