Skip to main content

entelix_graph/
command.rs

1//! `Command<S>` — caller's instruction for `CompiledGraph::resume_with`.
2//!
3//! After an interrupt the caller has four reasonable next moves:
4//! - `Resume` as-is from the saved next-node and saved state.
5//! - `Update(s)` the state (e.g. inject the human's reply) and continue
6//!   from the saved next-node.
7//! - `GoTo(node)` skip ahead to a different node, keeping the saved state.
8//! - `ApproveTool { tool_use_id, decision }` thread an out-of-band
9//!   approval decision back into the graph for an `AwaitExternal`
10//!   pause raised by an approval layer (`entelix-agents::ApprovalLayer`).
11//!   The resume path attaches the decision to `ExecutionContext` via
12//!   the typed `entelix_core::PendingApprovalDecisions` extension so
13//!   the layer's override-lookup short-circuits the approver on
14//!   re-entry.
15
16use entelix_core::ApprovalDecision;
17
18/// Resume directive supplied to `CompiledGraph::resume_with`.
19#[derive(Clone, Debug)]
20#[non_exhaustive]
21pub enum Command<S>
22where
23    S: Clone + Send + Sync + 'static,
24{
25    /// Continue from the saved checkpoint exactly as it stands.
26    Resume,
27    /// Replace the saved state, then continue from the saved next-node.
28    Update(S),
29    /// Continue with the saved state but jump to `node` next.
30    GoTo(String),
31    /// Resume an `AwaitExternal` pause with the operator's eventual
32    /// decision for the named `tool_use_id`. The resume path
33    /// attaches the decision to `ExecutionContext` via
34    /// `PendingApprovalDecisions` so the agent's approval layer
35    /// short-circuits the approver on re-entry; the pending tool
36    /// dispatches with `decision` applied. Saved state is kept
37    /// intact (combine with `Update(s)` outside `resume_with` if
38    /// state mutation is also needed).
39    ///
40    /// This variant does not depend on the enum's `S` parameter —
41    /// the tool-use id and decision are state-agnostic. The `S`
42    /// generic is part of the enum's shape (other variants need
43    /// it); operators reach this variant via the same
44    /// `Command::<S>::ApproveTool { ... }` path as any other.
45    ApproveTool {
46        /// Tool-use id matching the originating `ContentPart::ToolUse`
47        /// — the same id carried in the `Error::Interrupted::payload`
48        /// emitted by the layer.
49        tool_use_id: String,
50        /// Operator's decision (`Approve` to fire the dispatch,
51        /// `Reject { reason }` to short-circuit). `AwaitExternal`
52        /// is rejected at runtime — pausing again on resume is
53        /// almost certainly an operator bug.
54        decision: ApprovalDecision,
55    },
56}