feat(TASK-033): add hook config schema across all scopes
Introduce src/hooks.rs as a types-only module (HookDef, HooksMap) and plumb hooks:/global_hooks: config fields through every scope: - Config + AppConfig hooks field, both Default impls, the manual from_config copy, and a COYOTE_HOOKS env override - Role frontmatter: hand-parsed hooks arm, private field, getter, and JSON-inline re-serialization in Role::export (malformed maps degrade to None) - AgentConfig + Graph: hooks + global_hooks on both structs, copied in AgentConfig::from_graph, with a per-agent global_hooks env override - paths::hooks_dir() = <config_dir>/hooks with COYOTE_HOOKS_DIR override - Commented hooks: block in the global config template (global scope only; no global_hooks key) No engine or dispatch logic yet; existing configs parse unchanged.
This commit is contained in:
12 files changed
+344
-1
No files matched your search
+33
-1
@@ -2,7 +2,7 @@ use super::role::Role;
|
||||
use super::{
|
||||
AGENT_GRAPH_FILE_NAME, AGENTS_DIR_NAME, BASH_PROMPT_UTILS_FILE_NAME, CONFIG_FILE_NAME,
|
||||
ENV_FILE_NAME, FUNCTIONS_BIN_DIR_NAME, FUNCTIONS_DIR_NAME, GLOBAL_TOOLS_DIR_NAME,
|
||||
GLOBAL_TOOLS_UTILS_DIR_NAME, HIDDEN_MCP_FILE_NAME, INSTALLED_BUNDLES_FILE_NAME,
|
||||
GLOBAL_TOOLS_UTILS_DIR_NAME, HIDDEN_MCP_FILE_NAME, HOOKS_DIR_NAME, INSTALLED_BUNDLES_FILE_NAME,
|
||||
MACROS_DIR_NAME, MCP_FILE_NAME, MEMORY_DIR_NAME, MEMORY_INDEX_FILE_NAME, ModelsOverride,
|
||||
RAGS_DIR_NAME, ROLES_DIR_NAME, SBX_KIT_DIR_NAME, SBX_KIT_HASH_FILE, SBX_MIXIN_FILE_NAME,
|
||||
SBX_MIXIN_KITS_DIR_NAME, SKILLS_DIR_NAME, WORKSPACE_COYOTE_DIR_NAME,
|
||||
@@ -184,6 +184,14 @@ pub fn role_file(name: &str) -> PathBuf {
|
||||
roles_dir().join(format!("{name}.md"))
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn hooks_dir() -> PathBuf {
|
||||
match env::var(get_env_name("hooks_dir")) {
|
||||
Ok(value) => PathBuf::from(value),
|
||||
Err(_) => local_dir(HOOKS_DIR_NAME),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn skills_dir() -> PathBuf {
|
||||
match env::var(get_env_name("skills_dir")) {
|
||||
Ok(value) => PathBuf::from(value),
|
||||
@@ -947,6 +955,30 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hooks_dir_reflects_env_var_state() {
|
||||
let env_name = get_env_name("hooks_dir");
|
||||
let prev = env::var_os(&env_name);
|
||||
|
||||
unsafe {
|
||||
env::remove_var(&env_name);
|
||||
}
|
||||
assert_eq!(hooks_dir(), config_dir().join("hooks"));
|
||||
|
||||
let probe = PathBuf::from("/tmp/coyote-hooks-dir-probe");
|
||||
unsafe {
|
||||
env::set_var(&env_name, &probe);
|
||||
}
|
||||
assert_eq!(hooks_dir(), probe);
|
||||
|
||||
unsafe {
|
||||
match prev {
|
||||
Some(v) => env::set_var(&env_name, v),
|
||||
None => env::remove_var(&env_name),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_skills_skips_invalid_directory_names() {
|
||||
let unique = time::SystemTime::now()
|
||||
|
||||
Reference in new issue
Block a user