@kwonye/mcpx 0.1.104 → 0.1.105
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/{chunk-wq4zd3t7.js → chunk-01s7rhx3.js} +4 -2
- package/dist/{chunk-cqenqnxk.js → chunk-4y0t0tfj.js} +8 -2
- package/dist/{chunk-z1k63fa3.js → chunk-56whm3hm.js} +329 -34
- package/dist/{chunk-31brdz5s.js → chunk-6mxr34tc.js} +2 -2
- package/dist/{chunk-b58zsdp4.js → chunk-am903qjk.js} +11 -5
- package/dist/{chunk-s9v1epnk.js → chunk-btbww96n.js} +7 -5
- package/dist/{chunk-02r7k4ax.js → chunk-d2v9rxy0.js} +5 -5
- package/dist/{chunk-cz8cdmw1.js → chunk-fw8dyt89.js} +1 -1
- package/dist/{chunk-0xhdyt4z.js → chunk-h158rkts.js} +4 -4
- package/dist/{chunk-941dqsx2.js → chunk-t4hqf6yh.js} +244 -9
- package/dist/{chunk-z34m83m4.js → chunk-y9a1rx7j.js} +2 -2
- package/dist/cli.js +146 -32
- package/dist/core/index.d.ts +5 -3
- package/dist/core/index.js +37 -9
- package/dist/core/paths.d.ts +2 -0
- package/dist/core/plugin-manager.d.ts +4 -1
- package/dist/core/share.d.ts +71 -0
- package/dist/core/skills.d.ts +7 -0
- package/dist/core/telemetry.d.ts +1 -1
- package/dist/types.d.ts +10 -0
- package/package.json +1 -1
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
getConfigPath,
|
|
4
4
|
readJsonFile,
|
|
5
5
|
writeJsonAtomic
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-4y0t0tfj.js";
|
|
7
7
|
import {
|
|
8
8
|
normalizeServerSpecEnabled
|
|
9
9
|
} from "./chunk-bjw71y54.js";
|
|
@@ -508,6 +508,8 @@ var managedPluginSchema = z.object({
|
|
|
508
508
|
sourceFingerprint: z.string()
|
|
509
509
|
}).optional(),
|
|
510
510
|
updateError: z.string().optional(),
|
|
511
|
+
pinned: z.boolean().default(false),
|
|
512
|
+
previous: z.object({ version: z.string(), resolvedSha: z.string(), root: z.string() }).optional(),
|
|
511
513
|
projectOverrides: z.record(z.string(), z.object({
|
|
512
514
|
enabled: z.boolean().optional(),
|
|
513
515
|
components: z.record(pluginComponentSchema, z.boolean()).optional(),
|
|
@@ -735,4 +737,4 @@ function resolveActiveConfig(options = {}) {
|
|
|
735
737
|
|
|
736
738
|
export { tokenizeCommandLine, parseCliAddCommand, ConfigLoadError, defaultConfig, loadConfig, saveConfig, loadProjectConfig, saveProjectConfig, loadMergedConfig, migrateProjectServers, resolveActiveConfig };
|
|
737
739
|
|
|
738
|
-
//# debugId=
|
|
740
|
+
//# debugId=5F19AEF9E1E9E38564756E2164756E21
|
|
@@ -30,6 +30,12 @@ function getTelemetryPath() {
|
|
|
30
30
|
function getSkillsDir() {
|
|
31
31
|
return path.join(getConfigRoot(), "mcpx", "skills");
|
|
32
32
|
}
|
|
33
|
+
function getSkillPackagesRoot() {
|
|
34
|
+
return path.join(getDataRoot(), "mcpx", "skills", "packages");
|
|
35
|
+
}
|
|
36
|
+
function getSkillStatePath() {
|
|
37
|
+
return path.join(getDataRoot(), "mcpx", "skills", "state.json");
|
|
38
|
+
}
|
|
33
39
|
function getManagedIndexPath() {
|
|
34
40
|
return path.join(getDataRoot(), "mcpx", "managed-index.json");
|
|
35
41
|
}
|
|
@@ -132,6 +138,6 @@ function sha256(value) {
|
|
|
132
138
|
return crypto2.createHash("sha256").update(value).digest("hex");
|
|
133
139
|
}
|
|
134
140
|
|
|
135
|
-
export { homeDir, getConfigPath, getTelemetryPath, getSkillsDir, getManagedIndexPath, getSecretsStorePath, getSecretsKeyPath, getPidPath, getLogPath, getGatewayTokenPath, getUpdatesDir, getStagedVersionPath, getUpdateLockPath, getOAuthLockPath, getPluginCacheRoot, getPluginDataRoot, getMarketplaceCacheRoot, getMarketplaceUpdateStatePath, getMarketplaceUpdateLockPath, ensureDir, ensureParentDir, findProjectConfigPath, readJsonFile, writeJsonAtomic, sha256 };
|
|
141
|
+
export { homeDir, getConfigPath, getTelemetryPath, getSkillsDir, getSkillPackagesRoot, getSkillStatePath, getManagedIndexPath, getSecretsStorePath, getSecretsKeyPath, getPidPath, getLogPath, getGatewayTokenPath, getUpdatesDir, getStagedVersionPath, getUpdateLockPath, getOAuthLockPath, getPluginCacheRoot, getPluginDataRoot, getMarketplaceCacheRoot, getMarketplaceUpdateStatePath, getMarketplaceUpdateLockPath, ensureDir, ensureParentDir, findProjectConfigPath, readJsonFile, writeJsonAtomic, sha256 };
|
|
136
142
|
|
|
137
|
-
//# debugId=
|
|
143
|
+
//# debugId=BCB55F79AB94B71A64756E2164756E21
|
|
@@ -3,11 +3,11 @@ import {
|
|
|
3
3
|
loadProjectConfig,
|
|
4
4
|
saveConfig,
|
|
5
5
|
saveProjectConfig
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-01s7rhx3.js";
|
|
7
7
|
import {
|
|
8
8
|
SecretsManager,
|
|
9
9
|
ensureGatewayToken
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-fw8dyt89.js";
|
|
11
11
|
import {
|
|
12
12
|
ensureDir,
|
|
13
13
|
findProjectConfigPath,
|
|
@@ -15,12 +15,14 @@ import {
|
|
|
15
15
|
getManagedIndexPath,
|
|
16
16
|
getPluginCacheRoot,
|
|
17
17
|
getPluginDataRoot,
|
|
18
|
+
getSkillPackagesRoot,
|
|
19
|
+
getSkillStatePath,
|
|
18
20
|
getSkillsDir,
|
|
19
21
|
homeDir,
|
|
20
22
|
readJsonFile,
|
|
21
23
|
sha256,
|
|
22
24
|
writeJsonAtomic
|
|
23
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-4y0t0tfj.js";
|
|
24
26
|
import {
|
|
25
27
|
isServerEnabled
|
|
26
28
|
} from "./chunk-bjw71y54.js";
|
|
@@ -35,6 +37,7 @@ import path21 from "node:path";
|
|
|
35
37
|
// src/core/plugin-cache.ts
|
|
36
38
|
import fs from "node:fs";
|
|
37
39
|
import path from "node:path";
|
|
40
|
+
import crypto from "node:crypto";
|
|
38
41
|
import { execFile } from "node:child_process";
|
|
39
42
|
import { promisify } from "node:util";
|
|
40
43
|
var TMP_PREFIX = "mcpx-acquire-";
|
|
@@ -83,7 +86,13 @@ class PluginCache {
|
|
|
83
86
|
return computeTreeHash(resolved);
|
|
84
87
|
}
|
|
85
88
|
if (source.type === "npm") {
|
|
86
|
-
|
|
89
|
+
const pkg = source.original.replace(/^npm:/, "");
|
|
90
|
+
const spec = source.ref ? `${pkg}@${source.ref}` : pkg;
|
|
91
|
+
const { stdout } = await execFileAsync("npm", ["view", spec, "version", "dist.integrity", "--json"], { timeout: 30000 });
|
|
92
|
+
const metadata = JSON.parse(stdout);
|
|
93
|
+
if (!metadata.version)
|
|
94
|
+
throw new Error(`Could not resolve npm package ${spec}`);
|
|
95
|
+
return `npm-${metadata.version}-${metadata.dist?.integrity ?? metadata["dist.integrity"] ?? "unverified"}`;
|
|
87
96
|
}
|
|
88
97
|
throw new Error(`Cannot resolve SHA for source type: ${source.type}`);
|
|
89
98
|
}
|
|
@@ -161,7 +170,27 @@ class PluginCache {
|
|
|
161
170
|
return { source: source.original, name: pluginName, sha, root: destDir };
|
|
162
171
|
}
|
|
163
172
|
if (source.type === "npm") {
|
|
164
|
-
|
|
173
|
+
const pkg = source.original.replace(/^npm:/, "");
|
|
174
|
+
const spec = source.ref ? `${pkg}@${source.ref}` : pkg;
|
|
175
|
+
const tmpDir = fs.mkdtempSync(path.join(this.cacheRoot, TMP_PREFIX));
|
|
176
|
+
try {
|
|
177
|
+
const { stdout } = await execFileAsync("npm", ["pack", spec, "--ignore-scripts", "--json", "--pack-destination", tmpDir], { timeout: 120000 });
|
|
178
|
+
const packed = JSON.parse(stdout);
|
|
179
|
+
const filename = packed[0]?.filename;
|
|
180
|
+
if (!filename)
|
|
181
|
+
throw new Error(`npm did not produce an archive for ${spec}`);
|
|
182
|
+
const archive = path.join(tmpDir, filename);
|
|
183
|
+
const actualSha = `npm-${packed[0]?.version ?? source.ref ?? "latest"}-${crypto.createHash("sha256").update(fs.readFileSync(archive)).digest("hex")}`;
|
|
184
|
+
const finalDest = this.shaDir(srcDir, actualSha);
|
|
185
|
+
if (!fs.existsSync(finalDest)) {
|
|
186
|
+
ensureDir(finalDest);
|
|
187
|
+
await execFileAsync("tar", ["-xzf", archive, "--strip-components=1", "-C", finalDest], { timeout: 30000 });
|
|
188
|
+
}
|
|
189
|
+
this.updateRef(srcDir, actualSha);
|
|
190
|
+
return { source: source.original, name: pluginName, sha: actualSha, root: finalDest };
|
|
191
|
+
} finally {
|
|
192
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
193
|
+
}
|
|
165
194
|
}
|
|
166
195
|
throw new Error(`Cannot fetch source type: ${source.type}`);
|
|
167
196
|
}
|
|
@@ -224,7 +253,6 @@ class PluginCache {
|
|
|
224
253
|
}
|
|
225
254
|
function computeTreeHash(dir) {
|
|
226
255
|
const entries = fs.readdirSync(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
|
|
227
|
-
const crypto = __require("node:crypto");
|
|
228
256
|
const hash = crypto.createHash("sha256");
|
|
229
257
|
for (const entry of entries) {
|
|
230
258
|
if (entry.name.startsWith(".git"))
|
|
@@ -1280,6 +1308,29 @@ function copyPluginDir(src, dest, exclude = [], errors) {
|
|
|
1280
1308
|
}
|
|
1281
1309
|
function copyFileOrDir(src, dest, errors) {
|
|
1282
1310
|
try {
|
|
1311
|
+
if (path6.basename(src).toLowerCase() === "skill.md") {
|
|
1312
|
+
const sourceRoot = path6.dirname(src);
|
|
1313
|
+
const targetRoot = path6.dirname(dest);
|
|
1314
|
+
ensureDir(path6.dirname(targetRoot));
|
|
1315
|
+
if (fs6.existsSync(targetRoot)) {
|
|
1316
|
+
const stat = fs6.lstatSync(targetRoot);
|
|
1317
|
+
if (stat.isSymbolicLink())
|
|
1318
|
+
fs6.rmSync(targetRoot, { force: true });
|
|
1319
|
+
else if (stat.isDirectory() && fs6.readdirSync(targetRoot).length === 0)
|
|
1320
|
+
fs6.rmSync(targetRoot, { recursive: true, force: true });
|
|
1321
|
+
}
|
|
1322
|
+
if (!fs6.existsSync(targetRoot)) {
|
|
1323
|
+
const relativeTarget = path6.relative(path6.dirname(targetRoot), path6.resolve(sourceRoot));
|
|
1324
|
+
try {
|
|
1325
|
+
fs6.symlinkSync(relativeTarget, targetRoot, process.platform === "win32" ? "junction" : "dir");
|
|
1326
|
+
} catch {
|
|
1327
|
+
fs6.cpSync(sourceRoot, targetRoot, { recursive: true, dereference: true });
|
|
1328
|
+
}
|
|
1329
|
+
} else {
|
|
1330
|
+
fs6.cpSync(sourceRoot, targetRoot, { recursive: true, dereference: true });
|
|
1331
|
+
}
|
|
1332
|
+
return;
|
|
1333
|
+
}
|
|
1283
1334
|
ensureDir(path6.dirname(dest));
|
|
1284
1335
|
if (fs6.statSync(src).isDirectory()) {
|
|
1285
1336
|
copyPluginDir(src, dest, [], errors);
|
|
@@ -1334,8 +1385,9 @@ function loadOwnership2(targetDir) {
|
|
|
1334
1385
|
}
|
|
1335
1386
|
try {
|
|
1336
1387
|
const parsed = ownershipSchema.safeParse(JSON.parse(fs7.readFileSync(manifestPath2, "utf8")));
|
|
1337
|
-
if (parsed.success)
|
|
1338
|
-
return parsed.data;
|
|
1388
|
+
if (parsed.success) {
|
|
1389
|
+
return { ...parsed.data, paths: parsed.data.paths.map((ownedPath) => ownedPath.endsWith("/SKILL.md") ? path7.dirname(ownedPath) : ownedPath) };
|
|
1390
|
+
}
|
|
1339
1391
|
} catch {
|
|
1340
1392
|
console.error(`[mcpx] Warning: corrupt ownership manifest at ${manifestPath2}, resetting`);
|
|
1341
1393
|
return { version: 1, paths: [] };
|
|
@@ -1348,7 +1400,7 @@ function saveOwnership2(targetDir, manifest) {
|
|
|
1348
1400
|
}
|
|
1349
1401
|
function projectSkillsToDir(targetDir, skills, layout) {
|
|
1350
1402
|
const owned = loadOwnership2(targetDir);
|
|
1351
|
-
const newPaths = new Set(skills.map((s) => layout === "dir" ?
|
|
1403
|
+
const newPaths = new Set(skills.map((s) => layout === "dir" ? s.id : `${s.id}.md`));
|
|
1352
1404
|
for (const ownedPath of owned.paths) {
|
|
1353
1405
|
if (!newPaths.has(ownedPath)) {
|
|
1354
1406
|
const fullPath = path7.join(targetDir, ownedPath);
|
|
@@ -1374,10 +1426,46 @@ function projectSkillsToDir(targetDir, skills, layout) {
|
|
|
1374
1426
|
}
|
|
1375
1427
|
for (const skill of skills) {
|
|
1376
1428
|
validateSkillId(skill.id);
|
|
1377
|
-
const
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1429
|
+
const ownedTarget = layout === "dir" ? skill.id : `${skill.id}.md`;
|
|
1430
|
+
if ((fs7.existsSync(path7.join(targetDir, ownedTarget)) || (() => {
|
|
1431
|
+
try {
|
|
1432
|
+
fs7.lstatSync(path7.join(targetDir, ownedTarget));
|
|
1433
|
+
return true;
|
|
1434
|
+
} catch {
|
|
1435
|
+
return false;
|
|
1436
|
+
}
|
|
1437
|
+
})()) && !owned.paths.includes(ownedTarget)) {
|
|
1438
|
+
console.error(`[mcpx] Warning: preserving unowned skill projection: ${path7.join(targetDir, ownedTarget)}`);
|
|
1439
|
+
continue;
|
|
1440
|
+
}
|
|
1441
|
+
if (layout === "dir" && skill.root && fs7.existsSync(skill.root)) {
|
|
1442
|
+
const targetPath = path7.join(targetDir, skill.id);
|
|
1443
|
+
assertWithinBase2(targetDir, targetPath);
|
|
1444
|
+
if (path7.resolve(targetPath) !== path7.resolve(skill.root)) {
|
|
1445
|
+
if (fs7.existsSync(targetPath) || (() => {
|
|
1446
|
+
try {
|
|
1447
|
+
fs7.lstatSync(targetPath);
|
|
1448
|
+
return true;
|
|
1449
|
+
} catch {
|
|
1450
|
+
return false;
|
|
1451
|
+
}
|
|
1452
|
+
})()) {
|
|
1453
|
+
fs7.rmSync(targetPath, { recursive: true, force: true });
|
|
1454
|
+
}
|
|
1455
|
+
ensureDir(path7.dirname(targetPath));
|
|
1456
|
+
const relativeTarget = path7.relative(path7.dirname(targetPath), path7.resolve(skill.root));
|
|
1457
|
+
try {
|
|
1458
|
+
fs7.symlinkSync(relativeTarget, targetPath, process.platform === "win32" ? "junction" : "dir");
|
|
1459
|
+
} catch {
|
|
1460
|
+
fs7.cpSync(skill.root, targetPath, { recursive: true, dereference: true });
|
|
1461
|
+
}
|
|
1462
|
+
}
|
|
1463
|
+
} else {
|
|
1464
|
+
const filePath = layout === "dir" ? path7.join(targetDir, skill.id, "SKILL.md") : path7.join(targetDir, `${skill.id}.md`);
|
|
1465
|
+
assertWithinBase2(targetDir, filePath);
|
|
1466
|
+
ensureDir(path7.dirname(filePath));
|
|
1467
|
+
fs7.writeFileSync(filePath, skill.content, "utf-8");
|
|
1468
|
+
}
|
|
1381
1469
|
}
|
|
1382
1470
|
saveOwnership2(targetDir, { version: 1, paths: Array.from(newPaths) });
|
|
1383
1471
|
}
|
|
@@ -2969,50 +3057,222 @@ function saveManagedIndex(index, filePath = getManagedIndexPath()) {
|
|
|
2969
3057
|
// src/core/skills.ts
|
|
2970
3058
|
import fs13 from "node:fs";
|
|
2971
3059
|
import path19 from "node:path";
|
|
3060
|
+
import { z as z15 } from "zod";
|
|
3061
|
+
var skillStateSchema = z15.record(z15.string(), z15.object({ source: z15.string(), skillName: z15.string().optional(), pinned: z15.boolean().default(false), previousPath: z15.string().optional() }));
|
|
3062
|
+
function readSkillState() {
|
|
3063
|
+
const statePath = getSkillStatePath();
|
|
3064
|
+
if (!fs13.existsSync(statePath))
|
|
3065
|
+
return {};
|
|
3066
|
+
try {
|
|
3067
|
+
return skillStateSchema.parse(JSON.parse(fs13.readFileSync(statePath, "utf8")));
|
|
3068
|
+
} catch {
|
|
3069
|
+
return {};
|
|
3070
|
+
}
|
|
3071
|
+
}
|
|
3072
|
+
function writeSkillState(state) {
|
|
3073
|
+
ensureDir(path19.dirname(getSkillStatePath()));
|
|
3074
|
+
fs13.writeFileSync(getSkillStatePath(), JSON.stringify(state, null, 2) + `
|
|
3075
|
+
`, "utf8");
|
|
3076
|
+
}
|
|
3077
|
+
function validateSkillPackage(root) {
|
|
3078
|
+
const skillPath = path19.join(root, "SKILL.md");
|
|
3079
|
+
if (!fs13.existsSync(skillPath))
|
|
3080
|
+
throw new Error(`Agent Skill is missing SKILL.md: ${root}`);
|
|
3081
|
+
const content = fs13.readFileSync(skillPath, "utf8");
|
|
3082
|
+
const match = content.match(/^---\s*[\s\S]*?^name:\s*([^\r\n]+)[\s\S]*?^description:\s*([^\r\n]+)[\s\S]*?^---/m);
|
|
3083
|
+
if (!match || !/^[a-z0-9][a-z0-9-]{0,63}$/.test(match[1].trim()) || !match[2].trim()) {
|
|
3084
|
+
throw new Error(`Invalid Agent Skill frontmatter in ${skillPath}; name and description are required`);
|
|
3085
|
+
}
|
|
3086
|
+
}
|
|
3087
|
+
function installedSkills() {
|
|
3088
|
+
const root = getSkillPackagesRoot();
|
|
3089
|
+
if (!fs13.existsSync(root))
|
|
3090
|
+
return [];
|
|
3091
|
+
return fs13.readdirSync(root, { withFileTypes: true }).flatMap((entry) => {
|
|
3092
|
+
if (!entry.isDirectory())
|
|
3093
|
+
return [];
|
|
3094
|
+
const packageRoot = path19.join(root, entry.name);
|
|
3095
|
+
const skillFile = path19.join(packageRoot, "SKILL.md");
|
|
3096
|
+
if (!fs13.existsSync(skillFile))
|
|
3097
|
+
return [];
|
|
3098
|
+
return [{ id: entry.name, content: fs13.readFileSync(skillFile, "utf8"), root: packageRoot, source: "installed", readOnly: true }];
|
|
3099
|
+
});
|
|
3100
|
+
}
|
|
2972
3101
|
function listSkills() {
|
|
2973
3102
|
const skillsDir = getSkillsDir();
|
|
2974
|
-
if (!fs13.existsSync(skillsDir)) {
|
|
2975
|
-
return [];
|
|
2976
|
-
}
|
|
2977
|
-
const files = fs13.readdirSync(skillsDir);
|
|
2978
3103
|
const skills = [];
|
|
3104
|
+
const files = fs13.existsSync(skillsDir) ? fs13.readdirSync(skillsDir, { withFileTypes: true }) : [];
|
|
3105
|
+
const authoredDirectories = new Set(files.filter((file) => file.isDirectory()).map((file) => file.name));
|
|
2979
3106
|
for (const file of files) {
|
|
2980
|
-
|
|
2981
|
-
|
|
3107
|
+
const id = file.isDirectory() ? file.name : file.name.endsWith(".md") ? path19.basename(file.name, ".md") : null;
|
|
3108
|
+
if (id && (file.isDirectory() || !authoredDirectories.has(id))) {
|
|
2982
3109
|
try {
|
|
2983
|
-
const
|
|
2984
|
-
|
|
3110
|
+
const root = file.isDirectory() ? path19.join(skillsDir, id) : skillsDir;
|
|
3111
|
+
const filePath = file.isDirectory() ? path19.join(root, "SKILL.md") : path19.join(skillsDir, file.name);
|
|
3112
|
+
if (!fs13.existsSync(filePath))
|
|
3113
|
+
continue;
|
|
3114
|
+
const content = fs13.readFileSync(filePath, "utf-8");
|
|
3115
|
+
skills.push({ id, content, root: file.isDirectory() ? root : undefined, source: "authored" });
|
|
2985
3116
|
} catch {
|
|
2986
|
-
console.error(`[mcpx] Warning: could not read skill ${file}`);
|
|
3117
|
+
console.error(`[mcpx] Warning: could not read skill ${file.name}`);
|
|
2987
3118
|
}
|
|
2988
3119
|
}
|
|
2989
3120
|
}
|
|
2990
|
-
|
|
3121
|
+
const authoredIds = new Set(skills.map((skill) => skill.id));
|
|
3122
|
+
return [...skills, ...installedSkills().filter((skill) => !authoredIds.has(skill.id))];
|
|
2991
3123
|
}
|
|
2992
3124
|
function getSkill(id) {
|
|
2993
3125
|
validateSkillId(id);
|
|
2994
3126
|
const skillsDir = getSkillsDir();
|
|
2995
|
-
const
|
|
3127
|
+
const directory = path19.join(skillsDir, id);
|
|
3128
|
+
const packagePath = path19.join(directory, "SKILL.md");
|
|
3129
|
+
const legacyPath = path19.join(skillsDir, `${id}.md`);
|
|
3130
|
+
const filePath = fs13.existsSync(packagePath) ? packagePath : legacyPath;
|
|
2996
3131
|
if (!fs13.existsSync(filePath)) {
|
|
2997
|
-
|
|
3132
|
+
const installedPath = path19.join(getSkillPackagesRoot(), id, "SKILL.md");
|
|
3133
|
+
if (!fs13.existsSync(installedPath))
|
|
3134
|
+
return null;
|
|
3135
|
+
const installedRoot = path19.dirname(installedPath);
|
|
3136
|
+
return { id, content: fs13.readFileSync(installedPath, "utf8"), root: installedRoot, source: "installed", readOnly: true };
|
|
2998
3137
|
}
|
|
2999
3138
|
const content = fs13.readFileSync(filePath, "utf-8");
|
|
3000
|
-
return { id, content };
|
|
3139
|
+
return { id, content, root: fs13.existsSync(packagePath) ? directory : undefined, source: "authored" };
|
|
3001
3140
|
}
|
|
3002
3141
|
function saveSkill(id, content) {
|
|
3003
3142
|
validateSkillId(id);
|
|
3004
3143
|
const skillsDir = getSkillsDir();
|
|
3005
3144
|
ensureDir(skillsDir);
|
|
3006
|
-
const
|
|
3145
|
+
const directory = path19.join(skillsDir, id);
|
|
3146
|
+
const filePath = path19.join(directory, "SKILL.md");
|
|
3147
|
+
ensureDir(directory);
|
|
3007
3148
|
fs13.writeFileSync(filePath, content, "utf-8");
|
|
3149
|
+
const legacyPath = path19.join(skillsDir, `${id}.md`);
|
|
3150
|
+
if (fs13.existsSync(legacyPath)) {
|
|
3151
|
+
if (fs13.readFileSync(filePath, "utf-8") === fs13.readFileSync(legacyPath, "utf-8"))
|
|
3152
|
+
fs13.unlinkSync(legacyPath);
|
|
3153
|
+
else
|
|
3154
|
+
console.error(`[mcpx] Warning: preserving conflicting legacy skill file: ${legacyPath}`);
|
|
3155
|
+
}
|
|
3008
3156
|
}
|
|
3009
3157
|
function deleteSkill(id) {
|
|
3010
3158
|
validateSkillId(id);
|
|
3011
3159
|
const skillsDir = getSkillsDir();
|
|
3012
|
-
const
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3160
|
+
const directory = path19.join(skillsDir, id);
|
|
3161
|
+
const filePath = path19.join(directory, "SKILL.md");
|
|
3162
|
+
const legacyPath = path19.join(skillsDir, `${id}.md`);
|
|
3163
|
+
const hadAuthored = fs13.existsSync(directory) || fs13.existsSync(legacyPath);
|
|
3164
|
+
if (fs13.existsSync(directory))
|
|
3165
|
+
fs13.rmSync(directory, { recursive: true, force: true });
|
|
3166
|
+
if (fs13.existsSync(legacyPath))
|
|
3167
|
+
fs13.unlinkSync(legacyPath);
|
|
3168
|
+
if (!hadAuthored) {
|
|
3169
|
+
const installedPath = path19.join(getSkillPackagesRoot(), id);
|
|
3170
|
+
if (fs13.existsSync(installedPath))
|
|
3171
|
+
fs13.rmSync(installedPath, { recursive: true, force: true });
|
|
3172
|
+
const state = readSkillState();
|
|
3173
|
+
delete state[id];
|
|
3174
|
+
writeSkillState(state);
|
|
3175
|
+
}
|
|
3176
|
+
}
|
|
3177
|
+
function customizeSkill(id, targetId = id) {
|
|
3178
|
+
validateSkillId(id);
|
|
3179
|
+
validateSkillId(targetId);
|
|
3180
|
+
const existing = getSkill(id);
|
|
3181
|
+
if (!existing)
|
|
3182
|
+
throw new Error(`Skill "${id}" not found`);
|
|
3183
|
+
saveSkill(targetId, existing.content);
|
|
3184
|
+
return getSkill(targetId);
|
|
3185
|
+
}
|
|
3186
|
+
async function installSkillFromSource(source, skillName) {
|
|
3187
|
+
const parsed = parseSource(source);
|
|
3188
|
+
const cache = new PluginCache;
|
|
3189
|
+
const cached = await cache.fetch(parsed, skillName ?? "skill");
|
|
3190
|
+
const candidates = [];
|
|
3191
|
+
const declaredName = (root) => {
|
|
3192
|
+
try {
|
|
3193
|
+
const content = fs13.readFileSync(path19.join(root, "SKILL.md"), "utf8");
|
|
3194
|
+
const frontmatter = content.match(/^---\s*[\s\S]*?^name:\s*([^\r\n]+)[\s\S]*?^---/m)?.[1]?.trim();
|
|
3195
|
+
return frontmatter && /^[a-z0-9][a-z0-9-]*$/.test(frontmatter) ? frontmatter : undefined;
|
|
3196
|
+
} catch {
|
|
3197
|
+
return;
|
|
3198
|
+
}
|
|
3199
|
+
};
|
|
3200
|
+
const addCandidate = (root, id = path19.basename(root)) => {
|
|
3201
|
+
if (fs13.existsSync(path19.join(root, "SKILL.md"))) {
|
|
3202
|
+
validateSkillPackage(root);
|
|
3203
|
+
candidates.push({ id: declaredName(root) ?? id, root });
|
|
3204
|
+
}
|
|
3205
|
+
};
|
|
3206
|
+
addCandidate(cached.root);
|
|
3207
|
+
const skillsRoot = path19.join(cached.root, "skills");
|
|
3208
|
+
if (fs13.existsSync(skillsRoot)) {
|
|
3209
|
+
for (const entry of fs13.readdirSync(skillsRoot, { withFileTypes: true })) {
|
|
3210
|
+
if (entry.isDirectory())
|
|
3211
|
+
addCandidate(path19.join(skillsRoot, entry.name), entry.name);
|
|
3212
|
+
}
|
|
3213
|
+
}
|
|
3214
|
+
if (candidates.length === 0)
|
|
3215
|
+
throw new Error(`No Agent Skill package found in ${source}`);
|
|
3216
|
+
const selected = skillName ? candidates.find((candidate) => candidate.id === skillName) : candidates[0];
|
|
3217
|
+
if (!selected)
|
|
3218
|
+
throw new Error(`Skill "${skillName}" was not found in ${source}`);
|
|
3219
|
+
validateSkillId(selected.id);
|
|
3220
|
+
const destination = path19.join(getSkillPackagesRoot(), selected.id);
|
|
3221
|
+
ensureDir(path19.dirname(destination));
|
|
3222
|
+
const state = readSkillState();
|
|
3223
|
+
const stateSource = parsed.type === "local" ? path19.resolve(source) : source;
|
|
3224
|
+
if (fs13.existsSync(destination)) {
|
|
3225
|
+
if (state[selected.id]?.pinned)
|
|
3226
|
+
throw new Error(`Skill "${selected.id}" is pinned; unpin it before updating`);
|
|
3227
|
+
const previousPath = `${destination}.previous`;
|
|
3228
|
+
if (fs13.existsSync(previousPath))
|
|
3229
|
+
fs13.rmSync(previousPath, { recursive: true, force: true });
|
|
3230
|
+
fs13.renameSync(destination, previousPath);
|
|
3231
|
+
state[selected.id] = { ...state[selected.id], source: stateSource, skillName: selected.id, pinned: false, previousPath };
|
|
3232
|
+
} else {
|
|
3233
|
+
state[selected.id] = { source: stateSource, skillName: selected.id, pinned: false };
|
|
3234
|
+
}
|
|
3235
|
+
fs13.cpSync(selected.root, destination, { recursive: true, dereference: true });
|
|
3236
|
+
writeSkillState(state);
|
|
3237
|
+
return { id: selected.id, content: fs13.readFileSync(path19.join(destination, "SKILL.md"), "utf8"), root: destination, source: "installed", readOnly: true };
|
|
3238
|
+
}
|
|
3239
|
+
function pinSkill(id) {
|
|
3240
|
+
const state = readSkillState();
|
|
3241
|
+
if (!state[id])
|
|
3242
|
+
throw new Error(`Skill "${id}" is not installed`);
|
|
3243
|
+
state[id].pinned = true;
|
|
3244
|
+
writeSkillState(state);
|
|
3245
|
+
}
|
|
3246
|
+
function unpinSkill(id) {
|
|
3247
|
+
const state = readSkillState();
|
|
3248
|
+
if (!state[id])
|
|
3249
|
+
throw new Error(`Skill "${id}" is not installed`);
|
|
3250
|
+
state[id].pinned = false;
|
|
3251
|
+
writeSkillState(state);
|
|
3252
|
+
}
|
|
3253
|
+
async function updateSkill(id) {
|
|
3254
|
+
const state = readSkillState();
|
|
3255
|
+
const entry = state[id];
|
|
3256
|
+
if (!entry)
|
|
3257
|
+
throw new Error(`Skill "${id}" is not installed`);
|
|
3258
|
+
if (entry.pinned)
|
|
3259
|
+
throw new Error(`Skill "${id}" is pinned; unpin it before updating`);
|
|
3260
|
+
return installSkillFromSource(entry.source, entry.skillName ?? id);
|
|
3261
|
+
}
|
|
3262
|
+
function rollbackSkill(id) {
|
|
3263
|
+
const state = readSkillState();
|
|
3264
|
+
const entry = state[id];
|
|
3265
|
+
if (!entry?.previousPath || !fs13.existsSync(entry.previousPath))
|
|
3266
|
+
throw new Error(`Skill "${id}" has no previous revision`);
|
|
3267
|
+
const destination = path19.join(getSkillPackagesRoot(), id);
|
|
3268
|
+
const failedPath = `${destination}.failed`;
|
|
3269
|
+
if (fs13.existsSync(failedPath))
|
|
3270
|
+
fs13.rmSync(failedPath, { recursive: true, force: true });
|
|
3271
|
+
fs13.renameSync(destination, failedPath);
|
|
3272
|
+
fs13.renameSync(entry.previousPath, destination);
|
|
3273
|
+
entry.previousPath = failedPath;
|
|
3274
|
+
writeSkillState(state);
|
|
3275
|
+
return { id, content: fs13.readFileSync(path19.join(destination, "SKILL.md"), "utf8"), root: destination, source: "installed", readOnly: true };
|
|
3016
3276
|
}
|
|
3017
3277
|
|
|
3018
3278
|
// src/core/managed-index-lock.ts
|
|
@@ -3444,6 +3704,8 @@ class PluginManager {
|
|
|
3444
3704
|
const current = loadConfig(this.configPath).plugins?.[pluginId];
|
|
3445
3705
|
if (!current)
|
|
3446
3706
|
throw new Error(`Plugin ${pluginId} not found`);
|
|
3707
|
+
if (current.pinned)
|
|
3708
|
+
throw new Error(`Plugin ${pluginId} is pinned; unpin it before updating`);
|
|
3447
3709
|
const info = await this.inspectSource(current.source);
|
|
3448
3710
|
return this.applyPluginUpdate(pluginId, info, undefined, true);
|
|
3449
3711
|
}
|
|
@@ -3466,6 +3728,7 @@ class PluginManager {
|
|
|
3466
3728
|
for (const oldName of current.serverNames) {
|
|
3467
3729
|
delete config.servers[oldName];
|
|
3468
3730
|
}
|
|
3731
|
+
current.previous = { version: current.version, resolvedSha: current.resolvedSha, root: current.root };
|
|
3469
3732
|
current.version = info.manifest?.version || current.version;
|
|
3470
3733
|
current.resolvedSha = info.sha;
|
|
3471
3734
|
current.root = info.root;
|
|
@@ -3614,12 +3877,44 @@ async function updatePlugin(nameOrId) {
|
|
|
3614
3877
|
const manager = new PluginManager;
|
|
3615
3878
|
const config = loadConfig(manager["configPath"]);
|
|
3616
3879
|
const id = resolvePluginId(config, nameOrId);
|
|
3880
|
+
if (config.plugins?.[id]?.pinned)
|
|
3881
|
+
throw new Error(`Plugin ${nameOrId} is pinned; unpin it before updating`);
|
|
3617
3882
|
if (config.plugins?.[id]?.marketplace) {
|
|
3618
|
-
const { updateMarketplaceInstalledPlugin } = await import("./chunk-
|
|
3883
|
+
const { updateMarketplaceInstalledPlugin } = await import("./chunk-d2v9rxy0.js");
|
|
3619
3884
|
return updateMarketplaceInstalledPlugin(id);
|
|
3620
3885
|
}
|
|
3621
3886
|
return manager.updatePlugin(id);
|
|
3622
3887
|
}
|
|
3888
|
+
async function pinPlugin(nameOrId) {
|
|
3889
|
+
await mutateConfig((config) => {
|
|
3890
|
+
const id = resolvePluginId(config, nameOrId);
|
|
3891
|
+
const plugin = config.plugins?.[id];
|
|
3892
|
+
if (!plugin)
|
|
3893
|
+
throw new Error(`Plugin ${nameOrId} not found`);
|
|
3894
|
+
plugin.pinned = true;
|
|
3895
|
+
});
|
|
3896
|
+
}
|
|
3897
|
+
async function unpinPlugin(nameOrId) {
|
|
3898
|
+
await mutateConfig((config) => {
|
|
3899
|
+
const id = resolvePluginId(config, nameOrId);
|
|
3900
|
+
const plugin = config.plugins?.[id];
|
|
3901
|
+
if (!plugin)
|
|
3902
|
+
throw new Error(`Plugin ${nameOrId} not found`);
|
|
3903
|
+
plugin.pinned = false;
|
|
3904
|
+
});
|
|
3905
|
+
}
|
|
3906
|
+
async function rollbackPlugin(nameOrId) {
|
|
3907
|
+
const manager = new PluginManager;
|
|
3908
|
+
const config = loadConfig(manager["configPath"]);
|
|
3909
|
+
const id = resolvePluginId(config, nameOrId);
|
|
3910
|
+
const current = config.plugins?.[id];
|
|
3911
|
+
if (!current?.previous)
|
|
3912
|
+
throw new Error(`Plugin ${nameOrId} has no previous revision`);
|
|
3913
|
+
const source = parseSource(current.source);
|
|
3914
|
+
source.resolvedSha = current.previous.resolvedSha;
|
|
3915
|
+
const info = await manager.inspectResolvedSource(source, current.source);
|
|
3916
|
+
return manager["applyPluginUpdate"](id, info, undefined, true);
|
|
3917
|
+
}
|
|
3623
3918
|
async function uninstallPlugin(nameOrId, keepData) {
|
|
3624
3919
|
const manager = new PluginManager;
|
|
3625
3920
|
const config = loadConfig(manager["configPath"]);
|
|
@@ -3755,6 +4050,6 @@ async function preparePlugin(name) {
|
|
|
3755
4050
|
await manager.preparePlugin(name);
|
|
3756
4051
|
}
|
|
3757
4052
|
|
|
3758
|
-
export { mutateConfig, mutateProjectConfig, mutateActiveConfig, listSkills, getSkill, saveSkill, deleteSkill, prunePluginProjections, pruneAllPluginProjections, syncPluginsToClient, APP_VERSION, getAdapters, loadManagedIndex, getGatewayUrl, getGatewayInternalUrl, syncAllClients, persistSyncState,
|
|
4053
|
+
export { mutateConfig, mutateProjectConfig, mutateActiveConfig, validateSkillId, parseSource, PluginCache, validateSkillPackage, listSkills, getSkill, saveSkill, deleteSkill, customizeSkill, installSkillFromSource, pinSkill, unpinSkill, updateSkill, rollbackSkill, prunePluginProjections, pruneAllPluginProjections, syncPluginsToClient, APP_VERSION, getAdapters, loadManagedIndex, getGatewayUrl, getGatewayInternalUrl, syncAllClients, persistSyncState, readManifest, discoverComponents, hasManifest, resolvePluginVars, PluginDataManager, PluginLifecycle, PluginManager, inspectPlugin, installPlugin, updatePlugin, pinPlugin, unpinPlugin, rollbackPlugin, uninstallPlugin, enablePlugin, disablePlugin, setPluginProjectOverride, resetPluginProjectOverride, approvePluginComponent, getPluginStatus, listPlugins, resolvePluginId, pluginConfigSet, pluginSync, preparePlugin };
|
|
3759
4054
|
|
|
3760
|
-
//# debugId=
|
|
4055
|
+
//# debugId=250A96A4D45E61A664756E2164756E21
|
|
@@ -8,8 +8,8 @@ import {
|
|
|
8
8
|
resolveActiveConfig,
|
|
9
9
|
saveConfig,
|
|
10
10
|
saveProjectConfig
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import"./chunk-
|
|
11
|
+
} from "./chunk-01s7rhx3.js";
|
|
12
|
+
import"./chunk-4y0t0tfj.js";
|
|
13
13
|
import"./chunk-bjw71y54.js";
|
|
14
14
|
import"./chunk-wj4tjacg.js";
|
|
15
15
|
export {
|
|
@@ -7,18 +7,21 @@ import {
|
|
|
7
7
|
inspectPlugin,
|
|
8
8
|
installPlugin,
|
|
9
9
|
listPlugins,
|
|
10
|
+
pinPlugin,
|
|
10
11
|
pluginConfigSet,
|
|
11
12
|
pluginSync,
|
|
12
13
|
preparePlugin,
|
|
13
14
|
resetPluginProjectOverride,
|
|
14
15
|
resolvePluginId,
|
|
16
|
+
rollbackPlugin,
|
|
15
17
|
setPluginProjectOverride,
|
|
16
18
|
uninstallPlugin,
|
|
19
|
+
unpinPlugin,
|
|
17
20
|
updatePlugin
|
|
18
|
-
} from "./chunk-
|
|
19
|
-
import"./chunk-
|
|
20
|
-
import"./chunk-
|
|
21
|
-
import"./chunk-
|
|
21
|
+
} from "./chunk-56whm3hm.js";
|
|
22
|
+
import"./chunk-01s7rhx3.js";
|
|
23
|
+
import"./chunk-fw8dyt89.js";
|
|
24
|
+
import"./chunk-4y0t0tfj.js";
|
|
22
25
|
import"./chunk-bjw71y54.js";
|
|
23
26
|
import"./chunk-wj4tjacg.js";
|
|
24
27
|
export {
|
|
@@ -30,14 +33,17 @@ export {
|
|
|
30
33
|
inspectPlugin,
|
|
31
34
|
installPlugin,
|
|
32
35
|
listPlugins,
|
|
36
|
+
pinPlugin,
|
|
33
37
|
pluginConfigSet,
|
|
34
38
|
pluginSync,
|
|
35
39
|
preparePlugin,
|
|
36
40
|
resetPluginProjectOverride,
|
|
37
41
|
resolvePluginId,
|
|
42
|
+
rollbackPlugin,
|
|
38
43
|
setPluginProjectOverride,
|
|
39
44
|
uninstallPlugin,
|
|
45
|
+
unpinPlugin,
|
|
40
46
|
updatePlugin
|
|
41
47
|
};
|
|
42
48
|
|
|
43
|
-
//# debugId=
|
|
49
|
+
//# debugId=F3AE0823719415BE64756E2164756E21
|
|
@@ -6,14 +6,14 @@ import {
|
|
|
6
6
|
mutateConfig,
|
|
7
7
|
readManifest,
|
|
8
8
|
uninstallPlugin
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-56whm3hm.js";
|
|
10
10
|
import {
|
|
11
11
|
loadConfig
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-01s7rhx3.js";
|
|
13
13
|
import {
|
|
14
14
|
ensureDir,
|
|
15
15
|
getMarketplaceCacheRoot
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-4y0t0tfj.js";
|
|
17
17
|
import {
|
|
18
18
|
__require
|
|
19
19
|
} from "./chunk-wj4tjacg.js";
|
|
@@ -537,6 +537,8 @@ async function updateMarketplaceInstalledPlugin(pluginId, sync = true) {
|
|
|
537
537
|
const plugin = loadConfig().plugins?.[pluginId];
|
|
538
538
|
if (!plugin?.marketplace)
|
|
539
539
|
throw new Error(`Plugin ${pluginId} is not marketplace-managed`);
|
|
540
|
+
if (plugin.pinned)
|
|
541
|
+
throw new Error(`Plugin ${pluginId} is pinned; unpin it before updating`);
|
|
540
542
|
const qualified = `${plugin.marketplace.pluginName}@${plugin.marketplace.name}`;
|
|
541
543
|
try {
|
|
542
544
|
const detail = await inspectMarketplacePlugin(qualified);
|
|
@@ -578,7 +580,7 @@ async function refreshMarketplaceWithPlugins(name) {
|
|
|
578
580
|
}
|
|
579
581
|
}
|
|
580
582
|
if (updated.length > 0) {
|
|
581
|
-
const { pluginSync } = await import("./chunk-
|
|
583
|
+
const { pluginSync } = await import("./chunk-am903qjk.js");
|
|
582
584
|
await pluginSync();
|
|
583
585
|
}
|
|
584
586
|
return { marketplace, updated, errors };
|
|
@@ -600,4 +602,4 @@ async function refreshAutoUpdateMarketplaces() {
|
|
|
600
602
|
|
|
601
603
|
export { resolveMarketplacePluginSource, listMarketplaces, addMarketplace, refreshMarketplace, setMarketplaceAutoUpdate, removeMarketplace, listMarketplacePlugins, inspectMarketplacePlugin, installMarketplacePlugin, updateMarketplaceInstalledPlugin, refreshMarketplaceWithPlugins, refreshAutoUpdateMarketplaces };
|
|
602
604
|
|
|
603
|
-
//# debugId=
|
|
605
|
+
//# debugId=347C06BDB5A3194064756E2164756E21
|
|
@@ -11,11 +11,11 @@ import {
|
|
|
11
11
|
resolveMarketplacePluginSource,
|
|
12
12
|
setMarketplaceAutoUpdate,
|
|
13
13
|
updateMarketplaceInstalledPlugin
|
|
14
|
-
} from "./chunk-
|
|
15
|
-
import"./chunk-
|
|
16
|
-
import"./chunk-
|
|
17
|
-
import"./chunk-
|
|
18
|
-
import"./chunk-
|
|
14
|
+
} from "./chunk-btbww96n.js";
|
|
15
|
+
import"./chunk-56whm3hm.js";
|
|
16
|
+
import"./chunk-01s7rhx3.js";
|
|
17
|
+
import"./chunk-fw8dyt89.js";
|
|
18
|
+
import"./chunk-4y0t0tfj.js";
|
|
19
19
|
import"./chunk-bjw71y54.js";
|
|
20
20
|
import"./chunk-wj4tjacg.js";
|
|
21
21
|
export {
|