Skip to content

feat(ai-skills): add @gemstack/ai-skills — portable capability bundles#16

Merged
suleimansh merged 1 commit into
mainfrom
feat/ai-skills
Jun 25, 2026
Merged

feat(ai-skills): add @gemstack/ai-skills — portable capability bundles#16
suleimansh merged 1 commit into
mainfrom
feat/ai-skills

Conversation

@suleimansh

Copy link
Copy Markdown
Member

Implements #8 — the second package of the GemStack AI family. Loads SKILL.md skills (instructions + tools + resources) and composes them onto an @gemstack/ai-sdk Agent. Greenfield: builds the registry + loader + runtime around the existing boost/skills convention.

Surface

  • manifestparseSkillManifest(): SKILL.md YAML frontmatter + markdown body, zod-validated. Matches the shipped boost/skills convention and the Anthropic Agent Skills shape (a skill authored for Claude loads here; a gemstack skill ships as a plain folder).
  • loaderloadSkill() / loadSkills(): a skill dir's instructions, co-located tool() exports, and resources/.
  • registrySkillRegistry: discover skills by their cheap frontmatter, load the full body + tools on demand (progressive disclosure — index hundreds, pay for what you compose).
  • composecomposeInstructions / composeTools / composeMiddleware + surface. The agent's own declarations stay authoritative: own tools win name collisions; colliding skill tools are namespaced (<skill>__<tool>) rather than dropped.
  • SkillfulAgent — an Agent base that composes skills() declaratively alongside baseInstructions() / baseTools() / baseMiddleware().

Design decisions honored (Architecture.md / #8)

  • Manifest = SKILL.md frontmatter, not a TS-first definition — zero divergence from the shipped convention; progressive disclosure falls out (index frontmatter, load body on demand).
  • Tools = reuse ai-sdk tool() directly via a co-located tools.ts; the loader imports + merges. One tool API across the framework.
  • Security = explicit trust boundary, no in-process sandbox. No auto-loading of untrusted dirs (explicit paths only); surface-before-compose (discover() runs no code; loadTools: false; surface()); the risky moment (tool execution) stays on the agent's existing approval/middleware path.
  • Composition = declarative, the agent authoritative (own wins, skills augment + yield).

The composition seam (why SkillfulAgent works)

ai-skills depends on ai-sdk, never the reverse, so it can't add a skills() hook to the Agent base. I traced the read sites: ai-sdk reads instructions() (abstract) and getTools(a) at loop construction (tools are frozen there — middleware can't add tools). So SkillfulAgent seals instructions()/tools()/middleware() as composing finals over user-authored baseInstructions()/baseTools()/skills(). The low-level compose* helpers are the same merge for anyone who can't extend the base.

Verification

  • pnpm build + pnpm typecheck — all 3 packages ✓
  • 33 tests pass across manifest / loader / registry / compose / agent, including an end-to-end AiFake run asserting ai-sdk delivers the composed system prompt and skill tools to the provider.
  • One-directional confirmed: ai-sdk references ai-skills nowhere.

Changeset: @gemstack/ai-skills minor → 0.1.0.

Follow-up design options remain low-priority and out of scope: TS-first defineSkill (#11), skillTool() wrapper (#12), imperative agent.use() (#13).

Second package of the AI family (#8). Loads SKILL.md skills (instructions +
tools + resources) and composes them onto an @gemstack/ai-sdk Agent.

- manifest: SKILL.md YAML frontmatter + markdown body (matches boost/skills +
  Anthropic Agent Skills shape), zod-validated.
- loader: loadSkill/loadSkills — instructions, co-located tool() exports,
  resources/.
- registry: SkillRegistry discovers skills by cheap frontmatter and loads the
  full body + tools on demand (progressive disclosure).
- compose: composeInstructions/Tools/Middleware merge skills into an agent; the
  agent's own declarations stay authoritative (own tools win collisions, skill
  tools namespaced as backstop). SkillfulAgent base wraps this declaratively.
- trust boundary: no in-process sandbox; discovery runs no skill code,
  loadTools:false surfaces without executing, tool exec stays on the agent's
  approval/middleware path.

One-directional (ai-skills -> ai-sdk). 33 tests incl. an end-to-end run proving
ai-sdk delivers the composed system prompt + skill tools to the provider.

Closes #8
@suleimansh suleimansh added enhancement New feature or request priority: medium Worth doing, not urgent labels Jun 25, 2026
@suleimansh suleimansh self-assigned this Jun 25, 2026
@suleimansh suleimansh merged commit c9758d0 into main Jun 25, 2026
1 check passed
@suleimansh suleimansh deleted the feat/ai-skills branch June 25, 2026 23:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request priority: medium Worth doing, not urgent

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant