feat(ai-skills): add @tanstack/ai-skills — portable Agent Skills middleware - #1236
Draft
jherr wants to merge 7 commits into
Draft
feat(ai-skills): add @tanstack/ai-skills — portable Agent Skills middleware#1236jherr wants to merge 7 commits into
jherr wants to merge 7 commits into
Conversation
Introduce `@tanstack/ai-skills`: portable `SKILL.md` skills as a first-class `chat()` middleware. `withSkills(sources, options?)` renders a per-model-family catalog and a `load_skill` tool so any tool-calling model loads skills on demand, on any provider, with no server sandbox. - Sources: `inlineSkill`, `skillDirectory` (/node), build-time `staticSkills` (/static) with a Vite plugin; combinators `aggregate`/`dedupe`/`filter`/`cache`. - Tools: `load_skill` (enum-constrained names, activation dedupe, frozen result shape) and `createResourceTool` (`read_skill_resource`, path-traversal guard). - `validateSkill` for author-time native-constraint linting; conformance suite at /testing (`runSkillSourceConformance`). - Catalog renders `<available_skills>` XML for Anthropic, markdown elsewhere. Portable and hosted (native) skills refuse to combine in one call. Core `@tanstack/ai` now exports `SkillLimitError`; `codeExecutionTool` (ai-anthropic) frames its 8-skill cap with it, and `shellTool` (openai-base) now validates `skill_id` format. `ai-sandbox` reuses the shared skill-directory walk. Adds e2e wire coverage (portable catalog per family + co-existence refusal), docs (docs/skills/*), a per-package SKILL.md, and a `/skills` demo in testing/panel. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…rry code - Route the new `ai-skills` skill from `ai-core` (sub-skills table + a companion-packages entry) and list `@tanstack/ai-skills` in the getting-started "Skills Shipped" table, so coding agents can find it. - Add a "Skills that come with code" section to the portable-skills guide and the ai-skills SKILL.md: withSkills composes with your own tools, so pass an execution tool (e.g. execute_shell) for skills that reference scripts. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Contributor
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: trueThanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
View your CI Pipeline Execution ↗ for commit fa120d1
☁️ Nx Cloud last updated this comment at |
@tanstack/ai
@tanstack/ai-acp
@tanstack/ai-angular
@tanstack/ai-anthropic
@tanstack/ai-bedrock
@tanstack/ai-byteplus
@tanstack/ai-claude-code
@tanstack/ai-client
@tanstack/ai-code-mode
@tanstack/ai-code-mode-snippets
@tanstack/ai-codex
@tanstack/ai-cohere
@tanstack/ai-devtools-core
@tanstack/ai-durable-stream
@tanstack/ai-elevenlabs
@tanstack/ai-event-client
@tanstack/ai-fal
@tanstack/ai-gemini
@tanstack/ai-grok
@tanstack/ai-grok-build
@tanstack/ai-groq
@tanstack/ai-isolate-cloudflare
@tanstack/ai-isolate-daytona
@tanstack/ai-isolate-node
@tanstack/ai-isolate-quickjs
@tanstack/ai-isolate-quickjs-bun
@tanstack/ai-llmgateway
@tanstack/ai-lovable
@tanstack/ai-mcp
@tanstack/ai-memory
@tanstack/ai-mistral
@tanstack/ai-octane
@tanstack/ai-ollama
@tanstack/ai-openai
@tanstack/ai-opencode
@tanstack/ai-openrouter
@tanstack/ai-perplexity
@tanstack/ai-persistence
@tanstack/ai-preact
@tanstack/ai-react
@tanstack/ai-react-ui
@tanstack/ai-sandbox
@tanstack/ai-sandbox-cloudflare
@tanstack/ai-sandbox-daytona
@tanstack/ai-sandbox-docker
@tanstack/ai-sandbox-local-process
@tanstack/ai-sandbox-sprites
@tanstack/ai-sandbox-vercel
@tanstack/ai-skills
@tanstack/ai-solid
@tanstack/ai-solid-ui
@tanstack/ai-svelte
@tanstack/ai-utils
@tanstack/ai-vercel-gateway
@tanstack/ai-vertex
@tanstack/ai-vue
@tanstack/ai-vue-ui
@tanstack/openai-base
@tanstack/preact-ai-devtools
@tanstack/react-ai-devtools
@tanstack/solid-ai-devtools
@tanstack/svelte-ai-devtools
commit: |
Formatters (autofix-ci) add a trailing newline to the fixture references/note.md, so a file-backed SkillSource reads 'hello\n' while the inline source returns 'hello'. The shared conformance assertion compared byte-exact and failed only for skillDirectory on CI. trimEnd the read value — the payload is what the contract cares about. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
withSkills(...)now gives any tool-calling model a skill catalog and aload_skilltool. The model loads aSKILL.mdonly when it needs it. No hosted sandbox.TanStack AI DevTools now has a Skills tab. It shows the catalog from a
skills:statestream chunk, and it marks a skill loaded when the model callsload_skill. Click the SkillsuseChatrow and the detail pane opens. Before this PR that click did nothing, because the hook registered with an empty id.This also fixes review bugs:
skillDirectorycan load on Windows and by frontmatter name,filter()now hidesload/readResource, filesystem resources return utf8 forreferences/, and catalog overflow throwsSkillLimitError.Changes
@tanstack/ai-skillswithwithSkills,inlineSkill,skillDirectory(/node),staticSkills, and combinators.createResourceToolexposes bundled files asread_skill_resource.SkillLimitError. Native factories throw it for hosted caps. Portable catalog overflow throws it too.useChatwith nothreadIdis selectable.Checklist
pnpm run test:pr.docs/for this change, or this change is not user-facing.pnpm changeset), or this PR does not change a published package.Release Impact
Testing
Commands run. Package tests passed:
pnpm --filter @tanstack/ai-skills test:lib(61 tests)pnpm --filter @tanstack/ai-skills test:typespnpm --filter @tanstack/ai-client test:lib -- tests/devtools.test.ts(38 tests)pnpm --filter @tanstack/ai-devtools-core test:lib(50 tests)I did not run
pnpm test:pr.Manual test.
testing/panel(pnpm devon a free port, for example 3020)./skills.useChatrow. The right pane must show the hook header and tabs (Conversation, Tools, State, Memory, Skills).load_skillin the conversation. The Skills tab marks that skill loaded.How this PR makes testing easy.
packages/ai-skills/tests/(parse, walk, combinators,withSkills,skillDirectory, load-skill).packages/ai-client/tests/devtools.test.ts(skills:stateCUSTOM chunk, plus auseChatwith nothreadIdmust register a generatedhookId) andpackages/ai-devtools/tests/skills-registry.test.ts.testing/e2e/tests/portable-skills-wire.spec.ts./skillsintesting/panel.Risk / rollback
Low risk. The package is opt-in. Nothing loads skills unless you add
withSkills(...). The DevTools tab is empty when noskills:statechunk arrives. To roll back, revert the PR.Public API change
New export
withSkillsfrom@tanstack/ai-skills, plusskillDirectoryfrom@tanstack/ai-skills/node. Caller usage:Before
After
Core
@tanstack/aialso addsSkillLimitError. Portable catalog overflow throws it withpath: 'portable'. DevTools users need no new calls: the Skills tab appears whenwithSkillsis on the server.