@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/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025-present Tanner Linsley
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -34,20 +34,32 @@ If you use Deno, support is best-effort today via `npm:` interop with `node_modu
|
|
|
34
34
|
|
|
35
35
|
### For library consumers
|
|
36
36
|
|
|
37
|
-
Set up skill
|
|
37
|
+
Set up skill loading guidance in your project's agent config files (CLAUDE.md, .cursorrules, etc.):
|
|
38
38
|
|
|
39
39
|
```bash
|
|
40
40
|
npx @tanstack/intent@latest install
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
-
No per-library setup. No hunting for rules files. Install the package, run `npx @tanstack/intent@latest install` through your preferred command runner, and
|
|
43
|
+
No per-library setup. No hunting for rules files. Install the package, run `npx @tanstack/intent@latest install` through your preferred command runner, and Intent writes guidance that tells your agent to discover and load matching package skills. Update the package, and skills update too. Pass `--map` if you want explicit task-to-skill mappings in your agent config.
|
|
44
44
|
|
|
45
|
-
List available skills from installed packages:
|
|
45
|
+
List available skills from local installed packages:
|
|
46
46
|
|
|
47
47
|
```bash
|
|
48
48
|
npx @tanstack/intent@latest list
|
|
49
49
|
```
|
|
50
50
|
|
|
51
|
+
Include global packages explicitly:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
npx @tanstack/intent@latest list --global
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Load an installed skill:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
npx @tanstack/intent@latest load @tanstack/query#fetching
|
|
61
|
+
```
|
|
62
|
+
|
|
51
63
|
### For library maintainers
|
|
52
64
|
|
|
53
65
|
Generate skills for your library by telling your AI coding agent to run:
|
|
@@ -78,10 +90,10 @@ npx @tanstack/intent@latest stale
|
|
|
78
90
|
|
|
79
91
|
From a monorepo root, `intent stale` checks every workspace package that ships skills. To scope it to one package, pass a directory like `intent stale packages/router`.
|
|
80
92
|
|
|
81
|
-
Copy CI workflow templates into your repo so validation and staleness checks run
|
|
93
|
+
Copy CI workflow templates into your repo so validation and staleness checks can run in GitHub Actions:
|
|
82
94
|
|
|
83
95
|
```bash
|
|
84
|
-
npx @tanstack/intent@latest setup
|
|
96
|
+
npx @tanstack/intent@latest setup
|
|
85
97
|
```
|
|
86
98
|
|
|
87
99
|
## Compatibility
|
|
@@ -96,14 +108,14 @@ npx @tanstack/intent@latest setup-github-actions
|
|
|
96
108
|
|
|
97
109
|
## Monorepos
|
|
98
110
|
|
|
99
|
-
- Run `npx @tanstack/intent@latest setup
|
|
100
|
-
- Generated workflows are monorepo-aware: validation loops over workspace packages with skills, staleness checks run from the workspace root
|
|
111
|
+
- Run `npx @tanstack/intent@latest setup` from either the repo root or a package directory. Intent detects the workspace root and writes workflows to the repo-level `.github/workflows/` directory.
|
|
112
|
+
- Generated workflows are monorepo-aware: validation loops over workspace packages with skills, and staleness checks run from the workspace root.
|
|
101
113
|
- Run `npx @tanstack/intent@latest validate packages/<pkg>/skills` from the repo root to validate one package without root-level packaging warnings.
|
|
102
|
-
- Run `npx @tanstack/intent@latest stale` from the repo root to check
|
|
114
|
+
- Run `npx @tanstack/intent@latest stale` from the repo root to check workspace packages with skills and public workspace packages missing skill or `_artifacts` coverage, or `intent stale packages/<pkg>` to check one package.
|
|
103
115
|
|
|
104
116
|
## Keeping skills current
|
|
105
117
|
|
|
106
|
-
The real risk with any derived artifact is staleness. `npx @tanstack/intent@latest stale` flags skills whose source docs have changed, and CI templates catch drift before it ships.
|
|
118
|
+
The real risk with any derived artifact is staleness. `npx @tanstack/intent@latest stale` flags skills whose source docs have changed, generated skills that drift from `_artifacts`, and public workspace packages missing coverage. CI templates catch drift before it ships.
|
|
107
119
|
|
|
108
120
|
The feedback loop runs both directions. `npx @tanstack/intent@latest feedback` lets users submit structured reports when a skill produces wrong output — which skill, which version, what broke. That context flows back to the maintainer, and the fix ships to everyone on the next package update. Every support interaction produces an artifact that prevents the same class of problem for all future users — not just the one who reported it.
|
|
109
121
|
|
|
@@ -111,12 +123,13 @@ The feedback loop runs both directions. `npx @tanstack/intent@latest feedback` l
|
|
|
111
123
|
|
|
112
124
|
| Command | Description |
|
|
113
125
|
| -------------------------------------------------- | --------------------------------------------------- |
|
|
114
|
-
| `npx @tanstack/intent@latest install` | Set up skill
|
|
115
|
-
| `npx @tanstack/intent@latest list [--json]` | Discover intent-enabled packages
|
|
126
|
+
| `npx @tanstack/intent@latest install` | Set up skill loading guidance in agent config files |
|
|
127
|
+
| `npx @tanstack/intent@latest list [--json]` | Discover local intent-enabled packages |
|
|
128
|
+
| `npx @tanstack/intent@latest load <use>` | Load `<package>#<skill>` SKILL.md content |
|
|
116
129
|
| `npx @tanstack/intent@latest meta` | List meta-skills for library maintainers |
|
|
117
130
|
| `npx @tanstack/intent@latest scaffold` | Print the guided skill generation prompt |
|
|
118
131
|
| `npx @tanstack/intent@latest validate [dir]` | Validate SKILL.md files |
|
|
119
|
-
| `npx @tanstack/intent@latest setup
|
|
132
|
+
| `npx @tanstack/intent@latest setup` | Copy CI templates into your repo |
|
|
120
133
|
| `npx @tanstack/intent@latest stale [dir] [--json]` | Check skills for version drift |
|
|
121
134
|
| `npx @tanstack/intent@latest feedback` | Submit skill feedback |
|
|
122
135
|
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { parse } from "yaml";
|
|
4
|
+
|
|
5
|
+
//#region src/artifact-coverage.ts
|
|
6
|
+
function isRecord(value) {
|
|
7
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
8
|
+
}
|
|
9
|
+
function stringValue(value) {
|
|
10
|
+
return typeof value === "string" && value.trim() ? value : void 0;
|
|
11
|
+
}
|
|
12
|
+
function stringArray(value) {
|
|
13
|
+
if (!Array.isArray(value)) return [];
|
|
14
|
+
return value.filter((entry) => typeof entry === "string");
|
|
15
|
+
}
|
|
16
|
+
function detectArtifactKind(fileName) {
|
|
17
|
+
if (fileName.endsWith("skill_tree.yaml")) return "skill-tree";
|
|
18
|
+
if (fileName.endsWith("domain_map.yaml")) return "domain-map";
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
function readArtifactYaml(artifactPath, warnings) {
|
|
22
|
+
let parsed;
|
|
23
|
+
try {
|
|
24
|
+
parsed = parse(readFileSync(artifactPath, "utf8"));
|
|
25
|
+
} catch (err) {
|
|
26
|
+
warnings.push({
|
|
27
|
+
artifactPath,
|
|
28
|
+
message: `Invalid YAML: ${err instanceof Error ? err.message : String(err)}`
|
|
29
|
+
});
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
if (!isRecord(parsed)) {
|
|
33
|
+
warnings.push({
|
|
34
|
+
artifactPath,
|
|
35
|
+
message: "Artifact YAML must contain an object at the top level"
|
|
36
|
+
});
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
return parsed;
|
|
40
|
+
}
|
|
41
|
+
function parseArtifactFile(artifactPath, kind, parsed) {
|
|
42
|
+
const library = isRecord(parsed.library) ? parsed.library : {};
|
|
43
|
+
return {
|
|
44
|
+
path: artifactPath,
|
|
45
|
+
kind,
|
|
46
|
+
libraryName: stringValue(library.name),
|
|
47
|
+
libraryVersion: stringValue(library.version)
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function parseSkills(artifactPath, kind, parsed) {
|
|
51
|
+
if (!Array.isArray(parsed.skills)) return [];
|
|
52
|
+
const skills = [];
|
|
53
|
+
for (const skill of parsed.skills) {
|
|
54
|
+
if (!isRecord(skill)) continue;
|
|
55
|
+
const packagePath = stringValue(skill.package);
|
|
56
|
+
const packages = stringArray(skill.packages);
|
|
57
|
+
if (packagePath) packages.push(packagePath);
|
|
58
|
+
skills.push({
|
|
59
|
+
artifactPath,
|
|
60
|
+
artifactKind: kind,
|
|
61
|
+
name: stringValue(skill.name),
|
|
62
|
+
slug: stringValue(skill.slug),
|
|
63
|
+
path: stringValue(skill.path),
|
|
64
|
+
package: packagePath,
|
|
65
|
+
packages: [...new Set(packages)].sort((a, b) => a.localeCompare(b)),
|
|
66
|
+
sources: stringArray(skill.sources),
|
|
67
|
+
covers: stringArray(skill.covers)
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
return skills;
|
|
71
|
+
}
|
|
72
|
+
function parseCoverageIgnores(artifactPath, parsed) {
|
|
73
|
+
const ignored = (isRecord(parsed.coverage) ? parsed.coverage : null)?.ignored_packages;
|
|
74
|
+
if (!Array.isArray(ignored)) return [];
|
|
75
|
+
const ignores = [];
|
|
76
|
+
for (const entry of ignored) {
|
|
77
|
+
if (typeof entry === "string") {
|
|
78
|
+
if (entry.trim()) ignores.push({
|
|
79
|
+
packageName: entry,
|
|
80
|
+
artifactPath
|
|
81
|
+
});
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
if (!isRecord(entry)) continue;
|
|
85
|
+
const packageName = stringValue(entry.name);
|
|
86
|
+
if (!packageName) continue;
|
|
87
|
+
ignores.push({
|
|
88
|
+
packageName,
|
|
89
|
+
reason: stringValue(entry.reason),
|
|
90
|
+
artifactPath
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
return ignores;
|
|
94
|
+
}
|
|
95
|
+
function readIntentArtifacts(root) {
|
|
96
|
+
const artifactsDir = join(root, "_artifacts");
|
|
97
|
+
if (!existsSync(artifactsDir)) return null;
|
|
98
|
+
const warnings = [];
|
|
99
|
+
const skillTrees = [];
|
|
100
|
+
const domainMaps = [];
|
|
101
|
+
const skills = [];
|
|
102
|
+
const ignoredPackages = [];
|
|
103
|
+
for (const entry of readdirSync(artifactsDir, { withFileTypes: true })) {
|
|
104
|
+
if (!entry.isFile()) continue;
|
|
105
|
+
const kind = detectArtifactKind(entry.name);
|
|
106
|
+
if (!kind) continue;
|
|
107
|
+
const artifactPath = join(artifactsDir, entry.name);
|
|
108
|
+
const parsed = readArtifactYaml(artifactPath, warnings);
|
|
109
|
+
if (!parsed) continue;
|
|
110
|
+
const artifactFile = parseArtifactFile(artifactPath, kind, parsed);
|
|
111
|
+
if (kind === "skill-tree") skillTrees.push(artifactFile);
|
|
112
|
+
else domainMaps.push(artifactFile);
|
|
113
|
+
skills.push(...parseSkills(artifactPath, kind, parsed));
|
|
114
|
+
ignoredPackages.push(...parseCoverageIgnores(artifactPath, parsed));
|
|
115
|
+
}
|
|
116
|
+
return {
|
|
117
|
+
root,
|
|
118
|
+
artifactsDir,
|
|
119
|
+
skillTrees: skillTrees.sort((a, b) => a.path.localeCompare(b.path)),
|
|
120
|
+
domainMaps: domainMaps.sort((a, b) => a.path.localeCompare(b.path)),
|
|
121
|
+
skills: skills.sort((a, b) => `${a.artifactPath}:${a.slug ?? a.name ?? ""}`.localeCompare(`${b.artifactPath}:${b.slug ?? b.name ?? ""}`)),
|
|
122
|
+
ignoredPackages: ignoredPackages.sort((a, b) => a.packageName.localeCompare(b.packageName)),
|
|
123
|
+
warnings
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
//#endregion
|
|
128
|
+
export { readIntentArtifacts as t };
|
package/dist/cli.d.mts
CHANGED
|
File without changes
|
package/dist/cli.mjs
CHANGED
|
@@ -1,72 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import "./utils-COlDcU72.mjs";
|
|
3
|
-
import "./workspace-patterns-
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import "./workspace-patterns-BN2A_60g.mjs";
|
|
4
|
+
import { i as parseSkillUse } from "./skill-use-uwGleSOz.mjs";
|
|
5
|
+
import { r as resolveSkillUse } from "./resolver-D2CgIYGg.mjs";
|
|
6
|
+
import { t as resolveProjectContext } from "./project-context-IDLpJU3S.mjs";
|
|
7
|
+
import { a as scanIntentsOrFail, c as fail, i as resolveStaleTargets, l as isCliFailure, n as runInstallCommand, o as scanOptionsFromGlobalFlags, r as getMetaDir, s as printWarnings } from "./install-PUnIfBNC.mjs";
|
|
6
8
|
import { existsSync, readFileSync, readdirSync, realpathSync } from "node:fs";
|
|
7
|
-
import {
|
|
9
|
+
import { isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
8
10
|
import { fileURLToPath } from "node:url";
|
|
9
11
|
import { cac } from "cac";
|
|
10
12
|
|
|
11
|
-
//#region src/cli-error.ts
|
|
12
|
-
const CLI_FAILURE = Symbol("CliFailure");
|
|
13
|
-
function fail(message, exitCode = 1) {
|
|
14
|
-
throw {
|
|
15
|
-
[CLI_FAILURE]: true,
|
|
16
|
-
message,
|
|
17
|
-
exitCode
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
function isCliFailure(value) {
|
|
21
|
-
return !!value && typeof value === "object" && CLI_FAILURE in value;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
//#endregion
|
|
25
|
-
//#region src/cli-support.ts
|
|
26
|
-
function printWarnings(warnings) {
|
|
27
|
-
if (warnings.length === 0) return;
|
|
28
|
-
console.log("Warnings:");
|
|
29
|
-
for (const warning of warnings) console.log(` ⚠ ${warning}`);
|
|
30
|
-
}
|
|
31
|
-
function getMetaDir() {
|
|
32
|
-
return join(dirname(fileURLToPath(import.meta.url)), "..", "meta");
|
|
33
|
-
}
|
|
34
|
-
async function scanIntentsOrFail() {
|
|
35
|
-
const { scanForIntents } = await import("./scanner-CP4U8F_n.mjs");
|
|
36
|
-
try {
|
|
37
|
-
return scanForIntents();
|
|
38
|
-
} catch (err) {
|
|
39
|
-
fail(err instanceof Error ? err.message : String(err));
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
function readPackageName(root) {
|
|
43
|
-
try {
|
|
44
|
-
const pkgJson = JSON.parse(readFileSync(join(root, "package.json"), "utf8"));
|
|
45
|
-
return typeof pkgJson.name === "string" ? pkgJson.name : relative(process.cwd(), root) || "unknown";
|
|
46
|
-
} catch {
|
|
47
|
-
return relative(process.cwd(), root) || "unknown";
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
async function resolveStaleTargets(targetDir) {
|
|
51
|
-
const resolvedRoot = targetDir ? resolve(process.cwd(), targetDir) : process.cwd();
|
|
52
|
-
const context = resolveProjectContext({
|
|
53
|
-
cwd: process.cwd(),
|
|
54
|
-
targetPath: targetDir
|
|
55
|
-
});
|
|
56
|
-
const { checkStaleness } = await import("./staleness-LRbiWWZK.mjs");
|
|
57
|
-
if (context.packageRoot && (context.targetSkillsDir !== null || resolvedRoot !== context.workspaceRoot)) return { reports: [await checkStaleness(context.packageRoot, readPackageName(context.packageRoot))] };
|
|
58
|
-
if (existsSync(join(resolvedRoot, "skills"))) return { reports: [await checkStaleness(resolvedRoot, readPackageName(resolvedRoot))] };
|
|
59
|
-
const { findPackagesWithSkills, findWorkspaceRoot } = await import("./workspace-patterns-D_y6rlqX.mjs");
|
|
60
|
-
const workspaceRoot = findWorkspaceRoot(resolvedRoot);
|
|
61
|
-
if (workspaceRoot) {
|
|
62
|
-
const packageDirs = findPackagesWithSkills(workspaceRoot);
|
|
63
|
-
if (packageDirs.length > 0) return { reports: await Promise.all(packageDirs.map((packageDir) => checkStaleness(packageDir, readPackageName(packageDir)))) };
|
|
64
|
-
}
|
|
65
|
-
const staleResult = await scanIntentsOrFail();
|
|
66
|
-
return { reports: await Promise.all(staleResult.packages.map((pkg) => checkStaleness(pkg.packageRoot, pkg.name))) };
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
//#endregion
|
|
70
13
|
//#region src/commands/edit-package-json.ts
|
|
71
14
|
async function runEditPackageJsonCommand(root) {
|
|
72
15
|
const { runEditPackageJsonAll } = await import("./setup.mjs");
|
|
@@ -95,12 +38,12 @@ function printVersionConflicts(result) {
|
|
|
95
38
|
}
|
|
96
39
|
}
|
|
97
40
|
async function runListCommand(options, scanIntentsOrFail$1) {
|
|
98
|
-
const
|
|
99
|
-
const result = await scanIntentsOrFail$1();
|
|
41
|
+
const result = await scanIntentsOrFail$1(scanOptionsFromGlobalFlags(options));
|
|
100
42
|
if (options.json) {
|
|
101
43
|
console.log(JSON.stringify(result, null, 2));
|
|
102
44
|
return;
|
|
103
45
|
}
|
|
46
|
+
const { computeSkillNameWidth, printSkillTree, printTable } = await import("./display-DvLbcWzq.mjs");
|
|
104
47
|
const scanCoverage = formatScanCoverage(result);
|
|
105
48
|
if (result.packages.length === 0) {
|
|
106
49
|
console.log("No intent-enabled packages found.");
|
|
@@ -116,11 +59,13 @@ async function runListCommand(options, scanIntentsOrFail$1) {
|
|
|
116
59
|
if (scanCoverage) console.log(`Scanned: ${scanCoverage}${result.nodeModules.global.scanned ? " (local packages take precedence)" : ""}\n`);
|
|
117
60
|
printTable([
|
|
118
61
|
"PACKAGE",
|
|
62
|
+
"SOURCE",
|
|
119
63
|
"VERSION",
|
|
120
64
|
"SKILLS",
|
|
121
65
|
"REQUIRES"
|
|
122
66
|
], result.packages.map((pkg) => [
|
|
123
67
|
pkg.name,
|
|
68
|
+
pkg.source,
|
|
124
69
|
pkg.version,
|
|
125
70
|
String(pkg.skills.length),
|
|
126
71
|
pkg.intent.requires?.join(", ") || "–"
|
|
@@ -133,6 +78,7 @@ async function runListCommand(options, scanIntentsOrFail$1) {
|
|
|
133
78
|
console.log(` ${pkg.name}`);
|
|
134
79
|
printSkillTree(pkg.skills, {
|
|
135
80
|
nameWidth,
|
|
81
|
+
packageName: pkg.name,
|
|
136
82
|
showTypes
|
|
137
83
|
});
|
|
138
84
|
console.log();
|
|
@@ -144,6 +90,46 @@ async function runListCommand(options, scanIntentsOrFail$1) {
|
|
|
144
90
|
printWarnings(result.warnings);
|
|
145
91
|
}
|
|
146
92
|
|
|
93
|
+
//#endregion
|
|
94
|
+
//#region src/commands/load.ts
|
|
95
|
+
function resolveFromCwd(path) {
|
|
96
|
+
return resolve(process.cwd(), path);
|
|
97
|
+
}
|
|
98
|
+
function isPathInsidePackageRoot(path, packageRoot) {
|
|
99
|
+
const relativePath = relative(resolveFromCwd(packageRoot), resolveFromCwd(path));
|
|
100
|
+
return relativePath === "" || !relativePath.startsWith("..") && !isAbsolute(relativePath);
|
|
101
|
+
}
|
|
102
|
+
async function runLoadCommand(use, options, scanIntentsOrFail$1) {
|
|
103
|
+
if (!use) fail("Missing skill use. Expected: intent load <package>#<skill>");
|
|
104
|
+
if (options.json && options.path) fail("Use either --json or --path, not both.");
|
|
105
|
+
parseSkillUse(use);
|
|
106
|
+
const resolved = resolveSkillUse(use, await scanIntentsOrFail$1(scanOptionsFromGlobalFlags(options)));
|
|
107
|
+
const resolvedPath = resolveFromCwd(resolved.path);
|
|
108
|
+
if (!isPathInsidePackageRoot(resolved.path, resolved.packageRoot)) fail(`Resolved skill path for "${use}" is outside package root: ${resolved.path}`);
|
|
109
|
+
if (!existsSync(resolvedPath)) fail(`Resolved skill file was not found: ${resolved.path}`);
|
|
110
|
+
if (options.path) {
|
|
111
|
+
console.log(resolved.path);
|
|
112
|
+
for (const warning of resolved.warnings) console.error(`Warning: ${warning}`);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
const content = readFileSync(resolvedPath, "utf8");
|
|
116
|
+
if (options.json) {
|
|
117
|
+
console.log(JSON.stringify({
|
|
118
|
+
package: resolved.packageName,
|
|
119
|
+
skill: resolved.skillName,
|
|
120
|
+
path: resolved.path,
|
|
121
|
+
packageRoot: resolved.packageRoot,
|
|
122
|
+
source: resolved.source,
|
|
123
|
+
version: resolved.version,
|
|
124
|
+
content,
|
|
125
|
+
warnings: resolved.warnings
|
|
126
|
+
}, null, 2));
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
process.stdout.write(content);
|
|
130
|
+
for (const warning of resolved.warnings) console.error(`Warning: ${warning}`);
|
|
131
|
+
}
|
|
132
|
+
|
|
147
133
|
//#endregion
|
|
148
134
|
//#region src/commands/meta.ts
|
|
149
135
|
async function runMetaCommand(name, metaDir) {
|
|
@@ -259,22 +245,31 @@ async function runSetupGithubActionsCommand(root, metaDir) {
|
|
|
259
245
|
//#endregion
|
|
260
246
|
//#region src/commands/stale.ts
|
|
261
247
|
async function runStaleCommand(targetDir, options, resolveStaleTargets$1) {
|
|
262
|
-
const { reports } = await resolveStaleTargets$1(targetDir);
|
|
263
|
-
if (reports.length === 0) {
|
|
264
|
-
console.log("No intent-enabled packages found.");
|
|
265
|
-
return;
|
|
266
|
-
}
|
|
248
|
+
const { reports, workflowAdvisories = [] } = await resolveStaleTargets$1(targetDir);
|
|
267
249
|
if (options.json) {
|
|
268
250
|
console.log(JSON.stringify(reports, null, 2));
|
|
269
251
|
return;
|
|
270
252
|
}
|
|
253
|
+
for (const advisory of workflowAdvisories) console.log(advisory);
|
|
254
|
+
if (workflowAdvisories.length > 0) console.log();
|
|
255
|
+
if (reports.length === 0) {
|
|
256
|
+
console.log("No intent-enabled packages found.");
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
271
259
|
for (const report of reports) {
|
|
272
260
|
const driftLabel = report.versionDrift ? ` [${report.versionDrift} drift]` : "";
|
|
273
261
|
const vLabel = report.skillVersion && report.currentVersion ? ` (${report.skillVersion} → ${report.currentVersion})` : "";
|
|
274
262
|
console.log(`${report.library}${vLabel}${driftLabel}`);
|
|
275
263
|
const stale = report.skills.filter((skill) => skill.needsReview);
|
|
276
|
-
|
|
277
|
-
|
|
264
|
+
const signals = report.signals.filter((signal) => signal.needsReview);
|
|
265
|
+
if (stale.length === 0 && signals.length === 0) console.log(" All skills up-to-date");
|
|
266
|
+
else {
|
|
267
|
+
for (const skill of stale) console.log(` ⚠ ${skill.name}: ${skill.reasons.join(", ")}`);
|
|
268
|
+
for (const signal of signals) {
|
|
269
|
+
const subject = signal.packageName ?? signal.packageRoot ?? signal.skill ?? signal.artifactPath ?? signal.subject ?? report.library;
|
|
270
|
+
console.log(` ⚠ ${subject}: ${signal.reasons.join(", ")}`);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
278
273
|
console.log();
|
|
279
274
|
}
|
|
280
275
|
}
|
|
@@ -429,27 +424,33 @@ async function runValidateCommand(dir) {
|
|
|
429
424
|
function createCli() {
|
|
430
425
|
const cli = cac("intent");
|
|
431
426
|
cli.usage("<command> [options]");
|
|
432
|
-
cli.command("list", "Discover intent-enabled packages").usage("list [--json]").option("--json", "Output JSON").example("list").example("list --json").action(async (options) => {
|
|
427
|
+
cli.command("list", "Discover intent-enabled packages from the project or workspace").usage("list [--json] [--global] [--global-only]").option("--json", "Output JSON").option("--global", "Include global packages after project packages").option("--global-only", "List global packages only").example("list").example("list --json").example("list --global").action(async (options) => {
|
|
433
428
|
await runListCommand(options, scanIntentsOrFail);
|
|
434
429
|
});
|
|
430
|
+
cli.command("load [use]", "Load a compact skill use and print its SKILL.md").usage("load <use> [--path] [--json] [--global] [--global-only]").option("--path", "Print the resolved skill path instead of file content").option("--json", "Output JSON").option("--global", "Load from project packages, then global packages").option("--global-only", "Load from global packages only").example("load @tanstack/query#core").example("load @tanstack/query#core --path").action(async (use, options) => {
|
|
431
|
+
await runLoadCommand(use, options, scanIntentsOrFail);
|
|
432
|
+
});
|
|
435
433
|
cli.command("meta [name]", "List meta-skills, or print one by name").usage("meta [name]").example("meta").example("meta domain-discovery").action(async (name) => {
|
|
436
434
|
await runMetaCommand(name, getMetaDir());
|
|
437
435
|
});
|
|
438
436
|
cli.command("validate [dir]", "Validate skill files").usage("validate [dir]").example("validate").example("validate packages/query/skills").action(async (dir) => {
|
|
439
437
|
await runValidateCommand(dir);
|
|
440
438
|
});
|
|
441
|
-
cli.command("install", "
|
|
442
|
-
runInstallCommand();
|
|
439
|
+
cli.command("install", "Create or update skill loading guidance in an agent config file").usage("install [--map] [--dry-run] [--print-prompt] [--global] [--global-only]").option("--map", "Write explicit skill-to-task mappings").option("--dry-run", "Print the generated block without writing").option("--print-prompt", "Print the legacy agent setup prompt instead of writing").option("--global", "Include global packages after project packages").option("--global-only", "Install mappings from global packages only").example("install").example("install --map").example("install --dry-run").example("install --print-prompt").example("install --global").action(async (options) => {
|
|
440
|
+
await runInstallCommand(options, scanIntentsOrFail);
|
|
443
441
|
});
|
|
444
442
|
cli.command("scaffold", "Print maintainer scaffold prompt").usage("scaffold").action(() => {
|
|
445
443
|
runScaffoldCommand(getMetaDir());
|
|
446
444
|
});
|
|
447
|
-
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) => {
|
|
445
|
+
cli.command("stale [dir]", "Check skills for staleness in the current package or workspace").usage("stale [dir] [--json]").option("--json", "Output JSON").example("stale").example("stale packages/query").example("stale --json").action(async (targetDir, options) => {
|
|
448
446
|
await runStaleCommand(targetDir, options, resolveStaleTargets);
|
|
449
447
|
});
|
|
450
448
|
cli.command("edit-package-json", "Update package.json files so skills are published").usage("edit-package-json").action(async () => {
|
|
451
449
|
await runEditPackageJsonCommand(process.cwd());
|
|
452
450
|
});
|
|
451
|
+
cli.command("setup", "Copy Intent CI workflow templates into .github/workflows/").usage("setup").action(async () => {
|
|
452
|
+
await runSetupGithubActionsCommand(process.cwd(), getMetaDir());
|
|
453
|
+
});
|
|
453
454
|
cli.command("setup-github-actions", "Copy Intent CI workflow templates into .github/workflows/").usage("setup-github-actions").action(async () => {
|
|
454
455
|
await runSetupGithubActionsCommand(process.cwd(), getMetaDir());
|
|
455
456
|
});
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { n as isStableLoadPath, t as formatRuntimeSkillLookupHint } from "./skill-paths-8k9K9y26.mjs";
|
|
2
|
+
|
|
1
3
|
//#region src/display.ts
|
|
2
4
|
function padColumn(text, width) {
|
|
3
5
|
return text.length >= width ? text + " " : text.padEnd(width);
|
|
@@ -15,7 +17,14 @@ function printSkillLine(displayName, skill, indent, opts) {
|
|
|
15
17
|
const padding = " ".repeat(Math.max(2, opts.nameWidth - nameStr.length));
|
|
16
18
|
const typeCol = opts.showTypes ? (skill.type ? `[${skill.type}]` : "").padEnd(14) : "";
|
|
17
19
|
console.log(`${nameStr}${padding}${typeCol}${skill.description}`);
|
|
18
|
-
if (skill.path)
|
|
20
|
+
if (skill.path) {
|
|
21
|
+
const pathIndent = " ".repeat(indent + 2);
|
|
22
|
+
if (isStableLoadPath(skill.path)) console.log(`${pathIndent}${skill.path}`);
|
|
23
|
+
else console.log(`${pathIndent}${formatRuntimeSkillLookupHint({
|
|
24
|
+
packageName: opts.packageName,
|
|
25
|
+
skillName: skill.name
|
|
26
|
+
})}`);
|
|
27
|
+
}
|
|
19
28
|
}
|
|
20
29
|
function printSkillTree(skills, opts) {
|
|
21
30
|
const roots = [];
|
package/dist/index.d.mts
CHANGED
|
@@ -1,11 +1,29 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
import { i as runEditPackageJson, o as runSetupGithubActions, r as SetupGithubActionsResult, t as EditPackageJsonResult } from "./setup-
|
|
1
|
+
import { _ as StalenessReport, a as IntentArtifactSet, c as IntentConfig, d as MetaFeedbackPayload, f as MetaSkillName, g as SkillStaleness, h as SkillEntry, i as IntentArtifactFile, l as IntentPackage, m as ScanResult, n as FeedbackPayload, o as IntentArtifactSkill, p as ScanOptions, r as IntentArtifactCoverageIgnore, s as IntentArtifactWarning, t as AgentName, u as IntentProjectConfig, v as StalenessSignal, y as VersionConflict } from "./types-_y9b00bI.mjs";
|
|
2
|
+
import { i as runEditPackageJson, o as runSetupGithubActions, r as SetupGithubActionsResult, t as EditPackageJsonResult } from "./setup-D2CGdTsx.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/scanner.d.ts
|
|
5
|
-
declare function scanForIntents(root?: string): ScanResult;
|
|
5
|
+
declare function scanForIntents(root?: string, options?: ScanOptions): ScanResult;
|
|
6
6
|
//#endregion
|
|
7
7
|
//#region src/staleness.d.ts
|
|
8
|
-
declare function checkStaleness(packageDir: string, packageName?: string): Promise<StalenessReport>;
|
|
8
|
+
declare function checkStaleness(packageDir: string, packageName?: string, artifactRoot?: string): Promise<StalenessReport>;
|
|
9
|
+
//#endregion
|
|
10
|
+
//#region src/artifact-coverage.d.ts
|
|
11
|
+
declare function readIntentArtifacts(root: string): IntentArtifactSet | null;
|
|
12
|
+
//#endregion
|
|
13
|
+
//#region src/workflow-review.d.ts
|
|
14
|
+
interface StaleReviewItem {
|
|
15
|
+
type: string;
|
|
16
|
+
library: string;
|
|
17
|
+
subject: string;
|
|
18
|
+
reasons: Array<string>;
|
|
19
|
+
artifactPath?: string;
|
|
20
|
+
packageName?: string;
|
|
21
|
+
packageRoot?: string;
|
|
22
|
+
skill?: string;
|
|
23
|
+
}
|
|
24
|
+
declare function collectStaleReviewItems(reports: Array<StalenessReport>): Array<StaleReviewItem>;
|
|
25
|
+
declare function createFailedStaleReviewItem(library: string): StaleReviewItem;
|
|
26
|
+
declare function buildStaleReviewBody(items: Array<StaleReviewItem>): string;
|
|
9
27
|
//#endregion
|
|
10
28
|
//#region src/feedback.d.ts
|
|
11
29
|
declare function containsSecrets(text: string): boolean;
|
|
@@ -55,4 +73,57 @@ declare function resolveDepDir(depName: string, parentDir: string): string | nul
|
|
|
55
73
|
*/
|
|
56
74
|
declare function parseFrontmatter(filePath: string): Record<string, unknown> | null;
|
|
57
75
|
//#endregion
|
|
58
|
-
|
|
76
|
+
//#region src/skill-use.d.ts
|
|
77
|
+
interface SkillUse {
|
|
78
|
+
packageName: string;
|
|
79
|
+
skillName: string;
|
|
80
|
+
}
|
|
81
|
+
type SkillUseParseErrorCode = 'missing-separator' | 'empty-package' | 'empty-skill';
|
|
82
|
+
declare class SkillUseParseError extends Error {
|
|
83
|
+
readonly code: SkillUseParseErrorCode;
|
|
84
|
+
readonly value: string;
|
|
85
|
+
constructor(code: SkillUseParseErrorCode, value: string);
|
|
86
|
+
}
|
|
87
|
+
declare function isSkillUseParseError(error: unknown): error is SkillUseParseError;
|
|
88
|
+
declare function formatSkillUse(packageName: string, skillName: string): string;
|
|
89
|
+
declare function parseSkillUse(value: string): SkillUse;
|
|
90
|
+
//#endregion
|
|
91
|
+
//#region src/resolver.d.ts
|
|
92
|
+
interface ResolveSkillResult {
|
|
93
|
+
packageName: string;
|
|
94
|
+
skillName: string;
|
|
95
|
+
path: string;
|
|
96
|
+
source: IntentPackage['source'];
|
|
97
|
+
version: string;
|
|
98
|
+
packageRoot: string;
|
|
99
|
+
warnings: Array<string>;
|
|
100
|
+
conflict: VersionConflict | null;
|
|
101
|
+
}
|
|
102
|
+
type ResolveSkillUseErrorCode = 'package-not-found' | 'skill-not-found';
|
|
103
|
+
declare class ResolveSkillUseError extends Error {
|
|
104
|
+
readonly code: ResolveSkillUseErrorCode;
|
|
105
|
+
readonly use: string;
|
|
106
|
+
readonly packageName: string;
|
|
107
|
+
readonly skillName: string;
|
|
108
|
+
readonly availablePackages: Array<string>;
|
|
109
|
+
readonly availableSkills: Array<string>;
|
|
110
|
+
constructor({
|
|
111
|
+
availablePackages,
|
|
112
|
+
availableSkills,
|
|
113
|
+
code,
|
|
114
|
+
packageName,
|
|
115
|
+
skillName,
|
|
116
|
+
use
|
|
117
|
+
}: {
|
|
118
|
+
availablePackages?: Array<string>;
|
|
119
|
+
availableSkills?: Array<string>;
|
|
120
|
+
code: ResolveSkillUseErrorCode;
|
|
121
|
+
packageName: string;
|
|
122
|
+
skillName: string;
|
|
123
|
+
use: string;
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
declare function isResolveSkillUseError(error: unknown): error is ResolveSkillUseError;
|
|
127
|
+
declare function resolveSkillUse(use: string, scanResult: ScanResult): ResolveSkillResult;
|
|
128
|
+
//#endregion
|
|
129
|
+
export { type AgentName, type EditPackageJsonResult, type FeedbackPayload, type IntentArtifactCoverageIgnore, type IntentArtifactFile, type IntentArtifactSet, type IntentArtifactSkill, type IntentArtifactWarning, type IntentConfig, type IntentPackage, type IntentProjectConfig, type MetaFeedbackPayload, type MetaSkillName, type ResolveSkillResult, ResolveSkillUseError, type ResolveSkillUseErrorCode, type ScanOptions, type ScanResult, type SetupGithubActionsResult, type SkillEntry, type SkillStaleness, type SkillUse, SkillUseParseError, type SkillUseParseErrorCode, type StaleReviewItem, type StalenessReport, type StalenessSignal, buildStaleReviewBody, checkStaleness, collectStaleReviewItems, containsSecrets, createFailedStaleReviewItem, findSkillFiles, formatSkillUse, getDeps, hasGhCli, isResolveSkillUseError, isSkillUseParseError, metaToMarkdown, parseFrontmatter, parseSkillUse, readIntentArtifacts, resolveDepDir, resolveFrequency, resolveSkillUse, runEditPackageJson, runSetupGithubActions, scanForIntents, submitFeedback, submitMetaFeedback, toMarkdown, validateMetaPayload, validatePayload };
|