@vibe-agent-toolkit/cli 0.1.0 → 0.1.1
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/README.md +67 -4
- package/dist/bin.js +15 -12
- package/dist/bin.js.map +1 -1
- package/dist/commands/agent/index.d.ts.map +1 -1
- package/dist/commands/agent/index.js +0 -37
- package/dist/commands/agent/index.js.map +1 -1
- package/dist/commands/audit/cache-detector.d.ts +32 -0
- package/dist/commands/audit/cache-detector.d.ts.map +1 -0
- package/dist/commands/audit/cache-detector.js +68 -0
- package/dist/commands/audit/cache-detector.js.map +1 -0
- package/dist/commands/audit/hierarchical-output.d.ts +41 -0
- package/dist/commands/audit/hierarchical-output.d.ts.map +1 -0
- package/dist/commands/audit/hierarchical-output.js +267 -0
- package/dist/commands/audit/hierarchical-output.js.map +1 -0
- package/dist/commands/audit.d.ts +18 -0
- package/dist/commands/audit.d.ts.map +1 -0
- package/dist/commands/audit.js +386 -0
- package/dist/commands/audit.js.map +1 -0
- package/dist/commands/doctor.d.ts +106 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +499 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/resources/scan.d.ts.map +1 -1
- package/dist/commands/resources/scan.js +8 -0
- package/dist/commands/resources/scan.js.map +1 -1
- package/dist/utils/config-loader.d.ts +6 -0
- package/dist/utils/config-loader.d.ts.map +1 -1
- package/dist/utils/config-loader.js +18 -0
- package/dist/utils/config-loader.js.map +1 -1
- package/docs/audit.md +446 -0
- package/docs/doctor.md +268 -0
- package/docs/index.md +32 -0
- package/package.json +11 -8
- package/dist/commands/agent/audit.d.ts +0 -9
- package/dist/commands/agent/audit.d.ts.map +0 -1
- package/dist/commands/agent/audit.js +0 -139
- package/dist/commands/agent/audit.js.map +0 -1
package/README.md
CHANGED
|
@@ -71,6 +71,69 @@ vat rag clear
|
|
|
71
71
|
- 384-dimensional embeddings
|
|
72
72
|
- No API key required
|
|
73
73
|
|
|
74
|
+
### Doctor Command
|
|
75
|
+
|
|
76
|
+
Diagnose vat setup and environment health.
|
|
77
|
+
|
|
78
|
+
**Usage:**
|
|
79
|
+
```bash
|
|
80
|
+
# Check environment and configuration
|
|
81
|
+
vat doctor
|
|
82
|
+
|
|
83
|
+
# Show all checks (including passing ones)
|
|
84
|
+
vat doctor --verbose
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
**What it checks:**
|
|
88
|
+
- Node.js version (>=20 required)
|
|
89
|
+
- Git installation and repository
|
|
90
|
+
- Configuration file exists and is valid
|
|
91
|
+
- VAT version (checks for updates)
|
|
92
|
+
- CLI build status (in VAT source tree only)
|
|
93
|
+
|
|
94
|
+
**Exit codes:**
|
|
95
|
+
- `0` - All checks passed
|
|
96
|
+
- `1` - One or more checks failed
|
|
97
|
+
|
|
98
|
+
**Example output:**
|
|
99
|
+
```
|
|
100
|
+
🩺 vat doctor
|
|
101
|
+
|
|
102
|
+
Running diagnostic checks...
|
|
103
|
+
|
|
104
|
+
✅ Node.js version
|
|
105
|
+
v22.0.0 (meets requirement: >=20.0.0)
|
|
106
|
+
|
|
107
|
+
✅ Git installed
|
|
108
|
+
git version 2.43.0
|
|
109
|
+
|
|
110
|
+
✅ Git repository
|
|
111
|
+
Current directory is a git repository
|
|
112
|
+
|
|
113
|
+
✅ Configuration file
|
|
114
|
+
Found: vibe-agent-toolkit.config.yaml
|
|
115
|
+
|
|
116
|
+
✅ Configuration valid
|
|
117
|
+
Configuration is valid
|
|
118
|
+
|
|
119
|
+
✅ vat version
|
|
120
|
+
Current: 0.1.0 — up to date
|
|
121
|
+
|
|
122
|
+
📊 Results: 6/6 checks passed
|
|
123
|
+
|
|
124
|
+
✨ All checks passed! Your vat setup looks healthy.
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
**Troubleshooting:**
|
|
128
|
+
|
|
129
|
+
If checks fail, doctor provides specific suggestions:
|
|
130
|
+
|
|
131
|
+
```
|
|
132
|
+
❌ Node.js version
|
|
133
|
+
v18.0.0 is too old. Node.js 20+ required.
|
|
134
|
+
💡 Upgrade Node.js: https://nodejs.org/ or use nvm
|
|
135
|
+
```
|
|
136
|
+
|
|
74
137
|
### Configuration
|
|
75
138
|
|
|
76
139
|
Create `vibe-agent-toolkit.config.yaml` at project root:
|
|
@@ -111,10 +174,10 @@ vat --version # Shows: 0.1.0-dev (/path/to/vibe-agent-toolkit)
|
|
|
111
174
|
# Build
|
|
112
175
|
bun run build
|
|
113
176
|
|
|
114
|
-
# Test
|
|
115
|
-
bun test
|
|
116
|
-
bun test:integration
|
|
117
|
-
bun test:system
|
|
177
|
+
# Test (do NOT use 'bun test' directly)
|
|
178
|
+
bun run test:unit
|
|
179
|
+
bun run test:integration
|
|
180
|
+
bun run test:system
|
|
118
181
|
|
|
119
182
|
# Prepare binaries after build
|
|
120
183
|
bun run prepare-cli-bin
|
package/dist/bin.js
CHANGED
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { Command } from 'commander';
|
|
7
7
|
import { createAgentCommand, showAgentVerboseHelp } from './commands/agent/index.js';
|
|
8
|
+
import { createAuditCommand } from './commands/audit.js';
|
|
9
|
+
import { doctorCommand } from './commands/doctor.js';
|
|
8
10
|
import { createRagCommand, showRagVerboseHelp } from './commands/rag/index.js';
|
|
9
11
|
import { createResourcesCommand, showResourcesVerboseHelp } from './commands/resources/index.js';
|
|
10
12
|
import { loadVerboseHelp } from './utils/help-loader.js';
|
|
@@ -23,7 +25,6 @@ program
|
|
|
23
25
|
.description('Agent-friendly toolkit for building, testing, and deploying portable AI agents')
|
|
24
26
|
.version(getVersionString(version, context), '-v, --version', 'Output version number')
|
|
25
27
|
.option('--debug', 'Enable debug logging')
|
|
26
|
-
.option('--verbose', 'Show verbose help (markdown format)')
|
|
27
28
|
.helpCommand(false) // Disable redundant 'help' command, use --help instead
|
|
28
29
|
.showHelpAfterError()
|
|
29
30
|
.configureOutput({
|
|
@@ -41,17 +42,16 @@ For command details: vat resources --help
|
|
|
41
42
|
For comprehensive help: vat --help --verbose
|
|
42
43
|
For agent guidance: docs/cli/CLAUDE.md
|
|
43
44
|
`);
|
|
44
|
-
// Handle --help --verbose at root level
|
|
45
|
-
//
|
|
45
|
+
// Handle --help --verbose at root level before parsing
|
|
46
|
+
// Manually check process.argv since --verbose is not a root-level option
|
|
47
|
+
const hasHelp = process.argv.includes('--help') || process.argv.includes('-h');
|
|
48
|
+
const hasVerbose = process.argv.includes('--verbose');
|
|
46
49
|
const hasSubcommand = process.argv.slice(2).some(arg => !arg.startsWith('-'));
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
process.exit(0);
|
|
53
|
-
}
|
|
54
|
-
});
|
|
50
|
+
if (hasHelp && hasVerbose && !hasSubcommand) {
|
|
51
|
+
// Root level: vat --help --verbose
|
|
52
|
+
showVerboseHelp();
|
|
53
|
+
process.exit(0);
|
|
54
|
+
}
|
|
55
55
|
// Special handling for "resources --verbose" before parsing
|
|
56
56
|
if (process.argv.includes('resources') && process.argv.includes('--verbose')) {
|
|
57
57
|
const argv = process.argv.slice(2);
|
|
@@ -88,10 +88,13 @@ if (process.argv.includes('agent') && process.argv.includes('--verbose')) {
|
|
|
88
88
|
process.exit(0);
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
|
-
// Add command groups
|
|
91
|
+
// Add command groups (audit is common, should be first)
|
|
92
|
+
program.addCommand(createAuditCommand());
|
|
92
93
|
program.addCommand(createResourcesCommand());
|
|
93
94
|
program.addCommand(createRagCommand());
|
|
94
95
|
program.addCommand(createAgentCommand());
|
|
96
|
+
// Add standalone commands
|
|
97
|
+
doctorCommand(program);
|
|
95
98
|
// Handle unknown commands
|
|
96
99
|
program.on('command:*', (operands) => {
|
|
97
100
|
const logger = createLogger();
|
package/dist/bin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AAEA;;;GAGG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACrF,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC/E,OAAO,EAAE,sBAAsB,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACjG,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAuB,MAAM,cAAc,CAAC;AAE9E,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,qCAAqC;AACrC,MAAM,OAAO,GAA0B,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;IAC/D,CAAC,CAAE;QACC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,aAAa,CAA+B;QAC9D,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;KACnB;IACtB,CAAC,CAAC,IAAI,CAAC;AAET,OAAO;KACJ,IAAI,CAAC,KAAK,CAAC;KACX,WAAW,CAAC,gFAAgF,CAAC;KAC7F,OAAO,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,eAAe,EAAE,uBAAuB,CAAC;KACrF,MAAM,CAAC,SAAS,EAAE,sBAAsB,CAAC;KACzC,
|
|
1
|
+
{"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AAEA;;;GAGG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACrF,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC/E,OAAO,EAAE,sBAAsB,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACjG,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAuB,MAAM,cAAc,CAAC;AAE9E,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,qCAAqC;AACrC,MAAM,OAAO,GAA0B,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;IAC/D,CAAC,CAAE;QACC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,aAAa,CAA+B;QAC9D,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;KACnB;IACtB,CAAC,CAAC,IAAI,CAAC;AAET,OAAO;KACJ,IAAI,CAAC,KAAK,CAAC;KACX,WAAW,CAAC,gFAAgF,CAAC;KAC7F,OAAO,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,eAAe,EAAE,uBAAuB,CAAC;KACrF,MAAM,CAAC,SAAS,EAAE,sBAAsB,CAAC;KACzC,WAAW,CAAC,KAAK,CAAC,CAAC,uDAAuD;KAC1E,kBAAkB,EAAE;KACpB,eAAe,CAAC;IACf,QAAQ,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,iCAAiC;IAC/E,QAAQ,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,sBAAsB;CACrE,CAAC;KACD,WAAW,CACV,OAAO,EACP;;;;;;;;;;CAUH,CACE,CAAC;AAEJ,uDAAuD;AACvD,yEAAyE;AACzE,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AAC/E,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AACtD,MAAM,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;AAE9E,IAAI,OAAO,IAAI,UAAU,IAAI,CAAC,aAAa,EAAE,CAAC;IAC5C,mCAAmC;IACnC,eAAe,EAAE,CAAC;IAClB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,4DAA4D;AAC5D,IAAI,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;IAC7E,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnC,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IACjD,mDAAmD;IACnD,MAAM,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,GAAG,CAAC,CAAC,CAAC;IACtD,MAAM,aAAa,GAAG,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;IAEvE,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,wBAAwB,EAAE,CAAC;QAC3B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,sDAAsD;AACtD,IAAI,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;IACvE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACrC,6CAA6C;IAC7C,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC;IAC1C,MAAM,aAAa,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;IAEjE,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,kBAAkB,EAAE,CAAC;QACrB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,wDAAwD;AACxD,IAAI,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;IACzE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACzC,+CAA+C;IAC/C,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC;IAC9C,MAAM,aAAa,GAAG,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;IAEnE,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,oBAAoB,EAAE,CAAC;QACvB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,wDAAwD;AACxD,OAAO,CAAC,UAAU,CAAC,kBAAkB,EAAE,CAAC,CAAC;AACzC,OAAO,CAAC,UAAU,CAAC,sBAAsB,EAAE,CAAC,CAAC;AAC7C,OAAO,CAAC,UAAU,CAAC,gBAAgB,EAAE,CAAC,CAAC;AACvC,OAAO,CAAC,UAAU,CAAC,kBAAkB,EAAE,CAAC,CAAC;AAEzC,0BAA0B;AAC1B,aAAa,CAAC,OAAO,CAAC,CAAC;AAEvB,0BAA0B;AAC1B,OAAO,CAAC,EAAE,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE,EAAE;IACnC,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAC9B,MAAM,CAAC,KAAK,CAAC,2BAA2B,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACxD,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACjB,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AAChC,CAAC,CAAC,CAAC;AAEH,OAAO,CAAC,KAAK,EAAE,CAAC;AAEhB,SAAS,eAAe;IACtB,MAAM,WAAW,GAAG,eAAe,EAAE,CAAC,CAAC,+BAA+B;IACtE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IAClC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AAC7B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/agent/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/agent/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAoBpC,wBAAgB,kBAAkB,IAAI,OAAO,CA8Q5C;AAED,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC"}
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
* Agent command group
|
|
3
3
|
*/
|
|
4
4
|
import { Command } from 'commander';
|
|
5
|
-
import { auditCommand } from './audit.js';
|
|
6
5
|
import { buildCommand } from './build.js';
|
|
7
6
|
import { importCommand } from './import.js';
|
|
8
7
|
import { installAgent } from './install.js';
|
|
@@ -138,42 +137,6 @@ Examples:
|
|
|
138
137
|
$ vat agent validate agent-generator # Validate by name
|
|
139
138
|
$ vat agent validate ./my-agent # Validate by path
|
|
140
139
|
$ vat agent validate ./agent.yaml # Validate specific file
|
|
141
|
-
`);
|
|
142
|
-
agent
|
|
143
|
-
.command('audit [path]')
|
|
144
|
-
.description('Audit Claude Skills for quality and compatibility')
|
|
145
|
-
.option('-r, --recursive', 'Scan directories recursively for SKILL.md files')
|
|
146
|
-
.option('--debug', DEBUG_OPTION_DESC)
|
|
147
|
-
.action(auditCommand)
|
|
148
|
-
.addHelpText('after', `
|
|
149
|
-
Description:
|
|
150
|
-
Audits Claude Skills (SKILL.md files) for quality, correctness, and
|
|
151
|
-
console compatibility. Validates frontmatter, links, naming conventions,
|
|
152
|
-
and warns about console-incompatible features. Outputs YAML report to
|
|
153
|
-
stdout, errors/warnings to stderr.
|
|
154
|
-
|
|
155
|
-
Path can be: directory, single SKILL.md file, or VAT agent directory
|
|
156
|
-
Default: current directory
|
|
157
|
-
|
|
158
|
-
Validation Checks:
|
|
159
|
-
Errors (must fix):
|
|
160
|
-
- Missing or invalid frontmatter (name, description)
|
|
161
|
-
- Broken links to other files
|
|
162
|
-
- Reserved words in names (anthropic, claude)
|
|
163
|
-
- XML tags in frontmatter fields
|
|
164
|
-
- Windows-style backslashes in paths
|
|
165
|
-
|
|
166
|
-
Warnings (should fix):
|
|
167
|
-
- Skill exceeds recommended length (>5000 lines)
|
|
168
|
-
- References console-incompatible tools (Write, Edit, Bash)
|
|
169
|
-
|
|
170
|
-
Exit Codes:
|
|
171
|
-
0 - Success | 1 - Errors found | 2 - System error
|
|
172
|
-
|
|
173
|
-
Examples:
|
|
174
|
-
$ vat agent audit # Audit current directory
|
|
175
|
-
$ vat agent audit ./my-skill/SKILL.md # Audit single skill
|
|
176
|
-
$ vat agent audit ./skills --recursive # Audit all skills recursively
|
|
177
140
|
`);
|
|
178
141
|
agent
|
|
179
142
|
.command('import <skillPath>')
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/agent/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/agent/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { ResourceMetadata } from '@vibe-agent-toolkit/resources';
|
|
2
|
+
export interface CacheStalenessResult {
|
|
3
|
+
fresh: FreshEntry[];
|
|
4
|
+
stale: StaleEntry[];
|
|
5
|
+
cacheOnly: ResourceMetadata[];
|
|
6
|
+
installedOnly: ResourceMetadata[];
|
|
7
|
+
}
|
|
8
|
+
export interface FreshEntry {
|
|
9
|
+
installed: ResourceMetadata;
|
|
10
|
+
cached: ResourceMetadata;
|
|
11
|
+
}
|
|
12
|
+
export interface StaleEntry {
|
|
13
|
+
installed: ResourceMetadata;
|
|
14
|
+
cached: ResourceMetadata;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Detect cache staleness by comparing checksums between installed and cached resources.
|
|
18
|
+
*
|
|
19
|
+
* Compares resources by filename and checksum to determine:
|
|
20
|
+
* - Fresh: Cache and installed have matching checksums
|
|
21
|
+
* - Stale: Cache and installed have different checksums
|
|
22
|
+
* - Cache-only: File exists in cache but not in installed
|
|
23
|
+
* - Installed-only: File exists in installed but not in cache
|
|
24
|
+
*
|
|
25
|
+
* Uses O(1) Map lookups for efficient matching.
|
|
26
|
+
*
|
|
27
|
+
* @param installed - Resources from installed plugin locations
|
|
28
|
+
* @param cached - Resources from ~/.claude/plugins/cache/
|
|
29
|
+
* @returns Categorized comparison results
|
|
30
|
+
*/
|
|
31
|
+
export declare function detectCacheStaleness(installed: ResourceMetadata[], cached: ResourceMetadata[]): CacheStalenessResult;
|
|
32
|
+
//# sourceMappingURL=cache-detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache-detector.d.ts","sourceRoot":"","sources":["../../../src/commands/audit/cache-detector.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAEtE,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,SAAS,EAAE,gBAAgB,EAAE,CAAC;IAC9B,aAAa,EAAE,gBAAgB,EAAE,CAAC;CACnC;AAED,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,gBAAgB,CAAC;IAC5B,MAAM,EAAE,gBAAgB,CAAC;CAC1B;AAED,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,gBAAgB,CAAC;IAC5B,MAAM,EAAE,gBAAgB,CAAC;CAC1B;AASD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,gBAAgB,EAAE,EAC7B,MAAM,EAAE,gBAAgB,EAAE,GACzB,oBAAoB,CAmDtB"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
/**
|
|
3
|
+
* Extract filename from file path
|
|
4
|
+
*/
|
|
5
|
+
function getFileName(filePath) {
|
|
6
|
+
return path.basename(filePath);
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Detect cache staleness by comparing checksums between installed and cached resources.
|
|
10
|
+
*
|
|
11
|
+
* Compares resources by filename and checksum to determine:
|
|
12
|
+
* - Fresh: Cache and installed have matching checksums
|
|
13
|
+
* - Stale: Cache and installed have different checksums
|
|
14
|
+
* - Cache-only: File exists in cache but not in installed
|
|
15
|
+
* - Installed-only: File exists in installed but not in cache
|
|
16
|
+
*
|
|
17
|
+
* Uses O(1) Map lookups for efficient matching.
|
|
18
|
+
*
|
|
19
|
+
* @param installed - Resources from installed plugin locations
|
|
20
|
+
* @param cached - Resources from ~/.claude/plugins/cache/
|
|
21
|
+
* @returns Categorized comparison results
|
|
22
|
+
*/
|
|
23
|
+
export function detectCacheStaleness(installed, cached) {
|
|
24
|
+
const fresh = [];
|
|
25
|
+
const stale = [];
|
|
26
|
+
const cacheOnly = [];
|
|
27
|
+
const installedOnly = [];
|
|
28
|
+
// Build index of installed resources by filename for O(1) lookup
|
|
29
|
+
const installedByName = new Map();
|
|
30
|
+
for (const resource of installed) {
|
|
31
|
+
const filename = getFileName(resource.filePath);
|
|
32
|
+
installedByName.set(filename, resource);
|
|
33
|
+
}
|
|
34
|
+
// Check each cached resource
|
|
35
|
+
const matchedInstalledNames = new Set();
|
|
36
|
+
for (const cachedResource of cached) {
|
|
37
|
+
const cachedFilename = getFileName(cachedResource.filePath);
|
|
38
|
+
const installedResource = installedByName.get(cachedFilename);
|
|
39
|
+
if (!installedResource) {
|
|
40
|
+
// Cache file has no corresponding installed file
|
|
41
|
+
cacheOnly.push(cachedResource);
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
matchedInstalledNames.add(cachedFilename);
|
|
45
|
+
if (cachedResource.checksum === installedResource.checksum) {
|
|
46
|
+
// Checksums match - cache is fresh
|
|
47
|
+
fresh.push({
|
|
48
|
+
installed: installedResource,
|
|
49
|
+
cached: cachedResource,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
// Checksums differ - cache is stale
|
|
54
|
+
stale.push({
|
|
55
|
+
installed: installedResource,
|
|
56
|
+
cached: cachedResource,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// Find installed resources with no cache entry
|
|
61
|
+
for (const [name, resource] of installedByName) {
|
|
62
|
+
if (!matchedInstalledNames.has(name)) {
|
|
63
|
+
installedOnly.push(resource);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return { fresh, stale, cacheOnly, installedOnly };
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=cache-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache-detector.js","sourceRoot":"","sources":["../../../src/commands/audit/cache-detector.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAqB7B;;GAEG;AACH,SAAS,WAAW,CAAC,QAAgB;IACnC,OAAO,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AACjC,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,oBAAoB,CAClC,SAA6B,EAC7B,MAA0B;IAE1B,MAAM,KAAK,GAAiB,EAAE,CAAC;IAC/B,MAAM,KAAK,GAAiB,EAAE,CAAC;IAC/B,MAAM,SAAS,GAAuB,EAAE,CAAC;IACzC,MAAM,aAAa,GAAuB,EAAE,CAAC;IAE7C,iEAAiE;IACjE,MAAM,eAAe,GAAG,IAAI,GAAG,EAA4B,CAAC;IAC5D,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,MAAM,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAChD,eAAe,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC1C,CAAC;IAED,6BAA6B;IAC7B,MAAM,qBAAqB,GAAG,IAAI,GAAG,EAAU,CAAC;IAEhD,KAAK,MAAM,cAAc,IAAI,MAAM,EAAE,CAAC;QACpC,MAAM,cAAc,GAAG,WAAW,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QAC5D,MAAM,iBAAiB,GAAG,eAAe,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;QAE9D,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACvB,iDAAiD;YACjD,SAAS,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YAC/B,SAAS;QACX,CAAC;QAED,qBAAqB,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;QAE1C,IAAI,cAAc,CAAC,QAAQ,KAAK,iBAAiB,CAAC,QAAQ,EAAE,CAAC;YAC3D,mCAAmC;YACnC,KAAK,CAAC,IAAI,CAAC;gBACT,SAAS,EAAE,iBAAiB;gBAC5B,MAAM,EAAE,cAAc;aACvB,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,oCAAoC;YACpC,KAAK,CAAC,IAAI,CAAC;gBACT,SAAS,EAAE,iBAAiB;gBAC5B,MAAM,EAAE,cAAc;aACvB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,+CAA+C;IAC/C,KAAK,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,eAAe,EAAE,CAAC;QAC/C,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACrC,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC;AACpD,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { ValidationIssue, ValidationResult } from '@vibe-agent-toolkit/runtime-claude-skills';
|
|
2
|
+
export interface HierarchicalOutput {
|
|
3
|
+
marketplaces: MarketplaceGroup[];
|
|
4
|
+
cachedPlugins: PluginGroup[];
|
|
5
|
+
standalonePlugins: PluginGroup[];
|
|
6
|
+
standaloneSkills: SkillEntry[];
|
|
7
|
+
}
|
|
8
|
+
export interface MarketplaceGroup {
|
|
9
|
+
name: string;
|
|
10
|
+
plugins: PluginGroup[];
|
|
11
|
+
}
|
|
12
|
+
export interface PluginGroup {
|
|
13
|
+
name: string;
|
|
14
|
+
skills: SkillEntry[];
|
|
15
|
+
}
|
|
16
|
+
export type CacheStatus = 'stale' | 'orphaned' | 'fresh';
|
|
17
|
+
export interface SkillEntry {
|
|
18
|
+
name: string;
|
|
19
|
+
path: string;
|
|
20
|
+
status: 'success' | 'warning' | 'error';
|
|
21
|
+
issues: ValidationIssue[];
|
|
22
|
+
cacheStatus?: CacheStatus;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Build hierarchical output structure from validation results.
|
|
26
|
+
*
|
|
27
|
+
* Groups skills by:
|
|
28
|
+
* 1. Marketplace -> Plugin -> Skills (for marketplace-installed plugins)
|
|
29
|
+
* 2. Standalone Plugins -> Skills (for non-marketplace plugins)
|
|
30
|
+
* 3. Standalone Skills (for skills without plugins)
|
|
31
|
+
*
|
|
32
|
+
* By default, only includes skills with issues (terse principle).
|
|
33
|
+
* With verbose=true, includes all scanned skills regardless of status.
|
|
34
|
+
* Replaces home directory with ~ for cleaner display.
|
|
35
|
+
*
|
|
36
|
+
* @param results - Validation results from audit command
|
|
37
|
+
* @param verbose - If true, include all results; if false, only show results with issues
|
|
38
|
+
* @returns Hierarchical structure for display
|
|
39
|
+
*/
|
|
40
|
+
export declare function buildHierarchicalOutput(results: ValidationResult[], verbose?: boolean): HierarchicalOutput;
|
|
41
|
+
//# sourceMappingURL=hierarchical-output.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hierarchical-output.d.ts","sourceRoot":"","sources":["../../../src/commands/audit/hierarchical-output.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,2CAA2C,CAAC;AAGnG,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,gBAAgB,EAAE,CAAC;IACjC,aAAa,EAAE,WAAW,EAAE,CAAC;IAC7B,iBAAiB,EAAE,WAAW,EAAE,CAAC;IACjC,gBAAgB,EAAE,UAAU,EAAE,CAAC;CAChC;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,WAAW,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,UAAU,EAAE,CAAC;CACtB;AAED,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,UAAU,GAAG,OAAO,CAAC;AAEzD,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;IACxC,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AA+RD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,gBAAgB,EAAE,EAAE,OAAO,GAAE,OAAe,GAAG,kBAAkB,CAiCjH"}
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import * as os from 'node:os';
|
|
2
|
+
import { toForwardSlash } from '@vibe-agent-toolkit/utils';
|
|
3
|
+
/**
|
|
4
|
+
* Replace home directory with ~ for cleaner paths
|
|
5
|
+
* Normalizes paths for cross-platform comparison (handles Windows backslashes)
|
|
6
|
+
*/
|
|
7
|
+
function replaceHomeDir(filePath) {
|
|
8
|
+
const homeDir = os.homedir();
|
|
9
|
+
// Normalize both paths to forward slashes for comparison
|
|
10
|
+
const normalizedFilePath = toForwardSlash(filePath);
|
|
11
|
+
const normalizedHomeDir = toForwardSlash(homeDir);
|
|
12
|
+
if (normalizedFilePath.startsWith(normalizedHomeDir)) {
|
|
13
|
+
// Replace using original paths to preserve platform separators in output
|
|
14
|
+
return filePath.replace(homeDir, '~');
|
|
15
|
+
}
|
|
16
|
+
return filePath;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Parse path structure to extract marketplace, plugin, and skill names
|
|
20
|
+
*
|
|
21
|
+
* Expected patterns:
|
|
22
|
+
* - Marketplace plugin skill: .../marketplaces/{marketplace}/{plugin}/skills/{skill}/SKILL.md
|
|
23
|
+
* - Standalone plugin skill: .../plugins/{plugin}/skills/{skill}/SKILL.md (no marketplaces/)
|
|
24
|
+
* - Standalone skill: .../plugins/{skill}/SKILL.md (no skills/)
|
|
25
|
+
*/
|
|
26
|
+
function parsePathStructure(filePath) {
|
|
27
|
+
// Normalize to forward slashes for cross-platform parsing
|
|
28
|
+
const normalizedPath = toForwardSlash(filePath);
|
|
29
|
+
const parts = normalizedPath.split('/');
|
|
30
|
+
// Detect if this is a cached resource
|
|
31
|
+
const isCached = parts.includes('cache');
|
|
32
|
+
// Find key indices
|
|
33
|
+
const marketplacesIdx = parts.indexOf('marketplaces');
|
|
34
|
+
const pluginsIdx = parts.indexOf('plugins');
|
|
35
|
+
const skillsIdx = parts.indexOf('skills');
|
|
36
|
+
// Marketplace plugin skill: .../marketplaces/{marketplace}/{plugin}/skills/{skill}/SKILL.md
|
|
37
|
+
if (marketplacesIdx >= 0 && skillsIdx >= 0) {
|
|
38
|
+
const marketplace = parts[marketplacesIdx + 1];
|
|
39
|
+
const plugin = parts[marketplacesIdx + 2];
|
|
40
|
+
const skill = parts[skillsIdx + 1];
|
|
41
|
+
if (marketplace !== undefined && plugin !== undefined && skill !== undefined) {
|
|
42
|
+
return { marketplace, plugin, skill, isCached };
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
// Standalone plugin skill: .../plugins/{plugin}/skills/{skill}/SKILL.md
|
|
46
|
+
if (pluginsIdx >= 0 && skillsIdx >= 0) {
|
|
47
|
+
const plugin = parts[skillsIdx - 1]; // Plugin name is before /skills/
|
|
48
|
+
const skill = parts[skillsIdx + 1];
|
|
49
|
+
if (plugin !== undefined && skill !== undefined) {
|
|
50
|
+
return { plugin, skill, isCached };
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// Standalone skill: .../plugins/{skill}/SKILL.md
|
|
54
|
+
if (pluginsIdx >= 0) {
|
|
55
|
+
const skill = parts[pluginsIdx + 1];
|
|
56
|
+
if (skill !== undefined) {
|
|
57
|
+
return { skill, isCached };
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// Fallback: use directory name before SKILL.md
|
|
61
|
+
const skill = parts.at(-2) ?? 'unknown';
|
|
62
|
+
return { skill, isCached };
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Add skill entry to marketplace map
|
|
66
|
+
*/
|
|
67
|
+
function addToMarketplaceMap(marketplacesMap, marketplace, plugin, entry) {
|
|
68
|
+
if (!marketplacesMap.has(marketplace)) {
|
|
69
|
+
marketplacesMap.set(marketplace, new Map());
|
|
70
|
+
}
|
|
71
|
+
const pluginsMap = marketplacesMap.get(marketplace);
|
|
72
|
+
if (pluginsMap === undefined) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (!pluginsMap.has(plugin)) {
|
|
76
|
+
pluginsMap.set(plugin, []);
|
|
77
|
+
}
|
|
78
|
+
pluginsMap.get(plugin)?.push(entry);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Add skill entry to cached plugin map
|
|
82
|
+
*/
|
|
83
|
+
function addToCachedPluginMap(cachedPluginsMap, plugin, entry) {
|
|
84
|
+
if (!cachedPluginsMap.has(plugin)) {
|
|
85
|
+
cachedPluginsMap.set(plugin, []);
|
|
86
|
+
}
|
|
87
|
+
cachedPluginsMap.get(plugin)?.push(entry);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Add skill entry to standalone plugin map
|
|
91
|
+
*/
|
|
92
|
+
function addToStandalonePluginMap(standalonePluginsMap, plugin, entry) {
|
|
93
|
+
if (!standalonePluginsMap.has(plugin)) {
|
|
94
|
+
standalonePluginsMap.set(plugin, []);
|
|
95
|
+
}
|
|
96
|
+
standalonePluginsMap.get(plugin)?.push(entry);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Filter out duplicate cache results that match their source
|
|
100
|
+
*
|
|
101
|
+
* Suppresses cache entries when:
|
|
102
|
+
* - A matching source (marketplace/plugin) exists
|
|
103
|
+
* - Same validation status (success/warning/error)
|
|
104
|
+
* - Same issues (count and content)
|
|
105
|
+
*
|
|
106
|
+
* Keeps cache entries when:
|
|
107
|
+
* - No matching source found (orphaned cache)
|
|
108
|
+
* - Different validation status or issues (stale/different)
|
|
109
|
+
*
|
|
110
|
+
* @returns Filtered results and cache status map
|
|
111
|
+
*/
|
|
112
|
+
function filterCacheDuplicates(results) {
|
|
113
|
+
const sourceBySkillName = new Map();
|
|
114
|
+
const cacheResults = [];
|
|
115
|
+
const nonCacheResults = [];
|
|
116
|
+
const cacheStatusMap = new Map();
|
|
117
|
+
// First pass: categorize results and build source index
|
|
118
|
+
for (const result of results) {
|
|
119
|
+
const { skill, isCached } = parsePathStructure(result.path);
|
|
120
|
+
if (isCached) {
|
|
121
|
+
cacheResults.push(result);
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
nonCacheResults.push(result);
|
|
125
|
+
// Index source results by skill name for matching
|
|
126
|
+
sourceBySkillName.set(skill, result);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
// Second pass: filter cache results and track status
|
|
130
|
+
const filteredCache = [];
|
|
131
|
+
for (const cacheResult of cacheResults) {
|
|
132
|
+
const { skill } = parsePathStructure(cacheResult.path);
|
|
133
|
+
const sourceResult = sourceBySkillName.get(skill);
|
|
134
|
+
if (!sourceResult) {
|
|
135
|
+
// Orphaned cache - no matching source, keep it
|
|
136
|
+
filteredCache.push(cacheResult);
|
|
137
|
+
cacheStatusMap.set(cacheResult.path, 'orphaned');
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
// Check if cache and source have identical validation results
|
|
141
|
+
const statusMatches = cacheResult.status === sourceResult.status;
|
|
142
|
+
const issuesMatch = cacheResult.issues.length === sourceResult.issues.length &&
|
|
143
|
+
cacheResult.issues.every((issue, idx) => issue.code === sourceResult.issues[idx]?.code &&
|
|
144
|
+
issue.severity === sourceResult.issues[idx]?.severity);
|
|
145
|
+
if (!statusMatches || !issuesMatch) {
|
|
146
|
+
// Different validation results - keep both (stale or different)
|
|
147
|
+
filteredCache.push(cacheResult);
|
|
148
|
+
cacheStatusMap.set(cacheResult.path, 'stale');
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
// Fresh cache - matches source, will be suppressed
|
|
152
|
+
cacheStatusMap.set(cacheResult.path, 'fresh');
|
|
153
|
+
}
|
|
154
|
+
// If they match exactly, suppress the cache copy (don't add to filteredCache)
|
|
155
|
+
}
|
|
156
|
+
return {
|
|
157
|
+
filtered: [...nonCacheResults, ...filteredCache],
|
|
158
|
+
cacheStatusMap,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Create skill entry from validation result
|
|
163
|
+
*/
|
|
164
|
+
function createSkillEntry(result, cacheStatusMap) {
|
|
165
|
+
const { skill, isCached } = parsePathStructure(result.path);
|
|
166
|
+
const entry = {
|
|
167
|
+
name: skill,
|
|
168
|
+
path: replaceHomeDir(result.path),
|
|
169
|
+
status: result.status,
|
|
170
|
+
issues: result.issues,
|
|
171
|
+
};
|
|
172
|
+
// Add cache status if this is a cached resource
|
|
173
|
+
if (isCached) {
|
|
174
|
+
const cacheStatus = cacheStatusMap.get(result.path);
|
|
175
|
+
if (cacheStatus !== undefined) {
|
|
176
|
+
entry.cacheStatus = cacheStatus;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return entry;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Categorize entry into appropriate map
|
|
183
|
+
*/
|
|
184
|
+
function categorizeEntry(entry, marketplace, plugin, isCached, maps) {
|
|
185
|
+
if (marketplace !== undefined && plugin !== undefined) {
|
|
186
|
+
addToMarketplaceMap(maps.marketplacesMap, marketplace, plugin, entry);
|
|
187
|
+
}
|
|
188
|
+
else if (plugin === undefined) {
|
|
189
|
+
maps.standaloneSkills.push(entry);
|
|
190
|
+
}
|
|
191
|
+
else if (isCached) {
|
|
192
|
+
addToCachedPluginMap(maps.cachedPluginsMap, plugin, entry);
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
addToStandalonePluginMap(maps.standalonePluginsMap, plugin, entry);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Convert marketplace map to array structure
|
|
200
|
+
*/
|
|
201
|
+
function convertMarketplacesMapToArray(marketplacesMap) {
|
|
202
|
+
const marketplaces = [];
|
|
203
|
+
for (const [marketplaceName, pluginsMap] of marketplacesMap) {
|
|
204
|
+
const plugins = [];
|
|
205
|
+
for (const [pluginName, skills] of pluginsMap) {
|
|
206
|
+
plugins.push({ name: pluginName, skills });
|
|
207
|
+
}
|
|
208
|
+
marketplaces.push({ name: marketplaceName, plugins });
|
|
209
|
+
}
|
|
210
|
+
return marketplaces;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Convert plugin map to array structure
|
|
214
|
+
*/
|
|
215
|
+
function convertPluginMapToArray(pluginMap) {
|
|
216
|
+
const plugins = [];
|
|
217
|
+
for (const [pluginName, skills] of pluginMap) {
|
|
218
|
+
plugins.push({ name: pluginName, skills });
|
|
219
|
+
}
|
|
220
|
+
return plugins;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Build hierarchical output structure from validation results.
|
|
224
|
+
*
|
|
225
|
+
* Groups skills by:
|
|
226
|
+
* 1. Marketplace -> Plugin -> Skills (for marketplace-installed plugins)
|
|
227
|
+
* 2. Standalone Plugins -> Skills (for non-marketplace plugins)
|
|
228
|
+
* 3. Standalone Skills (for skills without plugins)
|
|
229
|
+
*
|
|
230
|
+
* By default, only includes skills with issues (terse principle).
|
|
231
|
+
* With verbose=true, includes all scanned skills regardless of status.
|
|
232
|
+
* Replaces home directory with ~ for cleaner display.
|
|
233
|
+
*
|
|
234
|
+
* @param results - Validation results from audit command
|
|
235
|
+
* @param verbose - If true, include all results; if false, only show results with issues
|
|
236
|
+
* @returns Hierarchical structure for display
|
|
237
|
+
*/
|
|
238
|
+
export function buildHierarchicalOutput(results, verbose = false) {
|
|
239
|
+
// Filter out cache duplicates that match their source
|
|
240
|
+
const { filtered: filteredResults, cacheStatusMap } = filterCacheDuplicates(results);
|
|
241
|
+
const marketplacesMap = new Map();
|
|
242
|
+
const cachedPluginsMap = new Map();
|
|
243
|
+
const standalonePluginsMap = new Map();
|
|
244
|
+
const standaloneSkills = [];
|
|
245
|
+
const maps = {
|
|
246
|
+
marketplacesMap,
|
|
247
|
+
cachedPluginsMap,
|
|
248
|
+
standalonePluginsMap,
|
|
249
|
+
standaloneSkills,
|
|
250
|
+
};
|
|
251
|
+
for (const result of filteredResults) {
|
|
252
|
+
// Only include results with issues (terse principle), unless verbose mode
|
|
253
|
+
if (!verbose && result.status === 'success') {
|
|
254
|
+
continue;
|
|
255
|
+
}
|
|
256
|
+
const { marketplace, plugin, isCached } = parsePathStructure(result.path);
|
|
257
|
+
const entry = createSkillEntry(result, cacheStatusMap);
|
|
258
|
+
categorizeEntry(entry, marketplace, plugin, isCached, maps);
|
|
259
|
+
}
|
|
260
|
+
return {
|
|
261
|
+
marketplaces: convertMarketplacesMapToArray(marketplacesMap),
|
|
262
|
+
cachedPlugins: convertPluginMapToArray(cachedPluginsMap),
|
|
263
|
+
standalonePlugins: convertPluginMapToArray(standalonePluginsMap),
|
|
264
|
+
standaloneSkills,
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
//# sourceMappingURL=hierarchical-output.js.map
|