feat: add enabled_macros config field at global, role, agent, and session levels
Mirrors the enabled_skills plumbing per plans/custom-commands-design.md §5: - global: Config + AppConfig structs, from_config copy, and the COYOTE_ENABLED_MACROS env-override arm (csv_to_vec parsing) - role: frontmatter via parse_string_or_array (list or csv string), plus the export() mirror so Role::save round-trips the field - agent (non-graph): plain serde on AgentConfig; graph.yaml silently ignores the key (pinned by test, no field on Graph by design) - session: plain serde with csv-or-vec deserializer Empty list/string deserializes to Some([]) (explicit zero), distinct from absent/null (None) — pinned by tests at every level, including the env arm (serial-fenced against the from_config tests, which read the process env via load_envs).
This commit is contained in:
@@ -46,6 +46,12 @@ pub struct Session {
|
||||
deserialize_with = "super::deserialize_csv_or_vec"
|
||||
)]
|
||||
enabled_skills: Option<Vec<String>>,
|
||||
#[serde(
|
||||
default,
|
||||
skip_serializing_if = "Option::is_none",
|
||||
deserialize_with = "super::deserialize_csv_or_vec"
|
||||
)]
|
||||
enabled_macros: Option<Vec<String>>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
save_session: Option<bool>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
@@ -931,6 +937,45 @@ mod tests {
|
||||
assert!(!session.dirty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn session_enabled_macros_absent_is_none() {
|
||||
let session: Session = serde_yaml::from_str("model: provider:test\nmessages: []").unwrap();
|
||||
assert_eq!(session.enabled_macros, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn session_enabled_macros_empty_list_is_some_empty() {
|
||||
let session: Session =
|
||||
serde_yaml::from_str("model: provider:test\nenabled_macros: []\nmessages: []").unwrap();
|
||||
assert_eq!(session.enabled_macros, Some(vec![]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn session_enabled_macros_empty_string_is_some_empty() {
|
||||
let session: Session =
|
||||
serde_yaml::from_str("model: provider:test\nenabled_macros: \"\"\nmessages: []")
|
||||
.unwrap();
|
||||
assert_eq!(session.enabled_macros, Some(vec![]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn session_enabled_macros_csv_string() {
|
||||
let session: Session =
|
||||
serde_yaml::from_str("model: provider:test\nenabled_macros: \"a,b\"\nmessages: []")
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
session.enabled_macros,
|
||||
Some(vec!["a".to_string(), "b".to_string()])
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn session_serialize_omits_enabled_macros_when_none() {
|
||||
let session = Session::default();
|
||||
let yaml = serde_yaml::to_string(&session).unwrap();
|
||||
assert!(!yaml.contains("enabled_macros"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn session_new_from_ctx_captures_save_session() {
|
||||
let app_config = Arc::new(AppConfig::default());
|
||||
|
||||
Reference in New Issue
Block a user