@wowok/skills 3.0.4 → 3.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 +146 -122
- package/dist/cli.d.ts +6 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +223 -837
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24 -1
- package/dist/index.js.map +1 -1
- package/dist/installer.d.ts +121 -0
- package/dist/installer.d.ts.map +1 -0
- package/dist/installer.js +802 -0
- package/dist/installer.js.map +1 -0
- package/dist/skills.d.ts +5 -2
- package/dist/skills.d.ts.map +1 -1
- package/dist/skills.js +86 -62
- package/dist/skills.js.map +1 -1
- package/dist/targets.d.ts +94 -0
- package/dist/targets.d.ts.map +1 -0
- package/dist/targets.js +421 -0
- package/dist/targets.js.map +1 -0
- package/dist/types.d.ts +5 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +0 -32
- package/dist/types.js.map +1 -1
- package/package.json +5 -4
- package/scripts/install.js +21 -859
- package/wowok-arbitrator/SKILL.md +5 -12
- package/wowok-auditor/SKILL.md +5 -17
- package/wowok-collaborator/SKILL.md +5 -17
- package/wowok-governance/SKILL.md +10 -30
- package/wowok-machine/SKILL.md +5 -18
- package/wowok-market/SKILL.md +5 -21
- package/wowok-messenger/SKILL.md +32 -50
- package/wowok-onboard/SKILL.md +5 -22
- package/wowok-order/SKILL.md +6 -19
- package/wowok-output/SKILL.md +5 -10
- package/wowok-planner/SKILL.md +6 -20
- package/wowok-provider/SKILL.md +6 -18
- package/wowok-supplier/SKILL.md +5 -16
- package/examples/Insurance/Insurance.md +0 -1245
- package/examples/MyShop/MyShop.md +0 -2003
- package/examples/MyShop/myshop_machine_nodes.json +0 -93
- package/examples/MyShop_Advanced/MyShop_Advanced.md +0 -2880
- package/examples/ThreeBody_Signature/ThreeBody_Signature.md +0 -1831
- package/examples/Travel/Travel.md +0 -1849
- package/examples/Travel/calc-weather-timestamps.js +0 -12
package/dist/cli.js
CHANGED
|
@@ -1,934 +1,320 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
-
if (k2 === undefined) k2 = k;
|
|
5
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
-
}
|
|
9
|
-
Object.defineProperty(o, k2, desc);
|
|
10
|
-
}) : (function(o, m, k, k2) {
|
|
11
|
-
if (k2 === undefined) k2 = k;
|
|
12
|
-
o[k2] = m[k];
|
|
13
|
-
}));
|
|
14
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
-
}) : function(o, v) {
|
|
17
|
-
o["default"] = v;
|
|
18
|
-
});
|
|
19
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
-
var ownKeys = function(o) {
|
|
21
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
-
var ar = [];
|
|
23
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
-
return ar;
|
|
25
|
-
};
|
|
26
|
-
return ownKeys(o);
|
|
27
|
-
};
|
|
28
|
-
return function (mod) {
|
|
29
|
-
if (mod && mod.__esModule) return mod;
|
|
30
|
-
var result = {};
|
|
31
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
-
__setModuleDefault(result, mod);
|
|
33
|
-
return result;
|
|
34
|
-
};
|
|
35
|
-
})();
|
|
36
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
-
const fs = __importStar(require("fs"));
|
|
38
|
-
const path = __importStar(require("path"));
|
|
39
|
-
const child_process_1 = require("child_process");
|
|
40
|
-
const os = __importStar(require("os"));
|
|
41
|
-
const skills_1 = require("./skills");
|
|
42
|
-
const types_1 = require("./types");
|
|
43
3
|
/**
|
|
44
|
-
*
|
|
45
|
-
* Must stay in sync with scripts/install.js SKILL_DIRS
|
|
46
|
-
* Ordered by role for clarity:
|
|
47
|
-
* - Customer: wowok-order
|
|
48
|
-
* - Provider: wowok-provider, wowok-machine
|
|
49
|
-
* - Arbitrator: wowok-arbitrator
|
|
50
|
-
* - Shared: wowok-messenger, wowok-output
|
|
51
|
-
* - Onboarding: wowok-onboard, wowok-planner, wowok-auditor
|
|
4
|
+
* `wowok-skills` CLI.
|
|
52
5
|
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*/
|
|
56
|
-
const SKILL_DIRS = [
|
|
57
|
-
'wowok-order',
|
|
58
|
-
'wowok-provider',
|
|
59
|
-
'wowok-machine',
|
|
60
|
-
'wowok-arbitrator',
|
|
61
|
-
'wowok-messenger',
|
|
62
|
-
'wowok-output',
|
|
63
|
-
'wowok-onboard',
|
|
64
|
-
'wowok-planner',
|
|
65
|
-
'wowok-auditor',
|
|
66
|
-
'wowok-supplier',
|
|
67
|
-
'wowok-collaborator',
|
|
68
|
-
'wowok-governance',
|
|
69
|
-
];
|
|
70
|
-
/**
|
|
71
|
-
* Deprecated skill dirs — never installed, but uninit still removes them
|
|
72
|
-
* from legacy installs so users can clean up pre-refactor installations.
|
|
73
|
-
*/
|
|
74
|
-
const LEGACY_SKILL_DIRS = [...skills_1.DEPRECATED_SKILLS];
|
|
75
|
-
/**
|
|
76
|
-
* Role display names for CLI output
|
|
6
|
+
* All installation/MCP logic lives in src/installer.ts + src/targets.ts so the
|
|
7
|
+
* CLI and the npm postinstall hook can never drift apart again.
|
|
77
8
|
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
const skills_1 = require("./skills");
|
|
11
|
+
const targets_1 = require("./targets");
|
|
12
|
+
const installer_1 = require("./installer");
|
|
78
13
|
const ROLE_DISPLAY = {
|
|
79
14
|
customer: '👤 Customer',
|
|
80
15
|
provider: '🏪 Provider',
|
|
81
16
|
supplier: '📦 Supplier',
|
|
82
17
|
collaborator: '🤝 Collaborator',
|
|
83
18
|
arbitrator: '⚖️ Arbitrator',
|
|
84
|
-
shared: '🛠️ Shared'
|
|
19
|
+
shared: '🛠️ Shared',
|
|
85
20
|
};
|
|
86
|
-
function getPackageRoot() {
|
|
87
|
-
return path.resolve(__dirname, '..');
|
|
88
|
-
}
|
|
89
|
-
function copyDir(src, dest) {
|
|
90
|
-
if (!fs.existsSync(src))
|
|
91
|
-
return false;
|
|
92
|
-
fs.mkdirSync(dest, { recursive: true });
|
|
93
|
-
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
94
|
-
for (const entry of entries) {
|
|
95
|
-
const srcPath = path.join(src, entry.name);
|
|
96
|
-
const destPath = path.join(dest, entry.name);
|
|
97
|
-
if (entry.isDirectory()) {
|
|
98
|
-
copyDir(srcPath, destPath);
|
|
99
|
-
}
|
|
100
|
-
else {
|
|
101
|
-
fs.copyFileSync(srcPath, destPath);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
return true;
|
|
105
|
-
}
|
|
106
|
-
function removeDir(dir) {
|
|
107
|
-
if (!fs.existsSync(dir))
|
|
108
|
-
return;
|
|
109
|
-
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
110
|
-
for (const entry of entries) {
|
|
111
|
-
const fullPath = path.join(dir, entry.name);
|
|
112
|
-
if (entry.isDirectory()) {
|
|
113
|
-
removeDir(fullPath);
|
|
114
|
-
}
|
|
115
|
-
else {
|
|
116
|
-
fs.unlinkSync(fullPath);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
fs.rmdirSync(dir);
|
|
120
|
-
}
|
|
121
|
-
function parseFrontmatter(content) {
|
|
122
|
-
const match = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
|
123
|
-
if (!match)
|
|
124
|
-
return null;
|
|
125
|
-
const frontmatterStr = match[1];
|
|
126
|
-
const body = match[2];
|
|
127
|
-
const frontmatter = {};
|
|
128
|
-
let currentKey = null;
|
|
129
|
-
let currentValue = '';
|
|
130
|
-
for (const line of frontmatterStr.split('\n')) {
|
|
131
|
-
const kvMatch = line.match(/^(\w[\w-]*)\s*:\s*(.*)$/);
|
|
132
|
-
if (kvMatch) {
|
|
133
|
-
if (currentKey) {
|
|
134
|
-
frontmatter[currentKey] = currentValue.trim();
|
|
135
|
-
}
|
|
136
|
-
currentKey = kvMatch[1];
|
|
137
|
-
currentValue = kvMatch[2];
|
|
138
|
-
}
|
|
139
|
-
else if (currentKey) {
|
|
140
|
-
currentValue += '\n' + line;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
if (currentKey) {
|
|
144
|
-
frontmatter[currentKey] = currentValue.trim();
|
|
145
|
-
}
|
|
146
|
-
return { frontmatter, body };
|
|
147
|
-
}
|
|
148
|
-
function convertToCursor(content, skillDir) {
|
|
149
|
-
const parsed = parseFrontmatter(content);
|
|
150
|
-
if (!parsed)
|
|
151
|
-
return content;
|
|
152
|
-
const { frontmatter, body } = parsed;
|
|
153
|
-
let description = frontmatter.description || frontmatter.name || skillDir;
|
|
154
|
-
if (typeof description === 'string') {
|
|
155
|
-
description = description.replace(/\n/g, ' ');
|
|
156
|
-
}
|
|
157
|
-
const isAlways = frontmatter.loading === 'always' || frontmatter.always === true || frontmatter.always === 'true';
|
|
158
|
-
const alwaysApply = isAlways ? 'true' : 'false';
|
|
159
|
-
const newFrontmatter = [
|
|
160
|
-
'---',
|
|
161
|
-
`description: "${description}"`,
|
|
162
|
-
`alwaysApply: ${alwaysApply}`,
|
|
163
|
-
'---',
|
|
164
|
-
].join('\n');
|
|
165
|
-
return newFrontmatter + '\n' + body;
|
|
166
|
-
}
|
|
167
|
-
function convertToCopilot(content) {
|
|
168
|
-
const parsed = parseFrontmatter(content);
|
|
169
|
-
if (!parsed)
|
|
170
|
-
return content;
|
|
171
|
-
return parsed.body;
|
|
172
|
-
}
|
|
173
|
-
function convertSkillContent(content, target, skillDir) {
|
|
174
|
-
if (target === 'cursor')
|
|
175
|
-
return convertToCursor(content, skillDir);
|
|
176
|
-
if (target === 'copilot')
|
|
177
|
-
return convertToCopilot(content);
|
|
178
|
-
return content;
|
|
179
|
-
}
|
|
180
21
|
// =========================================================================
|
|
181
|
-
//
|
|
22
|
+
// Informational commands
|
|
182
23
|
// =========================================================================
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
*
|
|
193
|
-
* Read rule : pick the FIRST existing candidate.
|
|
194
|
-
* Write rule: if any file exists, merge into that first existing file;
|
|
195
|
-
* if none exist, create the highest-priority one (.mcp.json).
|
|
196
|
-
*/
|
|
197
|
-
function resolveCodeBuddyMcpFile() {
|
|
198
|
-
const home = os.homedir();
|
|
199
|
-
const candidates = [
|
|
200
|
-
path.join(home, '.codebuddy', '.mcp.json'), // 1. recommended
|
|
201
|
-
path.join(home, '.codebuddy', 'mcp.json'), // 2. deprecated
|
|
202
|
-
path.join(home, '.codebuddy.json'), // 3. legacy
|
|
203
|
-
];
|
|
204
|
-
const existing = candidates.find((p) => fs.existsSync(p));
|
|
205
|
-
return existing || candidates[0];
|
|
206
|
-
}
|
|
207
|
-
/**
|
|
208
|
-
* Resolve VS Code globalStorage MCP settings files for a given extension ID.
|
|
209
|
-
* See install.js resolveVscodeGlobalStorageFiles for full path references.
|
|
210
|
-
*/
|
|
211
|
-
function resolveVscodeGlobalStorageFiles(extensionId, fileName) {
|
|
212
|
-
const home = os.homedir();
|
|
213
|
-
const vsBaseDirs = (() => {
|
|
214
|
-
switch (process.platform) {
|
|
215
|
-
case 'darwin':
|
|
216
|
-
return [path.join(home, 'Library', 'Application Support')];
|
|
217
|
-
case 'win32':
|
|
218
|
-
return [process.env.APPDATA || path.join(home, 'AppData', 'Roaming')];
|
|
219
|
-
default:
|
|
220
|
-
return [process.env.XDG_CONFIG_HOME || path.join(home, '.config')];
|
|
221
|
-
}
|
|
222
|
-
})();
|
|
223
|
-
const results = [];
|
|
224
|
-
const vsVariants = ['Code', 'Code - Insiders', 'VSCodium', 'Cursor'];
|
|
225
|
-
for (const base of vsBaseDirs) {
|
|
226
|
-
for (const variant of vsVariants) {
|
|
227
|
-
const vsUserDir = path.join(base, variant, 'User');
|
|
228
|
-
if (fs.existsSync(vsUserDir)) {
|
|
229
|
-
results.push(path.join(vsUserDir, 'globalStorage', extensionId, 'settings', fileName));
|
|
230
|
-
}
|
|
24
|
+
function cmdList() {
|
|
25
|
+
console.log('Available WoWok Skills (by role):\n');
|
|
26
|
+
for (const group of (0, skills_1.getRoleSkills)()) {
|
|
27
|
+
console.log(ROLE_DISPLAY[group.role]);
|
|
28
|
+
console.log(` ${group.description}`);
|
|
29
|
+
for (const skill of group.skills) {
|
|
30
|
+
const loading = skill.loading === 'always' ? '[always]' : '[on-demand]';
|
|
31
|
+
console.log(` • ${skill.name} ${loading}`);
|
|
32
|
+
console.log(` ${skill.description}`);
|
|
231
33
|
}
|
|
34
|
+
console.log('');
|
|
232
35
|
}
|
|
233
|
-
return results;
|
|
234
|
-
}
|
|
235
|
-
/**
|
|
236
|
-
* Resolve ALL Roo Code MCP config files that should receive the wowok entry.
|
|
237
|
-
* Covers both Standalone CLI config and VS Code extension globalStorage
|
|
238
|
-
* entries for every detected VS Code variant (Code, Insiders, VSCodium, Cursor).
|
|
239
|
-
*
|
|
240
|
-
* See detailed references in install.js resolveRooMcpFiles comments.
|
|
241
|
-
*/
|
|
242
|
-
function resolveRooMcpFiles() {
|
|
243
|
-
const results = [];
|
|
244
|
-
// (A) Standalone CLI config
|
|
245
|
-
results.push(path.join(os.homedir(), '.roo', 'mcp_settings.json'));
|
|
246
|
-
// (B) VS Code extension globalStorage entries
|
|
247
|
-
results.push(...resolveVscodeGlobalStorageFiles('rooveterinaryinc.roo-cline', 'cline_mcp_settings.json'));
|
|
248
|
-
return results;
|
|
249
|
-
}
|
|
250
|
-
/**
|
|
251
|
-
* Resolve ALL Cline (VS Code) MCP config files.
|
|
252
|
-
* Cline stores MCP settings in VS Code globalStorage under its extension ID
|
|
253
|
-
* (saoudrizwan.claude-dev), filename cline_mcp_settings.json.
|
|
254
|
-
* Reference: https://www.skillmd.ai/skills/mcp-installer-1/
|
|
255
|
-
*/
|
|
256
|
-
function resolveClineMcpFiles() {
|
|
257
|
-
return resolveVscodeGlobalStorageFiles('saoudrizwan.claude-dev', 'cline_mcp_settings.json');
|
|
258
36
|
}
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
return results;
|
|
37
|
+
function cmdGet(name) {
|
|
38
|
+
const skill = (0, skills_1.getSkillByName)(name);
|
|
39
|
+
if (!skill) {
|
|
40
|
+
console.error(`Skill not found: ${name}`);
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
43
|
+
console.log(`Name: ${skill.name}`);
|
|
44
|
+
console.log(`Role: ${ROLE_DISPLAY[skill.role]}`);
|
|
45
|
+
console.log(`Loading: ${skill.loading}`);
|
|
46
|
+
console.log(`Version: ${skill.version}`);
|
|
47
|
+
console.log(`Description: ${skill.description}`);
|
|
48
|
+
if (skill.related?.length)
|
|
49
|
+
console.log(`Related: ${skill.related.join(', ')}`);
|
|
273
50
|
}
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
return config;
|
|
281
|
-
},
|
|
282
|
-
},
|
|
283
|
-
codebuddy: {
|
|
284
|
-
resolveConfigPaths: () => [resolveCodeBuddyMcpFile()],
|
|
285
|
-
merge: (config) => {
|
|
286
|
-
config.mcpServers = config.mcpServers || {};
|
|
287
|
-
config.mcpServers.wowok = { command: 'npx', args: ['-y', '@wowok/agent-mcp'] };
|
|
288
|
-
return config;
|
|
289
|
-
},
|
|
290
|
-
},
|
|
291
|
-
windsurf: {
|
|
292
|
-
configPath: path.join(os.homedir(), '.codeium', 'windsurf', 'mcp_config.json'),
|
|
293
|
-
merge: (config) => {
|
|
294
|
-
config.mcpServers = config.mcpServers || {};
|
|
295
|
-
config.mcpServers.wowok = { command: 'npx', args: ['-y', '@wowok/agent-mcp'] };
|
|
296
|
-
return config;
|
|
297
|
-
},
|
|
298
|
-
},
|
|
299
|
-
qoder: {
|
|
300
|
-
configPath: (() => {
|
|
301
|
-
if (process.platform === 'win32') {
|
|
302
|
-
return path.join(process.env.APPDATA || path.join(os.homedir(), 'AppData', 'Roaming'), 'Qoder', 'mcp-settings.json');
|
|
303
|
-
}
|
|
304
|
-
if (process.platform === 'darwin') {
|
|
305
|
-
return path.join(os.homedir(), 'Library', 'Application Support', 'Qoder', 'mcp-settings.json');
|
|
306
|
-
}
|
|
307
|
-
return path.join(process.env.XDG_CONFIG_HOME || path.join(os.homedir(), '.config'), 'qoder', 'mcp-settings.json');
|
|
308
|
-
})(),
|
|
309
|
-
merge: (config) => {
|
|
310
|
-
config.mcpServers = config.mcpServers || {};
|
|
311
|
-
config.mcpServers.wowok = { command: 'npx', args: ['-y', '@wowok/agent-mcp'] };
|
|
312
|
-
return config;
|
|
313
|
-
},
|
|
314
|
-
},
|
|
315
|
-
roo: {
|
|
316
|
-
resolveConfigPaths: () => resolveRooMcpFiles(),
|
|
317
|
-
merge: (config) => {
|
|
318
|
-
config.mcpServers = config.mcpServers || {};
|
|
319
|
-
config.mcpServers.wowok = { command: 'npx', args: ['-y', '@wowok/agent-mcp'] };
|
|
320
|
-
return config;
|
|
321
|
-
},
|
|
322
|
-
},
|
|
323
|
-
cline: {
|
|
324
|
-
resolveConfigPaths: () => resolveClineMcpFiles(),
|
|
325
|
-
merge: (config) => {
|
|
326
|
-
config.mcpServers = config.mcpServers || {};
|
|
327
|
-
config.mcpServers.wowok = { command: 'npx', args: ['-y', '@wowok/agent-mcp'] };
|
|
328
|
-
return config;
|
|
329
|
-
},
|
|
330
|
-
},
|
|
331
|
-
kilo: {
|
|
332
|
-
resolveConfigPaths: () => resolveKiloMcpFiles(),
|
|
333
|
-
merge: (config) => {
|
|
334
|
-
config.mcpServers = config.mcpServers || {};
|
|
335
|
-
config.mcpServers.wowok = { command: 'npx', args: ['-y', '@wowok/agent-mcp'] };
|
|
336
|
-
return config;
|
|
337
|
-
},
|
|
338
|
-
},
|
|
339
|
-
// trae / agents: IDE-managed MCP via ~/.trae-cn/mcps/ directory structure
|
|
340
|
-
trae: null,
|
|
341
|
-
agents: null,
|
|
342
|
-
// cursor: project-level only
|
|
343
|
-
cursor: null,
|
|
344
|
-
// copilot: user-level MCP config (Copilot CLI)
|
|
345
|
-
copilot: {
|
|
346
|
-
configPath: path.join(os.homedir(), '.copilot', 'mcp-config.json'),
|
|
347
|
-
merge: (config) => {
|
|
348
|
-
config.mcpServers = config.mcpServers || {};
|
|
349
|
-
config.mcpServers.wowok = { type: 'local', command: 'npx', args: ['-y', '@wowok/agent-mcp'] };
|
|
350
|
-
return config;
|
|
351
|
-
},
|
|
352
|
-
},
|
|
353
|
-
// codex: global TOML config (~/.codex/config.toml)
|
|
354
|
-
codex: {
|
|
355
|
-
configPath: path.join(os.homedir(), '.codex', 'config.toml'),
|
|
356
|
-
format: 'toml',
|
|
357
|
-
},
|
|
358
|
-
};
|
|
359
|
-
/** Project-level MCP configs (written relative to cwd). */
|
|
360
|
-
const MCP_PROJECT_CONFIGS = {
|
|
361
|
-
cursor: {
|
|
362
|
-
configPath: '.cursor/mcp.json',
|
|
363
|
-
merge: (config) => {
|
|
364
|
-
config.mcpServers = config.mcpServers || {};
|
|
365
|
-
config.mcpServers.wowok = { command: 'npx', args: ['-y', '@wowok/agent-mcp'] };
|
|
366
|
-
return config;
|
|
367
|
-
},
|
|
368
|
-
},
|
|
369
|
-
windsurf: {
|
|
370
|
-
configPath: '.windsurf/mcp.json',
|
|
371
|
-
merge: (config) => {
|
|
372
|
-
config.mcpServers = config.mcpServers || {};
|
|
373
|
-
config.mcpServers.wowok = { command: 'npx', args: ['-y', '@wowok/agent-mcp'] };
|
|
374
|
-
return config;
|
|
375
|
-
},
|
|
376
|
-
},
|
|
377
|
-
trae: {
|
|
378
|
-
configPath: '.trae/mcp.json',
|
|
379
|
-
merge: (config) => {
|
|
380
|
-
config.mcpServers = config.mcpServers || {};
|
|
381
|
-
config.mcpServers.wowok = { command: 'npx', args: ['-y', '@wowok/agent-mcp'] };
|
|
382
|
-
return config;
|
|
383
|
-
},
|
|
384
|
-
},
|
|
385
|
-
agents: {
|
|
386
|
-
configPath: '.trae/mcp.json',
|
|
387
|
-
merge: (config) => {
|
|
388
|
-
config.mcpServers = config.mcpServers || {};
|
|
389
|
-
config.mcpServers.wowok = { command: 'npx', args: ['-y', '@wowok/agent-mcp'] };
|
|
390
|
-
return config;
|
|
391
|
-
},
|
|
392
|
-
},
|
|
393
|
-
qoder: {
|
|
394
|
-
configPath: '.qoder/mcp.json',
|
|
395
|
-
merge: (config) => {
|
|
396
|
-
config.mcpServers = config.mcpServers || {};
|
|
397
|
-
config.mcpServers.wowok = { command: 'npx', args: ['-y', '@wowok/agent-mcp'] };
|
|
398
|
-
return config;
|
|
399
|
-
},
|
|
400
|
-
},
|
|
401
|
-
roo: {
|
|
402
|
-
configPath: '.roo/mcp.json',
|
|
403
|
-
merge: (config) => {
|
|
404
|
-
config.mcpServers = config.mcpServers || {};
|
|
405
|
-
config.mcpServers.wowok = { command: 'npx', args: ['-y', '@wowok/agent-mcp'] };
|
|
406
|
-
return config;
|
|
407
|
-
},
|
|
408
|
-
},
|
|
409
|
-
kilo: {
|
|
410
|
-
configPath: '.kilocode/mcp.json',
|
|
411
|
-
merge: (config) => {
|
|
412
|
-
config.mcpServers = config.mcpServers || {};
|
|
413
|
-
config.mcpServers.wowok = { command: 'npx', args: ['-y', '@wowok/agent-mcp'] };
|
|
414
|
-
return config;
|
|
415
|
-
},
|
|
416
|
-
},
|
|
417
|
-
};
|
|
418
|
-
function getInstalledMcpVersion() {
|
|
419
|
-
try {
|
|
420
|
-
const output = (0, child_process_1.execSync)(`npm ls -g ${MCP_PACKAGE} --depth=0 --json`, {
|
|
421
|
-
encoding: 'utf-8',
|
|
422
|
-
stdio: 'pipe',
|
|
423
|
-
timeout: 15000,
|
|
424
|
-
});
|
|
425
|
-
const parsed = JSON.parse(output);
|
|
426
|
-
const pkg = parsed.dependencies?.[MCP_PACKAGE] || parsed[MCP_PACKAGE];
|
|
427
|
-
return pkg?.version || null;
|
|
51
|
+
function cmdRole(role) {
|
|
52
|
+
const roles = ['customer', 'provider', 'supplier', 'collaborator', 'arbitrator', 'shared'];
|
|
53
|
+
if (!roles.includes(role)) {
|
|
54
|
+
console.error(`Invalid role: ${role}`);
|
|
55
|
+
console.error(`Valid roles: ${roles.join(' | ')}`);
|
|
56
|
+
process.exit(1);
|
|
428
57
|
}
|
|
429
|
-
|
|
430
|
-
|
|
58
|
+
console.log(`${ROLE_DISPLAY[role]} Skills:\n`);
|
|
59
|
+
for (const skill of (0, skills_1.getSkillsByRole)(role)) {
|
|
60
|
+
const loading = skill.loading === 'always' ? '[always]' : '[on-demand]';
|
|
61
|
+
console.log(` • ${skill.name} ${loading}`);
|
|
62
|
+
console.log(` ${skill.description}`);
|
|
431
63
|
}
|
|
432
64
|
}
|
|
433
|
-
function
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
timeout: 15000,
|
|
441
|
-
});
|
|
442
|
-
return output.trim();
|
|
65
|
+
function cmdRecommend(intent) {
|
|
66
|
+
var _a;
|
|
67
|
+
const recommended = (0, skills_1.recommendSkills)(intent);
|
|
68
|
+
console.log(`Recommended skills for: "${intent}"\n`);
|
|
69
|
+
if (recommended.length === 0) {
|
|
70
|
+
console.log(' (no skill matches — this knowledge is served by the MCP server directly)');
|
|
71
|
+
return;
|
|
443
72
|
}
|
|
444
|
-
|
|
445
|
-
|
|
73
|
+
const byRole = {};
|
|
74
|
+
for (const skill of recommended)
|
|
75
|
+
(byRole[_a = skill.role] || (byRole[_a] = [])).push(skill.name);
|
|
76
|
+
for (const [role, names] of Object.entries(byRole)) {
|
|
77
|
+
console.log(`${ROLE_DISPLAY[role]}:`);
|
|
78
|
+
for (const name of names)
|
|
79
|
+
console.log(` • ${name}`);
|
|
80
|
+
console.log('');
|
|
446
81
|
}
|
|
447
82
|
}
|
|
448
|
-
function
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
try {
|
|
457
|
-
(0, child_process_1.execSync)(`npm install -g ${pkg}`, { stdio: 'inherit', timeout: 120000 });
|
|
458
|
-
return true;
|
|
459
|
-
}
|
|
460
|
-
catch (err) {
|
|
461
|
-
if (attempt < retries) {
|
|
462
|
-
console.log(`[wowok-skills] npm install attempt ${attempt} failed, retrying...`);
|
|
463
|
-
const waitCmd = process.platform === 'win32'
|
|
464
|
-
? 'ping -n 3 127.0.0.1 >nul'
|
|
465
|
-
: 'sleep 2';
|
|
466
|
-
(0, child_process_1.execSync)(waitCmd, { stdio: 'pipe', timeout: 5000 });
|
|
467
|
-
}
|
|
468
|
-
else {
|
|
469
|
-
console.error(`[wowok-skills] npm install failed after ${retries} attempts: ${err.message}`);
|
|
470
|
-
return false;
|
|
471
|
-
}
|
|
83
|
+
function parseInitArgs(args) {
|
|
84
|
+
const parsed = { noMcp: false, force: false, user: false, project: false };
|
|
85
|
+
for (let i = 0; i < args.length; i++) {
|
|
86
|
+
const arg = args[i];
|
|
87
|
+
if (arg === '--target' || arg === '-t') {
|
|
88
|
+
const value = args[++i];
|
|
89
|
+
if (value)
|
|
90
|
+
parsed.targets = value.split(',').map((t) => t.trim()).filter(Boolean);
|
|
472
91
|
}
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
}
|
|
476
|
-
function ensureMcpServer() {
|
|
477
|
-
const currentVersion = getInstalledMcpVersion();
|
|
478
|
-
const latestVersion = getLatestMcpVersion();
|
|
479
|
-
if (currentVersion) {
|
|
480
|
-
console.log(`[wowok-skills] MCP server ${MCP_PACKAGE} v${currentVersion} found.`);
|
|
481
|
-
if (!latestVersion) {
|
|
482
|
-
console.log(`[wowok-skills] Cannot check latest version (offline or registry unreachable). Keeping v${currentVersion}.`);
|
|
483
|
-
return false;
|
|
92
|
+
else if (arg === '--no-mcp') {
|
|
93
|
+
parsed.noMcp = true;
|
|
484
94
|
}
|
|
485
|
-
if (
|
|
486
|
-
|
|
487
|
-
return false;
|
|
95
|
+
else if (arg === '--force') {
|
|
96
|
+
parsed.force = true;
|
|
488
97
|
}
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
if (latestMajor > currentMajor) {
|
|
492
|
-
console.warn(`[wowok-skills] ⚠ WARNING: Major version bump detected v${currentVersion} → v${latestVersion}.`);
|
|
493
|
-
console.warn(`[wowok-skills] Skipping auto-upgrade to avoid breaking changes.`);
|
|
494
|
-
console.warn(`[wowok-skills] To upgrade manually: npm install -g ${MCP_PACKAGE}@latest`);
|
|
495
|
-
return false;
|
|
98
|
+
else if (arg === '--user') {
|
|
99
|
+
parsed.user = true;
|
|
496
100
|
}
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
console.log(`[wowok-skills] MCP server upgraded to v${latestVersion}.`);
|
|
500
|
-
return true;
|
|
101
|
+
else if (arg === '--project') {
|
|
102
|
+
parsed.project = true;
|
|
501
103
|
}
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
}
|
|
505
|
-
console.log(`[wowok-skills] Installing MCP server ${MCP_PACKAGE}...`);
|
|
506
|
-
if (npmInstallGlobal(MCP_PACKAGE)) {
|
|
507
|
-
console.log(`[wowok-skills] MCP server installed.`);
|
|
508
|
-
return true;
|
|
509
|
-
}
|
|
510
|
-
console.error(`[wowok-skills] MCP server installation FAILED.`);
|
|
511
|
-
return false;
|
|
512
|
-
}
|
|
513
|
-
function writeMcpConfig(target, configMap, cwd) {
|
|
514
|
-
const cfg = configMap[target];
|
|
515
|
-
if (!cfg) {
|
|
516
|
-
console.log(`[wowok-skills] MCP config: ${target} does not support external MCP registration (skipped).`);
|
|
517
|
-
return false;
|
|
518
|
-
}
|
|
519
|
-
// Expand to an array of concrete paths. Project-level configs always use
|
|
520
|
-
// `configPath` (single file); global configs for CodeBuddy / Roo / Cline /
|
|
521
|
-
// Kilo use `resolveConfigPaths()` to yield one or more paths.
|
|
522
|
-
const rawPaths = cfg.resolveConfigPaths
|
|
523
|
-
? cfg.resolveConfigPaths(cwd)
|
|
524
|
-
: [cfg.configPath];
|
|
525
|
-
const configPaths = cwd && !cfg.resolveConfigPaths
|
|
526
|
-
? rawPaths.map((p) => path.join(cwd, p))
|
|
527
|
-
: rawPaths;
|
|
528
|
-
if (configPaths.length === 0) {
|
|
529
|
-
console.log(`[wowok-skills] MCP config: no config file detected for ${target} (client not installed) — skipped.`);
|
|
530
|
-
return false;
|
|
531
|
-
}
|
|
532
|
-
let anyWritten = false;
|
|
533
|
-
for (const configPath of configPaths) {
|
|
534
|
-
try {
|
|
535
|
-
// ── TOML format (Codex CLI uses ~/.codex/config.toml) ──────────────
|
|
536
|
-
if (cfg.format === 'toml') {
|
|
537
|
-
const tomlEntry = '\n[mcp_servers.wowok]\ncommand = "npx"\nargs = ["-y", "@wowok/agent-mcp"]\n';
|
|
538
|
-
let content = '';
|
|
539
|
-
if (fs.existsSync(configPath)) {
|
|
540
|
-
content = fs.readFileSync(configPath, 'utf-8');
|
|
541
|
-
}
|
|
542
|
-
// Line-level regex: avoid matches inside comments or string literals.
|
|
543
|
-
if (/^\s*\[mcp_servers\.wowok\]\s*$/m.test(content)) {
|
|
544
|
-
console.log(`[wowok-skills] MCP config already up to date: ${configPath}`);
|
|
545
|
-
continue;
|
|
546
|
-
}
|
|
547
|
-
fs.mkdirSync(path.dirname(configPath), { recursive: true });
|
|
548
|
-
fs.writeFileSync(configPath, content + tomlEntry, 'utf-8');
|
|
549
|
-
console.log(`[wowok-skills] MCP config written: ${configPath}`);
|
|
550
|
-
anyWritten = true;
|
|
551
|
-
continue;
|
|
552
|
-
}
|
|
553
|
-
// ── JSON format (all other clients) ────────────────────────────────
|
|
554
|
-
let config = {};
|
|
555
|
-
if (fs.existsSync(configPath)) {
|
|
556
|
-
config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
557
|
-
}
|
|
558
|
-
const before = JSON.stringify(config);
|
|
559
|
-
config = cfg.merge(config);
|
|
560
|
-
const after = JSON.stringify(config);
|
|
561
|
-
if (before !== after) {
|
|
562
|
-
fs.mkdirSync(path.dirname(configPath), { recursive: true });
|
|
563
|
-
fs.writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8');
|
|
564
|
-
console.log(`[wowok-skills] MCP config written: ${configPath}`);
|
|
565
|
-
anyWritten = true;
|
|
566
|
-
}
|
|
567
|
-
else {
|
|
568
|
-
console.log(`[wowok-skills] MCP config already up to date: ${configPath}`);
|
|
569
|
-
}
|
|
104
|
+
else if (arg === '--referrer') {
|
|
105
|
+
parsed.referrer = args[++i]?.trim() || undefined;
|
|
570
106
|
}
|
|
571
|
-
|
|
572
|
-
|
|
107
|
+
else if (!arg.startsWith('-') && targets_1.DEFAULT_TARGET_IDS.includes(arg)) {
|
|
108
|
+
parsed.targets = [arg];
|
|
573
109
|
}
|
|
574
110
|
}
|
|
575
|
-
return
|
|
111
|
+
return parsed;
|
|
576
112
|
}
|
|
577
|
-
function
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
const encoded = Buffer.from(psScript, 'utf16le').toString('base64');
|
|
583
|
-
(0, child_process_1.execSync)(`powershell -NoProfile -EncodedCommand ${encoded}`, { stdio: 'pipe', timeout: 10000 });
|
|
584
|
-
}
|
|
585
|
-
else {
|
|
586
|
-
(0, child_process_1.execSync)('pkill -f "wowok.*agent-mcp" 2>/dev/null || true', { stdio: 'pipe', timeout: 5000 });
|
|
587
|
-
}
|
|
588
|
-
console.log('[wowok-skills] MCP server process terminated (IDE will auto-restart).');
|
|
589
|
-
}
|
|
590
|
-
catch {
|
|
591
|
-
console.log('[wowok-skills] No running MCP server process found. Start your IDE to launch it.');
|
|
113
|
+
function printTargets() {
|
|
114
|
+
console.log('Targets (--target <t> — repeatable, comma-separated; omit for all):');
|
|
115
|
+
for (const target of targets_1.CLIENT_TARGETS) {
|
|
116
|
+
const roots = target.projectSkillDirs.join(', ');
|
|
117
|
+
console.log(` ${target.id.padEnd(10)} project: ${roots.padEnd(20)} ${target.label}`);
|
|
592
118
|
}
|
|
119
|
+
console.log(` ${'all'.padEnd(10)} every target above (default)`);
|
|
593
120
|
}
|
|
594
|
-
function
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
121
|
+
function cmdInit(parsed) {
|
|
122
|
+
const { targets, unknown } = (0, installer_1.resolveTargets)(parsed.targets);
|
|
123
|
+
if (unknown.length > 0) {
|
|
124
|
+
console.error(`Unknown target(s): ${unknown.join(', ')}`);
|
|
125
|
+
console.error('');
|
|
126
|
+
printTargets();
|
|
127
|
+
process.exit(1);
|
|
600
128
|
}
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
console.error(' cursor .cursor/rules/ (Cursor IDE)');
|
|
606
|
-
console.error(' windsurf .windsurf/skills/ (Windsurf / Codeium)');
|
|
607
|
-
console.error(' codebuddy .codebuddy/skills/ (CodeBuddy)');
|
|
608
|
-
console.error(' codex .codex/skills/ (OpenAI Codex / ChatGPT Desktop Codex Mode)');
|
|
609
|
-
console.error(' trae .agents/skills/ (Trae CN & Trae Work)');
|
|
610
|
-
console.error(' qoder .qoder/skills/ (Qoder / Qoder CN)');
|
|
611
|
-
console.error(' roo .roo/skills/ (Roo Code)');
|
|
612
|
-
console.error(' cline .cline/skills/ (Cline - VS Code)');
|
|
613
|
-
console.error(' kilo .kilo/skills/ (Kilo Code)');
|
|
614
|
-
console.error(' copilot .github/prompts/ (GitHub Copilot)');
|
|
615
|
-
console.error(' all All of the above (default)');
|
|
616
|
-
process.exit(1);
|
|
617
|
-
}
|
|
618
|
-
function cmdInit(targetArg, withMcp, referrer) {
|
|
129
|
+
const scopes = parsed.user || parsed.project
|
|
130
|
+
? [...(parsed.user ? ['user'] : []), ...(parsed.project ? ['project'] : [])]
|
|
131
|
+
: ['user', 'project'];
|
|
132
|
+
// Project scope always targets the current working directory.
|
|
619
133
|
const cwd = process.cwd();
|
|
620
|
-
|
|
621
|
-
const
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
const
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
fs.mkdirSync(targetDir, { recursive: true });
|
|
629
|
-
for (const dir of SKILL_DIRS) {
|
|
630
|
-
const src = path.join(pkgRoot, dir, 'SKILL.md');
|
|
631
|
-
if (!fs.existsSync(src)) {
|
|
632
|
-
console.warn(`[wowok-skills] WARN: SKILL.md not found for ${dir}`);
|
|
633
|
-
continue;
|
|
634
|
-
}
|
|
635
|
-
const content = fs.readFileSync(src, 'utf-8');
|
|
636
|
-
const converted = convertSkillContent(content, target, dir);
|
|
637
|
-
const basename = target === 'cursor' || target === 'copilot'
|
|
638
|
-
? `wowok-${dir.replace('wowok-', '')}${ext}`
|
|
639
|
-
: 'SKILL.md';
|
|
640
|
-
const destDir = path.join(targetDir, dir);
|
|
641
|
-
const dest = path.join(destDir, basename);
|
|
642
|
-
fs.mkdirSync(destDir, { recursive: true });
|
|
643
|
-
fs.writeFileSync(dest, converted, 'utf-8');
|
|
644
|
-
count++;
|
|
645
|
-
console.log(`[wowok-skills] installed: ${dest}`);
|
|
646
|
-
}
|
|
647
|
-
totalCount += count;
|
|
648
|
-
console.log(`[wowok-skills] Done — ${count} skills installed to ${targetDir}`);
|
|
649
|
-
// GLM5-31 §3.2: detect stale pre-refactor skills and print migration hint.
|
|
650
|
-
const legacyFound = LEGACY_SKILL_DIRS.filter((dir) => fs.existsSync(path.join(targetDir, dir)));
|
|
651
|
-
if (legacyFound.length > 0) {
|
|
652
|
-
const migration = (0, skills_1.checkSkillMigration)(legacyFound);
|
|
653
|
-
console.warn(`\n[wowok-skills] ⚠ ${migration.message}`);
|
|
654
|
-
console.warn('[wowok-skills] Remove them with: wowok-skills uninit\n');
|
|
655
|
-
}
|
|
656
|
-
}
|
|
657
|
-
if (targets.length > 1) {
|
|
658
|
-
console.log(`[wowok-skills] Total: ${totalCount} skills across ${targets.length} clients.`);
|
|
659
|
-
}
|
|
660
|
-
// ─── MCP setup (default: enabled, use --no-mcp to skip) ────────────
|
|
661
|
-
if (withMcp) {
|
|
134
|
+
console.log(`[wowok-skills] Installing skills (${scopes.join(' + ')}) for ${targets.length} target(s)...`);
|
|
135
|
+
const results = (0, installer_1.installSkillsForTargets)(targets, scopes, cwd, { force: parsed.force });
|
|
136
|
+
for (const r of results) {
|
|
137
|
+
console.log(` → ${r.root}\n ${r.written} written · ${r.unchanged} up to date · ${r.pruned} pruned · ${r.legacyRemoved} deprecated removed`);
|
|
138
|
+
for (const err of r.errors)
|
|
139
|
+
console.error(` ERROR: ${err}`);
|
|
140
|
+
}
|
|
141
|
+
if (!parsed.noMcp) {
|
|
662
142
|
console.log('');
|
|
663
|
-
console.log('[wowok-skills]
|
|
664
|
-
const
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
}
|
|
676
|
-
|
|
143
|
+
console.log('[wowok-skills] Checking MCP server...');
|
|
144
|
+
const changed = (0, installer_1.ensureMcpServer)();
|
|
145
|
+
const launch = (0, installer_1.resolveMcpLaunch)();
|
|
146
|
+
console.log(`[wowok-skills] launcher: ${launch.command} ${launch.args.join(' ')}`);
|
|
147
|
+
const mcpScopes = parsed.project
|
|
148
|
+
? ['project']
|
|
149
|
+
: parsed.user
|
|
150
|
+
? ['user']
|
|
151
|
+
: ['user', 'project'];
|
|
152
|
+
console.log('[wowok-skills] Registering MCP server...');
|
|
153
|
+
for (const r of (0, installer_1.registerMcpForTargets)(targets, mcpScopes, cwd)) {
|
|
154
|
+
console.log(` ${r.status.padEnd(9)} ${r.path}${r.detail ? ` (${r.detail})` : ''}`);
|
|
155
|
+
}
|
|
156
|
+
if (changed)
|
|
157
|
+
(0, installer_1.restartMcpServer)();
|
|
677
158
|
}
|
|
678
159
|
else {
|
|
679
|
-
console.log('');
|
|
680
|
-
console.log('[wowok-skills] --no-mcp: MCP server setup skipped (skills only).');
|
|
681
|
-
}
|
|
682
|
-
// ─── Airdrop referrer (--referrer <addr|name>) ─────────────────────
|
|
683
|
-
// Persist it in the MCP data dir; the MCP auto-injects it into every call,
|
|
684
|
-
// so it is recorded on-chain at the user's first real on-chain interaction.
|
|
685
|
-
// No manual "tell your AI" step needed.
|
|
686
|
-
if (referrer) {
|
|
687
|
-
saveReferrer(referrer);
|
|
160
|
+
console.log('[wowok-skills] --no-mcp: MCP setup skipped.');
|
|
688
161
|
}
|
|
689
|
-
|
|
690
|
-
function cmdUninit(targetArg) {
|
|
691
|
-
const cwd = process.cwd();
|
|
692
|
-
const targets = getTargets(targetArg);
|
|
693
|
-
let totalCount = 0;
|
|
694
|
-
for (const target of targets) {
|
|
695
|
-
const skillsDir = types_1.CLIENT_SKILL_DIRS[target];
|
|
696
|
-
const targetDir = path.join(cwd, skillsDir);
|
|
697
|
-
let count = 0;
|
|
698
|
-
// Remove both retained and legacy (deprecated) skills — legacy dirs may
|
|
699
|
-
// still exist from pre-refactor installs and must be cleaned up.
|
|
700
|
-
for (const dir of [...SKILL_DIRS, ...LEGACY_SKILL_DIRS]) {
|
|
701
|
-
const dirPath = path.join(targetDir, dir);
|
|
702
|
-
if (fs.existsSync(dirPath)) {
|
|
703
|
-
removeDir(dirPath);
|
|
704
|
-
count++;
|
|
705
|
-
console.log(`[wowok-skills] removed: ${dirPath}`);
|
|
706
|
-
}
|
|
707
|
-
}
|
|
708
|
-
totalCount += count;
|
|
709
|
-
if (count === 0) {
|
|
710
|
-
console.log(`[wowok-skills] No skills found in ${targetDir}. Nothing to remove.`);
|
|
711
|
-
}
|
|
712
|
-
else {
|
|
713
|
-
console.log(`[wowok-skills] Done — ${count} skills removed from ${targetDir}`);
|
|
714
|
-
}
|
|
715
|
-
}
|
|
716
|
-
if (targets.length > 1 && totalCount > 0) {
|
|
717
|
-
console.log(`[wowok-skills] Total: ${totalCount} skills across ${targets.length} clients.`);
|
|
718
|
-
}
|
|
719
|
-
}
|
|
720
|
-
function cmdList() {
|
|
721
|
-
console.log('Available WoWok Skills (organized by role):\n');
|
|
722
|
-
const roleSkills = (0, skills_1.getRoleSkills)();
|
|
723
|
-
for (const roleGroup of roleSkills) {
|
|
724
|
-
console.log(`${ROLE_DISPLAY[roleGroup.role]}`);
|
|
725
|
-
console.log(` ${roleGroup.description}`);
|
|
726
|
-
for (const skill of roleGroup.skills) {
|
|
727
|
-
const loading = skill.loading === 'always' ? '[always]' : '[on-demand]';
|
|
728
|
-
console.log(` • ${skill.name} ${loading}`);
|
|
729
|
-
console.log(` ${skill.description}`);
|
|
730
|
-
}
|
|
162
|
+
if (parsed.referrer) {
|
|
731
163
|
console.log('');
|
|
164
|
+
(0, installer_1.saveReferrer)(parsed.referrer);
|
|
732
165
|
}
|
|
166
|
+
console.log('');
|
|
167
|
+
console.log('[wowok-skills] Done. Verify with: wowok-skills doctor');
|
|
733
168
|
}
|
|
734
|
-
function
|
|
735
|
-
const
|
|
736
|
-
if (
|
|
737
|
-
console.
|
|
738
|
-
console.log(`Role: ${ROLE_DISPLAY[skill.role]}`);
|
|
739
|
-
console.log(`Loading: ${skill.loading}`);
|
|
740
|
-
console.log(`Version: ${skill.version}`);
|
|
741
|
-
console.log(`Description: ${skill.description}`);
|
|
742
|
-
if (skill.related && skill.related.length > 0) {
|
|
743
|
-
console.log(`Related: ${skill.related.join(', ')}`);
|
|
744
|
-
}
|
|
745
|
-
}
|
|
746
|
-
else {
|
|
747
|
-
console.error(`Skill not found: ${name}`);
|
|
169
|
+
function cmdUninit(parsed) {
|
|
170
|
+
const { targets, unknown } = (0, installer_1.resolveTargets)(parsed.targets);
|
|
171
|
+
if (unknown.length > 0) {
|
|
172
|
+
console.error(`Unknown target(s): ${unknown.join(', ')}`);
|
|
748
173
|
process.exit(1);
|
|
749
174
|
}
|
|
175
|
+
const scopes = parsed.user || parsed.project
|
|
176
|
+
? [...(parsed.user ? ['user'] : []), ...(parsed.project ? ['project'] : [])]
|
|
177
|
+
: ['user', 'project'];
|
|
178
|
+
const removed = (0, installer_1.uninstallSkillsForTargets)(targets, scopes, process.cwd());
|
|
179
|
+
console.log(`[wowok-skills] Removed ${removed} skill director${removed === 1 ? 'y' : 'ies'}.`);
|
|
180
|
+
console.log('[wowok-skills] MCP config entries are left in place — delete the "wowok" entry manually if unwanted.');
|
|
750
181
|
}
|
|
751
|
-
function
|
|
752
|
-
const
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
182
|
+
function cmdDoctor() {
|
|
183
|
+
const cwd = process.cwd();
|
|
184
|
+
const { targets } = (0, installer_1.resolveTargets)(undefined);
|
|
185
|
+
console.log(`WoWok Skills doctor · CLI v${(0, installer_1.packageVersion)()}`);
|
|
186
|
+
console.log(`Dirs: home=${(0, targets_1.expandHome)('~')} cwd=${cwd}\n`);
|
|
187
|
+
const launch = (0, installer_1.resolveMcpLaunch)();
|
|
188
|
+
console.log(`MCP launcher: ${launch.command} ${launch.args.join(' ')}`);
|
|
189
|
+
console.log(launch.command === 'node'
|
|
190
|
+
? ' ✔ version-pinned to the verified global install, Windows-safe\n'
|
|
191
|
+
: ' ⚠ falling back to npx (global install not found) — run: npm install -g @wowok/agent-mcp\n');
|
|
192
|
+
const statuses = (0, installer_1.statusForTargets)(targets, cwd);
|
|
193
|
+
for (const status of statuses) {
|
|
194
|
+
console.log(`${status.label} [${status.id}]`);
|
|
195
|
+
const sections = [
|
|
196
|
+
['user ', status.userRoots],
|
|
197
|
+
['project', status.projectRoots],
|
|
198
|
+
];
|
|
199
|
+
for (const [label, roots] of sections) {
|
|
200
|
+
for (const root of roots) {
|
|
201
|
+
if (!root.present) {
|
|
202
|
+
// Project roots only matter inside a project — report quietly.
|
|
203
|
+
console.log(` ${label} ✗ not installed ${root.root}`);
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
const total = root.fresh + root.stale + root.missing;
|
|
207
|
+
const marker = total === 13 && root.stale === 0 && root.missing === 0 ? '✔' : '⚠';
|
|
208
|
+
console.log(` ${label} ${marker} ${root.fresh} current / ${root.stale} stale / ${root.missing} missing` +
|
|
209
|
+
`${root.legacy > 0 ? ` / ${root.legacy} deprecated` : ''}` +
|
|
210
|
+
` ${root.root}${root.manifestVersion ? ` (installed by v${root.manifestVersion})` : ''}`);
|
|
211
|
+
}
|
|
765
212
|
}
|
|
213
|
+
for (const mcp of status.mcp) {
|
|
214
|
+
if (!mcp.present) {
|
|
215
|
+
console.log(` mcp ○ no config file ${mcp.path}`);
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
console.log(` mcp ${mcp.registered ? '✔' : '✗'} ${mcp.path}${mcp.detail ? `\n ↳ ${mcp.detail}` : ''}`);
|
|
219
|
+
}
|
|
220
|
+
for (const note of status.notes)
|
|
221
|
+
console.log(` note ↳ ${note}`);
|
|
766
222
|
console.log('');
|
|
767
223
|
}
|
|
224
|
+
const problems = statuses.filter((s) => [...s.userRoots, ...s.projectRoots].some((r) => r.present && (r.stale > 0 || r.missing > 0 || r.legacy > 0)));
|
|
225
|
+
console.log('-----------------------------------------------------------');
|
|
226
|
+
console.log(`Manifest file written per root: ${targets_1.MANIFEST_FILE}`);
|
|
227
|
+
console.log(problems.length === 0
|
|
228
|
+
? '✅ No stale installs detected.'
|
|
229
|
+
: `⚠ ${problems.length} root(s) need a refresh — run: wowok-skills init --force`);
|
|
230
|
+
console.log('Tip: `wowok-skills init` inside a project adds project-scoped copies (team sharing via git).');
|
|
768
231
|
}
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
console.error('Valid roles: customer, provider, supplier, collaborator, arbitrator, shared');
|
|
773
|
-
process.exit(1);
|
|
774
|
-
}
|
|
775
|
-
const skills = (0, skills_1.getSkillsByRole)(role);
|
|
776
|
-
console.log(`${ROLE_DISPLAY[role]} Skills:\n`);
|
|
777
|
-
for (const skill of skills) {
|
|
778
|
-
const loading = skill.loading === 'always' ? '[always]' : '[on-demand]';
|
|
779
|
-
console.log(` • ${skill.name} ${loading}`);
|
|
780
|
-
console.log(` ${skill.description}`);
|
|
781
|
-
}
|
|
782
|
-
}
|
|
232
|
+
// =========================================================================
|
|
233
|
+
// Help
|
|
234
|
+
// =========================================================================
|
|
783
235
|
function printUsage() {
|
|
784
236
|
console.log('WoWok Skills CLI');
|
|
785
|
-
console.log('Usage: wowok-skills <command> [
|
|
786
|
-
console.log('');
|
|
237
|
+
console.log('Usage: wowok-skills <command> [options]\n');
|
|
787
238
|
console.log('Commands:');
|
|
788
|
-
console.log(' list
|
|
789
|
-
console.log(' get <name>
|
|
790
|
-
console.log(' role <role>
|
|
791
|
-
console.log(' recommend <intent>
|
|
792
|
-
console.log(' init [
|
|
793
|
-
console.log('
|
|
794
|
-
console.log('
|
|
795
|
-
console.log(' referrer <addr|name>
|
|
796
|
-
console.log('
|
|
797
|
-
console.log('');
|
|
798
|
-
console.log('
|
|
799
|
-
console.log('
|
|
800
|
-
console.log('
|
|
801
|
-
console.log('
|
|
802
|
-
|
|
803
|
-
console.log('
|
|
804
|
-
console.log('
|
|
805
|
-
console.log('
|
|
806
|
-
console.log('
|
|
807
|
-
console.log('
|
|
808
|
-
console.log(' kilo .kilo/skills/ (Kilo Code)');
|
|
809
|
-
console.log(' copilot .github/prompts/ (GitHub Copilot)');
|
|
810
|
-
console.log(' all All of the above (default)');
|
|
811
|
-
console.log('');
|
|
812
|
-
console.log('Examples:');
|
|
813
|
-
console.log(' wowok-skills list');
|
|
814
|
-
console.log(' wowok-skills get wowok-provider');
|
|
815
|
-
console.log(' wowok-skills role provider');
|
|
816
|
-
console.log(' wowok-skills recommend "create a service"');
|
|
817
|
-
console.log(' wowok-skills init # All clients (default)');
|
|
818
|
-
console.log(' wowok-skills init --target claude # One client only');
|
|
819
|
-
console.log(' wowok-skills init --no-mcp');
|
|
820
|
-
console.log(' wowok-skills uninit # All clients (default)');
|
|
239
|
+
console.log(' list List all skills (by role)');
|
|
240
|
+
console.log(' get <name> Show skill details');
|
|
241
|
+
console.log(' role <role> List skills for a role');
|
|
242
|
+
console.log(' recommend <intent> Recommend skills from a user intent');
|
|
243
|
+
console.log(' init [options] Install skills + register MCP (default: user + project, all targets)');
|
|
244
|
+
console.log(' uninit [options] Remove installed skills (MCP entries are left alone)');
|
|
245
|
+
console.log(' doctor Show per-client install + MCP registration state');
|
|
246
|
+
console.log(' referrer <addr|name> Save the airdrop referrer globally\n');
|
|
247
|
+
console.log('Options:');
|
|
248
|
+
console.log(' --target <t> Target(s), comma separated (default: all)');
|
|
249
|
+
console.log(' --user / --project Restrict the scope (default: both for init)');
|
|
250
|
+
console.log(' --force Rewrite every file even when unchanged');
|
|
251
|
+
console.log(' --no-mcp Skip MCP server install/registration');
|
|
252
|
+
console.log(' --referrer <addr|name> Save the airdrop referrer during init\n');
|
|
253
|
+
printTargets();
|
|
254
|
+
console.log('\nExamples:');
|
|
255
|
+
console.log(' wowok-skills init # all targets, user + project');
|
|
256
|
+
console.log(' wowok-skills init --target claude,cursor --project');
|
|
257
|
+
console.log(' wowok-skills doctor');
|
|
258
|
+
console.log(' wowok-skills uninit --target codex');
|
|
821
259
|
}
|
|
822
260
|
function main() {
|
|
823
261
|
const args = process.argv.slice(2);
|
|
824
|
-
|
|
262
|
+
const command = args[0];
|
|
263
|
+
if (!command || command === '--help' || command === '-h' || command === 'help') {
|
|
825
264
|
printUsage();
|
|
826
265
|
process.exit(0);
|
|
827
266
|
}
|
|
828
|
-
const command = args[0];
|
|
829
267
|
switch (command) {
|
|
830
268
|
case 'list':
|
|
831
269
|
cmdList();
|
|
832
270
|
break;
|
|
833
271
|
case 'get':
|
|
834
|
-
if (args
|
|
835
|
-
console.error('Error:
|
|
272
|
+
if (!args[1]) {
|
|
273
|
+
console.error('Error: skill name required');
|
|
836
274
|
process.exit(1);
|
|
837
275
|
}
|
|
838
276
|
cmdGet(args[1]);
|
|
839
277
|
break;
|
|
840
278
|
case 'role':
|
|
841
|
-
if (args
|
|
842
|
-
console.error('Error:
|
|
279
|
+
if (!args[1]) {
|
|
280
|
+
console.error('Error: role required (customer|provider|supplier|collaborator|arbitrator|shared)');
|
|
843
281
|
process.exit(1);
|
|
844
282
|
}
|
|
845
283
|
cmdRole(args[1]);
|
|
846
284
|
break;
|
|
847
285
|
case 'recommend':
|
|
848
286
|
if (args.length < 2) {
|
|
849
|
-
console.error('Error:
|
|
287
|
+
console.error('Error: intent description required');
|
|
850
288
|
process.exit(1);
|
|
851
289
|
}
|
|
852
290
|
cmdRecommend(args.slice(1).join(' '));
|
|
853
291
|
break;
|
|
854
|
-
case 'init':
|
|
855
|
-
|
|
856
|
-
const withMcp = !rest.includes('--no-mcp');
|
|
857
|
-
const referrer = parseReferrerArg(rest);
|
|
858
|
-
cmdInit(parseTargetArg(rest), withMcp, referrer);
|
|
292
|
+
case 'init':
|
|
293
|
+
cmdInit(parseInitArgs(args.slice(1)));
|
|
859
294
|
break;
|
|
860
|
-
}
|
|
861
295
|
case 'uninit':
|
|
862
|
-
cmdUninit(
|
|
296
|
+
cmdUninit(parseInitArgs(args.slice(1)));
|
|
297
|
+
break;
|
|
298
|
+
case 'doctor':
|
|
299
|
+
cmdDoctor();
|
|
863
300
|
break;
|
|
864
301
|
case 'referrer': {
|
|
865
302
|
const value = args[1];
|
|
866
303
|
if (!value || value.startsWith('--')) {
|
|
867
|
-
console.error('Error:
|
|
304
|
+
console.error('Error: referrer address or name required — wowok-skills referrer <addr|name>');
|
|
868
305
|
process.exit(1);
|
|
869
306
|
}
|
|
870
|
-
saveReferrer(value);
|
|
307
|
+
(0, installer_1.saveReferrer)(value);
|
|
871
308
|
break;
|
|
872
309
|
}
|
|
310
|
+
case 'targets':
|
|
311
|
+
printTargets();
|
|
312
|
+
break;
|
|
873
313
|
default:
|
|
874
|
-
console.error(`Unknown command: ${command}`);
|
|
314
|
+
console.error(`Unknown command: ${command}\n`);
|
|
875
315
|
printUsage();
|
|
876
316
|
process.exit(1);
|
|
877
317
|
}
|
|
878
318
|
}
|
|
879
|
-
function parseTargetArg(rest) {
|
|
880
|
-
// Check for --target <value> first
|
|
881
|
-
const idx = rest.indexOf('--target');
|
|
882
|
-
if (idx !== -1 && idx + 1 < rest.length) {
|
|
883
|
-
return rest[idx + 1];
|
|
884
|
-
}
|
|
885
|
-
// Check for positional argument (first non-flag arg)
|
|
886
|
-
const positional = rest.find(a => !a.startsWith('--'));
|
|
887
|
-
if (positional && types_1.ALL_CLIENT_TARGETS.includes(positional)) {
|
|
888
|
-
return positional;
|
|
889
|
-
}
|
|
890
|
-
return undefined;
|
|
891
|
-
}
|
|
892
|
-
function parseReferrerArg(rest) {
|
|
893
|
-
const idx = rest.indexOf('--referrer');
|
|
894
|
-
if (idx !== -1 && idx + 1 < rest.length) {
|
|
895
|
-
const v = rest[idx + 1].trim();
|
|
896
|
-
return v || undefined;
|
|
897
|
-
}
|
|
898
|
-
return undefined;
|
|
899
|
-
}
|
|
900
|
-
/** Wow MCP data dir — mirrors @wowok/wowok getWowMcpDir(): dirname(wowDir)/mcp. */
|
|
901
|
-
function wowMcpDir() {
|
|
902
|
-
const home = os.homedir();
|
|
903
|
-
let wowDir;
|
|
904
|
-
if (process.env.WOWOK_DATA_DIR) {
|
|
905
|
-
wowDir = process.env.WOWOK_DATA_DIR;
|
|
906
|
-
}
|
|
907
|
-
else if (process.platform === 'win32') {
|
|
908
|
-
wowDir = path.join(home, '.wow', 'V1');
|
|
909
|
-
}
|
|
910
|
-
else if (process.platform === 'darwin') {
|
|
911
|
-
wowDir = path.join(home, 'Library', 'Application Support', '.wow', 'V1');
|
|
912
|
-
}
|
|
913
|
-
else {
|
|
914
|
-
const xdgConfig = process.env.XDG_CONFIG_HOME;
|
|
915
|
-
if (xdgConfig) {
|
|
916
|
-
wowDir = path.join(xdgConfig, '.wow', 'V1');
|
|
917
|
-
}
|
|
918
|
-
else {
|
|
919
|
-
const xdgData = process.env.XDG_DATA_HOME;
|
|
920
|
-
wowDir = xdgData ? path.join(xdgData, '.wow', 'V1') : path.join(home, '.wow', 'V1');
|
|
921
|
-
}
|
|
922
|
-
}
|
|
923
|
-
return path.join(path.dirname(wowDir), 'mcp');
|
|
924
|
-
}
|
|
925
|
-
/** Persist the airdrop referrer so the MCP auto-injects it on every call. */
|
|
926
|
-
function saveReferrer(referrer) {
|
|
927
|
-
const dir = wowMcpDir();
|
|
928
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
929
|
-
fs.writeFileSync(path.join(dir, 'referrer'), referrer.trim() + '\n', 'utf-8');
|
|
930
|
-
console.log(`[wowok-skills] airdrop referrer saved: ${referrer.trim()}`);
|
|
931
|
-
console.log('[wowok-skills] it is auto-recorded on your first on-chain interaction.');
|
|
932
|
-
}
|
|
933
319
|
main();
|
|
934
320
|
//# sourceMappingURL=cli.js.map
|