feat: first-class skill packs on agents + ship gifsmith builtin
executus CI / test (push) Successful in 3m21s

Lifts the 'an agent uses a SKILL.md pack' concept out of a host and into the
harness:
- run.Ports.SkillPacks (SkillPackActivator) — nil-safe port; the executor folds
  a loaded agent's pack catalog into the system prompt and adds a skill_use
  loader tool to the toolbox (uses the existing ra.SystemPrompt + toolbox seams)
- run.RunnableAgent.SkillPacks + persona.Agent.SkillPacks (+ skill_packs YAML,
  extends-inherit, ToRunnable) — the Agent noun is now pack-aware
- skillpack.Activator — the battery's default port impl (resolve names → packs →
  catalog + skill_use), with a per-run BundleStager factory the host plumbs;
  satisfies the port structurally (no import of run)
- agentbuiltins: ships gifsmith, a portable focused GIF/MP4 render agent that
  uses the gif pack — references tool/tier/pack NAMES only, no host coupling

A host now wires run.Ports.SkillPacks instead of carrying its own activation
glue. Tests: Activator resolution + gifsmith loads through persona→RunnableAgent.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-05 01:05:58 -04:00
parent d5ea9b6e5e
commit 8ecdadf8b8
11 changed files with 279 additions and 0 deletions
+50
View File
@@ -0,0 +1,50 @@
package skillpack
import (
"context"
"testing"
)
func TestActivator(t *testing.T) {
ctx := context.Background()
src := &fakeSource{tree: packTree("alpha", "do alpha things"), ref: "r1"}
y := newTestSyncer(src)
if _, err := y.Subscribe(ctx, src, "main", "steve"); err != nil {
t.Fatal(err)
}
staged := 0
act := &Activator{
Cache: y.Cache, Subs: y.Subs,
StagerFor: func(runID, subjectID string) BundleStager {
return func(context.Context, *Pack) (string, error) { staged++; return "", nil }
},
}
instr, tools, err := act.ActivateSkillPacks(ctx, []string{"alpha"}, "run1", "agent1")
if err != nil {
t.Fatal(err)
}
if instr == "" {
t.Error("expected catalog instructions")
}
found := false
for _, tl := range tools {
if tl.Name == "skill_use" {
found = true
}
}
if !found {
t.Errorf("expected a skill_use tool, got %d tools", len(tools))
}
// unknown name → nothing resolves (no error, no tools).
if in, tl, err := act.ActivateSkillPacks(ctx, []string{"nope"}, "r", "a"); err != nil || in != "" || tl != nil {
t.Fatalf("unknown pack should resolve to nothing: in=%q tools=%v err=%v", in, tl, err)
}
// nil-safe: a zero Activator (or empty names) is inert.
if in, tl, err := (&Activator{}).ActivateSkillPacks(ctx, []string{"alpha"}, "r", "a"); err != nil || in != "" || tl != nil {
t.Fatalf("zero Activator should be inert: %q %v %v", in, tl, err)
}
}