@tanstack/intent 0.0.20 → 0.0.23
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/dist/cli.d.mts +1 -2
- package/dist/cli.mjs +273 -282
- package/dist/index.d.mts +3 -3
- package/dist/index.mjs +3 -3
- package/dist/{install-prompt-C0M-U3WZ.mjs → install-BHbA_wkb.mjs} +5 -2
- package/dist/intent-library.mjs +5 -5
- package/dist/{library-scanner-DBOEhfm8.mjs → library-scanner-DlWy8VeZ.mjs} +7 -5
- package/dist/library-scanner.d.mts +1 -1
- package/dist/library-scanner.mjs +1 -1
- package/dist/{scanner-DVepyEwz.mjs → scanner-BCgNt-oI.mjs} +2 -2
- package/dist/scanner-CsDGCRDm.mjs +5 -0
- package/dist/{setup-B-zdCBu4.d.mts → setup-BNBVotfR.d.mts} +1 -7
- package/dist/{setup-mGV2dZrq.mjs → setup-Nyfl1KTS.mjs} +30 -102
- package/dist/setup.d.mts +2 -2
- package/dist/setup.mjs +2 -2
- package/meta/templates/workflows/notify-intent.yml +6 -7
- package/package.json +3 -1
- package/dist/scanner-BHPl60jH.mjs +0 -5
package/dist/cli.d.mts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
//#region src/cli.d.ts
|
|
3
|
-
declare const USAGE = "TanStack Intent CLI\n\nUsage:\n intent list [--json] Discover intent-enabled packages\n intent meta [name] List meta-skills, or print one by name\n intent validate [<dir>] Validate skill files (default: skills/)\n intent install Print a skill that guides your coding agent to set up skill-to-task mappings\n intent scaffold Print maintainer scaffold prompt\n intent add-library-bin Generate bin/intent.{js,mjs} bridge file\n intent edit-package-json Wire package.json (files, bin) for skill publishing\n intent setup-github-actions Copy CI workflow templates to .github/workflows/\n intent stale [dir] [--json] Check skills for staleness";
|
|
4
3
|
declare function main(argv?: Array<string>): Promise<number>;
|
|
5
4
|
//#endregion
|
|
6
|
-
export {
|
|
5
|
+
export { main };
|
package/dist/cli.mjs
CHANGED
|
@@ -1,35 +1,72 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { n as runInstallCommand } from "./install-BHbA_wkb.mjs";
|
|
3
3
|
import { existsSync, readFileSync, readdirSync, realpathSync } from "node:fs";
|
|
4
4
|
import { dirname, join, relative, sep } from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
|
+
import { cac } from "cac";
|
|
6
7
|
|
|
7
|
-
//#region src/cli.ts
|
|
8
|
-
|
|
9
|
-
return join(dirname(fileURLToPath(import.meta.url)), "..", "meta");
|
|
10
|
-
}
|
|
8
|
+
//#region src/cli-error.ts
|
|
9
|
+
const CLI_FAILURE = Symbol("CliFailure");
|
|
11
10
|
function fail(message, exitCode = 1) {
|
|
12
11
|
throw {
|
|
12
|
+
[CLI_FAILURE]: true,
|
|
13
13
|
message,
|
|
14
14
|
exitCode
|
|
15
15
|
};
|
|
16
16
|
}
|
|
17
17
|
function isCliFailure(value) {
|
|
18
|
-
return !!value && typeof value === "object" &&
|
|
18
|
+
return !!value && typeof value === "object" && CLI_FAILURE in value;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
//#endregion
|
|
22
|
+
//#region src/cli-support.ts
|
|
23
|
+
function printWarnings(warnings) {
|
|
24
|
+
if (warnings.length === 0) return;
|
|
25
|
+
console.log("Warnings:");
|
|
26
|
+
for (const warning of warnings) console.log(` ⚠ ${warning}`);
|
|
27
|
+
}
|
|
28
|
+
function getMetaDir() {
|
|
29
|
+
return join(dirname(fileURLToPath(import.meta.url)), "..", "meta");
|
|
19
30
|
}
|
|
20
31
|
async function scanIntentsOrFail() {
|
|
21
|
-
const { scanForIntents } = await import("./scanner-
|
|
32
|
+
const { scanForIntents } = await import("./scanner-CsDGCRDm.mjs");
|
|
22
33
|
try {
|
|
23
|
-
return
|
|
34
|
+
return scanForIntents();
|
|
24
35
|
} catch (err) {
|
|
25
|
-
fail(err.message);
|
|
36
|
+
fail(err instanceof Error ? err.message : String(err));
|
|
26
37
|
}
|
|
27
38
|
}
|
|
28
|
-
function
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
39
|
+
function readPackageName(root) {
|
|
40
|
+
try {
|
|
41
|
+
const pkgJson = JSON.parse(readFileSync(join(root, "package.json"), "utf8"));
|
|
42
|
+
return typeof pkgJson.name === "string" ? pkgJson.name : relative(process.cwd(), root) || "unknown";
|
|
43
|
+
} catch {
|
|
44
|
+
return relative(process.cwd(), root) || "unknown";
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
async function resolveStaleTargets(targetDir) {
|
|
48
|
+
const resolvedRoot = targetDir ? join(process.cwd(), targetDir) : process.cwd();
|
|
49
|
+
const { checkStaleness } = await import("./staleness-Dr5-5wj5.mjs");
|
|
50
|
+
if (existsSync(join(resolvedRoot, "skills"))) return { reports: [await checkStaleness(resolvedRoot, readPackageName(resolvedRoot))] };
|
|
51
|
+
const { findPackagesWithSkills, findWorkspaceRoot } = await import("./setup.mjs");
|
|
52
|
+
const workspaceRoot = findWorkspaceRoot(resolvedRoot);
|
|
53
|
+
if (workspaceRoot) {
|
|
54
|
+
const packageDirs = findPackagesWithSkills(workspaceRoot);
|
|
55
|
+
if (packageDirs.length > 0) return { reports: await Promise.all(packageDirs.map((packageDir) => checkStaleness(packageDir, readPackageName(packageDir)))) };
|
|
56
|
+
}
|
|
57
|
+
const staleResult = await scanIntentsOrFail();
|
|
58
|
+
return { reports: await Promise.all(staleResult.packages.map((pkg) => checkStaleness(pkg.packageRoot, pkg.name))) };
|
|
32
59
|
}
|
|
60
|
+
|
|
61
|
+
//#endregion
|
|
62
|
+
//#region src/commands/edit-package-json.ts
|
|
63
|
+
async function runEditPackageJsonCommand(root) {
|
|
64
|
+
const { runEditPackageJsonAll } = await import("./setup.mjs");
|
|
65
|
+
runEditPackageJsonAll(root);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
//#endregion
|
|
69
|
+
//#region src/commands/list.ts
|
|
33
70
|
function formatScanCoverage(result) {
|
|
34
71
|
const coverage = [];
|
|
35
72
|
if (result.nodeModules.local.scanned) coverage.push("project node_modules");
|
|
@@ -49,24 +86,10 @@ function printVersionConflicts(result) {
|
|
|
49
86
|
console.log();
|
|
50
87
|
}
|
|
51
88
|
}
|
|
52
|
-
function
|
|
53
|
-
const lines = [
|
|
54
|
-
"",
|
|
55
|
-
`❌ Validation failed with ${errors.length} error(s):`,
|
|
56
|
-
""
|
|
57
|
-
];
|
|
58
|
-
for (const { file, message } of errors) lines.push(` ${file}: ${message}`);
|
|
59
|
-
if (warnings.length > 0) {
|
|
60
|
-
lines.push("", "⚠ Packaging warnings:");
|
|
61
|
-
for (const warning of warnings) lines.push(` ${warning}`);
|
|
62
|
-
}
|
|
63
|
-
return lines.join("\n");
|
|
64
|
-
}
|
|
65
|
-
async function cmdList(args) {
|
|
89
|
+
async function runListCommand(options, scanIntentsOrFail$1) {
|
|
66
90
|
const { computeSkillNameWidth, printSkillTree, printTable } = await import("./display-CuCDLPP_.mjs");
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
if (jsonOutput) {
|
|
91
|
+
const result = await scanIntentsOrFail$1();
|
|
92
|
+
if (options.json) {
|
|
70
93
|
console.log(JSON.stringify(result, null, 2));
|
|
71
94
|
return;
|
|
72
95
|
}
|
|
@@ -80,7 +103,7 @@ async function cmdList(args) {
|
|
|
80
103
|
}
|
|
81
104
|
return;
|
|
82
105
|
}
|
|
83
|
-
const totalSkills = result.packages.reduce((sum,
|
|
106
|
+
const totalSkills = result.packages.reduce((sum, pkg) => sum + pkg.skills.length, 0);
|
|
84
107
|
console.log(`\n${result.packages.length} intent-enabled packages, ${totalSkills} skills (${result.packageManager})\n`);
|
|
85
108
|
if (scanCoverage) console.log(`Scanned: ${scanCoverage}${result.nodeModules.global.scanned ? " (local packages take precedence)" : ""}\n`);
|
|
86
109
|
printTable([
|
|
@@ -95,8 +118,8 @@ async function cmdList(args) {
|
|
|
95
118
|
pkg.intent.requires?.join(", ") || "–"
|
|
96
119
|
]));
|
|
97
120
|
printVersionConflicts(result);
|
|
98
|
-
const nameWidth = computeSkillNameWidth(result.packages.map((
|
|
99
|
-
const showTypes = result.packages.some((
|
|
121
|
+
const nameWidth = computeSkillNameWidth(result.packages.map((pkg) => pkg.skills));
|
|
122
|
+
const showTypes = result.packages.some((pkg) => pkg.skills.some((skill) => skill.type));
|
|
100
123
|
console.log(`\nSkills:\n`);
|
|
101
124
|
for (const pkg of result.packages) {
|
|
102
125
|
console.log(` ${pkg.name}`);
|
|
@@ -106,18 +129,18 @@ async function cmdList(args) {
|
|
|
106
129
|
});
|
|
107
130
|
console.log();
|
|
108
131
|
}
|
|
109
|
-
console.log(
|
|
110
|
-
console.log(
|
|
111
|
-
console.log(
|
|
132
|
+
console.log("Feedback:");
|
|
133
|
+
console.log(" Submit feedback on skill usage to help maintainers improve the skills.");
|
|
134
|
+
console.log(" Load: node_modules/@tanstack/intent/meta/feedback-collection/SKILL.md");
|
|
112
135
|
console.log();
|
|
113
136
|
printWarnings(result.warnings);
|
|
114
137
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
138
|
+
|
|
139
|
+
//#endregion
|
|
140
|
+
//#region src/commands/meta.ts
|
|
141
|
+
async function runMetaCommand(name, metaDir) {
|
|
118
142
|
if (!existsSync(metaDir)) fail("Meta-skills directory not found.");
|
|
119
|
-
if (
|
|
120
|
-
const name = args[0];
|
|
143
|
+
if (name) {
|
|
121
144
|
if (name.includes("..") || name.includes("/") || name.includes("\\")) fail(`Invalid meta-skill name: "${name}"`);
|
|
122
145
|
const skillFile = join(metaDir, name, "SKILL.md");
|
|
123
146
|
if (!existsSync(skillFile)) fail(`Meta-skill "${name}" not found. Run \`intent meta\` to list available meta-skills.`);
|
|
@@ -128,7 +151,8 @@ async function cmdMeta(args) {
|
|
|
128
151
|
}
|
|
129
152
|
return;
|
|
130
153
|
}
|
|
131
|
-
const
|
|
154
|
+
const { parseFrontmatter } = await import("./utils-D7OKi0Rn.mjs");
|
|
155
|
+
const entries = readdirSync(metaDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).filter((entry) => existsSync(join(metaDir, entry.name, "SKILL.md")));
|
|
132
156
|
if (entries.length === 0) {
|
|
133
157
|
console.log("No meta-skills found.");
|
|
134
158
|
return;
|
|
@@ -138,11 +162,145 @@ async function cmdMeta(args) {
|
|
|
138
162
|
const fm = parseFrontmatter(join(metaDir, entry.name, "SKILL.md"));
|
|
139
163
|
let description = "";
|
|
140
164
|
if (typeof fm?.description === "string") description = fm.description.replace(/\s+/g, " ").trim();
|
|
141
|
-
const shortDesc = description.length > 60 ? description.slice(0, 57)
|
|
165
|
+
const shortDesc = description.length > 60 ? `${description.slice(0, 57)}...` : description;
|
|
142
166
|
console.log(` ${entry.name.padEnd(28)} ${shortDesc}`);
|
|
143
167
|
}
|
|
144
|
-
console.log(
|
|
145
|
-
console.log(
|
|
168
|
+
console.log("\nUsage: load the SKILL.md into your AI agent conversation.");
|
|
169
|
+
console.log("Path: node_modules/@tanstack/intent/meta/<name>/SKILL.md");
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
//#endregion
|
|
173
|
+
//#region src/commands/scaffold.ts
|
|
174
|
+
function runScaffoldCommand(metaDir) {
|
|
175
|
+
function metaSkillPath(name) {
|
|
176
|
+
return join(metaDir, name, "SKILL.md");
|
|
177
|
+
}
|
|
178
|
+
const prompt = `You are helping a library maintainer scaffold Intent skills.
|
|
179
|
+
|
|
180
|
+
Run the three meta skills below **one at a time, in order**. For each step:
|
|
181
|
+
1. Load the SKILL.md file specified
|
|
182
|
+
2. Follow its instructions completely
|
|
183
|
+
3. Present outputs to the maintainer for review
|
|
184
|
+
4. Do NOT proceed to the next step until the maintainer confirms
|
|
185
|
+
|
|
186
|
+
## Before you start
|
|
187
|
+
|
|
188
|
+
Gather this context yourself (do not ask the maintainer — agents should never
|
|
189
|
+
ask for information they can discover):
|
|
190
|
+
1. Read package.json for library name, repository URL, and homepage/docs URL
|
|
191
|
+
2. Detect if this is a monorepo (look for workspaces field, packages/ directory, lerna.json)
|
|
192
|
+
3. Use skills/ as the default skills root
|
|
193
|
+
4. For monorepos:
|
|
194
|
+
- Domain map artifacts go at the REPO ROOT: _artifacts/
|
|
195
|
+
- Skills go INSIDE EACH PACKAGE: packages/<pkg>/skills/
|
|
196
|
+
- Identify which packages are client-facing (usually client SDKs and primary framework adapters)
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## Step 1 — Domain Discovery
|
|
201
|
+
|
|
202
|
+
Load and follow: ${metaSkillPath("domain-discovery")}
|
|
203
|
+
|
|
204
|
+
This produces: domain_map.yaml and skill_spec.md in the artifacts directory.
|
|
205
|
+
Domain discovery covers the WHOLE library (one domain map even for monorepos).
|
|
206
|
+
|
|
207
|
+
**STOP. Review outputs with the maintainer before continuing.**
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## Step 2 — Tree Generator
|
|
212
|
+
|
|
213
|
+
Load and follow: ${metaSkillPath("tree-generator")}
|
|
214
|
+
|
|
215
|
+
This produces: skill_tree.yaml in the artifacts directory.
|
|
216
|
+
For monorepos, each skill entry should include a \`package\` field.
|
|
217
|
+
|
|
218
|
+
**STOP. Review outputs with the maintainer before continuing.**
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## Step 3 — Generate Skills
|
|
223
|
+
|
|
224
|
+
Load and follow: ${metaSkillPath("generate-skill")}
|
|
225
|
+
|
|
226
|
+
This produces: individual SKILL.md files.
|
|
227
|
+
- Single-repo: skills/<domain>/<skill>/SKILL.md
|
|
228
|
+
- Monorepo: packages/<pkg>/skills/<domain>/<skill>/SKILL.md
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## After all skills are generated
|
|
233
|
+
|
|
234
|
+
1. Run \`intent validate\` in each package directory
|
|
235
|
+
2. Commit skills/ and artifacts
|
|
236
|
+
3. For each publishable package, run: \`npx @tanstack/intent edit-package-json\`
|
|
237
|
+
4. Ensure each package has \`@tanstack/intent\` as a devDependency
|
|
238
|
+
5. Create a \`skill:<skill-name>\` label on the GitHub repo for each skill (use \`gh label create\`)
|
|
239
|
+
6. Add a README note: "If you use an AI agent, run \`npx @tanstack/intent@latest install\`"
|
|
240
|
+
`;
|
|
241
|
+
console.log(prompt);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
//#endregion
|
|
245
|
+
//#region src/commands/setup-github-actions.ts
|
|
246
|
+
async function runSetupGithubActionsCommand(root, metaDir) {
|
|
247
|
+
const { runSetupGithubActions } = await import("./setup.mjs");
|
|
248
|
+
runSetupGithubActions(root, metaDir);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
//#endregion
|
|
252
|
+
//#region src/commands/stale.ts
|
|
253
|
+
async function runStaleCommand(targetDir, options, resolveStaleTargets$1) {
|
|
254
|
+
const { reports } = await resolveStaleTargets$1(targetDir);
|
|
255
|
+
if (reports.length === 0) {
|
|
256
|
+
console.log("No intent-enabled packages found.");
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
if (options.json) {
|
|
260
|
+
console.log(JSON.stringify(reports, null, 2));
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
for (const report of reports) {
|
|
264
|
+
const driftLabel = report.versionDrift ? ` [${report.versionDrift} drift]` : "";
|
|
265
|
+
const vLabel = report.skillVersion && report.currentVersion ? ` (${report.skillVersion} → ${report.currentVersion})` : "";
|
|
266
|
+
console.log(`${report.library}${vLabel}${driftLabel}`);
|
|
267
|
+
const stale = report.skills.filter((skill) => skill.needsReview);
|
|
268
|
+
if (stale.length === 0) console.log(" All skills up-to-date");
|
|
269
|
+
else for (const skill of stale) console.log(` ⚠ ${skill.name}: ${skill.reasons.join(", ")}`);
|
|
270
|
+
console.log();
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
//#endregion
|
|
275
|
+
//#region src/commands/validate.ts
|
|
276
|
+
function buildValidationFailure(errors, warnings) {
|
|
277
|
+
const lines = [
|
|
278
|
+
"",
|
|
279
|
+
`❌ Validation failed with ${errors.length} error(s):`,
|
|
280
|
+
""
|
|
281
|
+
];
|
|
282
|
+
for (const { file, message } of errors) lines.push(` ${file}: ${message}`);
|
|
283
|
+
if (warnings.length > 0) {
|
|
284
|
+
lines.push("", "⚠ Packaging warnings:");
|
|
285
|
+
for (const warning of warnings) lines.push(` ${warning}`);
|
|
286
|
+
}
|
|
287
|
+
return lines.join("\n");
|
|
288
|
+
}
|
|
289
|
+
function isInsideMonorepo(root) {
|
|
290
|
+
let dir = join(root, "..");
|
|
291
|
+
for (let i = 0; i < 5; i++) {
|
|
292
|
+
const parentPkg = join(dir, "package.json");
|
|
293
|
+
if (existsSync(parentPkg)) try {
|
|
294
|
+
const parent = JSON.parse(readFileSync(parentPkg, "utf8"));
|
|
295
|
+
return Array.isArray(parent.workspaces) || parent.workspaces?.packages;
|
|
296
|
+
} catch {
|
|
297
|
+
return false;
|
|
298
|
+
}
|
|
299
|
+
const next = dirname(dir);
|
|
300
|
+
if (next === dir) break;
|
|
301
|
+
dir = next;
|
|
302
|
+
}
|
|
303
|
+
return false;
|
|
146
304
|
}
|
|
147
305
|
function collectPackagingWarnings(root) {
|
|
148
306
|
const pkgJsonPath = join(root, "package.json");
|
|
@@ -155,15 +313,12 @@ function collectPackagingWarnings(root) {
|
|
|
155
313
|
}
|
|
156
314
|
const warnings = [];
|
|
157
315
|
if (!pkgJson.devDependencies?.["@tanstack/intent"]) warnings.push("@tanstack/intent is not in devDependencies");
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
const shimMjs = join(root, "bin", "intent.mjs");
|
|
161
|
-
if (!existsSync(shimJs) && !existsSync(shimMjs)) warnings.push("No bin/intent.js or bin/intent.mjs shim found (run: npx @tanstack/intent add-library-bin)");
|
|
316
|
+
const keywords = pkgJson.keywords;
|
|
317
|
+
if (!Array.isArray(keywords) || !keywords.includes("tanstack-intent")) warnings.push("Missing \"tanstack-intent\" in keywords array");
|
|
162
318
|
const files = pkgJson.files;
|
|
163
319
|
if (Array.isArray(files)) {
|
|
164
320
|
if (!files.includes("skills")) warnings.push("\"skills\" is not in the \"files\" array — skills won't be published");
|
|
165
|
-
if (!files.includes("
|
|
166
|
-
if (!files.includes("!skills/_artifacts")) warnings.push("\"!skills/_artifacts\" is not in the \"files\" array — artifacts will be published unnecessarily");
|
|
321
|
+
if (!isInsideMonorepo(root) && !files.includes("!skills/_artifacts")) warnings.push("\"!skills/_artifacts\" is not in the \"files\" array — artifacts will be published unnecessarily");
|
|
167
322
|
}
|
|
168
323
|
return warnings;
|
|
169
324
|
}
|
|
@@ -176,30 +331,9 @@ function resolvePackageRoot(startDir) {
|
|
|
176
331
|
dir = next;
|
|
177
332
|
}
|
|
178
333
|
}
|
|
179
|
-
function
|
|
180
|
-
try {
|
|
181
|
-
const pkgJson = JSON.parse(readFileSync(join(root, "package.json"), "utf8"));
|
|
182
|
-
return typeof pkgJson.name === "string" ? pkgJson.name : relative(process.cwd(), root) || "unknown";
|
|
183
|
-
} catch {
|
|
184
|
-
return relative(process.cwd(), root) || "unknown";
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
async function resolveStaleTargets(targetDir) {
|
|
188
|
-
const resolvedRoot = targetDir ? join(process.cwd(), targetDir) : process.cwd();
|
|
189
|
-
const { checkStaleness } = await import("./staleness-Dr5-5wj5.mjs");
|
|
190
|
-
if (existsSync(join(resolvedRoot, "skills"))) return { reports: [await checkStaleness(resolvedRoot, readPackageName(resolvedRoot))] };
|
|
191
|
-
const { findPackagesWithSkills, findWorkspaceRoot } = await import("./setup.mjs");
|
|
192
|
-
const workspaceRoot = findWorkspaceRoot(resolvedRoot);
|
|
193
|
-
if (workspaceRoot) {
|
|
194
|
-
const packageDirs = findPackagesWithSkills(workspaceRoot);
|
|
195
|
-
if (packageDirs.length > 0) return { reports: await Promise.all(packageDirs.map((packageDir) => checkStaleness(packageDir, readPackageName(packageDir)))) };
|
|
196
|
-
}
|
|
197
|
-
const staleResult = await scanIntentsOrFail();
|
|
198
|
-
return { reports: await Promise.all(staleResult.packages.map((pkg) => checkStaleness(pkg.packageRoot, pkg.name))) };
|
|
199
|
-
}
|
|
200
|
-
async function cmdValidate(args) {
|
|
334
|
+
async function runValidateCommand(dir) {
|
|
201
335
|
const [{ parse: parseYaml }, { findSkillFiles }] = await Promise.all([import("yaml"), import("./utils-D7OKi0Rn.mjs")]);
|
|
202
|
-
const targetDir =
|
|
336
|
+
const targetDir = dir ?? "skills";
|
|
203
337
|
const skillsDir = join(process.cwd(), targetDir);
|
|
204
338
|
const packageRoot = resolvePackageRoot(skillsDir);
|
|
205
339
|
if (!existsSync(skillsDir)) fail(`Skills directory not found: ${skillsDir}`);
|
|
@@ -227,10 +361,11 @@ async function cmdValidate(args) {
|
|
|
227
361
|
let fm;
|
|
228
362
|
try {
|
|
229
363
|
fm = parseYaml(match[1]);
|
|
230
|
-
} catch {
|
|
364
|
+
} catch (err) {
|
|
365
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
231
366
|
errors.push({
|
|
232
367
|
file: rel,
|
|
233
|
-
message:
|
|
368
|
+
message: `Invalid YAML frontmatter: ${detail}`
|
|
234
369
|
});
|
|
235
370
|
continue;
|
|
236
371
|
}
|
|
@@ -287,10 +422,11 @@ async function cmdValidate(args) {
|
|
|
287
422
|
}
|
|
288
423
|
if (fileName.endsWith(".yaml")) try {
|
|
289
424
|
parseYaml(content);
|
|
290
|
-
} catch {
|
|
425
|
+
} catch (err) {
|
|
426
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
291
427
|
errors.push({
|
|
292
428
|
file: relative(process.cwd(), artifactPath),
|
|
293
|
-
message:
|
|
429
|
+
message: `Invalid YAML in artifact file: ${detail}`
|
|
294
430
|
});
|
|
295
431
|
}
|
|
296
432
|
}
|
|
@@ -300,221 +436,76 @@ async function cmdValidate(args) {
|
|
|
300
436
|
if (warnings.length > 0) console.log();
|
|
301
437
|
printWarnings(warnings);
|
|
302
438
|
}
|
|
303
|
-
function cmdScaffold() {
|
|
304
|
-
const metaDir = getMetaDir();
|
|
305
|
-
const metaSkillPath = (name) => join(metaDir, name, "SKILL.md");
|
|
306
|
-
const prompt = `You are helping a library maintainer scaffold Intent skills.
|
|
307
|
-
|
|
308
|
-
Run the three meta skills below **one at a time, in order**. For each step:
|
|
309
|
-
1. Load the SKILL.md file specified
|
|
310
|
-
2. Follow its instructions completely
|
|
311
|
-
3. Present outputs to the maintainer for review
|
|
312
|
-
4. Do NOT proceed to the next step until the maintainer confirms
|
|
313
|
-
|
|
314
|
-
## Before you start
|
|
315
|
-
|
|
316
|
-
Gather this context yourself (do not ask the maintainer — agents should never
|
|
317
|
-
ask for information they can discover):
|
|
318
|
-
1. Read package.json for library name, repository URL, and homepage/docs URL
|
|
319
|
-
2. Detect if this is a monorepo (look for workspaces field, packages/ directory, lerna.json)
|
|
320
|
-
3. Use skills/ as the default skills root
|
|
321
|
-
4. For monorepos:
|
|
322
|
-
- Domain map artifacts go at the REPO ROOT: _artifacts/
|
|
323
|
-
- Skills go INSIDE EACH PACKAGE: packages/<pkg>/skills/
|
|
324
|
-
- Identify which packages are client-facing (usually client SDKs and primary framework adapters)
|
|
325
|
-
|
|
326
|
-
---
|
|
327
|
-
|
|
328
|
-
## Step 1 — Domain Discovery
|
|
329
|
-
|
|
330
|
-
Load and follow: ${metaSkillPath("domain-discovery")}
|
|
331
|
-
|
|
332
|
-
This produces: domain_map.yaml and skill_spec.md in the artifacts directory.
|
|
333
|
-
Domain discovery covers the WHOLE library (one domain map even for monorepos).
|
|
334
|
-
|
|
335
|
-
**STOP. Review outputs with the maintainer before continuing.**
|
|
336
|
-
|
|
337
|
-
---
|
|
338
|
-
|
|
339
|
-
## Step 2 — Tree Generator
|
|
340
|
-
|
|
341
|
-
Load and follow: ${metaSkillPath("tree-generator")}
|
|
342
|
-
|
|
343
|
-
This produces: skill_tree.yaml in the artifacts directory.
|
|
344
|
-
For monorepos, each skill entry should include a \`package\` field.
|
|
345
|
-
|
|
346
|
-
**STOP. Review outputs with the maintainer before continuing.**
|
|
347
|
-
|
|
348
|
-
---
|
|
349
|
-
|
|
350
|
-
## Step 3 — Generate Skills
|
|
351
|
-
|
|
352
|
-
Load and follow: ${metaSkillPath("generate-skill")}
|
|
353
|
-
|
|
354
|
-
This produces: individual SKILL.md files.
|
|
355
|
-
- Single-repo: skills/<domain>/<skill>/SKILL.md
|
|
356
|
-
- Monorepo: packages/<pkg>/skills/<domain>/<skill>/SKILL.md
|
|
357
|
-
|
|
358
|
-
---
|
|
359
|
-
|
|
360
|
-
## After all skills are generated
|
|
361
|
-
|
|
362
|
-
1. Run \`intent validate\` in each package directory
|
|
363
|
-
2. Commit skills/ and artifacts
|
|
364
|
-
3. For each publishable package, run: \`npx @tanstack/intent add-library-bin\`
|
|
365
|
-
4. For each publishable package, run: \`npx @tanstack/intent edit-package-json\`
|
|
366
|
-
5. Ensure each package has \`@tanstack/intent\` as a devDependency
|
|
367
|
-
6. Create a \`skill:<skill-name>\` label on the GitHub repo for each skill (use \`gh label create\`)
|
|
368
|
-
7. Add a README note: "If you use an AI agent, run \`npx @tanstack/intent@latest install\`"
|
|
369
|
-
`;
|
|
370
|
-
console.log(prompt);
|
|
371
|
-
}
|
|
372
|
-
const USAGE = `TanStack Intent CLI
|
|
373
|
-
|
|
374
|
-
Usage:
|
|
375
|
-
intent list [--json] Discover intent-enabled packages
|
|
376
|
-
intent meta [name] List meta-skills, or print one by name
|
|
377
|
-
intent validate [<dir>] Validate skill files (default: skills/)
|
|
378
|
-
intent install Print a skill that guides your coding agent to set up skill-to-task mappings
|
|
379
|
-
intent scaffold Print maintainer scaffold prompt
|
|
380
|
-
intent add-library-bin Generate bin/intent.{js,mjs} bridge file
|
|
381
|
-
intent edit-package-json Wire package.json (files, bin) for skill publishing
|
|
382
|
-
intent setup-github-actions Copy CI workflow templates to .github/workflows/
|
|
383
|
-
intent stale [dir] [--json] Check skills for staleness`;
|
|
384
|
-
const HELP_BY_COMMAND = {
|
|
385
|
-
list: `${USAGE}
|
|
386
|
-
|
|
387
|
-
Examples:
|
|
388
|
-
intent list
|
|
389
|
-
intent list --json`,
|
|
390
|
-
meta: `intent meta [name]
|
|
391
|
-
|
|
392
|
-
List shipped meta-skills, or print a single meta-skill by name.
|
|
393
|
-
|
|
394
|
-
Examples:
|
|
395
|
-
intent meta
|
|
396
|
-
intent meta domain-discovery`,
|
|
397
|
-
validate: `intent validate [dir]
|
|
398
|
-
|
|
399
|
-
Validate SKILL.md files in the target directory.
|
|
400
|
-
|
|
401
|
-
Examples:
|
|
402
|
-
intent validate
|
|
403
|
-
intent validate packages/query/skills`,
|
|
404
|
-
install: `intent install
|
|
405
|
-
|
|
406
|
-
Print the install prompt used to set up skill-to-task mappings.`,
|
|
407
|
-
scaffold: `intent scaffold
|
|
408
|
-
|
|
409
|
-
Print the guided maintainer prompt for generating skills.`,
|
|
410
|
-
stale: `intent stale [dir] [--json]
|
|
411
|
-
|
|
412
|
-
Check installed skills for version and source drift.
|
|
413
439
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
"
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
};
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
440
|
+
//#endregion
|
|
441
|
+
//#region src/cli.ts
|
|
442
|
+
function createCli() {
|
|
443
|
+
const cli = cac("intent");
|
|
444
|
+
cli.usage("<command> [options]");
|
|
445
|
+
cli.command("list", "Discover intent-enabled packages").usage("list [--json]").option("--json", "Output JSON").example("list").example("list --json").action(async (options) => {
|
|
446
|
+
await runListCommand(options, scanIntentsOrFail);
|
|
447
|
+
});
|
|
448
|
+
cli.command("meta [name]", "List meta-skills, or print one by name").usage("meta [name]").example("meta").example("meta domain-discovery").action(async (name) => {
|
|
449
|
+
await runMetaCommand(name, getMetaDir());
|
|
450
|
+
});
|
|
451
|
+
cli.command("validate [dir]", "Validate skill files").usage("validate [dir]").example("validate").example("validate packages/query/skills").action(async (dir) => {
|
|
452
|
+
await runValidateCommand(dir);
|
|
453
|
+
});
|
|
454
|
+
cli.command("install", "Print a skill that guides your coding agent to set up skill-to-task mappings").usage("install").action(() => {
|
|
455
|
+
runInstallCommand();
|
|
456
|
+
});
|
|
457
|
+
cli.command("scaffold", "Print maintainer scaffold prompt").usage("scaffold").action(() => {
|
|
458
|
+
runScaffoldCommand(getMetaDir());
|
|
459
|
+
});
|
|
460
|
+
cli.command("stale [dir]", "Check skills for staleness").usage("stale [dir] [--json]").option("--json", "Output JSON").example("stale").example("stale packages/query").example("stale --json").action(async (targetDir, options) => {
|
|
461
|
+
await runStaleCommand(targetDir, options, resolveStaleTargets);
|
|
462
|
+
});
|
|
463
|
+
cli.command("edit-package-json", "Update package.json files so skills are published").usage("edit-package-json").action(async () => {
|
|
464
|
+
await runEditPackageJsonCommand(process.cwd());
|
|
465
|
+
});
|
|
466
|
+
cli.command("setup-github-actions", "Copy Intent CI workflow templates into .github/workflows/").usage("setup-github-actions").action(async () => {
|
|
467
|
+
await runSetupGithubActionsCommand(process.cwd(), getMetaDir());
|
|
468
|
+
});
|
|
469
|
+
cli.command("help [command]", "Display help for a command").action((commandName) => {
|
|
470
|
+
if (!commandName) {
|
|
471
|
+
cli.outputHelp();
|
|
472
|
+
return;
|
|
473
|
+
}
|
|
474
|
+
const command = cli.commands.find((candidate) => candidate.isMatched(commandName));
|
|
475
|
+
if (!command) fail(`Unknown command: ${commandName}`);
|
|
476
|
+
command.outputHelp();
|
|
477
|
+
});
|
|
478
|
+
cli.help();
|
|
479
|
+
return cli;
|
|
439
480
|
}
|
|
440
481
|
async function main(argv = process.argv.slice(2)) {
|
|
441
|
-
const command = argv[0];
|
|
442
|
-
const commandArgs = argv.slice(1);
|
|
443
482
|
try {
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
}
|
|
448
|
-
if (command === "help") {
|
|
449
|
-
printHelp(commandArgs[0]);
|
|
483
|
+
const cli = createCli();
|
|
484
|
+
if (argv.length === 0) {
|
|
485
|
+
cli.outputHelp();
|
|
450
486
|
return 0;
|
|
451
487
|
}
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
await cmdMeta(commandArgs);
|
|
462
|
-
return 0;
|
|
463
|
-
case "validate":
|
|
464
|
-
await cmdValidate(commandArgs);
|
|
465
|
-
return 0;
|
|
466
|
-
case "install":
|
|
467
|
-
console.log(INSTALL_PROMPT);
|
|
468
|
-
return 0;
|
|
469
|
-
case "scaffold":
|
|
470
|
-
cmdScaffold();
|
|
471
|
-
return 0;
|
|
472
|
-
case "stale": {
|
|
473
|
-
const jsonStale = commandArgs.includes("--json");
|
|
474
|
-
const { reports } = await resolveStaleTargets(commandArgs.find((arg) => !arg.startsWith("-")));
|
|
475
|
-
if (reports.length === 0) {
|
|
476
|
-
console.log("No intent-enabled packages found.");
|
|
477
|
-
return 0;
|
|
478
|
-
}
|
|
479
|
-
if (jsonStale) {
|
|
480
|
-
console.log(JSON.stringify(reports, null, 2));
|
|
481
|
-
return 0;
|
|
482
|
-
}
|
|
483
|
-
for (const report of reports) {
|
|
484
|
-
const driftLabel = report.versionDrift ? ` [${report.versionDrift} drift]` : "";
|
|
485
|
-
const vLabel = report.skillVersion && report.currentVersion ? ` (${report.skillVersion} → ${report.currentVersion})` : "";
|
|
486
|
-
console.log(`${report.library}${vLabel}${driftLabel}`);
|
|
487
|
-
const stale = report.skills.filter((s) => s.needsReview);
|
|
488
|
-
if (stale.length === 0) console.log(" All skills up-to-date");
|
|
489
|
-
else for (const skill of stale) console.log(` ⚠ ${skill.name}: ${skill.reasons.join(", ")}`);
|
|
490
|
-
console.log();
|
|
491
|
-
}
|
|
492
|
-
return 0;
|
|
493
|
-
}
|
|
494
|
-
case "add-library-bin": {
|
|
495
|
-
const { runAddLibraryBinAll } = await import("./setup.mjs");
|
|
496
|
-
runAddLibraryBinAll(process.cwd());
|
|
497
|
-
return 0;
|
|
498
|
-
}
|
|
499
|
-
case "edit-package-json": {
|
|
500
|
-
const { runEditPackageJsonAll } = await import("./setup.mjs");
|
|
501
|
-
runEditPackageJsonAll(process.cwd());
|
|
502
|
-
return 0;
|
|
503
|
-
}
|
|
504
|
-
case "setup-github-actions": {
|
|
505
|
-
const { runSetupGithubActions } = await import("./setup.mjs");
|
|
506
|
-
runSetupGithubActions(process.cwd(), getMetaDir());
|
|
507
|
-
return 0;
|
|
508
|
-
}
|
|
509
|
-
default:
|
|
510
|
-
printHelp();
|
|
511
|
-
return command ? 1 : 0;
|
|
488
|
+
cli.parse([
|
|
489
|
+
"intent",
|
|
490
|
+
"intent",
|
|
491
|
+
...argv
|
|
492
|
+
], { run: false });
|
|
493
|
+
if (cli.options.help) return 0;
|
|
494
|
+
if (!cli.matchedCommand) {
|
|
495
|
+
cli.outputHelp();
|
|
496
|
+
return 1;
|
|
512
497
|
}
|
|
498
|
+
await cli.runMatchedCommand();
|
|
499
|
+
return 0;
|
|
513
500
|
} catch (err) {
|
|
514
501
|
if (isCliFailure(err)) {
|
|
515
502
|
console.error(err.message);
|
|
516
503
|
return err.exitCode;
|
|
517
504
|
}
|
|
505
|
+
if (err instanceof Error) {
|
|
506
|
+
console.error(err.message);
|
|
507
|
+
return 1;
|
|
508
|
+
}
|
|
518
509
|
throw err;
|
|
519
510
|
}
|
|
520
511
|
}
|
|
@@ -528,4 +519,4 @@ if (isMain) {
|
|
|
528
519
|
}
|
|
529
520
|
|
|
530
521
|
//#endregion
|
|
531
|
-
export {
|
|
522
|
+
export { main };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { a as IntentProjectConfig, c as ScanResult, d as StalenessReport, i as IntentPackage, l as SkillEntry, n as FeedbackPayload, o as MetaFeedbackPayload, r as IntentConfig, s as MetaSkillName, t as AgentName, u as SkillStaleness } from "./types-ddLtccfV.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { c as runEditPackageJson, r as SetupGithubActionsResult, t as EditPackageJsonResult, u as runSetupGithubActions } from "./setup-BNBVotfR.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/scanner.d.ts
|
|
5
|
-
declare function scanForIntents(root?: string):
|
|
5
|
+
declare function scanForIntents(root?: string): ScanResult;
|
|
6
6
|
//#endregion
|
|
7
7
|
//#region src/staleness.d.ts
|
|
8
8
|
declare function checkStaleness(packageDir: string, packageName?: string): Promise<StalenessReport>;
|
|
@@ -55,4 +55,4 @@ declare function resolveDepDir(depName: string, parentDir: string): string | nul
|
|
|
55
55
|
*/
|
|
56
56
|
declare function parseFrontmatter(filePath: string): Record<string, unknown> | null;
|
|
57
57
|
//#endregion
|
|
58
|
-
export { type
|
|
58
|
+
export { type AgentName, type EditPackageJsonResult, type FeedbackPayload, type IntentConfig, type IntentPackage, type IntentProjectConfig, type MetaFeedbackPayload, type MetaSkillName, type ScanResult, type SetupGithubActionsResult, type SkillEntry, type SkillStaleness, type StalenessReport, checkStaleness, containsSecrets, findSkillFiles, getDeps, hasGhCli, metaToMarkdown, parseFrontmatter, resolveDepDir, resolveFrequency, runEditPackageJson, runSetupGithubActions, scanForIntents, submitFeedback, submitMetaFeedback, toMarkdown, validateMetaPayload, validatePayload };
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { a as parseFrontmatter, n as findSkillFiles, o as resolveDepDir, r as getDeps } from "./utils-BfjM1mQe.mjs";
|
|
2
|
-
import { a as
|
|
3
|
-
import { t as scanForIntents } from "./scanner-
|
|
2
|
+
import { a as runEditPackageJson, s as runSetupGithubActions } from "./setup-Nyfl1KTS.mjs";
|
|
3
|
+
import { t as scanForIntents } from "./scanner-BCgNt-oI.mjs";
|
|
4
4
|
import { t as checkStaleness } from "./staleness-DZKvsLVq.mjs";
|
|
5
5
|
import { readFileSync, writeFileSync } from "node:fs";
|
|
6
6
|
import { join } from "node:path";
|
|
@@ -269,4 +269,4 @@ function submitMetaFeedback(payload, opts) {
|
|
|
269
269
|
}
|
|
270
270
|
|
|
271
271
|
//#endregion
|
|
272
|
-
export { checkStaleness, containsSecrets, findSkillFiles, getDeps, hasGhCli, metaToMarkdown, parseFrontmatter, resolveDepDir, resolveFrequency,
|
|
272
|
+
export { checkStaleness, containsSecrets, findSkillFiles, getDeps, hasGhCli, metaToMarkdown, parseFrontmatter, resolveDepDir, resolveFrequency, runEditPackageJson, runSetupGithubActions, scanForIntents, submitFeedback, submitMetaFeedback, toMarkdown, validateMetaPayload, validatePayload };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//#region src/install
|
|
1
|
+
//#region src/commands/install.ts
|
|
2
2
|
const INSTALL_PROMPT = `You are an AI assistant helping a developer set up skill-to-task mappings for their project.
|
|
3
3
|
|
|
4
4
|
Follow these steps in order:
|
|
@@ -54,6 +54,9 @@ skills:
|
|
|
54
54
|
- Keep entries concise - this block is read on every agent task
|
|
55
55
|
- Preserve all content outside the block tags unchanged
|
|
56
56
|
- If the user is on Deno, note that this setup is best-effort today and relies on npm interop`;
|
|
57
|
+
function runInstallCommand() {
|
|
58
|
+
console.log(INSTALL_PROMPT);
|
|
59
|
+
}
|
|
57
60
|
|
|
58
61
|
//#endregion
|
|
59
|
-
export { INSTALL_PROMPT as t };
|
|
62
|
+
export { runInstallCommand as n, INSTALL_PROMPT as t };
|
package/dist/intent-library.mjs
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import "./utils-BfjM1mQe.mjs";
|
|
3
|
-
import { t as INSTALL_PROMPT } from "./install-
|
|
3
|
+
import { t as INSTALL_PROMPT } from "./install-BHbA_wkb.mjs";
|
|
4
4
|
import { n as printSkillTree, r as printTable, t as computeSkillNameWidth } from "./display-DhsUxNJW.mjs";
|
|
5
|
-
import { t as scanLibrary } from "./library-scanner-
|
|
5
|
+
import { t as scanLibrary } from "./library-scanner-DlWy8VeZ.mjs";
|
|
6
6
|
|
|
7
7
|
//#region src/intent-library.ts
|
|
8
|
-
|
|
8
|
+
function cmdList() {
|
|
9
9
|
let result;
|
|
10
10
|
try {
|
|
11
|
-
result =
|
|
11
|
+
result = scanLibrary(process.argv[1]);
|
|
12
12
|
} catch (err) {
|
|
13
13
|
console.error(err.message);
|
|
14
14
|
process.exit(1);
|
|
@@ -65,7 +65,7 @@ const command = process.argv[2];
|
|
|
65
65
|
switch (command) {
|
|
66
66
|
case "list":
|
|
67
67
|
case void 0:
|
|
68
|
-
|
|
68
|
+
cmdList();
|
|
69
69
|
break;
|
|
70
70
|
case "install":
|
|
71
71
|
cmdInstall();
|
|
@@ -19,10 +19,12 @@ function findHomeDir(scriptPath) {
|
|
|
19
19
|
dir = parent;
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
|
-
function
|
|
22
|
+
function isIntentPackage(pkg) {
|
|
23
|
+
const keywords = pkg.keywords;
|
|
24
|
+
if (Array.isArray(keywords) && keywords.includes("tanstack-intent")) return true;
|
|
23
25
|
const bin = pkg.bin;
|
|
24
|
-
if (
|
|
25
|
-
return
|
|
26
|
+
if (bin && typeof bin === "object" && "intent" in bin) return true;
|
|
27
|
+
return false;
|
|
26
28
|
}
|
|
27
29
|
function discoverSkills(skillsDir) {
|
|
28
30
|
const skills = [];
|
|
@@ -57,7 +59,7 @@ function discoverSkills(skillsDir) {
|
|
|
57
59
|
walk(skillsDir);
|
|
58
60
|
return skills;
|
|
59
61
|
}
|
|
60
|
-
|
|
62
|
+
function scanLibrary(scriptPath, _projectRoot) {
|
|
61
63
|
const packages = [];
|
|
62
64
|
const warnings = [];
|
|
63
65
|
const visited = /* @__PURE__ */ new Set();
|
|
@@ -91,7 +93,7 @@ async function scanLibrary(scriptPath, _projectRoot) {
|
|
|
91
93
|
const depDir = resolveDepDir(depName, dir);
|
|
92
94
|
if (!depDir) continue;
|
|
93
95
|
const depPkg = readPkgJson(depDir);
|
|
94
|
-
if (depPkg &&
|
|
96
|
+
if (depPkg && isIntentPackage(depPkg)) processPackage(depName, depDir);
|
|
95
97
|
}
|
|
96
98
|
}
|
|
97
99
|
processPackage(homeName, homeDir);
|
|
@@ -11,6 +11,6 @@ interface LibraryScanResult {
|
|
|
11
11
|
packages: Array<LibraryPackage>;
|
|
12
12
|
warnings: Array<string>;
|
|
13
13
|
}
|
|
14
|
-
declare function scanLibrary(scriptPath: string, _projectRoot?: string):
|
|
14
|
+
declare function scanLibrary(scriptPath: string, _projectRoot?: string): LibraryScanResult;
|
|
15
15
|
//#endregion
|
|
16
16
|
export { LibraryPackage, LibraryScanResult, scanLibrary };
|
package/dist/library-scanner.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as parseFrontmatter, i as listNodeModulesPackageDirs, o as resolveDepDir, r as getDeps, t as detectGlobalNodeModules } from "./utils-BfjM1mQe.mjs";
|
|
2
|
-
import { i as resolveWorkspacePackages, n as findWorkspaceRoot, r as readWorkspacePatterns } from "./setup-
|
|
2
|
+
import { i as resolveWorkspacePackages, n as findWorkspaceRoot, r as readWorkspacePatterns } from "./setup-Nyfl1KTS.mjs";
|
|
3
3
|
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
4
4
|
import { join, relative, sep } from "node:path";
|
|
5
5
|
|
|
@@ -169,7 +169,7 @@ function toVersionConflict(packageName, variants, chosen) {
|
|
|
169
169
|
variants
|
|
170
170
|
};
|
|
171
171
|
}
|
|
172
|
-
|
|
172
|
+
function scanForIntents(root) {
|
|
173
173
|
const projectRoot = root ?? process.cwd();
|
|
174
174
|
const packageManager = detectPackageManager(projectRoot);
|
|
175
175
|
const nodeModulesDir = join(projectRoot, "node_modules");
|
|
@@ -1,8 +1,4 @@
|
|
|
1
1
|
//#region src/setup.d.ts
|
|
2
|
-
interface AddLibraryBinResult {
|
|
3
|
-
shim: string | null;
|
|
4
|
-
skipped: string | null;
|
|
5
|
-
}
|
|
6
2
|
interface EditPackageJsonResult {
|
|
7
3
|
added: Array<string>;
|
|
8
4
|
alreadyPresent: Array<string>;
|
|
@@ -15,7 +11,6 @@ interface MonorepoResult<T> {
|
|
|
15
11
|
package: string;
|
|
16
12
|
result: T;
|
|
17
13
|
}
|
|
18
|
-
declare function runAddLibraryBin(root: string): AddLibraryBinResult;
|
|
19
14
|
declare function runEditPackageJson(root: string): EditPackageJsonResult;
|
|
20
15
|
declare function readWorkspacePatterns(root: string): Array<string> | null;
|
|
21
16
|
/**
|
|
@@ -30,7 +25,6 @@ declare function findWorkspaceRoot(start: string): string | null;
|
|
|
30
25
|
*/
|
|
31
26
|
declare function findPackagesWithSkills(root: string): Array<string>;
|
|
32
27
|
declare function runEditPackageJsonAll(root: string): Array<MonorepoResult<EditPackageJsonResult>> | EditPackageJsonResult;
|
|
33
|
-
declare function runAddLibraryBinAll(root: string): Array<MonorepoResult<AddLibraryBinResult>> | AddLibraryBinResult;
|
|
34
28
|
declare function runSetupGithubActions(root: string, metaDir: string): SetupGithubActionsResult;
|
|
35
29
|
//#endregion
|
|
36
|
-
export {
|
|
30
|
+
export { findWorkspaceRoot as a, runEditPackageJson as c, findPackagesWithSkills as i, runEditPackageJsonAll as l, MonorepoResult as n, readWorkspacePatterns as o, SetupGithubActionsResult as r, resolveWorkspacePackages as s, EditPackageJsonResult as t, runSetupGithubActions as u };
|
|
@@ -4,6 +4,19 @@ import { basename, join, relative } from "node:path";
|
|
|
4
4
|
import { parse } from "yaml";
|
|
5
5
|
|
|
6
6
|
//#region src/setup.ts
|
|
7
|
+
function isGenericWorkspaceName(name, root) {
|
|
8
|
+
const normalized = name.trim().toLowerCase();
|
|
9
|
+
return normalized.length === 0 || normalized === "unknown" || normalized === "root" || normalized === "workspace" || normalized === "monorepo" || normalized === basename(root).toLowerCase();
|
|
10
|
+
}
|
|
11
|
+
function deriveWorkspacePackageName(root, repo, packageDirs) {
|
|
12
|
+
const repoName = repo.split("/").filter(Boolean).pop() || basename(root);
|
|
13
|
+
for (const packageDir of packageDirs) {
|
|
14
|
+
const pkgJson = readPackageJson(packageDir);
|
|
15
|
+
const pkgName = typeof pkgJson.name === "string" ? pkgJson.name : null;
|
|
16
|
+
if (pkgName?.startsWith("@")) return `${pkgName.split("/")[0]}/${repoName}`;
|
|
17
|
+
}
|
|
18
|
+
return repoName;
|
|
19
|
+
}
|
|
7
20
|
function readPackageJson(root) {
|
|
8
21
|
const pkgPath = join(root, "package.json");
|
|
9
22
|
try {
|
|
@@ -41,19 +54,22 @@ function buildWatchPaths(root, packageDirs) {
|
|
|
41
54
|
}
|
|
42
55
|
function detectVars(root, packageDirs) {
|
|
43
56
|
const pkgJson = readPackageJson(root);
|
|
44
|
-
const
|
|
57
|
+
const rawName = typeof pkgJson.name === "string" ? pkgJson.name : "unknown";
|
|
45
58
|
const docs = typeof pkgJson.intent?.docs === "string" ? pkgJson.intent.docs : "docs/";
|
|
46
|
-
const repo = detectRepo(pkgJson, name.replace(/^@/, "").replace(/\//, "/"));
|
|
47
59
|
const isMonorepo = packageDirs !== void 0;
|
|
48
|
-
const
|
|
49
|
-
let
|
|
50
|
-
if (
|
|
60
|
+
const repo = detectRepo(pkgJson, detectRepo((packageDirs?.[0] ? readPackageJson(packageDirs[0]) : null) ?? {}, basename(root)));
|
|
61
|
+
let packageName = rawName;
|
|
62
|
+
if (isMonorepo && isGenericWorkspaceName(rawName, root)) packageName = deriveWorkspacePackageName(root, repo, packageDirs);
|
|
63
|
+
const shortName = packageName.replace(/^@[^/]+\//, "");
|
|
64
|
+
let srcPath = isMonorepo ? "packages/*/src/**" : `packages/${shortName}/src/**`;
|
|
65
|
+
if (!isMonorepo && existsSync(join(root, "src"))) srcPath = "src/**";
|
|
66
|
+
const docsPath = isMonorepo ? "packages/*/docs/**" : docs;
|
|
51
67
|
return {
|
|
52
|
-
PACKAGE_NAME:
|
|
53
|
-
PACKAGE_LABEL:
|
|
54
|
-
PAYLOAD_PACKAGE:
|
|
68
|
+
PACKAGE_NAME: packageName,
|
|
69
|
+
PACKAGE_LABEL: packageName,
|
|
70
|
+
PAYLOAD_PACKAGE: packageName,
|
|
55
71
|
REPO: repo,
|
|
56
|
-
DOCS_PATH:
|
|
72
|
+
DOCS_PATH: docsPath.endsWith("**") ? docsPath : docsPath.replace(/\/$/, "") + "/**",
|
|
57
73
|
SRC_PATH: srcPath,
|
|
58
74
|
WATCH_PATHS: isMonorepo ? buildWatchPaths(root, packageDirs) : ` - '${docs.endsWith("**") ? docs : docs.replace(/\/$/, "") + "/**"}'\n - '${srcPath}'`
|
|
59
75
|
};
|
|
@@ -86,64 +102,6 @@ function copyTemplates(srcDir, destDir, vars) {
|
|
|
86
102
|
skipped
|
|
87
103
|
};
|
|
88
104
|
}
|
|
89
|
-
function getShimContent(ext) {
|
|
90
|
-
return `#!/usr/bin/env node
|
|
91
|
-
// Auto-generated by @tanstack/intent setup
|
|
92
|
-
// Exposes the intent end-user CLI for consumers of this library.
|
|
93
|
-
// Commit this file, then add to your package.json:
|
|
94
|
-
// "bin": { "intent": "./bin/intent.${ext}" }
|
|
95
|
-
try {
|
|
96
|
-
await import('@tanstack/intent/intent-library')
|
|
97
|
-
} catch (e) {
|
|
98
|
-
if (e?.code === 'ERR_MODULE_NOT_FOUND' || e?.code === 'MODULE_NOT_FOUND') {
|
|
99
|
-
console.error('@tanstack/intent is not installed.')
|
|
100
|
-
console.error('')
|
|
101
|
-
console.error('Install it as a dev dependency:')
|
|
102
|
-
console.error(' npm add -D @tanstack/intent')
|
|
103
|
-
console.error('')
|
|
104
|
-
console.error('Or run directly:')
|
|
105
|
-
console.error(' npx @tanstack/intent@latest list')
|
|
106
|
-
process.exit(1)
|
|
107
|
-
}
|
|
108
|
-
throw e
|
|
109
|
-
}
|
|
110
|
-
`;
|
|
111
|
-
}
|
|
112
|
-
function detectShimExtension(root) {
|
|
113
|
-
try {
|
|
114
|
-
if (JSON.parse(readFileSync(join(root, "package.json"), "utf8")).type === "module") return "js";
|
|
115
|
-
} catch (err) {
|
|
116
|
-
if (!(err && typeof err === "object" && "code" in err && err.code === "ENOENT")) console.error(`Warning: could not read package.json: ${err instanceof Error ? err.message : err}`);
|
|
117
|
-
}
|
|
118
|
-
return "mjs";
|
|
119
|
-
}
|
|
120
|
-
function findExistingShim(root) {
|
|
121
|
-
const shimJs = join(root, "bin", "intent.js");
|
|
122
|
-
if (existsSync(shimJs)) return shimJs;
|
|
123
|
-
const shimMjs = join(root, "bin", "intent.mjs");
|
|
124
|
-
if (existsSync(shimMjs)) return shimMjs;
|
|
125
|
-
return null;
|
|
126
|
-
}
|
|
127
|
-
function runAddLibraryBin(root) {
|
|
128
|
-
const result = {
|
|
129
|
-
shim: null,
|
|
130
|
-
skipped: null
|
|
131
|
-
};
|
|
132
|
-
const existingShim = findExistingShim(root);
|
|
133
|
-
if (existingShim) {
|
|
134
|
-
result.skipped = existingShim;
|
|
135
|
-
console.log(` Already exists: ${existingShim}`);
|
|
136
|
-
return result;
|
|
137
|
-
}
|
|
138
|
-
const ext = detectShimExtension(root);
|
|
139
|
-
const shimPath = join(root, "bin", `intent.${ext}`);
|
|
140
|
-
mkdirSync(join(root, "bin"), { recursive: true });
|
|
141
|
-
writeFileSync(shimPath, getShimContent(ext));
|
|
142
|
-
result.shim = shimPath;
|
|
143
|
-
console.log(`✓ Generated intent shim: ${shimPath}`);
|
|
144
|
-
console.log(`\n Run \`npx @tanstack/intent edit-package-json\` to wire package.json.`);
|
|
145
|
-
return result;
|
|
146
|
-
}
|
|
147
105
|
function runEditPackageJson(root) {
|
|
148
106
|
const result = {
|
|
149
107
|
added: [],
|
|
@@ -168,10 +126,10 @@ function runEditPackageJson(root) {
|
|
|
168
126
|
const indentSize = indentMatch?.[1] ? indentMatch[1].length : 2;
|
|
169
127
|
if (!Array.isArray(pkg.keywords)) pkg.keywords = [];
|
|
170
128
|
const keywords = pkg.keywords;
|
|
171
|
-
|
|
129
|
+
if (keywords.includes("tanstack-intent")) result.alreadyPresent.push("keywords: \"tanstack-intent\"");
|
|
172
130
|
else {
|
|
173
|
-
keywords.push(
|
|
174
|
-
result.added.push(
|
|
131
|
+
keywords.push("tanstack-intent");
|
|
132
|
+
result.added.push("keywords: \"tanstack-intent\"");
|
|
175
133
|
}
|
|
176
134
|
if (!Array.isArray(pkg.files)) pkg.files = [];
|
|
177
135
|
const files = pkg.files;
|
|
@@ -191,39 +149,12 @@ function runEditPackageJson(root) {
|
|
|
191
149
|
dir = next;
|
|
192
150
|
}
|
|
193
151
|
return false;
|
|
194
|
-
})() ? ["skills", "
|
|
195
|
-
"skills",
|
|
196
|
-
"bin",
|
|
197
|
-
"!skills/_artifacts"
|
|
198
|
-
];
|
|
152
|
+
})() ? ["skills"] : ["skills", "!skills/_artifacts"];
|
|
199
153
|
for (const entry of requiredFiles) if (files.includes(entry)) result.alreadyPresent.push(`files: "${entry}"`);
|
|
200
154
|
else {
|
|
201
155
|
files.push(entry);
|
|
202
156
|
result.added.push(`files: "${entry}"`);
|
|
203
157
|
}
|
|
204
|
-
const existingShim = findExistingShim(root);
|
|
205
|
-
let ext;
|
|
206
|
-
if (existingShim) ext = existingShim.endsWith(".mjs") ? "mjs" : "js";
|
|
207
|
-
else ext = pkg.type === "module" ? "js" : "mjs";
|
|
208
|
-
const shimRelative = `./bin/intent.${ext}`;
|
|
209
|
-
if (typeof pkg.bin === "object" && pkg.bin !== null) {
|
|
210
|
-
const binObj = pkg.bin;
|
|
211
|
-
if (binObj.intent) result.alreadyPresent.push(`bin.intent`);
|
|
212
|
-
else {
|
|
213
|
-
binObj.intent = shimRelative;
|
|
214
|
-
result.added.push(`bin.intent: "${shimRelative}"`);
|
|
215
|
-
}
|
|
216
|
-
} else if (!pkg.bin) {
|
|
217
|
-
pkg.bin = { intent: shimRelative };
|
|
218
|
-
result.added.push(`bin.intent: "${shimRelative}"`);
|
|
219
|
-
} else if (typeof pkg.bin === "string") {
|
|
220
|
-
const pkgName = typeof pkg.name === "string" ? pkg.name.replace(/^@[^/]+\//, "") : "unknown";
|
|
221
|
-
pkg.bin = {
|
|
222
|
-
[pkgName]: pkg.bin,
|
|
223
|
-
intent: shimRelative
|
|
224
|
-
};
|
|
225
|
-
result.added.push(`bin.intent: "${shimRelative}" (converted bin from string to object)`);
|
|
226
|
-
}
|
|
227
158
|
writeFileSync(pkgPath, JSON.stringify(pkg, null, indentSize) + "\n");
|
|
228
159
|
for (const a of result.added) console.log(`✓ Added ${a}`);
|
|
229
160
|
for (const a of result.alreadyPresent) console.log(` Already present: ${a}`);
|
|
@@ -337,9 +268,6 @@ function runForEachPackage(root, runOne) {
|
|
|
337
268
|
function runEditPackageJsonAll(root) {
|
|
338
269
|
return runForEachPackage(root, runEditPackageJson);
|
|
339
270
|
}
|
|
340
|
-
function runAddLibraryBinAll(root) {
|
|
341
|
-
return runForEachPackage(root, runAddLibraryBin);
|
|
342
|
-
}
|
|
343
271
|
function runSetupGithubActions(root, metaDir) {
|
|
344
272
|
const workspaceRoot = findWorkspaceRoot(root) ?? root;
|
|
345
273
|
const packageDirs = findPackagesWithSkills(workspaceRoot);
|
|
@@ -364,4 +292,4 @@ function runSetupGithubActions(root, metaDir) {
|
|
|
364
292
|
}
|
|
365
293
|
|
|
366
294
|
//#endregion
|
|
367
|
-
export {
|
|
295
|
+
export { runEditPackageJson as a, resolveWorkspacePackages as i, findWorkspaceRoot as n, runEditPackageJsonAll as o, readWorkspacePatterns as r, runSetupGithubActions as s, findPackagesWithSkills as t };
|
package/dist/setup.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
export {
|
|
1
|
+
import { a as findWorkspaceRoot, c as runEditPackageJson, i as findPackagesWithSkills, l as runEditPackageJsonAll, n as MonorepoResult, o as readWorkspacePatterns, r as SetupGithubActionsResult, s as resolveWorkspacePackages, t as EditPackageJsonResult, u as runSetupGithubActions } from "./setup-BNBVotfR.mjs";
|
|
2
|
+
export { EditPackageJsonResult, MonorepoResult, SetupGithubActionsResult, findPackagesWithSkills, findWorkspaceRoot, readWorkspacePatterns, resolveWorkspacePackages, runEditPackageJson, runEditPackageJsonAll, runSetupGithubActions };
|
package/dist/setup.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import "./utils-BfjM1mQe.mjs";
|
|
2
|
-
import { a as
|
|
2
|
+
import { a as runEditPackageJson, i as resolveWorkspacePackages, n as findWorkspaceRoot, o as runEditPackageJsonAll, r as readWorkspacePatterns, s as runSetupGithubActions, t as findPackagesWithSkills } from "./setup-Nyfl1KTS.mjs";
|
|
3
3
|
|
|
4
|
-
export { findPackagesWithSkills, findWorkspaceRoot, readWorkspacePatterns, resolveWorkspacePackages,
|
|
4
|
+
export { findPackagesWithSkills, findWorkspaceRoot, readWorkspacePatterns, resolveWorkspacePackages, runEditPackageJson, runEditPackageJsonAll, runSetupGithubActions };
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
# notify-intent.yml — Drop this into your library repo's .github/workflows/
|
|
2
2
|
#
|
|
3
|
-
# Fires a repository_dispatch event
|
|
4
|
-
#
|
|
5
|
-
# check workflow in the intent repo.
|
|
3
|
+
# Fires a repository_dispatch event whenever docs or source files change
|
|
4
|
+
# on merge to main. This triggers the skill staleness check workflow.
|
|
6
5
|
#
|
|
7
6
|
# Requirements:
|
|
8
|
-
# - A fine-grained PAT with contents:write on
|
|
7
|
+
# - A fine-grained PAT with contents:write on this repository stored
|
|
9
8
|
# as the INTENT_NOTIFY_TOKEN repository secret.
|
|
10
9
|
#
|
|
11
10
|
# Template variables (replaced by `intent setup`):
|
|
@@ -13,7 +12,7 @@
|
|
|
13
12
|
# {{DOCS_PATH}} — e.g. docs/**
|
|
14
13
|
# {{SRC_PATH}} — e.g. packages/query-core/src/**
|
|
15
14
|
|
|
16
|
-
name:
|
|
15
|
+
name: Trigger Skill Review
|
|
17
16
|
|
|
18
17
|
on:
|
|
19
18
|
push:
|
|
@@ -24,7 +23,7 @@ on:
|
|
|
24
23
|
|
|
25
24
|
jobs:
|
|
26
25
|
notify:
|
|
27
|
-
name:
|
|
26
|
+
name: Trigger Skill Review
|
|
28
27
|
runs-on: ubuntu-latest
|
|
29
28
|
steps:
|
|
30
29
|
- name: Checkout
|
|
@@ -42,7 +41,7 @@ jobs:
|
|
|
42
41
|
uses: peter-evans/repository-dispatch@v3
|
|
43
42
|
with:
|
|
44
43
|
token: ${{ secrets.INTENT_NOTIFY_TOKEN }}
|
|
45
|
-
repository:
|
|
44
|
+
repository: ${{ github.repository }}
|
|
46
45
|
event-type: skill-check
|
|
47
46
|
client-payload: |
|
|
48
47
|
{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/intent",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.23",
|
|
4
4
|
"description": "Ship compositional knowledge for AI coding agents alongside your npm packages",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
"meta"
|
|
28
28
|
],
|
|
29
29
|
"dependencies": {
|
|
30
|
+
"cac": "^6.7.14",
|
|
30
31
|
"yaml": "^2.7.0"
|
|
31
32
|
},
|
|
32
33
|
"devDependencies": {
|
|
@@ -37,6 +38,7 @@
|
|
|
37
38
|
"scripts": {
|
|
38
39
|
"prepack": "npm run build",
|
|
39
40
|
"build": "tsdown src/index.ts src/cli.ts src/setup.ts src/intent-library.ts src/library-scanner.ts --format esm --dts",
|
|
41
|
+
"test:smoke": "pnpm run build && node dist/cli.mjs --help > /dev/null",
|
|
40
42
|
"test:lib": "vitest run --exclude 'tests/integration/**'",
|
|
41
43
|
"test:integration": "vitest run tests/integration/",
|
|
42
44
|
"test:types": "tsc --noEmit"
|