use crate::llm::compactors::SharedObservations;
use rig::{
message::ToolResultContent,
tool::{Tool, ToolContext},
};
use serde::{Deserialize, Serialize};
use serde_json::json;
#[derive(Deserialize, Serialize)]
pub struct RetrieveObservationArgs {
id: u64,
}
#[derive(Debug)]
pub struct RetrieveObservation {
pub observations: SharedObservations,
}
impl RetrieveObservation {
pub fn new(observations: SharedObservations) -> Self {
Self { observations }
}
}
impl Tool for RetrieveObservation {
const NAME: &'static str = "retrieve_observation";
type Error = super::ToolError;
type Args = RetrieveObservationArgs;
type Output = Vec<ToolResultContent>;
async fn call(
&self,
_context: &mut ToolContext,
args: Self::Args,
) -> Result<Self::Output, Self::Error> {
self.observations
.lock()
.await
.get(&args.id)
.ok_or_else(|| super::ToolError::ResourceNotFound {
resource_type: super::ResourceType::Observation,
identifier: args.id.to_string(),
})
.cloned()
}
fn description(&self) -> String {
"Retrieve the full content of a masked tool result from conversation history. \
When conversation history is compacted to save context space, older tool results \
are replaced with placeholders like '[Observation:3 - masked]'. \
Use this tool when you need to see the full content of a masked result. \
The number inside the brackets (e.g., 3 in '[Observation:3 - masked]') is the \
id you should pass to this tool. Each tool result in the history is assigned a \
unique observation number starting from 1."
.to_string()
}
fn parameters(&self) -> serde_json::Value {
let id_description = "The numeric identifier of the observation to retrieve. \
When a tool result is masked in the conversation history, it appears as \
'[Observation:N - masked]' where N is this identifier. For example, \
if you see '[Observation:3 - masked]', pass 3 as this parameter. \
Observation IDs start at 1 and increment sequentially.";
json!({
"type": "object",
"properties": {
"id": {
"type": "integer",
"description": id_description
},
},
"required": ["id"]
})
}
fn map_error(&self, error: Self::Error) -> rig::tool::ToolExecutionError {
rig::tool::ToolExecutionError::from_error(error)
}
}