use ras_types::ActionName;
use sha2::{Digest, Sha256};
use crate::domain::agent_output::ActionInvocation;
#[must_use]
pub fn compute_action_hash(action: &ActionInvocation) -> String {
let normalized = normalize_for_hash(&action.name, &action.parameters);
let mut h = Sha256::new();
h.update(action.name.0.as_bytes());
h.update(b"|");
h.update(normalized.as_bytes());
format!("{:x}", h.finalize())
}
fn normalize_for_hash(name: &ActionName, params: &serde_json::Value) -> String {
let mut params = params.clone();
if let Some(obj) = params.as_object_mut() {
match name.0.as_str() {
"search_page" | "find_elements" => {
obj.remove("max_results");
obj.remove("offset");
}
"navigate" => {
if let Some(url) = obj.get("url").and_then(|v| v.as_str()) {
obj.insert("url".into(), serde_json::Value::String(strip_query(url)));
}
}
_ => {}
}
}
serde_json::to_string(¶ms).unwrap_or_default()
}
fn strip_query(url: &str) -> String {
url.split('?')
.next()
.unwrap_or(url)
.trim_end_matches('/')
.to_string()
}