Add skill command env patching #21

Merged
alexion merged 1 commits from mk-skill-command-env into main 2026-08-26 21:19:42 -04:00
2 changed files with 70 additions and 0 deletions

View File

@@ -11,6 +11,30 @@ let
discovered = discoverSkills ./fixtures/valid; discovered = discoverSkills ./fixtures/valid;
built = map (skill: mkSkill { inherit pkgs; inherit (skill) name src; }) discovered; 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); collision = builtins.tryEval (discoverSkills ./fixtures/collision);
discoveredNames = lib.sort (a: b: a < b) (map (skill: skill.name) discovered); 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); pairs = lib.concatStringsSep " " (map (skill: "${skill.skillName}=${skill}") built);
collisionSucceeded = if collision.success then "yes" else "no"; collisionSucceeded = if collision.success then "yes" else "no";
expectedNames = lib.concatStringsSep " " discoveredNames; expectedNames = lib.concatStringsSep " " discoveredNames;
inherit commandSkill;
} }
'' ''
fail() { echo "FAIL: $1" >&2; exit 1; } fail() { echo "FAIL: $1" >&2; exit 1; }
@@ -52,5 +77,11 @@ pkgs.runCommandLocal "skill-build-check"
test -f "$beta_path/tools/SKILL.md" \ test -f "$beta_path/tools/SKILL.md" \
|| fail "beta's asset subfolder did not ride along into \$out" || 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" touch "$out"
'' ''

View File

@@ -3,7 +3,45 @@
pkgs, pkgs,
src, src,
name ? builtins.baseNameOf (toString 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 { pkgs.stdenvNoCC.mkDerivation {
inherit name src; inherit name src;
@@ -18,6 +56,7 @@ pkgs.stdenvNoCC.mkDerivation {
cp -R "$src"/. "$out/" cp -R "$src"/. "$out/"
test -f "$out/SKILL.md" \ test -f "$out/SKILL.md" \
|| { echo "mkSkill: skill '${name}' has no SKILL.md at its root" >&2; exit 1; } || { echo "mkSkill: skill '${name}' has no SKILL.md at its root" >&2; exit 1; }
${patchCommands}
runHook postInstall runHook postInstall
''; '';