From b833abbd9f2bed6aa031b5f12f616624b5453e01 Mon Sep 17 00:00:00 2001 From: alexion Date: Wed, 26 Aug 2026 21:12:13 -0400 Subject: [PATCH] Add skill command env patching --- checks/skill-build.nix | 31 +++++++++++++++++++++++++++++++ lib/mk-skill.nix | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/checks/skill-build.nix b/checks/skill-build.nix index 4d5dad5..baffeb9 100644 --- a/checks/skill-build.nix +++ b/checks/skill-build.nix @@ -11,6 +11,30 @@ let discovered = discoverSkills ./fixtures/valid; built = map (skill: mkSkill { inherit pkgs; inherit (skill) name src; }) discovered; + commandSrc = pkgs.runCommandLocal "command-skill-src" { } '' + mkdir -p "$out" + printf '%s\n' '---' 'name: command-skill' 'description: Fixture skill with a command.' '---' \ + > "$out/SKILL.md" + cat > "$out/run-command" <<'EOF' +#!/usr/bin/env sh +: "''${TOOL:=tool}" # mkSkill:TOOL +exec "$TOOL" "$@" +EOF + chmod +x "$out/run-command" + ''; + + commandSkill = mkSkill { + inherit pkgs; + name = "command-skill"; + src = commandSrc; + commands = [ + { + path = "run-command"; + env.TOOL = "${pkgs.coreutils}/bin/printf"; + } + ]; + }; + collision = builtins.tryEval (discoverSkills ./fixtures/collision); discoveredNames = lib.sort (a: b: a < b) (map (skill: skill.name) discovered); @@ -24,6 +48,7 @@ pkgs.runCommandLocal "skill-build-check" pairs = lib.concatStringsSep " " (map (skill: "${skill.skillName}=${skill}") built); collisionSucceeded = if collision.success then "yes" else "no"; expectedNames = lib.concatStringsSep " " discoveredNames; + inherit commandSkill; } '' fail() { echo "FAIL: $1" >&2; exit 1; } @@ -52,5 +77,11 @@ pkgs.runCommandLocal "skill-build-check" test -f "$beta_path/tools/SKILL.md" \ || fail "beta's asset subfolder did not ride along into \$out" + echo "command tier: declared command env defaults are patched" + test -x "$commandSkill/run-command" \ + || fail "declared command is not executable" + grep -qx ': "''${TOOL:=${pkgs.coreutils}/bin/printf}" # mkSkill:TOOL' "$commandSkill/run-command" \ + || fail "declared command env default was not patched" + touch "$out" '' diff --git a/lib/mk-skill.nix b/lib/mk-skill.nix index 5f675ed..f59a7db 100644 --- a/lib/mk-skill.nix +++ b/lib/mk-skill.nix @@ -3,7 +3,45 @@ pkgs, src, name ? builtins.baseNameOf (toString src), + commands ? [ ], }: +let + lib = pkgs.lib; + + patchEnvDefault = command: envName: value: + let + marker = "# mkSkill:${envName}"; + replacement = '': "''${${envName}:=${value}}" ${marker}''; + in + '' + if ! awk -v marker=${lib.escapeShellArg marker} -v replacement=${lib.escapeShellArg replacement} ' + index($0, marker) { print replacement; found = 1; next } + { print } + END { if (!found) exit 42 } + ' "$_mkskill_command" > "$_mkskill_command.tmp"; then + rm -f "$_mkskill_command.tmp" + echo "mkSkill: command '${command.path}' has no ${marker} marker" >&2 + exit 1 + fi + mv "$_mkskill_command.tmp" "$_mkskill_command" + chmod +x "$_mkskill_command" + ''; + + patchCommand = command: + let + env = command.env or { }; + in + '' + _mkskill_command="$out/${command.path}" + test -f "$_mkskill_command" \ + || { echo "mkSkill: command '${command.path}' does not exist" >&2; exit 1; } + test -x "$_mkskill_command" \ + || { echo "mkSkill: command '${command.path}' is not executable" >&2; exit 1; } + ${lib.concatStringsSep "\n" (lib.mapAttrsToList (patchEnvDefault command) env)} + ''; + + patchCommands = lib.concatStringsSep "\n" (map patchCommand commands); +in pkgs.stdenvNoCC.mkDerivation { inherit name src; @@ -18,6 +56,7 @@ pkgs.stdenvNoCC.mkDerivation { cp -R "$src"/. "$out/" test -f "$out/SKILL.md" \ || { echo "mkSkill: skill '${name}' has no SKILL.md at its root" >&2; exit 1; } +${patchCommands} runHook postInstall ''; -- 2.47.3