use crate::types::CallerKind;
pub fn normalize_event(vendor: &str, caller: &CallerKind) -> String {
let canonical = match caller {
CallerKind::ClaudeCode => normalize_claude_code_event(vendor),
CallerKind::Cursor => normalize_cursor_event(vendor),
CallerKind::Windsurf => normalize_windsurf_event(vendor),
CallerKind::Cline => normalize_cline_event(vendor),
CallerKind::Amp => normalize_amp_event(vendor),
CallerKind::Unknown => None,
};
canonical
.map(|s| s.to_owned())
.unwrap_or_else(|| vendor.to_owned())
}
fn normalize_claude_code_event(vendor: &str) -> Option<&'static str> {
match vendor {
"PreToolUse" => Some("tool:before"),
"PostToolUse" => Some("tool:after"),
"Startup" => Some("session:start"),
"Stop" => Some("session:stop"),
"SubagentStop" => Some("agent:stop"),
"Notification" => Some("notification"),
_ => None,
}
}
fn normalize_cursor_event(vendor: &str) -> Option<&'static str> {
match vendor {
"BeforeToolCall" => Some("tool:before"),
"AfterToolCall" => Some("tool:after"),
"SessionStart" => Some("session:start"),
"SessionEnd" => Some("session:stop"),
"Notification" => Some("notification"),
_ => None,
}
}
fn normalize_windsurf_event(vendor: &str) -> Option<&'static str> {
match vendor {
"pre_tool" => Some("tool:before"),
"post_tool" => Some("tool:after"),
"session_start" => Some("session:start"),
"session_end" => Some("session:stop"),
"notification" => Some("notification"),
_ => None,
}
}
fn normalize_cline_event(vendor: &str) -> Option<&'static str> {
match vendor {
"beforeToolUse" => Some("tool:before"),
"afterToolUse" => Some("tool:after"),
"onStart" => Some("session:start"),
"onStop" => Some("session:stop"),
_ => None,
}
}
fn normalize_amp_event(vendor: &str) -> Option<&'static str> {
match vendor {
"tool.before" => Some("tool:before"),
"tool.after" => Some("tool:after"),
"session.start" => Some("session:start"),
"session.stop" => Some("session:stop"),
"agent.stop" => Some("agent:stop"),
_ => None,
}
}
#[cfg(test)]
mod tests {
use super::normalize_event;
use crate::CallerKind;
#[test]
fn unknown_caller_returns_original_string() {
assert_eq!(normalize_event("SomeVendorEvent", &CallerKind::Unknown), "SomeVendorEvent");
assert_eq!(normalize_event("PreToolUse", &CallerKind::Unknown), "PreToolUse");
assert_eq!(normalize_event("", &CallerKind::Unknown), "");
}
#[test] fn cc_startup() { assert_eq!(normalize_event("Startup", &CallerKind::ClaudeCode), "session:start"); }
#[test] fn cc_stop() { assert_eq!(normalize_event("Stop", &CallerKind::ClaudeCode), "session:stop"); }
#[test] fn cc_subagent_stop(){ assert_eq!(normalize_event("SubagentStop", &CallerKind::ClaudeCode), "agent:stop"); }
#[test] fn cc_notification() { assert_eq!(normalize_event("Notification", &CallerKind::ClaudeCode), "notification"); }
#[test] fn cc_unknown_falls_through() { assert_eq!(normalize_event("Bogus", &CallerKind::ClaudeCode), "Bogus"); }
#[test] fn cur_session_start() { assert_eq!(normalize_event("SessionStart", &CallerKind::Cursor), "session:start"); }
#[test] fn cur_session_end() { assert_eq!(normalize_event("SessionEnd", &CallerKind::Cursor), "session:stop"); }
#[test] fn cur_notification() { assert_eq!(normalize_event("Notification", &CallerKind::Cursor), "notification"); }
#[test] fn cur_unknown_falls_through() { assert_eq!(normalize_event("Bogus", &CallerKind::Cursor), "Bogus"); }
#[test] fn ws_session_start() { assert_eq!(normalize_event("session_start", &CallerKind::Windsurf), "session:start"); }
#[test] fn ws_session_end() { assert_eq!(normalize_event("session_end", &CallerKind::Windsurf), "session:stop"); }
#[test] fn ws_notification() { assert_eq!(normalize_event("notification", &CallerKind::Windsurf), "notification"); }
#[test] fn ws_unknown_falls_through() { assert_eq!(normalize_event("bogus", &CallerKind::Windsurf), "bogus"); }
#[test] fn cl_on_start() { assert_eq!(normalize_event("onStart", &CallerKind::Cline), "session:start"); }
#[test] fn cl_on_stop() { assert_eq!(normalize_event("onStop", &CallerKind::Cline), "session:stop"); }
#[test] fn cl_unknown_falls_through() { assert_eq!(normalize_event("bogus", &CallerKind::Cline), "bogus"); }
#[test] fn amp_session_start() { assert_eq!(normalize_event("session.start", &CallerKind::Amp), "session:start"); }
#[test] fn amp_session_stop() { assert_eq!(normalize_event("session.stop", &CallerKind::Amp), "session:stop"); }
#[test] fn amp_agent_stop() { assert_eq!(normalize_event("agent.stop", &CallerKind::Amp), "agent:stop"); }
#[test] fn amp_unknown_falls_through() { assert_eq!(normalize_event("bogus.bogus", &CallerKind::Amp), "bogus.bogus"); }
}