use zeph_common::memory::{FunctionalType, MemoryRoute, MemoryRouter};
use zeph_config::memory::TypeAwareComposeConfig;
use zeph_memory::{HeuristicRouter, IntentClass};
fn intent_functional_types(intent: IntentClass) -> &'static [FunctionalType] {
match intent {
IntentClass::ProfileLookup => &[FunctionalType::UserFact],
IntentClass::TargetedRetrieval => &[
FunctionalType::Episodic,
FunctionalType::UserFact,
FunctionalType::CrossSessionSummary,
FunctionalType::GraphFact,
],
IntentClass::DeepReasoning => &[
FunctionalType::Episodic,
FunctionalType::ReasoningStrategy,
FunctionalType::CrossSessionSummary,
FunctionalType::GraphFact,
],
_ => &[],
}
}
#[must_use]
pub fn resolve_active_functional_types(
config: &TypeAwareComposeConfig,
query: &str,
) -> Vec<FunctionalType> {
if !config.enabled {
return Vec::new();
}
let mut active = config.default_compose_types.clone();
if config.intent_scoped {
let route: MemoryRoute = HeuristicRouter.route(query);
let intent = IntentClass::from_route(route);
for t in intent_functional_types(intent) {
if !active.contains(t) {
active.push(*t);
}
}
}
tracing::debug!(
enabled = config.enabled,
intent_scoped = config.intent_scoped,
?active,
"type-aware compose: resolved active set"
);
active
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn disabled_config_resolves_to_empty_set() {
let config = TypeAwareComposeConfig {
enabled: false,
default_compose_types: vec![FunctionalType::UserFact],
intent_scoped: true,
};
assert!(resolve_active_functional_types(&config, "anything").is_empty());
}
#[test]
fn enabled_with_empty_default_and_no_intent_scoping_resolves_to_empty_set() {
let config = TypeAwareComposeConfig {
enabled: true,
default_compose_types: Vec::new(),
intent_scoped: false,
};
assert!(resolve_active_functional_types(&config, "anything").is_empty());
}
#[test]
fn enabled_with_default_types_and_no_intent_scoping_returns_default_types() {
let config = TypeAwareComposeConfig {
enabled: true,
default_compose_types: vec![FunctionalType::UserFact],
intent_scoped: false,
};
let active = resolve_active_functional_types(&config, "what is my name");
assert_eq!(active, vec![FunctionalType::UserFact]);
}
#[test]
fn intent_scoped_widens_default_set_without_duplicates() {
let config = TypeAwareComposeConfig {
enabled: true,
default_compose_types: vec![FunctionalType::UserFact],
intent_scoped: true,
};
let active = resolve_active_functional_types(&config, "why did the deploy fail?");
assert!(active.contains(&FunctionalType::UserFact));
assert_eq!(
active
.iter()
.filter(|t| **t == FunctionalType::UserFact)
.count(),
1
);
}
#[test]
fn intent_functional_types_never_include_behavioral_rule() {
for intent in [
IntentClass::ProfileLookup,
IntentClass::TargetedRetrieval,
IntentClass::DeepReasoning,
] {
assert!(!intent_functional_types(intent).contains(&FunctionalType::BehavioralRule));
}
}
}