use crate::connection::AnyConnection;
use crate::connection::Connection;
use anyhow::Result;
use serde::{Serialize, de::DeserializeOwned};
use serde_json::Value;
use std::collections::HashMap;
use std::sync::Mutex;
#[derive(Debug)]
pub struct ToolContext {
connection: AnyConnection,
state: Mutex<HashMap<String, Value>>,
}
impl ToolContext {
pub fn new(connection: AnyConnection) -> Self {
Self {
connection,
state: Mutex::new(HashMap::new()),
}
}
pub fn conversation_id(&self) -> &str {
self.connection.conversation_id()
}
pub fn is_idle(&self) -> bool {
self.connection.is_idle()
}
pub async fn send(&self, message: &str) -> Result<()> {
self.connection.send_trigger_notification(message).await
}
pub fn get_state<T: DeserializeOwned>(&self, key: &str) -> Option<T> {
self.state
.lock()
.ok()
.and_then(|store| store.get(key).cloned())
.and_then(|v| serde_json::from_value(v).ok())
}
#[allow(clippy::collapsible_if)]
pub fn set_state<T: Serialize>(&self, key: &str, value: T) {
if let Ok(mut store) = self.state.lock() {
if let Ok(v) = serde_json::to_value(value) {
store.insert(key.to_string(), v);
}
}
}
}
#[cfg(test)]
mod tests {
#![allow(
clippy::unwrap_used,
clippy::expect_used,
clippy::panic,
clippy::significant_drop_tightening
)]
use super::*;
#[test]
fn test_state_set_and_get() {
let state: Mutex<HashMap<String, Value>> = Mutex::new(HashMap::new());
state
.lock()
.unwrap()
.insert("key".to_string(), serde_json::to_value("value").unwrap());
let val: String =
serde_json::from_value(state.lock().unwrap().get("key").cloned().unwrap()).unwrap();
assert_eq!(val, "value");
}
#[test]
fn test_state_overwrite() {
let state: Mutex<HashMap<String, Value>> = Mutex::new(HashMap::new());
{
let mut store = state.lock().unwrap();
store.insert("key".to_string(), serde_json::to_value(1i32).unwrap());
store.insert("key".to_string(), serde_json::to_value(2i32).unwrap());
}
let val: i32 =
serde_json::from_value(state.lock().unwrap().get("key").cloned().unwrap()).unwrap();
assert_eq!(val, 2);
}
}