@nano-step/skill-manager 5.4.2 → 5.5.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/dist/config.d.ts +2 -0
- package/dist/config.js +41 -0
- package/dist/index.js +18 -6
- package/dist/installer.js +4 -0
- package/dist/registry.d.ts +1 -0
- package/dist/registry.js +14 -0
- package/dist/utils.d.ts +3 -1
- package/dist/utils.js +5 -1
- package/package.json +3 -2
- package/private-catalog.json +32 -0
package/dist/config.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { SkillManifest } from "./utils";
|
|
2
2
|
export declare function mergeAgentConfig(agentConfigPath: string, manifest: SkillManifest): Promise<void>;
|
|
3
3
|
export declare function removeAgentConfig(agentConfigPath: string, manifest: SkillManifest): Promise<void>;
|
|
4
|
+
export declare function mergeMcpConfig(opencodeJsonPath: string, manifest: SkillManifest): Promise<void>;
|
|
5
|
+
export declare function removeMcpConfig(opencodeJsonPath: string, manifest: SkillManifest): Promise<void>;
|
|
4
6
|
export declare function copyCommands(manifest: SkillManifest, packageSkillDir: string, commandDir: string): Promise<void>;
|
|
5
7
|
export declare function removeCommands(manifest: SkillManifest, commandDir: string): Promise<void>;
|
package/dist/config.js
CHANGED
|
@@ -5,10 +5,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.mergeAgentConfig = mergeAgentConfig;
|
|
7
7
|
exports.removeAgentConfig = removeAgentConfig;
|
|
8
|
+
exports.mergeMcpConfig = mergeMcpConfig;
|
|
9
|
+
exports.removeMcpConfig = removeMcpConfig;
|
|
8
10
|
exports.copyCommands = copyCommands;
|
|
9
11
|
exports.removeCommands = removeCommands;
|
|
10
12
|
const path_1 = __importDefault(require("path"));
|
|
11
13
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
14
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
12
15
|
const utils_1 = require("./utils");
|
|
13
16
|
async function mergeAgentConfig(agentConfigPath, manifest) {
|
|
14
17
|
if (!manifest.agent)
|
|
@@ -33,6 +36,44 @@ async function removeAgentConfig(agentConfigPath, manifest) {
|
|
|
33
36
|
await (0, utils_1.writeJsonFile)(agentConfigPath, config);
|
|
34
37
|
}
|
|
35
38
|
}
|
|
39
|
+
async function mergeMcpConfig(opencodeJsonPath, manifest) {
|
|
40
|
+
if (!manifest.mcp)
|
|
41
|
+
return;
|
|
42
|
+
const exists = await fs_extra_1.default.pathExists(opencodeJsonPath);
|
|
43
|
+
if (!exists) {
|
|
44
|
+
console.log(chalk_1.default.yellow(`Warning: ${opencodeJsonPath} not found. Skipping MCP config merge.`));
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const config = await (0, utils_1.readJsonFile)(opencodeJsonPath, {});
|
|
48
|
+
const mcp = (config.mcp || {});
|
|
49
|
+
for (const [serverName, serverConfig] of Object.entries(manifest.mcp)) {
|
|
50
|
+
if (mcp[serverName]) {
|
|
51
|
+
console.log(chalk_1.default.yellow(` MCP server "${serverName}" already configured — skipping (edit opencode.json manually if needed)`));
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
mcp[serverName] = serverConfig;
|
|
55
|
+
console.log(chalk_1.default.green(` ✓ Added MCP server "${serverName}" to opencode.json (update connection strings!)`));
|
|
56
|
+
}
|
|
57
|
+
config.mcp = mcp;
|
|
58
|
+
await (0, utils_1.writeJsonFile)(opencodeJsonPath, config);
|
|
59
|
+
}
|
|
60
|
+
async function removeMcpConfig(opencodeJsonPath, manifest) {
|
|
61
|
+
if (!manifest.mcp)
|
|
62
|
+
return;
|
|
63
|
+
const exists = await fs_extra_1.default.pathExists(opencodeJsonPath);
|
|
64
|
+
if (!exists)
|
|
65
|
+
return;
|
|
66
|
+
const config = await (0, utils_1.readJsonFile)(opencodeJsonPath, {});
|
|
67
|
+
const mcp = (config.mcp || {});
|
|
68
|
+
for (const serverName of Object.keys(manifest.mcp)) {
|
|
69
|
+
if (Object.prototype.hasOwnProperty.call(mcp, serverName)) {
|
|
70
|
+
delete mcp[serverName];
|
|
71
|
+
console.log(chalk_1.default.green(` ✓ Removed MCP server "${serverName}" from opencode.json`));
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
config.mcp = mcp;
|
|
75
|
+
await (0, utils_1.writeJsonFile)(opencodeJsonPath, config);
|
|
76
|
+
}
|
|
36
77
|
async function copyCommands(manifest, packageSkillDir, commandDir) {
|
|
37
78
|
if (!manifest.commands || manifest.commands.length === 0)
|
|
38
79
|
return;
|
package/dist/index.js
CHANGED
|
@@ -29,6 +29,12 @@ async function run() {
|
|
|
29
29
|
.name("skill-manager")
|
|
30
30
|
.description("Install and manage AI agent skills for OpenCode")
|
|
31
31
|
.version(utils_1.MANAGER_VERSION);
|
|
32
|
+
program
|
|
33
|
+
.command("version")
|
|
34
|
+
.description("Show skill-manager version")
|
|
35
|
+
.action(() => {
|
|
36
|
+
console.log(utils_1.MANAGER_VERSION);
|
|
37
|
+
});
|
|
32
38
|
program
|
|
33
39
|
.command("login")
|
|
34
40
|
.description("Authenticate with GitHub to access private skills")
|
|
@@ -60,14 +66,11 @@ async function run() {
|
|
|
60
66
|
const paths = await (0, utils_1.detectOpenCodePaths)();
|
|
61
67
|
await (0, state_1.migrateV4State)(paths.configDir, paths.stateFilePath, paths.skillsDir);
|
|
62
68
|
const token = await (0, auth_1.resolveToken)();
|
|
63
|
-
const remoteSkills = token ? await (0, remote_registry_1.listRemoteSkills)() :
|
|
69
|
+
const remoteSkills = token ? await (0, remote_registry_1.listRemoteSkills)() : (0, registry_1.loadPrivateCatalog)(paths.packageSkillsDir);
|
|
64
70
|
const catalog = await (0, registry_1.loadMergedCatalog)(paths.packageSkillsDir, remoteSkills);
|
|
65
71
|
const state = await (0, state_1.loadState)(paths.stateFilePath);
|
|
66
72
|
if (catalog.length === 0) {
|
|
67
73
|
console.log(chalk_1.default.yellow("No skills found in catalog."));
|
|
68
|
-
if (!token) {
|
|
69
|
-
console.log(chalk_1.default.gray("Run 'skill-manager login' to access private skills."));
|
|
70
|
-
}
|
|
71
74
|
return;
|
|
72
75
|
}
|
|
73
76
|
console.log(chalk_1.default.bold("\nAvailable Skills:\n"));
|
|
@@ -85,7 +88,16 @@ async function run() {
|
|
|
85
88
|
for (const entry of catalog) {
|
|
86
89
|
const skill = entry.manifest;
|
|
87
90
|
const installed = state.skills[skill.name];
|
|
88
|
-
|
|
91
|
+
let status;
|
|
92
|
+
if (installed) {
|
|
93
|
+
status = chalk_1.default.green("installed");
|
|
94
|
+
}
|
|
95
|
+
else if (entry.source === "private" && !token) {
|
|
96
|
+
status = chalk_1.default.yellow("login required");
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
status = chalk_1.default.gray("not installed");
|
|
100
|
+
}
|
|
89
101
|
const sourceLabel = entry.source === "private" ? chalk_1.default.magenta("private") : chalk_1.default.blue("public");
|
|
90
102
|
console.log(" " +
|
|
91
103
|
chalk_1.default.cyan(skill.name.padEnd(nameWidth)) +
|
|
@@ -96,7 +108,7 @@ async function run() {
|
|
|
96
108
|
}
|
|
97
109
|
console.log("");
|
|
98
110
|
if (!token) {
|
|
99
|
-
console.log(chalk_1.default.gray("Tip: Run 'skill-manager login' to
|
|
111
|
+
console.log(chalk_1.default.gray("Tip: Run 'skill-manager login --token <github-token>' to install private skills."));
|
|
100
112
|
console.log("");
|
|
101
113
|
}
|
|
102
114
|
});
|
package/dist/installer.js
CHANGED
|
@@ -26,6 +26,7 @@ async function installFromDir(manifest, sourceDir, paths, source) {
|
|
|
26
26
|
await fs_extra_1.default.copy(sourceDir, targetSkillDir, { overwrite: true });
|
|
27
27
|
await (0, config_1.copyCommands)(manifest, sourceDir, paths.commandDir);
|
|
28
28
|
await (0, config_1.mergeAgentConfig)(paths.agentConfigPath, manifest);
|
|
29
|
+
await (0, config_1.mergeMcpConfig)(paths.opencodeJsonPath, manifest);
|
|
29
30
|
state.skills[manifest.name] = {
|
|
30
31
|
version: manifest.version,
|
|
31
32
|
installedAt: new Date().toISOString(),
|
|
@@ -88,6 +89,7 @@ async function removeSkill(name, paths) {
|
|
|
88
89
|
if (effectiveManifest) {
|
|
89
90
|
await (0, config_1.removeCommands)(effectiveManifest, paths.commandDir);
|
|
90
91
|
await (0, config_1.removeAgentConfig)(paths.agentConfigPath, effectiveManifest);
|
|
92
|
+
await (0, config_1.removeMcpConfig)(paths.opencodeJsonPath, effectiveManifest);
|
|
91
93
|
}
|
|
92
94
|
delete state.skills[name];
|
|
93
95
|
await (0, state_1.saveState)(paths.stateFilePath, state);
|
|
@@ -111,6 +113,7 @@ async function updateSkill(name, paths) {
|
|
|
111
113
|
await fs_extra_1.default.copy(packageSkillDir, targetSkillDir, { overwrite: true });
|
|
112
114
|
await (0, config_1.copyCommands)(localManifest, packageSkillDir, paths.commandDir);
|
|
113
115
|
await (0, config_1.mergeAgentConfig)(paths.agentConfigPath, localManifest);
|
|
116
|
+
await (0, config_1.mergeMcpConfig)(paths.opencodeJsonPath, localManifest);
|
|
114
117
|
state.skills[name] = {
|
|
115
118
|
version: localManifest.version,
|
|
116
119
|
installedAt: new Date().toISOString(),
|
|
@@ -133,6 +136,7 @@ async function updateSkill(name, paths) {
|
|
|
133
136
|
await fs_extra_1.default.copy(tempDir, targetSkillDir, { overwrite: true });
|
|
134
137
|
await (0, config_1.copyCommands)(remoteManifest, tempDir, paths.commandDir);
|
|
135
138
|
await (0, config_1.mergeAgentConfig)(paths.agentConfigPath, remoteManifest);
|
|
139
|
+
await (0, config_1.mergeMcpConfig)(paths.opencodeJsonPath, remoteManifest);
|
|
136
140
|
state.skills[name] = {
|
|
137
141
|
version: remoteManifest.version,
|
|
138
142
|
installedAt: new Date().toISOString(),
|
package/dist/registry.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { SkillManifest, CatalogEntry } from "./utils";
|
|
2
2
|
export declare function loadCatalog(packageSkillsDir: string): Promise<SkillManifest[]>;
|
|
3
3
|
export declare function getSkillManifest(packageSkillsDir: string, name: string): Promise<SkillManifest | null>;
|
|
4
|
+
export declare function loadPrivateCatalog(packageSkillsDir: string): SkillManifest[];
|
|
4
5
|
export declare function loadMergedCatalog(packageSkillsDir: string, remoteSkills: SkillManifest[]): Promise<CatalogEntry[]>;
|
package/dist/registry.js
CHANGED
|
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.loadCatalog = loadCatalog;
|
|
7
7
|
exports.getSkillManifest = getSkillManifest;
|
|
8
|
+
exports.loadPrivateCatalog = loadPrivateCatalog;
|
|
8
9
|
exports.loadMergedCatalog = loadMergedCatalog;
|
|
9
10
|
const path_1 = __importDefault(require("path"));
|
|
10
11
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
@@ -62,6 +63,19 @@ async function getSkillManifest(packageSkillsDir, name) {
|
|
|
62
63
|
return null;
|
|
63
64
|
}
|
|
64
65
|
}
|
|
66
|
+
function loadPrivateCatalog(packageSkillsDir) {
|
|
67
|
+
const catalogPath = path_1.default.join(packageSkillsDir, "..", "private-catalog.json");
|
|
68
|
+
try {
|
|
69
|
+
const raw = fs_extra_1.default.readFileSync(catalogPath, "utf8");
|
|
70
|
+
const data = JSON.parse(raw);
|
|
71
|
+
if (!Array.isArray(data))
|
|
72
|
+
return [];
|
|
73
|
+
return data.filter(isValidManifest);
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return [];
|
|
77
|
+
}
|
|
78
|
+
}
|
|
65
79
|
async function loadMergedCatalog(packageSkillsDir, remoteSkills) {
|
|
66
80
|
const localCatalog = await loadCatalog(packageSkillsDir);
|
|
67
81
|
const localNames = new Set(localCatalog.map((s) => s.name));
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const MANAGER_VERSION = "5.
|
|
1
|
+
export declare const MANAGER_VERSION = "5.5.1";
|
|
2
2
|
export interface SkillManifest {
|
|
3
3
|
name: string;
|
|
4
4
|
version: string;
|
|
@@ -8,6 +8,7 @@ export interface SkillManifest {
|
|
|
8
8
|
id: string;
|
|
9
9
|
config: Record<string, unknown>;
|
|
10
10
|
} | null;
|
|
11
|
+
mcp?: Record<string, Record<string, unknown>> | null;
|
|
11
12
|
commands?: string[];
|
|
12
13
|
tags?: string[];
|
|
13
14
|
}
|
|
@@ -32,6 +33,7 @@ export interface OpenCodePaths {
|
|
|
32
33
|
agentConfigPath: string;
|
|
33
34
|
stateFilePath: string;
|
|
34
35
|
packageSkillsDir: string;
|
|
36
|
+
opencodeJsonPath: string;
|
|
35
37
|
}
|
|
36
38
|
export declare function detectOpenCodePaths(): Promise<OpenCodePaths>;
|
|
37
39
|
export declare function ensureDirExists(dirPath: string): Promise<void>;
|
package/dist/utils.js
CHANGED
|
@@ -13,7 +13,7 @@ exports.writeText = writeText;
|
|
|
13
13
|
const path_1 = __importDefault(require("path"));
|
|
14
14
|
const os_1 = __importDefault(require("os"));
|
|
15
15
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
16
|
-
exports.MANAGER_VERSION = "5.
|
|
16
|
+
exports.MANAGER_VERSION = "5.5.1";
|
|
17
17
|
async function detectOpenCodePaths() {
|
|
18
18
|
const homeConfig = path_1.default.join(os_1.default.homedir(), ".config", "opencode");
|
|
19
19
|
const cwd = process.cwd();
|
|
@@ -24,6 +24,9 @@ async function detectOpenCodePaths() {
|
|
|
24
24
|
throw new Error("OpenCode config not found. Expected ~/.config/opencode or .opencode in project.");
|
|
25
25
|
}
|
|
26
26
|
const configDir = hasProjectConfig ? projectConfig : homeConfig;
|
|
27
|
+
const opencodeJsonPath = hasProjectConfig
|
|
28
|
+
? path_1.default.join(cwd, "opencode.json")
|
|
29
|
+
: path_1.default.join(configDir, "opencode.json");
|
|
27
30
|
return {
|
|
28
31
|
configDir,
|
|
29
32
|
commandDir: path_1.default.join(configDir, "command"),
|
|
@@ -31,6 +34,7 @@ async function detectOpenCodePaths() {
|
|
|
31
34
|
agentConfigPath: path_1.default.join(configDir, "oh-my-opencode.json"),
|
|
32
35
|
stateFilePath: path_1.default.join(configDir, ".skill-manager.json"),
|
|
33
36
|
packageSkillsDir: path_1.default.join(__dirname, "..", "skills"),
|
|
37
|
+
opencodeJsonPath,
|
|
34
38
|
};
|
|
35
39
|
}
|
|
36
40
|
async function ensureDirExists(dirPath) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nano-step/skill-manager",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.5.1",
|
|
4
4
|
"description": "CLI tool that installs and manages AI agent skills, MCP tool routing, and workflow configurations.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
"files": [
|
|
11
11
|
"bin",
|
|
12
12
|
"dist",
|
|
13
|
-
"skills"
|
|
13
|
+
"skills",
|
|
14
|
+
"private-catalog.json"
|
|
14
15
|
],
|
|
15
16
|
"scripts": {
|
|
16
17
|
"build": "tsc",
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"name": "database-inspector",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"description": "Database schema inspection for MySQL and PostgreSQL — progressive discovery workflow with read-only SQL execution"
|
|
6
|
+
},
|
|
7
|
+
{
|
|
8
|
+
"name": "e2e-test-generator",
|
|
9
|
+
"version": "1.0.0",
|
|
10
|
+
"description": "AI-driven E2E test generation from PRD requirements using Playwright MCP"
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"name": "feature-analysis",
|
|
14
|
+
"version": "2.0.0",
|
|
15
|
+
"description": "Deep code analysis of any feature or service before writing docs, diagrams, or making changes"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"name": "mcp-management",
|
|
19
|
+
"version": "2.0.0",
|
|
20
|
+
"description": "MCP tool routing and execution with token-saving isolation"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"name": "pr-code-reviewer",
|
|
24
|
+
"version": "2.6.0",
|
|
25
|
+
"description": "Comprehensive code review with 4 parallel subagents and GitHub Copilot-style PR summaries"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"name": "rri-t-testing",
|
|
29
|
+
"version": "1.0.0",
|
|
30
|
+
"description": "RRI-T QA methodology — 5-phase testing with 7 dimensions, 5 personas, and release gates"
|
|
31
|
+
}
|
|
32
|
+
]
|