@tanstack/intent 0.0.29 → 0.0.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +25 -12
- package/dist/artifact-coverage-BAN2W6aH.mjs +3 -0
- package/dist/artifact-coverage-wLNVX8yC.mjs +128 -0
- package/dist/cli.d.mts +0 -0
- package/dist/cli.mjs +77 -76
- package/dist/{display-hdsqb4w-.mjs → display-BTZWCjzT.mjs} +10 -1
- package/dist/display-DvLbcWzq.mjs +5 -0
- package/dist/index.d.mts +76 -5
- package/dist/index.mjs +126 -6
- package/dist/install-PUnIfBNC.mjs +542 -0
- package/dist/intent-library.mjs +9 -5
- package/dist/{library-scanner-B51qV5aX.mjs → library-scanner-Cl-XPEMf.mjs} +10 -3
- package/dist/library-scanner.d.mts +2 -2
- package/dist/library-scanner.mjs +2 -1
- package/dist/{project-context-D6A5sBBO.mjs → project-context-IDLpJU3S.mjs} +1 -1
- package/dist/resolver-D2CgIYGg.mjs +70 -0
- package/dist/{scanner-B-bbXBLY.mjs → scanner-CW59cxE_.mjs} +176 -117
- package/dist/scanner-DlkcbVye.mjs +6 -0
- package/dist/{setup-B4ZwN5Hg.mjs → setup-DfLsziXU.mjs} +2 -2
- package/dist/setup.d.mts +1 -1
- package/dist/setup.mjs +3 -3
- package/dist/skill-paths-8k9K9y26.mjs +33 -0
- package/dist/skill-use-uwGleSOz.mjs +42 -0
- package/dist/staleness-DpbmYod4.mjs +5 -0
- package/dist/staleness-PdgakrCQ.mjs +243 -0
- package/dist/{types-BTQ9efv-.d.mts → types-_y9b00bI.d.mts} +54 -1
- package/dist/{workspace-patterns-Cndd-7vB.mjs → workspace-patterns-BN2A_60g.mjs} +6 -1
- package/dist/workspace-patterns-x-dLZxx4.mjs +4 -0
- package/meta/templates/workflows/check-skills.yml +199 -91
- package/package.json +3 -4
- package/dist/display-DdmZXLZm.mjs +0 -3
- package/dist/install-BzDmD5yI.mjs +0 -69
- package/dist/scanner-CP4U8F_n.mjs +0 -5
- package/dist/staleness-LRbiWWZK.mjs +0 -4
- package/dist/staleness-SY7-mZMH.mjs +0 -104
- package/dist/workspace-patterns-D_y6rlqX.mjs +0 -4
- package/meta/templates/workflows/notify-intent.yml +0 -51
- /package/dist/{setup-BA9RkENh.d.mts → setup-D2CGdTsx.d.mts} +0 -0
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/intent",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.33",
|
|
4
4
|
"description": "Ship compositional knowledge for AI coding agents alongside your npm packages",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
9
|
-
"url": "https://github.com/
|
|
9
|
+
"url": "https://github.com/TanStack/intent"
|
|
10
10
|
},
|
|
11
11
|
"exports": {
|
|
12
12
|
".": {
|
|
@@ -36,11 +36,10 @@
|
|
|
36
36
|
"verdaccio": "^6.3.2"
|
|
37
37
|
},
|
|
38
38
|
"scripts": {
|
|
39
|
-
"prepack": "npm run build",
|
|
40
39
|
"build": "tsdown src/index.ts src/cli.ts src/setup.ts src/intent-library.ts src/library-scanner.ts --format esm --dts",
|
|
41
40
|
"test:smoke": "pnpm run build && node dist/cli.mjs --help > /dev/null",
|
|
42
41
|
"test:lib": "vitest run --exclude 'tests/integration/**'",
|
|
43
42
|
"test:integration": "vitest run tests/integration/",
|
|
44
43
|
"test:types": "tsc --noEmit"
|
|
45
44
|
}
|
|
46
|
-
}
|
|
45
|
+
}
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
//#region src/commands/install.ts
|
|
2
|
-
const INSTALL_PROMPT = `You are an AI assistant helping a developer set up skill-to-task mappings for their project.
|
|
3
|
-
|
|
4
|
-
Follow these steps in order:
|
|
5
|
-
|
|
6
|
-
1. CHECK FOR EXISTING MAPPINGS
|
|
7
|
-
Search the project's agent config files (AGENTS.md, CLAUDE.md, .cursorrules,
|
|
8
|
-
.github/copilot-instructions.md) for a block delimited by:
|
|
9
|
-
<!-- intent-skills:start -->
|
|
10
|
-
<!-- intent-skills:end -->
|
|
11
|
-
- If found: show the user the current mappings, keep that file as the source of truth,
|
|
12
|
-
and ask "What would you like to update?" Then skip to step 4 with their requested changes.
|
|
13
|
-
- If not found: continue to step 2.
|
|
14
|
-
|
|
15
|
-
2. DISCOVER AVAILABLE SKILLS
|
|
16
|
-
Run: \`npx @tanstack/intent@latest list\`
|
|
17
|
-
This outputs each skill's name, description, full path, and whether it was found in
|
|
18
|
-
project-local node_modules or accessible global node_modules.
|
|
19
|
-
This works best in Node-compatible environments (npm, pnpm, Bun, or Deno npm interop
|
|
20
|
-
with node_modules enabled).
|
|
21
|
-
|
|
22
|
-
3. SCAN THE REPOSITORY
|
|
23
|
-
Build a picture of the project's structure and patterns:
|
|
24
|
-
- Read package.json for library dependencies
|
|
25
|
-
- Survey the directory layout (src/, app/, routes/, components/, api/, etc.)
|
|
26
|
-
- Note recurring patterns (routing, data fetching, auth, UI components, etc.)
|
|
27
|
-
|
|
28
|
-
Based on this, propose 3-5 skill-to-task mappings. For each one explain:
|
|
29
|
-
- The task or code area (in plain language the user would recognise)
|
|
30
|
-
- Which skill applies and why
|
|
31
|
-
|
|
32
|
-
Then ask: "What other tasks do you commonly use AI coding agents for?
|
|
33
|
-
I'll create mappings for those too."
|
|
34
|
-
Also ask: "I'll default to AGENTS.md unless you want another supported config file.
|
|
35
|
-
Do you have a preference?"
|
|
36
|
-
|
|
37
|
-
4. WRITE THE MAPPINGS BLOCK
|
|
38
|
-
Once you have the full set of mappings, write or update the agent config file.
|
|
39
|
-
- If you found an existing intent-skills block, update that file in place.
|
|
40
|
-
- Otherwise prefer AGENTS.md by default, unless the user asked for another supported file.
|
|
41
|
-
|
|
42
|
-
Use this exact block:
|
|
43
|
-
|
|
44
|
-
<!-- intent-skills:start -->
|
|
45
|
-
# Skill mappings - when working in these areas, load the linked skill file into context.
|
|
46
|
-
skills:
|
|
47
|
-
- task: "describe the task or code area here"
|
|
48
|
-
load: "node_modules/package-name/skills/skill-name/SKILL.md"
|
|
49
|
-
<!-- intent-skills:end -->
|
|
50
|
-
|
|
51
|
-
Rules:
|
|
52
|
-
- Use the user's own words for task descriptions
|
|
53
|
-
- Include the exact path from \`npx @tanstack/intent@latest list\` output so agents can load it directly
|
|
54
|
-
- Paths should use the stable \`node_modules/<package-name>/skills/...\` format (no version numbers)
|
|
55
|
-
- If a skill path from \`list\` contains package-manager-internal directories (e.g. \`.pnpm/\`, \`.bun/\`)
|
|
56
|
-
with version numbers, it is a transitive dependency without a stable top-level symlink.
|
|
57
|
-
For these skills, do NOT embed the versioned path. Instead, add a comment telling the agent
|
|
58
|
-
how to locate the skill at runtime:
|
|
59
|
-
- task: "describe the task"
|
|
60
|
-
# To load this skill, run: npx @tanstack/intent@latest list | grep <skill-name>
|
|
61
|
-
- Keep entries concise - this block is read on every agent task
|
|
62
|
-
- Preserve all content outside the block tags unchanged
|
|
63
|
-
- If the user is on Deno, note that this setup is best-effort today and relies on npm interop`;
|
|
64
|
-
function runInstallCommand() {
|
|
65
|
-
console.log(INSTALL_PROMPT);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
//#endregion
|
|
69
|
-
export { runInstallCommand as n, INSTALL_PROMPT as t };
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import { a as parseFrontmatter, n as findSkillFiles } from "./utils-COlDcU72.mjs";
|
|
2
|
-
import { readFileSync } from "node:fs";
|
|
3
|
-
import { join, relative, sep } from "node:path";
|
|
4
|
-
|
|
5
|
-
//#region src/staleness.ts
|
|
6
|
-
function classifyVersionDrift(oldVer, newVer) {
|
|
7
|
-
if (oldVer === newVer) return null;
|
|
8
|
-
const oldParts = oldVer.replace(/[^0-9.]/g, "").split(".").map(Number);
|
|
9
|
-
const newParts = newVer.replace(/[^0-9.]/g, "").split(".").map(Number);
|
|
10
|
-
if ((newParts[0] ?? 0) > (oldParts[0] ?? 0)) return "major";
|
|
11
|
-
if ((newParts[1] ?? 0) > (oldParts[1] ?? 0)) return "minor";
|
|
12
|
-
if ((newParts[2] ?? 0) > (oldParts[2] ?? 0)) return "patch";
|
|
13
|
-
return null;
|
|
14
|
-
}
|
|
15
|
-
function readLocalVersion(packageDir) {
|
|
16
|
-
try {
|
|
17
|
-
const pkgJson = JSON.parse(readFileSync(join(packageDir, "package.json"), "utf8"));
|
|
18
|
-
return typeof pkgJson.version === "string" ? pkgJson.version : null;
|
|
19
|
-
} catch {
|
|
20
|
-
return null;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
async function fetchNpmVersion(packageName) {
|
|
24
|
-
try {
|
|
25
|
-
const res = await fetch(`https://registry.npmjs.org/${encodeURIComponent(packageName)}/latest`);
|
|
26
|
-
if (!res.ok) return null;
|
|
27
|
-
const data = await res.json();
|
|
28
|
-
return typeof data.version === "string" ? data.version : null;
|
|
29
|
-
} catch {
|
|
30
|
-
return null;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
async function fetchCurrentVersion(packageDir, packageName) {
|
|
34
|
-
return readLocalVersion(packageDir) ?? await fetchNpmVersion(packageName);
|
|
35
|
-
}
|
|
36
|
-
function isStringRecord(value) {
|
|
37
|
-
return !!value && typeof value === "object" && !Array.isArray(value) && Object.values(value).every((entry) => typeof entry === "string");
|
|
38
|
-
}
|
|
39
|
-
function parseSyncState(value) {
|
|
40
|
-
if (!value || typeof value !== "object") return null;
|
|
41
|
-
const raw = value;
|
|
42
|
-
const parsed = {};
|
|
43
|
-
if (typeof raw.library_version === "string") parsed.library_version = raw.library_version;
|
|
44
|
-
if (raw.skills && typeof raw.skills === "object") {
|
|
45
|
-
const skills = {};
|
|
46
|
-
for (const [skillName, skillValue] of Object.entries(raw.skills)) {
|
|
47
|
-
if (!skillValue || typeof skillValue !== "object") continue;
|
|
48
|
-
const sourcesSha = skillValue.sources_sha;
|
|
49
|
-
if (sourcesSha !== void 0 && !isStringRecord(sourcesSha)) continue;
|
|
50
|
-
skills[skillName] = {};
|
|
51
|
-
if (sourcesSha) skills[skillName].sources_sha = sourcesSha;
|
|
52
|
-
}
|
|
53
|
-
parsed.skills = skills;
|
|
54
|
-
}
|
|
55
|
-
return parsed;
|
|
56
|
-
}
|
|
57
|
-
function readSyncState(packageDir) {
|
|
58
|
-
const statePath = join(packageDir, "skills", "sync-state.json");
|
|
59
|
-
try {
|
|
60
|
-
return parseSyncState(JSON.parse(readFileSync(statePath, "utf8")));
|
|
61
|
-
} catch {
|
|
62
|
-
return null;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
async function checkStaleness(packageDir, packageName) {
|
|
66
|
-
const skillsDir = join(packageDir, "skills");
|
|
67
|
-
const library = packageName ?? "unknown";
|
|
68
|
-
const skillMetas = findSkillFiles(skillsDir).map((filePath) => {
|
|
69
|
-
const fm = parseFrontmatter(filePath);
|
|
70
|
-
const relName = relative(skillsDir, filePath).replace(/[/\\]SKILL\.md$/, "").split(sep).join("/");
|
|
71
|
-
return {
|
|
72
|
-
name: typeof fm?.name === "string" ? fm.name : relName,
|
|
73
|
-
filePath,
|
|
74
|
-
libraryVersion: fm?.library_version,
|
|
75
|
-
sources: Array.isArray(fm?.sources) ? fm.sources : void 0
|
|
76
|
-
};
|
|
77
|
-
});
|
|
78
|
-
const skillVersion = skillMetas.find((s) => s.libraryVersion)?.libraryVersion ?? null;
|
|
79
|
-
const currentVersion = await fetchCurrentVersion(packageDir, library);
|
|
80
|
-
const versionDrift = skillVersion && currentVersion ? classifyVersionDrift(skillVersion, currentVersion) : null;
|
|
81
|
-
const syncState = readSyncState(packageDir);
|
|
82
|
-
return {
|
|
83
|
-
library,
|
|
84
|
-
currentVersion,
|
|
85
|
-
skillVersion,
|
|
86
|
-
versionDrift,
|
|
87
|
-
skills: skillMetas.map((skill) => {
|
|
88
|
-
const reasons = [];
|
|
89
|
-
if (currentVersion && skill.libraryVersion && skill.libraryVersion !== currentVersion) reasons.push(`version drift (${skill.libraryVersion} → ${currentVersion})`);
|
|
90
|
-
const storedShas = syncState?.skills?.[skill.name]?.sources_sha ?? {};
|
|
91
|
-
if (skill.sources && Object.keys(storedShas).length > 0) {
|
|
92
|
-
for (const source of skill.sources) if (!storedShas[source]) reasons.push(`new source (${source})`);
|
|
93
|
-
}
|
|
94
|
-
return {
|
|
95
|
-
name: skill.name,
|
|
96
|
-
reasons,
|
|
97
|
-
needsReview: reasons.length > 0
|
|
98
|
-
};
|
|
99
|
-
})
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
//#endregion
|
|
104
|
-
export { checkStaleness as t };
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
# notify-intent.yml — Drop this into your library repo's .github/workflows/
|
|
2
|
-
#
|
|
3
|
-
# Fires a repository_dispatch event whenever docs or source files change
|
|
4
|
-
# on merge to main. This triggers the skill staleness check workflow.
|
|
5
|
-
#
|
|
6
|
-
# Requirements:
|
|
7
|
-
# - A fine-grained PAT with contents:write on this repository stored
|
|
8
|
-
# as the INTENT_NOTIFY_TOKEN repository secret.
|
|
9
|
-
#
|
|
10
|
-
# Template variables (replaced by `intent setup`):
|
|
11
|
-
# {{PAYLOAD_PACKAGE}} — e.g. @tanstack/query or my-workspace workspace
|
|
12
|
-
# {{DOCS_PATH}} — e.g. docs/**
|
|
13
|
-
# {{SRC_PATH}} — e.g. packages/query-core/src/**
|
|
14
|
-
|
|
15
|
-
name: Trigger Skill Review
|
|
16
|
-
|
|
17
|
-
on:
|
|
18
|
-
push:
|
|
19
|
-
branches: [main]
|
|
20
|
-
paths:
|
|
21
|
-
- '{{DOCS_PATH}}'
|
|
22
|
-
- '{{SRC_PATH}}'
|
|
23
|
-
|
|
24
|
-
jobs:
|
|
25
|
-
notify:
|
|
26
|
-
name: Trigger Skill Review
|
|
27
|
-
runs-on: ubuntu-latest
|
|
28
|
-
steps:
|
|
29
|
-
- name: Checkout
|
|
30
|
-
uses: actions/checkout@v4
|
|
31
|
-
with:
|
|
32
|
-
fetch-depth: 2
|
|
33
|
-
|
|
34
|
-
- name: Collect changed files
|
|
35
|
-
id: changes
|
|
36
|
-
run: |
|
|
37
|
-
FILES=$(git diff --name-only HEAD~1 HEAD | jq -R -s -c 'split("\n") | map(select(length > 0))')
|
|
38
|
-
echo "files=$FILES" >> "$GITHUB_OUTPUT"
|
|
39
|
-
|
|
40
|
-
- name: Dispatch to intent repo
|
|
41
|
-
uses: peter-evans/repository-dispatch@v3
|
|
42
|
-
with:
|
|
43
|
-
token: ${{ secrets.INTENT_NOTIFY_TOKEN }}
|
|
44
|
-
repository: ${{ github.repository }}
|
|
45
|
-
event-type: skill-check
|
|
46
|
-
client-payload: |
|
|
47
|
-
{
|
|
48
|
-
"package": "{{PAYLOAD_PACKAGE}}",
|
|
49
|
-
"sha": "${{ github.sha }}",
|
|
50
|
-
"changed_files": ${{ steps.changes.outputs.files }}
|
|
51
|
-
}
|
|
File without changes
|