use std::sync::Arc;
use oris_runtime::{
agent::create_agent,
error::ToolError,
tools::{
EnhancedInMemoryStore, EnhancedToolStore, StoreValue, ToolResult, ToolRuntime, ToolStore,
},
};
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. Use this when you need to recall information about a user.".to_string()
}
fn parameters(&self) -> serde_json::Value {
json!({
"type": "object",
"properties": {
"user_id": {
"type": "string",
"description": "The user ID to look up"
}
},
"required": ["user_id"]
})
}
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 = input
.get("user_id")
.and_then(|v| v.as_str())
.ok_or_else(|| ToolError::MissingInput("user_id is required".to_string()))?;
let context_user_id = runtime.context().user_id().unwrap_or(user_id);
let user_info = runtime.store().get(&["users"], context_user_id).await;
match user_info {
Some(info) => Ok(ToolResult::Text(format!("User info: {}", info))),
None => Ok(ToolResult::Text(format!(
"No information found for user: {}",
context_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.".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"
}
},
"required": ["name"]
})
}
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 metadata = std::collections::HashMap::new();
metadata.insert(
"updated_at".to_string(),
json!(chrono::Utc::now().to_rfc3339()),
);
let store_value = StoreValue::with_metadata(
json!({
"name": input.get("name").and_then(|v| v.as_str()).unwrap_or("Unknown"),
"language": input.get("language").and_then(|v| v.as_str()).unwrap_or("English"),
}),
metadata,
);
runtime
.store()
.put(&["users"], user_id, store_value.value.clone())
.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::new(EnhancedInMemoryStore::new());
let mut metadata = std::collections::HashMap::new();
metadata.insert("created_at".to_string(), json!("2024-01-01"));
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 _agent = create_agent(
"gpt-4o-mini",
&tools,
Some("You are a helpful assistant that can remember user information."),
None,
)?;
println!("Long-term Memory Basic Example\n");
let user_info = store.get_with_metadata(&["users"], "user_123").await;
if let Some(info) = user_info {
println!("Retrieved user info:");
println!(" Value: {}", info.value);
println!(" Metadata: {:?}", info.metadata);
}
let new_info = StoreValue::new(json!({
"name": "Jane Doe",
"language": "Spanish",
}));
store
.put_with_metadata(&["users"], "user_456", new_info)
.await;
println!("\nSaved new user info");
let keys = store.list(&["users"]).await;
println!("\nKeys in 'users' namespace: {:?}", keys);
Ok(())
}