use std::collections::HashMap;
use std::sync::Arc;
use oris_runtime::{
agent::create_agent,
error::ToolError,
tools::{
EnhancedInMemoryStore, EnhancedToolStore, SimpleContext, StoreValue, ToolResult,
ToolRuntime,
},
};
use serde_json::json;
struct GetUserInfoTool;
#[async_trait::async_trait]
impl oris_runtime::tools::Tool for GetUserInfoTool {
fn name(&self) -> String {
"get_user_info".to_string()
}
fn description(&self) -> String {
"Get user information from long-term memory. Returns stored user preferences, language, and other information.".to_string()
}
fn parameters(&self) -> serde_json::Value {
json!({
"type": "object",
"properties": {},
"required": []
})
}
async fn run(&self, _input: serde_json::Value) -> Result<String, ToolError> {
Err(ToolError::ExecutionError(
"This tool requires runtime. Use run_with_runtime instead.".to_string(),
))
}
async fn run_with_runtime(
&self,
_input: serde_json::Value,
runtime: &ToolRuntime,
) -> Result<ToolResult, Box<dyn std::error::Error>> {
let user_id = runtime
.context()
.user_id()
.ok_or_else(|| ToolError::MissingInput("user_id is required in context".to_string()))?;
let user_info = runtime.store().get(&["users"], user_id).await;
match user_info {
Some(info) => Ok(ToolResult::Text(format!(
"User information: {}",
serde_json::to_string_pretty(&info)?
))),
None => Ok(ToolResult::Text(format!(
"No information found for user: {}",
user_id
))),
}
}
fn requires_runtime(&self) -> bool {
true
}
}
struct SaveUserInfoTool;
#[async_trait::async_trait]
impl oris_runtime::tools::Tool for SaveUserInfoTool {
fn name(&self) -> String {
"save_user_info".to_string()
}
fn description(&self) -> String {
"Save user information to long-term memory. Use this when the user provides information about themselves like name, language preferences, or other details.".to_string()
}
fn parameters(&self) -> serde_json::Value {
json!({
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "The user's name"
},
"language": {
"type": "string",
"description": "The user's preferred language"
},
"preferences": {
"type": "string",
"description": "Any additional user preferences"
}
},
"required": []
})
}
async fn run(&self, _input: serde_json::Value) -> Result<String, ToolError> {
Err(ToolError::ExecutionError(
"This tool requires runtime. Use run_with_runtime instead.".to_string(),
))
}
async fn run_with_runtime(
&self,
input: serde_json::Value,
runtime: &ToolRuntime,
) -> Result<ToolResult, Box<dyn std::error::Error>> {
let user_id = runtime
.context()
.user_id()
.ok_or_else(|| ToolError::MissingInput("user_id is required in context".to_string()))?;
let mut user_info = HashMap::new();
if let Some(name) = input.get("name").and_then(|v| v.as_str()) {
user_info.insert("name".to_string(), json!(name));
}
if let Some(language) = input.get("language").and_then(|v| v.as_str()) {
user_info.insert("language".to_string(), json!(language));
}
if let Some(preferences) = input.get("preferences").and_then(|v| v.as_str()) {
user_info.insert("preferences".to_string(), json!(preferences));
}
let value = json!(user_info);
let mut metadata = HashMap::new();
metadata.insert("updated_at".to_string(), json!("2024-01-01T00:00:00Z"));
runtime.store().put(&["users"], user_id, value).await;
Ok(ToolResult::Text(
"User information saved successfully.".to_string(),
))
}
fn requires_runtime(&self) -> bool {
true
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
env_logger::init();
let _store: Arc<dyn oris_runtime::tools::ToolStore> = Arc::new(EnhancedInMemoryStore::new());
let enhanced_store = Arc::new(EnhancedInMemoryStore::new());
let store: Arc<dyn oris_runtime::tools::ToolStore> = enhanced_store.clone();
let mut metadata = HashMap::new();
metadata.insert("created_at".to_string(), json!("2024-01-01"));
enhanced_store
.put_with_metadata(
&["users"],
"user_123",
StoreValue::with_metadata(
json!({
"name": "John Smith",
"language": "English",
}),
metadata,
),
)
.await;
let tools: Vec<Arc<dyn oris_runtime::tools::Tool>> =
vec![Arc::new(GetUserInfoTool), Arc::new(SaveUserInfoTool)];
let _context = Arc::new(SimpleContext::new().with_user_id("user_123".to_string()));
let _agent = create_agent(
"gpt-4o-mini",
&tools,
Some("You are a helpful assistant. Use get_user_info to recall user information and save_user_info to remember new information."),
None,
)?;
println!("Long-term Memory Tool Example\n");
println!("Long-term Memory Tool Example\n");
let user_info = store.get(&["users"], "user_123").await;
println!("Retrieved user info: {:?}", user_info);
let user_info_with_metadata = enhanced_store
.get_with_metadata(&["users"], "user_123")
.await;
if let Some(info) = user_info_with_metadata {
println!("Retrieved with metadata:");
println!(" Value: {}", info.value);
println!(" Metadata: {:?}", info.metadata);
}
Ok(())
}