Skip to main content

vtcode_core/core/agent/
steering.rs

1use serde::{Deserialize, Serialize};
2use std::fmt;
3use uuid::Uuid;
4
5/// Maximum number of follow-up intents held by a runtime before new intents
6/// park in the overflow buffer. The overflow buffer keeps rapid influx from
7/// silently dropping user messages; once both buffers are full the caller
8/// receives `FollowUpQueueFull` so back-pressure stays visible.
9pub const MAX_QUEUED_FOLLOW_UP_INTENTS: usize = 64;
10/// Overflow park capacity after the primary FIFO is full. Combined with the
11/// primary cap this bounds total retained follow-ups while still absorbing
12/// a burst instead of discarding it.
13pub const MAX_OVERFLOW_FOLLOW_UP_INTENTS: usize = 64;
14/// Maximum number of applied follow-up IDs retained for restart recovery.
15pub const MAX_APPLIED_FOLLOW_UP_INTENT_IDS: usize = 64;
16
17/// A follow-up instruction with a stable identity for recovery and
18/// de-duplication.
19#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
20pub struct QueuedFollowUpIntent {
21    id: String,
22    text: String,
23}
24
25impl QueuedFollowUpIntent {
26    /// Create a new intent with a UUIDv4 identity.
27    #[must_use]
28    pub fn new(text: String) -> Self {
29        Self { id: Uuid::new_v4().to_string(), text }
30    }
31
32    /// Reconstruct an intent recovered from durable state.
33    pub fn from_parts(id: impl Into<String>, text: impl Into<String>) -> Self {
34        Self { id: id.into(), text: text.into() }
35    }
36
37    #[must_use]
38    pub fn id(&self) -> &str {
39        &self.id
40    }
41
42    #[must_use]
43    pub fn text(&self) -> &str {
44        &self.text
45    }
46
47    /// Consume the intent and return its user-visible text.
48    #[must_use]
49    pub fn into_parts(self) -> (String, String) {
50        (self.id, self.text)
51    }
52}
53
54/// Error returned when a runtime cannot accept another follow-up intent.
55#[derive(Debug, Clone, PartialEq, Eq)]
56pub struct FollowUpQueueFull {
57    pub capacity: usize,
58}
59
60impl fmt::Display for FollowUpQueueFull {
61    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62        write!(f, "follow-up intent queue is full (capacity {})", self.capacity)
63    }
64}
65
66impl std::error::Error for FollowUpQueueFull {}
67
68/// Messages used to steer the agent's execution loop from an external source.
69#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
70pub enum SteeringMessage {
71    /// Stop the agent's execution loop immediately (Steering).
72    SteerStop,
73    /// Pause the agent's execution loop.
74    Pause,
75    /// Resume the agent's execution loop.
76    Resume,
77    /// Inject input as a follow-up user message. The turn loop applies it to
78    /// live history at the next iteration boundary (mid-turn steering) or, if
79    /// the turn ends first, delivers it at the next turn boundary.
80    FollowUpInput(String),
81}