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}