mirror of
https://github.com/0xrsydn/nix-hermes-agent.git
synced 2026-08-07 00:53:52 +00:00
feat(skills): add bundled.include for cherry-picking bundled skills
When bundled.include is set to a non-empty list, only the listed skills are installed from the upstream bundled skills directory. When empty (default), all bundled skills are installed (existing behavior). Invalid include paths cause a build error with available skills listed. DESCRIPTION.md files are only copied for categories that have at least one included skill.
This commit is contained in:
parent
ad607ee4dc
commit
880796fc0e
1 changed files with 39 additions and 0 deletions
39
module.nix
39
module.nix
|
|
@ -46,6 +46,7 @@ let
|
||||||
pkgs.runCommand "hermes-managed-skills"
|
pkgs.runCommand "hermes-managed-skills"
|
||||||
{
|
{
|
||||||
bundledEnabled = if cfg.skills.bundled.enable then "1" else "0";
|
bundledEnabled = if cfg.skills.bundled.enable then "1" else "0";
|
||||||
|
bundledIncludeJson = builtins.toJSON cfg.skills.bundled.include;
|
||||||
optionalSkillsJson = builtins.toJSON cfg.skills.optional;
|
optionalSkillsJson = builtins.toJSON cfg.skills.optional;
|
||||||
customSkillsJson = builtins.toJSON customSkillSpecs;
|
customSkillsJson = builtins.toJSON customSkillSpecs;
|
||||||
src = hermesUpstreamSrc;
|
src = hermesUpstreamSrc;
|
||||||
|
|
@ -64,6 +65,7 @@ let
|
||||||
out = Path(os.environ["out"])
|
out = Path(os.environ["out"])
|
||||||
src = Path(os.environ["src"])
|
src = Path(os.environ["src"])
|
||||||
bundled_enabled = os.environ["bundledEnabled"] == "1"
|
bundled_enabled = os.environ["bundledEnabled"] == "1"
|
||||||
|
bundled_include = json.loads(os.environ["bundledIncludeJson"])
|
||||||
optional_skills = json.loads(os.environ["optionalSkillsJson"])
|
optional_skills = json.loads(os.environ["optionalSkillsJson"])
|
||||||
custom_skills = json.loads(os.environ["customSkillsJson"])
|
custom_skills = json.loads(os.environ["customSkillsJson"])
|
||||||
managed = []
|
managed = []
|
||||||
|
|
@ -97,12 +99,32 @@ let
|
||||||
if not bundled_root.exists():
|
if not bundled_root.exists():
|
||||||
raise SystemExit(f"bundled skills directory missing: {bundled_root}")
|
raise SystemExit(f"bundled skills directory missing: {bundled_root}")
|
||||||
|
|
||||||
|
include_set = set(bundled_include) if bundled_include else None
|
||||||
|
|
||||||
|
# Validate include paths exist
|
||||||
|
if include_set:
|
||||||
|
all_skills = {str(s) for s in skill_dirs_under(bundled_root)}
|
||||||
|
missing = include_set - all_skills
|
||||||
|
if missing:
|
||||||
|
raise SystemExit(
|
||||||
|
f"bundled.include references non-existent skills: {', '.join(sorted(missing))}\n"
|
||||||
|
f"Available: {', '.join(sorted(all_skills))}"
|
||||||
|
)
|
||||||
|
|
||||||
for skill_rel in skill_dirs_under(bundled_root):
|
for skill_rel in skill_dirs_under(bundled_root):
|
||||||
|
# If include list is set, only install listed skills
|
||||||
|
if include_set and str(skill_rel) not in include_set:
|
||||||
|
continue
|
||||||
copy_tree(bundled_root / skill_rel, out / skill_rel)
|
copy_tree(bundled_root / skill_rel, out / skill_rel)
|
||||||
managed.append(str(skill_rel))
|
managed.append(str(skill_rel))
|
||||||
|
|
||||||
|
# Copy DESCRIPTION.md for categories that have at least one included skill
|
||||||
|
included_categories = {Path(s).parts[0] for s in managed} if managed else set()
|
||||||
for desc in bundled_root.rglob("DESCRIPTION.md"):
|
for desc in bundled_root.rglob("DESCRIPTION.md"):
|
||||||
rel = desc.relative_to(bundled_root)
|
rel = desc.relative_to(bundled_root)
|
||||||
|
cat = rel.parts[0] if rel.parts else None
|
||||||
|
if include_set and cat and cat not in included_categories:
|
||||||
|
continue
|
||||||
target = out / rel
|
target = out / rel
|
||||||
target.parent.mkdir(parents=True, exist_ok=True)
|
target.parent.mkdir(parents=True, exist_ok=True)
|
||||||
shutil.copy2(desc, target)
|
shutil.copy2(desc, target)
|
||||||
|
|
@ -285,6 +307,23 @@ in
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bundled.include = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [ ];
|
||||||
|
example = [
|
||||||
|
"autonomous-ai-agents/claude-code"
|
||||||
|
"software-development/code-review"
|
||||||
|
"research/arxiv"
|
||||||
|
];
|
||||||
|
description = ''
|
||||||
|
When non-empty, only install these specific bundled skills (by relative
|
||||||
|
path under upstream `skills/`). When empty (default), all bundled skills
|
||||||
|
are installed. Has no effect when `bundled.enable` is false.
|
||||||
|
|
||||||
|
Invalid paths cause a build error listing available skills.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
optional = mkOption {
|
optional = mkOption {
|
||||||
type = types.listOf types.str;
|
type = types.listOf types.str;
|
||||||
default = [ ];
|
default = [ ];
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue