use harn_vm::agent_events::AgentEvent;
pub(super) fn passthrough_projection(
event: &AgentEvent,
) -> Option<(&'static str, &serde_json::Value)> {
let (name, payload) = match event {
AgentEvent::CacheHit { payload, .. } => ("cache_hit", payload),
AgentEvent::CacheMiss { payload, .. } => ("cache_miss", payload),
AgentEvent::LlmCallLog { payload, .. } => ("llm_call_log", payload),
AgentEvent::LlmRoutingDecision { payload, .. } => ("llm_routing_decision", payload),
AgentEvent::LlmFallbackAttempt { payload, .. } => ("llm_fallback_attempt", payload),
AgentEvent::LlmShadowDiff { payload, .. } => ("llm_shadow_diff", payload),
AgentEvent::SemanticCacheHit { payload, .. } => ("semantic_cache_hit", payload),
AgentEvent::SemanticCacheMiss { payload, .. } => ("semantic_cache_miss", payload),
_ => return None,
};
Some((name, payload))
}
pub(super) fn has_progress_entries(entries: &serde_json::Value) -> bool {
entries
.as_array()
.map(|entries| !entries.is_empty())
.unwrap_or(false)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn a_handler_event_projects_under_its_wire_name_with_its_whole_record() {
let event = AgentEvent::LlmCallLog {
session_id: "s1".to_string(),
model: "gpt-5.6-luna".to_string(),
provider: "openai".to_string(),
status: "ok".to_string(),
latency_ms: 3067,
iteration: 1,
attempt: 1,
payload: serde_json::json!({"latency_ms": 3067, "status": "ok"}),
};
let (name, payload) = passthrough_projection(&event).expect("a passthrough family member");
assert_eq!(name, "llm_call_log");
assert_eq!(payload["latency_ms"], 3067);
}
#[test]
fn an_event_that_needs_real_projection_is_left_to_the_sink() {
let event = AgentEvent::AgentMessageChunk {
session_id: "s1".to_string(),
content: "hello".to_string(),
};
assert!(
passthrough_projection(&event).is_none(),
"claiming an event here would silently strip its real ACP shape"
);
}
}