diff --git a/scripts/dev-api.js b/scripts/dev-api.js index be1332c..2a7fe0d 100644 --- a/scripts/dev-api.js +++ b/scripts/dev-api.js @@ -4345,6 +4345,10 @@ export function buildHermesSkillsConfigValues(config = {}) { return { creationNudgeInterval: parseHermesInteger(skills.creation_nudge_interval, 'skills.creation_nudge_interval', 15, 0, 10000, false), externalDirs, + templateVars: readHermesBool(skills.template_vars, true), + inlineShell: readHermesBool(skills.inline_shell, false), + inlineShellTimeout: parseHermesInteger(skills.inline_shell_timeout, 'skills.inline_shell_timeout', 10, 1, 86400, false), + guardAgentCreated: readHermesBool(skills.guard_agent_created, false), } } @@ -4355,6 +4359,10 @@ export function mergeHermesSkillsConfig(config = {}, form = {}) { ? mergeConfigsPreservingFields(next.skills, {}) : {} skills.creation_nudge_interval = parseHermesInteger(Object.hasOwn(form, 'creationNudgeInterval') ? form.creationNudgeInterval : currentValues.creationNudgeInterval, 'skills.creation_nudge_interval', 15, 0, 10000, true) + skills.template_vars = formHermesBool(form, 'templateVars', currentValues.templateVars) + skills.inline_shell = formHermesBool(form, 'inlineShell', currentValues.inlineShell) + skills.inline_shell_timeout = parseHermesInteger(Object.hasOwn(form, 'inlineShellTimeout') ? form.inlineShellTimeout : currentValues.inlineShellTimeout, 'skills.inline_shell_timeout', 10, 1, 86400, true) + skills.guard_agent_created = formHermesBool(form, 'guardAgentCreated', currentValues.guardAgentCreated) const externalDirs = normalizeHermesMultilineList(Object.hasOwn(form, 'externalDirs') ? form.externalDirs : currentValues.externalDirs) if (externalDirs.length) skills.external_dirs = externalDirs else delete skills.external_dirs diff --git a/src-tauri/src/commands/hermes.rs b/src-tauri/src/commands/hermes.rs index 5bdd107..ef06a73 100644 --- a/src-tauri/src/commands/hermes.rs +++ b/src-tauri/src/commands/hermes.rs @@ -4352,6 +4352,12 @@ fn build_hermes_skills_config_values(config: &serde_yaml::Value) -> Value { serde_json::json!({ "creationNudgeInterval": creation_nudge_interval, "externalDirs": external_dirs, + "templateVars": skills.and_then(|map| yaml_bool_field(map, "template_vars")).unwrap_or(true), + "inlineShell": skills.and_then(|map| yaml_bool_field(map, "inline_shell")).unwrap_or(false), + "inlineShellTimeout": skills + .map(|map| bounded_hermes_i64(yaml_i64_field(map, "inline_shell_timeout"), 10, 1, 86400)) + .unwrap_or(10), + "guardAgentCreated": skills.and_then(|map| yaml_bool_field(map, "guard_agent_created")).unwrap_or(false), }) } @@ -4368,6 +4374,17 @@ fn merge_hermes_skills_config(config: &mut serde_yaml::Value, form: &Value) -> R 0, 10000, )?; + let inline_shell_timeout = validate_hermes_i64( + if form.get("inlineShellTimeout").is_some() { + form_i64(form, "inlineShellTimeout") + } else { + Some(current["inlineShellTimeout"].as_i64().unwrap_or(10)) + }, + "skills.inline_shell_timeout", + 10, + 1, + 86400, + )?; let external_dirs = normalize_hermes_multiline_list( form_string(form, "externalDirs") .or_else(|| current["externalDirs"].as_str().map(ToString::to_string)), @@ -4379,6 +4396,31 @@ fn merge_hermes_skills_config(config: &mut serde_yaml::Value, form: &Value) -> R yaml_key("creation_nudge_interval"), serde_yaml::Value::Number(creation_nudge_interval.into()), ); + skills.insert( + yaml_key("template_vars"), + serde_yaml::Value::Bool( + form_bool(form, "templateVars") + .unwrap_or_else(|| current["templateVars"].as_bool().unwrap_or(true)), + ), + ); + skills.insert( + yaml_key("inline_shell"), + serde_yaml::Value::Bool( + form_bool(form, "inlineShell") + .unwrap_or_else(|| current["inlineShell"].as_bool().unwrap_or(false)), + ), + ); + skills.insert( + yaml_key("inline_shell_timeout"), + serde_yaml::Value::Number(inline_shell_timeout.into()), + ); + skills.insert( + yaml_key("guard_agent_created"), + serde_yaml::Value::Bool( + form_bool(form, "guardAgentCreated") + .unwrap_or_else(|| current["guardAgentCreated"].as_bool().unwrap_or(false)), + ), + ); if external_dirs.is_empty() { skills.remove(yaml_key("external_dirs")); } else { @@ -17610,6 +17652,10 @@ mod hermes_skills_config_tests { let values = build_hermes_skills_config_values(&config); assert_eq!(values["creationNudgeInterval"], 15); assert_eq!(values["externalDirs"], ""); + assert_eq!(values["templateVars"], true); + assert_eq!(values["inlineShell"], false); + assert_eq!(values["inlineShellTimeout"], 10); + assert_eq!(values["guardAgentCreated"], false); } #[test] @@ -17621,6 +17667,10 @@ skills: external_dirs: - ~/.agents/skills - /home/shared/team-skills + template_vars: false + inline_shell: true + inline_shell_timeout: 25 + guard_agent_created: true "#, ) .unwrap(); @@ -17631,6 +17681,10 @@ skills: values["externalDirs"], "~/.agents/skills\n/home/shared/team-skills" ); + assert_eq!(values["templateVars"], false); + assert_eq!(values["inlineShell"], true); + assert_eq!(values["inlineShellTimeout"], 25); + assert_eq!(values["guardAgentCreated"], true); } #[test] @@ -17655,6 +17709,10 @@ memory: &json!({ "creationNudgeInterval": "0", "externalDirs": " ~/.agents/skills \n\n /home/shared/team-skills ", + "templateVars": false, + "inlineShell": true, + "inlineShellTimeout": "30", + "guardAgentCreated": true, }), ) .unwrap(); @@ -17673,6 +17731,13 @@ memory: config["skills"]["external_dirs"][1].as_str(), Some("/home/shared/team-skills") ); + assert_eq!(config["skills"]["template_vars"].as_bool(), Some(false)); + assert_eq!(config["skills"]["inline_shell"].as_bool(), Some(true)); + assert_eq!(config["skills"]["inline_shell_timeout"].as_i64(), Some(30)); + assert_eq!( + config["skills"]["guard_agent_created"].as_bool(), + Some(true) + ); assert_eq!( config["skills"]["disabled"][0].as_str(), Some("legacy-skill") @@ -17693,6 +17758,12 @@ memory: merge_hermes_skills_config(&mut config, &json!({ "creationNudgeInterval": 10001 })) .unwrap_err(); assert!(err.contains("skills.creation_nudge_interval")); + let err = merge_hermes_skills_config(&mut config, &json!({ "inlineShellTimeout": 0 })) + .unwrap_err(); + assert!(err.contains("skills.inline_shell_timeout")); + let err = merge_hermes_skills_config(&mut config, &json!({ "inlineShellTimeout": 86401 })) + .unwrap_err(); + assert!(err.contains("skills.inline_shell_timeout")); } } diff --git a/src/engines/hermes/pages/config.js b/src/engines/hermes/pages/config.js index fc27122..4b6168f 100644 --- a/src/engines/hermes/pages/config.js +++ b/src/engines/hermes/pages/config.js @@ -78,6 +78,10 @@ const MEMORY_DEFAULTS = { const SKILLS_DEFAULTS = { creationNudgeInterval: 15, externalDirs: '', + templateVars: true, + inlineShell: false, + inlineShellTimeout: 10, + guardAgentCreated: false, } const QUICK_COMMANDS_DEFAULTS = { @@ -935,11 +939,29 @@ export function render() { ${t('engine.hermesSkillsConfigCreationNudgeInterval')} + +