Skip to main content

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}