vtcode_core/core/interfaces/
session.rs1use anyhow::Result;
2use async_trait::async_trait;
3
4use crate::config::loader::VTCodeConfig;
5use crate::config::types::AgentConfig as CoreAgentConfig;
6use crate::core::agent::steering::SteeringMessage;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
10pub enum SessionMode {
11 Ask,
12 Architect,
13 #[default]
14 Code,
15}
16
17impl SessionMode {
18 pub const fn as_str(self) -> &'static str {
19 match self {
20 Self::Ask => "ask",
21 Self::Architect => "architect",
22 Self::Code => "code",
23 }
24 }
25
26 pub fn parse(value: &str) -> Option<Self> {
27 match value {
28 "ask" => Some(Self::Ask),
29 "architect" => Some(Self::Architect),
30 "code" => Some(Self::Code),
31 _ => None,
32 }
33 }
34}
35
36#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
38pub enum PlanModeEntrySource {
39 #[default]
40 None,
41 CliFlag,
42 ConfigDefault,
43 UserRequest,
44}
45
46impl PlanModeEntrySource {
47 pub const fn should_auto_enter(self) -> bool {
48 matches!(self, Self::CliFlag)
49 }
50
51 pub const fn requires_startup_prompt(self) -> bool {
52 matches!(self, Self::ConfigDefault)
53 }
54}
55
56#[derive(Debug)]
58pub struct SessionRuntimeParams<'a, Resume> {
59 pub agent_config: &'a CoreAgentConfig,
60 pub vt_config: Option<VTCodeConfig>,
61 pub skip_confirmations: bool,
62 pub full_auto: bool,
63 pub plan_mode_entry_source: PlanModeEntrySource,
64 pub resume: Option<Resume>,
65 pub steering_receiver: &'a mut Option<tokio::sync::mpsc::UnboundedReceiver<SteeringMessage>>,
66}
67
68impl<'a, Resume> SessionRuntimeParams<'a, Resume> {
69 #[expect(clippy::too_many_arguments)]
70 pub fn new(
71 agent_config: &'a CoreAgentConfig,
72 vt_config: Option<VTCodeConfig>,
73 skip_confirmations: bool,
74 full_auto: bool,
75 plan_mode_entry_source: PlanModeEntrySource,
76 resume: Option<Resume>,
77 steering_receiver: &'a mut Option<tokio::sync::mpsc::UnboundedReceiver<SteeringMessage>>,
78 ) -> Self {
79 Self {
80 agent_config,
81 vt_config,
82 skip_confirmations,
83 full_auto,
84 plan_mode_entry_source,
85 resume,
86 steering_receiver,
87 }
88 }
89}
90
91#[async_trait]
93pub trait SessionRuntime<Resume>: Send + Sync {
94 async fn run_session(&self, params: SessionRuntimeParams<'_, Resume>) -> Result<()>;
95}
96
97#[cfg(test)]
98mod tests {
99 use super::SessionMode;
100
101 #[test]
102 fn session_mode_round_trip() {
103 assert_eq!(
104 SessionMode::parse(SessionMode::Ask.as_str()),
105 Some(SessionMode::Ask)
106 );
107 assert_eq!(
108 SessionMode::parse(SessionMode::Architect.as_str()),
109 Some(SessionMode::Architect)
110 );
111 assert_eq!(
112 SessionMode::parse(SessionMode::Code.as_str()),
113 Some(SessionMode::Code)
114 );
115 assert_eq!(SessionMode::parse("unknown"), None);
116 }
117}