@alavida/agentpack 0.1.1 → 0.1.3
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 +16 -2
- package/bin/intent.js +20 -0
- package/package.json +11 -5
- package/skills/agentpack-cli/SKILL.md +16 -1
- package/skills/agentpack-cli/references/skill-lifecycle.md +21 -1
- package/skills/authoring-skillgraphs-from-knowledge/SKILL.md +148 -0
- package/skills/authoring-skillgraphs-from-knowledge/references/authored-metadata.md +6 -0
- package/skills/developing-and-testing-skills/SKILL.md +109 -0
- package/skills/developing-and-testing-skills/references/local-workbench.md +7 -0
- package/skills/getting-started-skillgraphs/SKILL.md +115 -0
- package/skills/getting-started-skillgraphs/references/command-routing.md +7 -0
- package/skills/identifying-skill-opportunities/SKILL.md +119 -0
- package/skills/identifying-skill-opportunities/references/capability-boundaries.md +6 -0
- package/skills/maintaining-skillgraph-freshness/SKILL.md +110 -0
- package/skills/repairing-broken-skill-or-plugin-state/SKILL.md +112 -0
- package/skills/repairing-broken-skill-or-plugin-state/references/diagnostic-flows.md +6 -0
- package/skills/shipping-production-plugins-and-packages/SKILL.md +123 -0
- package/skills/shipping-production-plugins-and-packages/references/plugin-delivery.md +6 -0
- package/src/application/plugins/build-plugin.js +5 -0
- package/src/application/plugins/inspect-plugin-bundle.js +5 -0
- package/src/application/plugins/validate-plugin-bundle.js +5 -0
- package/src/application/skills/build-skill-workbench-model.js +194 -0
- package/src/application/skills/inspect-skill.js +5 -0
- package/src/application/skills/list-stale-skills.js +9 -0
- package/src/application/skills/run-skill-workbench-action.js +23 -0
- package/src/application/skills/start-skill-dev-workbench.js +192 -0
- package/src/application/skills/validate-skills.js +5 -0
- package/src/cli.js +1 -1
- package/src/commands/plugin.js +7 -4
- package/src/commands/skills.js +14 -9
- package/src/dashboard/App.jsx +343 -0
- package/src/dashboard/components/Breadcrumbs.jsx +45 -0
- package/src/dashboard/components/ControlStrip.jsx +153 -0
- package/src/dashboard/components/InspectorPanel.jsx +203 -0
- package/src/dashboard/components/SkillGraph.jsx +567 -0
- package/src/dashboard/components/Tooltip.jsx +111 -0
- package/src/dashboard/dist/dashboard.js +26692 -0
- package/src/dashboard/index.html +81 -0
- package/src/dashboard/lib/api.js +19 -0
- package/src/dashboard/lib/router.js +15 -0
- package/src/dashboard/main.jsx +4 -0
- package/src/domain/plugins/load-plugin-definition.js +163 -0
- package/src/domain/plugins/plugin-diagnostic-error.js +18 -0
- package/src/domain/plugins/plugin-requirements.js +15 -0
- package/src/domain/skills/skill-graph.js +137 -0
- package/src/domain/skills/skill-model.js +187 -0
- package/src/domain/skills/skill-provenance.js +69 -0
- package/src/infrastructure/fs/build-state-repository.js +16 -0
- package/src/infrastructure/fs/install-state-repository.js +16 -0
- package/src/infrastructure/runtime/materialize-skills.js +117 -0
- package/src/infrastructure/runtime/open-browser.js +20 -0
- package/src/infrastructure/runtime/skill-dev-workbench-server.js +96 -0
- package/src/infrastructure/runtime/watch-skill-workbench.js +68 -0
- package/src/infrastructure/runtime/watch-tree.js +44 -0
- package/src/lib/plugins.js +46 -117
- package/src/lib/skills.js +141 -459
- package/src/utils/errors.js +33 -1
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { inspectStaleSkill, listStaleSkills } from '../../lib/skills.js';
|
|
2
|
+
|
|
3
|
+
export function listStaleSkillsUseCase(options) {
|
|
4
|
+
return listStaleSkills(options);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function inspectStaleSkillUseCase(target, options) {
|
|
8
|
+
return inspectStaleSkill(target, options);
|
|
9
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { inspectSkillDependencies } from '../../lib/skills.js';
|
|
2
|
+
import { inspectStaleSkillUseCase } from './list-stale-skills.js';
|
|
3
|
+
import { validateSkillsUseCase } from './validate-skills.js';
|
|
4
|
+
|
|
5
|
+
export function runSkillWorkbenchAction(action, context) {
|
|
6
|
+
if (action === 'check-stale') {
|
|
7
|
+
return inspectStaleSkillUseCase(context.packageName, { cwd: context.cwd });
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
if (action === 'show-dependencies') {
|
|
11
|
+
return inspectSkillDependencies(context.packageName, { cwd: context.cwd });
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (action === 'validate-skill') {
|
|
15
|
+
return validateSkillsUseCase(context.target, { cwd: context.cwd });
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (action === 'refresh') {
|
|
19
|
+
return { refreshed: true };
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
throw new Error(`Unsupported workbench action: ${action}`);
|
|
23
|
+
}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { dirname, join } from 'node:path';
|
|
3
|
+
import { parseSkillFrontmatterFile, readPackageMetadata, normalizeDisplayPath } from '../../domain/skills/skill-model.js';
|
|
4
|
+
import { readBuildState, compareRecordedSources } from '../../domain/skills/skill-provenance.js';
|
|
5
|
+
import { buildSkillGraph, buildSkillStatusMap } from '../../domain/skills/skill-graph.js';
|
|
6
|
+
import { buildTransitiveSkillWorkbenchModel } from './build-skill-workbench-model.js';
|
|
7
|
+
import { startSkillDevWorkbenchServer } from '../../infrastructure/runtime/skill-dev-workbench-server.js';
|
|
8
|
+
import { openBrowser } from '../../infrastructure/runtime/open-browser.js';
|
|
9
|
+
import { watchSkillWorkbench } from '../../infrastructure/runtime/watch-skill-workbench.js';
|
|
10
|
+
import { runSkillWorkbenchAction } from './run-skill-workbench-action.js';
|
|
11
|
+
|
|
12
|
+
function listPackagedSkillDirs(repoRoot) {
|
|
13
|
+
const stack = [repoRoot];
|
|
14
|
+
const results = [];
|
|
15
|
+
|
|
16
|
+
while (stack.length > 0) {
|
|
17
|
+
const current = stack.pop();
|
|
18
|
+
let entries = [];
|
|
19
|
+
try {
|
|
20
|
+
entries = readdirSync(current, { withFileTypes: true });
|
|
21
|
+
} catch {
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
let hasSkillFile = false;
|
|
26
|
+
let hasPackageFile = false;
|
|
27
|
+
|
|
28
|
+
for (const entry of entries) {
|
|
29
|
+
if (entry.name === '.git' || entry.name === 'node_modules' || entry.name === '.agentpack') continue;
|
|
30
|
+
const fullPath = join(current, entry.name);
|
|
31
|
+
|
|
32
|
+
if (entry.isDirectory()) {
|
|
33
|
+
stack.push(fullPath);
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (entry.name === 'SKILL.md') hasSkillFile = true;
|
|
38
|
+
if (entry.name === 'package.json') hasPackageFile = true;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (hasSkillFile && hasPackageFile) {
|
|
42
|
+
results.push(current);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return results.sort();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function findPackageDirByName(repoRoot, packageName) {
|
|
50
|
+
const stack = [repoRoot];
|
|
51
|
+
|
|
52
|
+
while (stack.length > 0) {
|
|
53
|
+
const current = stack.pop();
|
|
54
|
+
let entries = [];
|
|
55
|
+
try {
|
|
56
|
+
entries = readdirSync(current, { withFileTypes: true });
|
|
57
|
+
} catch {
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
for (const entry of entries) {
|
|
62
|
+
if (entry.name === '.git' || entry.name === 'node_modules') continue;
|
|
63
|
+
const fullPath = join(current, entry.name);
|
|
64
|
+
|
|
65
|
+
if (entry.isDirectory()) {
|
|
66
|
+
stack.push(fullPath);
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (entry.name !== 'package.json') continue;
|
|
71
|
+
|
|
72
|
+
try {
|
|
73
|
+
const pkg = JSON.parse(readFileSync(fullPath, 'utf-8'));
|
|
74
|
+
if (pkg.name === packageName) return dirname(fullPath);
|
|
75
|
+
} catch {
|
|
76
|
+
// skip
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const nodeModulesPath = join(repoRoot, 'node_modules', ...packageName.split('/'));
|
|
82
|
+
if (existsSync(join(nodeModulesPath, 'SKILL.md'))) return nodeModulesPath;
|
|
83
|
+
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function buildModelForSkill(repoRoot, targetPackageName) {
|
|
88
|
+
const packageDirs = listPackagedSkillDirs(repoRoot);
|
|
89
|
+
const skillGraph = buildSkillGraph(repoRoot, packageDirs, {
|
|
90
|
+
parseSkillFrontmatterFile,
|
|
91
|
+
readPackageMetadata,
|
|
92
|
+
findPackageDirByName: (root, name) => findPackageDirByName(root, name),
|
|
93
|
+
normalizeDisplayPath,
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
const buildState = readBuildState(repoRoot);
|
|
97
|
+
const staleSkills = new Set();
|
|
98
|
+
const changedSources = new Set(); // track individual changed source paths
|
|
99
|
+
|
|
100
|
+
for (const [packageName, record] of Object.entries(buildState.skills || buildState)) {
|
|
101
|
+
if (typeof record !== 'object' || !record.sources) continue;
|
|
102
|
+
try {
|
|
103
|
+
const changes = compareRecordedSources(repoRoot, record);
|
|
104
|
+
if (changes.length > 0) {
|
|
105
|
+
staleSkills.add(packageName);
|
|
106
|
+
for (const change of changes) changedSources.add(change.path);
|
|
107
|
+
}
|
|
108
|
+
} catch {
|
|
109
|
+
// skip
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const statusMap = buildSkillStatusMap(skillGraph, staleSkills);
|
|
114
|
+
|
|
115
|
+
function resolveSkillSources(packageName) {
|
|
116
|
+
const graphNode = skillGraph.get(packageName);
|
|
117
|
+
if (!graphNode) return [];
|
|
118
|
+
|
|
119
|
+
const skillFilePath = join(repoRoot, graphNode.skillFile);
|
|
120
|
+
try {
|
|
121
|
+
const metadata = parseSkillFrontmatterFile(skillFilePath);
|
|
122
|
+
return metadata.sources || [];
|
|
123
|
+
} catch {
|
|
124
|
+
return [];
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function resolveSkillRequires(packageName) {
|
|
129
|
+
const graphNode = skillGraph.get(packageName);
|
|
130
|
+
if (!graphNode) return [];
|
|
131
|
+
|
|
132
|
+
const skillFilePath = join(repoRoot, graphNode.skillFile);
|
|
133
|
+
try {
|
|
134
|
+
const metadata = parseSkillFrontmatterFile(skillFilePath);
|
|
135
|
+
return metadata.requires || [];
|
|
136
|
+
} catch {
|
|
137
|
+
return [];
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return buildTransitiveSkillWorkbenchModel({
|
|
142
|
+
repoRoot,
|
|
143
|
+
targetPackageName,
|
|
144
|
+
skillGraph,
|
|
145
|
+
statusMap,
|
|
146
|
+
changedSources,
|
|
147
|
+
resolveSkillSources,
|
|
148
|
+
resolveSkillRequires,
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export async function startSkillDevWorkbench({
|
|
153
|
+
repoRoot,
|
|
154
|
+
skillDir,
|
|
155
|
+
open = true,
|
|
156
|
+
disableBrowser = false,
|
|
157
|
+
}) {
|
|
158
|
+
const packageMetadata = readPackageMetadata(skillDir);
|
|
159
|
+
const defaultSkill = packageMetadata.packageName;
|
|
160
|
+
|
|
161
|
+
const server = await startSkillDevWorkbenchServer({
|
|
162
|
+
buildModel: (skillPackageName) => buildModelForSkill(repoRoot, skillPackageName),
|
|
163
|
+
defaultSkill,
|
|
164
|
+
onAction(action) {
|
|
165
|
+
return runSkillWorkbenchAction(action, {
|
|
166
|
+
cwd: repoRoot,
|
|
167
|
+
target: skillDir,
|
|
168
|
+
packageName: defaultSkill,
|
|
169
|
+
});
|
|
170
|
+
},
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
const watcher = watchSkillWorkbench(repoRoot, skillDir, () => {
|
|
174
|
+
// Model is rebuilt on each request, so no cache to invalidate
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
if (open && !disableBrowser) {
|
|
178
|
+
openBrowser(server.url);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return {
|
|
182
|
+
url: server.url,
|
|
183
|
+
port: server.port,
|
|
184
|
+
refresh() {
|
|
185
|
+
// no-op: models are built on demand per request
|
|
186
|
+
},
|
|
187
|
+
close() {
|
|
188
|
+
watcher.close();
|
|
189
|
+
server.close();
|
|
190
|
+
},
|
|
191
|
+
};
|
|
192
|
+
}
|
package/src/cli.js
CHANGED
|
@@ -68,7 +68,7 @@ export function run(argv) {
|
|
|
68
68
|
if (err instanceof AgentpackError) {
|
|
69
69
|
const opts = program.opts?.() || {};
|
|
70
70
|
if (opts.json) {
|
|
71
|
-
output.json(
|
|
71
|
+
output.json(err.toJSON());
|
|
72
72
|
} else {
|
|
73
73
|
output.error(formatError(err));
|
|
74
74
|
}
|
package/src/commands/plugin.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
|
-
import {
|
|
2
|
+
import { buildPluginUseCase } from '../application/plugins/build-plugin.js';
|
|
3
|
+
import { inspectPluginBundleUseCase } from '../application/plugins/inspect-plugin-bundle.js';
|
|
4
|
+
import { validatePluginBundleUseCase } from '../application/plugins/validate-plugin-bundle.js';
|
|
5
|
+
import { startPluginDev } from '../lib/plugins.js';
|
|
3
6
|
import { output } from '../utils/output.js';
|
|
4
7
|
import { EXIT_CODES } from '../utils/errors.js';
|
|
5
8
|
|
|
@@ -13,7 +16,7 @@ export function pluginCommand() {
|
|
|
13
16
|
.argument('<target>', 'Plugin directory path')
|
|
14
17
|
.action((target, opts, command) => {
|
|
15
18
|
const globalOpts = command.optsWithGlobals();
|
|
16
|
-
const result =
|
|
19
|
+
const result = inspectPluginBundleUseCase(target);
|
|
17
20
|
|
|
18
21
|
if (globalOpts.json) {
|
|
19
22
|
output.json(result);
|
|
@@ -76,7 +79,7 @@ export function pluginCommand() {
|
|
|
76
79
|
.argument('<target>', 'Plugin directory path')
|
|
77
80
|
.action((target, opts, command) => {
|
|
78
81
|
const globalOpts = command.optsWithGlobals();
|
|
79
|
-
const result =
|
|
82
|
+
const result = validatePluginBundleUseCase(target);
|
|
80
83
|
|
|
81
84
|
if (globalOpts.json) {
|
|
82
85
|
output.json(result);
|
|
@@ -114,7 +117,7 @@ export function pluginCommand() {
|
|
|
114
117
|
.argument('<target>', 'Plugin directory path')
|
|
115
118
|
.action((target, opts, command) => {
|
|
116
119
|
const globalOpts = command.optsWithGlobals();
|
|
117
|
-
const result =
|
|
120
|
+
const result = buildPluginUseCase(target, { clean: opts.clean });
|
|
118
121
|
|
|
119
122
|
if (globalOpts.json) {
|
|
120
123
|
output.json(result);
|
package/src/commands/skills.js
CHANGED
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
|
+
import { inspectSkillUseCase } from '../application/skills/inspect-skill.js';
|
|
3
|
+
import { inspectStaleSkillUseCase, listStaleSkillsUseCase } from '../application/skills/list-stale-skills.js';
|
|
4
|
+
import { validateSkillsUseCase } from '../application/skills/validate-skills.js';
|
|
2
5
|
import {
|
|
3
6
|
inspectSkillDependencies,
|
|
4
7
|
inspectMissingSkillDependencies,
|
|
5
8
|
inspectSkillsStatus,
|
|
6
9
|
inspectRegistryConfig,
|
|
7
|
-
inspectSkill,
|
|
8
10
|
inspectSkillsEnv,
|
|
9
|
-
inspectStaleSkill,
|
|
10
11
|
installSkills,
|
|
11
12
|
listOutdatedSkills,
|
|
12
|
-
listStaleSkills,
|
|
13
13
|
resolveInstallTargets,
|
|
14
14
|
startSkillDev,
|
|
15
15
|
unlinkSkill,
|
|
16
16
|
uninstallSkills,
|
|
17
|
-
validateSkills,
|
|
18
17
|
} from '../lib/skills.js';
|
|
19
18
|
import { output } from '../utils/output.js';
|
|
20
19
|
import { EXIT_CODES } from '../utils/errors.js';
|
|
@@ -27,11 +26,13 @@ export function skillsCommand() {
|
|
|
27
26
|
.command('dev')
|
|
28
27
|
.description('Link one local packaged skill for local Claude and agent discovery')
|
|
29
28
|
.option('--no-sync', 'Skip syncing managed package dependencies from requires')
|
|
29
|
+
.option('--no-dashboard', 'Skip starting the local skill development workbench')
|
|
30
30
|
.argument('<target>', 'Packaged skill directory or SKILL.md path')
|
|
31
|
-
.action((target, opts, command) => {
|
|
31
|
+
.action(async (target, opts, command) => {
|
|
32
32
|
const globalOpts = command.optsWithGlobals();
|
|
33
33
|
const session = startSkillDev(target, {
|
|
34
34
|
sync: opts.sync,
|
|
35
|
+
dashboard: opts.dashboard,
|
|
35
36
|
onStart(result) {
|
|
36
37
|
if (globalOpts.json) {
|
|
37
38
|
output.json(result);
|
|
@@ -46,6 +47,9 @@ export function skillsCommand() {
|
|
|
46
47
|
for (const link of result.links) {
|
|
47
48
|
output.write(`Linked: ${link}`);
|
|
48
49
|
}
|
|
50
|
+
if (result.workbench?.enabled) {
|
|
51
|
+
output.write(`Workbench URL: ${result.workbench.url}`);
|
|
52
|
+
}
|
|
49
53
|
output.write('Note: if your current agent session was already running, start a fresh session to pick up newly linked skills.');
|
|
50
54
|
if (result.unresolved.length > 0) {
|
|
51
55
|
output.write('Unresolved Dependencies:');
|
|
@@ -73,6 +77,7 @@ export function skillsCommand() {
|
|
|
73
77
|
|
|
74
78
|
process.once('SIGTERM', stop);
|
|
75
79
|
process.once('SIGINT', stop);
|
|
80
|
+
await session.ready;
|
|
76
81
|
});
|
|
77
82
|
|
|
78
83
|
cmd
|
|
@@ -250,7 +255,7 @@ export function skillsCommand() {
|
|
|
250
255
|
.argument('<target>', 'Skill directory, SKILL.md path, or package name')
|
|
251
256
|
.action((target, opts, command) => {
|
|
252
257
|
const globalOpts = command.optsWithGlobals();
|
|
253
|
-
const result =
|
|
258
|
+
const result = inspectSkillUseCase(target);
|
|
254
259
|
|
|
255
260
|
if (globalOpts.json) {
|
|
256
261
|
output.json(result);
|
|
@@ -291,7 +296,7 @@ export function skillsCommand() {
|
|
|
291
296
|
const globalOpts = command.optsWithGlobals();
|
|
292
297
|
|
|
293
298
|
if (target) {
|
|
294
|
-
const result =
|
|
299
|
+
const result = inspectStaleSkillUseCase(target);
|
|
295
300
|
|
|
296
301
|
if (globalOpts.json) {
|
|
297
302
|
output.json(result);
|
|
@@ -310,7 +315,7 @@ export function skillsCommand() {
|
|
|
310
315
|
return;
|
|
311
316
|
}
|
|
312
317
|
|
|
313
|
-
const results =
|
|
318
|
+
const results = listStaleSkillsUseCase();
|
|
314
319
|
|
|
315
320
|
if (globalOpts.json) {
|
|
316
321
|
output.json({
|
|
@@ -337,7 +342,7 @@ export function skillsCommand() {
|
|
|
337
342
|
.argument('[target]', 'Optional packaged skill directory, SKILL.md path, or package name')
|
|
338
343
|
.action((target, opts, command) => {
|
|
339
344
|
const globalOpts = command.optsWithGlobals();
|
|
340
|
-
const result =
|
|
345
|
+
const result = validateSkillsUseCase(target);
|
|
341
346
|
|
|
342
347
|
if (globalOpts.json) {
|
|
343
348
|
output.json(
|