vtcode_desktop_protocol/
interaction_registry.rs1use std::collections::HashMap;
3
4use super::{InteractionRequest, InteractionResponse, ProtocolError};
5
6#[derive(Debug, Default)]
8pub struct InteractionRegistry {
9 pending: HashMap<String, (String, String)>,
10}
11
12impl InteractionRegistry {
13 pub fn insert(&mut self, interaction: &InteractionRequest) -> Result<(), ProtocolError> {
15 if self.pending.contains_key(&interaction.interaction_id) {
16 return Err(ProtocolError::UnknownInteraction);
17 }
18 let replaced = self
19 .pending
20 .insert(interaction.interaction_id.clone(), (interaction.session_id.clone(), interaction.turn_id.clone()));
21 debug_assert!(replaced.is_none(), "duplicate interaction identity was checked before insertion");
22 Ok(())
23 }
24
25 pub fn validate(&self, response: &InteractionResponse) -> Result<(), ProtocolError> {
27 let Some((session_id, turn_id)) = self.pending.get(&response.interaction_id) else {
28 return Err(ProtocolError::UnknownInteraction);
29 };
30 if session_id != &response.session_id || turn_id != &response.turn_id {
31 return Err(ProtocolError::StaleInteraction);
32 }
33 Ok(())
34 }
35
36 pub fn resolve(&mut self, response: &InteractionResponse) -> Result<(), ProtocolError> {
38 self.validate(response)?;
39 if self.pending.remove(&response.interaction_id).is_none() {
40 return Err(ProtocolError::UnknownInteraction);
41 }
42 Ok(())
43 }
44
45 pub fn finish_turn(&mut self, session_id: &str, turn_id: &str) {
47 self.pending
48 .retain(|_, (pending_session, pending_turn)| pending_session != session_id || pending_turn != turn_id);
49 }
50
51 pub fn close_session(&mut self, session_id: &str) {
53 self.pending.retain(|_, (pending_session, _)| pending_session != session_id);
54 }
55}