agentinit 1.19.0 → 1.20.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/CHANGELOG.md +25 -0
- package/README.md +46 -4
- package/dist/cli.js +1927 -509
- package/dist/cli.js.map +1 -1
- package/dist/commands/lock.d.ts +3 -0
- package/dist/commands/lock.d.ts.map +1 -0
- package/dist/commands/lock.js +160 -0
- package/dist/commands/lock.js.map +1 -0
- package/dist/commands/mcp.d.ts.map +1 -1
- package/dist/commands/mcp.js +60 -0
- package/dist/commands/mcp.js.map +1 -1
- package/dist/commands/rules.d.ts.map +1 -1
- package/dist/commands/rules.js +50 -0
- package/dist/commands/rules.js.map +1 -1
- package/dist/commands/skills.d.ts.map +1 -1
- package/dist/commands/skills.js +299 -20
- package/dist/commands/skills.js.map +1 -1
- package/dist/core/installLock.d.ts +54 -0
- package/dist/core/installLock.d.ts.map +1 -0
- package/dist/core/installLock.js +274 -0
- package/dist/core/installLock.js.map +1 -0
- package/dist/core/skillSecurityScanner.d.ts +28 -0
- package/dist/core/skillSecurityScanner.d.ts.map +1 -0
- package/dist/core/skillSecurityScanner.js +167 -0
- package/dist/core/skillSecurityScanner.js.map +1 -0
- package/dist/core/skillsManager.d.ts +12 -0
- package/dist/core/skillsManager.d.ts.map +1 -1
- package/dist/core/skillsManager.js +373 -14
- package/dist/core/skillsManager.js.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/lockfile.d.ts +68 -0
- package/dist/types/lockfile.d.ts.map +1 -0
- package/dist/types/lockfile.js +2 -0
- package/dist/types/lockfile.js.map +1 -0
- package/dist/types/plugins.d.ts +1 -1
- package/dist/types/plugins.d.ts.map +1 -1
- package/dist/types/skills.d.ts +4 -1
- package/dist/types/skills.d.ts.map +1 -1
- package/dist/utils/lockSource.d.ts +9 -0
- package/dist/utils/lockSource.d.ts.map +1 -0
- package/dist/utils/lockSource.js +59 -0
- package/dist/utils/lockSource.js.map +1 -0
- package/dist/utils/promptUtils.d.ts +13 -2
- package/dist/utils/promptUtils.d.ts.map +1 -1
- package/dist/utils/promptUtils.js +61 -3
- package/dist/utils/promptUtils.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -8347,6 +8347,159 @@ var require_prompts3 = __commonJS((exports, module) => {
|
|
|
8347
8347
|
module.exports = isNodeLT("8.6.0") ? require_dist() : require_lib();
|
|
8348
8348
|
});
|
|
8349
8349
|
|
|
8350
|
+
// node_modules/kleur/colors.mjs
|
|
8351
|
+
var init, FORCE_COLOR, NODE_DISABLE_COLORS, NO_COLOR, TERM, isTTY, $, reset, bold, dim, italic, underline, inverse, hidden, strikethrough, black, red, green, yellow, blue, magenta, cyan, white, gray, grey, bgBlack, bgRed, bgGreen, bgYellow, bgBlue, bgMagenta, bgCyan, bgWhite;
|
|
8352
|
+
var init_colors = __esm(() => {
|
|
8353
|
+
init = function(x, y) {
|
|
8354
|
+
let rgx = new RegExp(`\\x1b\\[${y}m`, "g");
|
|
8355
|
+
let open = `\x1B[${x}m`, close = `\x1B[${y}m`;
|
|
8356
|
+
return function(txt) {
|
|
8357
|
+
if (!$.enabled || txt == null)
|
|
8358
|
+
return txt;
|
|
8359
|
+
return open + (~("" + txt).indexOf(close) ? txt.replace(rgx, close + open) : txt) + close;
|
|
8360
|
+
};
|
|
8361
|
+
};
|
|
8362
|
+
isTTY = true;
|
|
8363
|
+
if (typeof process !== "undefined") {
|
|
8364
|
+
({ FORCE_COLOR, NODE_DISABLE_COLORS, NO_COLOR, TERM } = process.env || {});
|
|
8365
|
+
isTTY = process.stdout && process.stdout.isTTY;
|
|
8366
|
+
}
|
|
8367
|
+
$ = {
|
|
8368
|
+
enabled: !NODE_DISABLE_COLORS && NO_COLOR == null && TERM !== "dumb" && (FORCE_COLOR != null && FORCE_COLOR !== "0" || isTTY)
|
|
8369
|
+
};
|
|
8370
|
+
reset = init(0, 0);
|
|
8371
|
+
bold = init(1, 22);
|
|
8372
|
+
dim = init(2, 22);
|
|
8373
|
+
italic = init(3, 23);
|
|
8374
|
+
underline = init(4, 24);
|
|
8375
|
+
inverse = init(7, 27);
|
|
8376
|
+
hidden = init(8, 28);
|
|
8377
|
+
strikethrough = init(9, 29);
|
|
8378
|
+
black = init(30, 39);
|
|
8379
|
+
red = init(31, 39);
|
|
8380
|
+
green = init(32, 39);
|
|
8381
|
+
yellow = init(33, 39);
|
|
8382
|
+
blue = init(34, 39);
|
|
8383
|
+
magenta = init(35, 39);
|
|
8384
|
+
cyan = init(36, 39);
|
|
8385
|
+
white = init(37, 39);
|
|
8386
|
+
gray = init(90, 39);
|
|
8387
|
+
grey = init(90, 39);
|
|
8388
|
+
bgBlack = init(40, 49);
|
|
8389
|
+
bgRed = init(41, 49);
|
|
8390
|
+
bgGreen = init(42, 49);
|
|
8391
|
+
bgYellow = init(43, 49);
|
|
8392
|
+
bgBlue = init(44, 49);
|
|
8393
|
+
bgMagenta = init(45, 49);
|
|
8394
|
+
bgCyan = init(46, 49);
|
|
8395
|
+
bgWhite = init(47, 49);
|
|
8396
|
+
});
|
|
8397
|
+
|
|
8398
|
+
// dist/utils/symbols.js
|
|
8399
|
+
var STATUS, TREE, BOX;
|
|
8400
|
+
var init_symbols = __esm(() => {
|
|
8401
|
+
STATUS = {
|
|
8402
|
+
success: "\u2713",
|
|
8403
|
+
error: "\u2717",
|
|
8404
|
+
warning: "\u26A0",
|
|
8405
|
+
info: "\u2139",
|
|
8406
|
+
debug: "\u2022"
|
|
8407
|
+
};
|
|
8408
|
+
TREE = {
|
|
8409
|
+
branch: "\u251C\u2500",
|
|
8410
|
+
last: "\u2514\u2500"
|
|
8411
|
+
};
|
|
8412
|
+
BOX = {
|
|
8413
|
+
topLeft: "\u250C",
|
|
8414
|
+
topRight: "\u2510",
|
|
8415
|
+
bottomLeft: "\u2514",
|
|
8416
|
+
bottomRight: "\u2518",
|
|
8417
|
+
horizontal: "\u2500",
|
|
8418
|
+
vertical: "\u2502"
|
|
8419
|
+
};
|
|
8420
|
+
});
|
|
8421
|
+
|
|
8422
|
+
// dist/utils/logger.js
|
|
8423
|
+
class Logger {
|
|
8424
|
+
static instance;
|
|
8425
|
+
static getInstance() {
|
|
8426
|
+
if (!Logger.instance) {
|
|
8427
|
+
Logger.instance = new Logger;
|
|
8428
|
+
}
|
|
8429
|
+
return Logger.instance;
|
|
8430
|
+
}
|
|
8431
|
+
info(message) {
|
|
8432
|
+
console.log(cyan(STATUS.info), message);
|
|
8433
|
+
}
|
|
8434
|
+
success(message) {
|
|
8435
|
+
console.log(green(STATUS.success), message);
|
|
8436
|
+
}
|
|
8437
|
+
warning(message) {
|
|
8438
|
+
console.log(yellow(STATUS.warning), message);
|
|
8439
|
+
}
|
|
8440
|
+
warn(message) {
|
|
8441
|
+
this.warning(message);
|
|
8442
|
+
}
|
|
8443
|
+
error(message) {
|
|
8444
|
+
console.log(red(STATUS.error), message);
|
|
8445
|
+
}
|
|
8446
|
+
debug(message) {
|
|
8447
|
+
console.log(dim(STATUS.debug), dim(message));
|
|
8448
|
+
}
|
|
8449
|
+
title(message) {
|
|
8450
|
+
console.log(bold(cyan(message)));
|
|
8451
|
+
}
|
|
8452
|
+
subtitle(message) {
|
|
8453
|
+
console.log(bold(message));
|
|
8454
|
+
}
|
|
8455
|
+
titleBox(message) {
|
|
8456
|
+
const w = getTerminalWidth();
|
|
8457
|
+
if (w < 8) {
|
|
8458
|
+
console.log(bold(cyan(truncateText(message, w))));
|
|
8459
|
+
return;
|
|
8460
|
+
}
|
|
8461
|
+
const maxInner = Math.max(4, w - 2);
|
|
8462
|
+
const inner = Math.min(Math.max(message.length + 4, 40), maxInner);
|
|
8463
|
+
const visibleMessage = truncateText(message, inner - 2);
|
|
8464
|
+
const padR = Math.max(0, inner - visibleMessage.length - 2);
|
|
8465
|
+
console.log(dim(BOX.topLeft + BOX.horizontal.repeat(inner) + BOX.topRight));
|
|
8466
|
+
console.log(dim(BOX.vertical) + " " + bold(cyan(visibleMessage)) + " ".repeat(padR) + " " + dim(BOX.vertical));
|
|
8467
|
+
console.log(dim(BOX.bottomLeft + BOX.horizontal.repeat(inner) + BOX.bottomRight));
|
|
8468
|
+
}
|
|
8469
|
+
section(title) {
|
|
8470
|
+
const w = getTerminalWidth();
|
|
8471
|
+
const lineLen = Math.max(0, w - title.length - 5);
|
|
8472
|
+
console.log("");
|
|
8473
|
+
console.log(bold(`${BOX.horizontal}${BOX.horizontal} ${title} ${BOX.horizontal.repeat(lineLen)}`));
|
|
8474
|
+
}
|
|
8475
|
+
tree(message, isLast) {
|
|
8476
|
+
const connector = isLast ? TREE.last : TREE.branch;
|
|
8477
|
+
console.log(`${connector} ${message}`);
|
|
8478
|
+
}
|
|
8479
|
+
}
|
|
8480
|
+
var getTerminalWidth, truncateText, logger;
|
|
8481
|
+
var init_logger = __esm(() => {
|
|
8482
|
+
init_colors();
|
|
8483
|
+
init_symbols();
|
|
8484
|
+
getTerminalWidth = function() {
|
|
8485
|
+
const columns = process.stdout.columns;
|
|
8486
|
+
return typeof columns === "number" && columns > 0 ? columns : 80;
|
|
8487
|
+
};
|
|
8488
|
+
truncateText = function(text, maxLength) {
|
|
8489
|
+
if (maxLength <= 0) {
|
|
8490
|
+
return "";
|
|
8491
|
+
}
|
|
8492
|
+
if (text.length <= maxLength) {
|
|
8493
|
+
return text;
|
|
8494
|
+
}
|
|
8495
|
+
if (maxLength <= 3) {
|
|
8496
|
+
return ".".repeat(maxLength);
|
|
8497
|
+
}
|
|
8498
|
+
return `${text.slice(0, maxLength - 3)}...`;
|
|
8499
|
+
};
|
|
8500
|
+
logger = Logger.getInstance();
|
|
8501
|
+
});
|
|
8502
|
+
|
|
8350
8503
|
// dist/utils/fs.js
|
|
8351
8504
|
import {promises as fs} from "fs";
|
|
8352
8505
|
import {platform} from "os";
|
|
@@ -16945,6 +17098,174 @@ var init_marketplaceRegistry = __esm(() => {
|
|
|
16945
17098
|
CUSTOM_MARKETPLACE_CACHE_TTL_MS = 3600000;
|
|
16946
17099
|
});
|
|
16947
17100
|
|
|
17101
|
+
// dist/core/skillSecurityScanner.js
|
|
17102
|
+
import {promises as fs22} from "fs";
|
|
17103
|
+
import {join as join4, relative as relative2} from "path";
|
|
17104
|
+
|
|
17105
|
+
class SkillSecurityScanner {
|
|
17106
|
+
async scanSkill(skill) {
|
|
17107
|
+
const findings = skill.generatedContent ? this.scanText(skill.generatedContent, "SKILL.md") : await this.scanDirectory(skill.path);
|
|
17108
|
+
const stats = findings.reduce((acc, finding) => {
|
|
17109
|
+
acc[finding.severity] += 1;
|
|
17110
|
+
return acc;
|
|
17111
|
+
}, { high: 0, medium: 0, low: 0 });
|
|
17112
|
+
return {
|
|
17113
|
+
blocked: findings.some((finding) => finding.blocking),
|
|
17114
|
+
findings,
|
|
17115
|
+
stats
|
|
17116
|
+
};
|
|
17117
|
+
}
|
|
17118
|
+
formatShortSummary(result) {
|
|
17119
|
+
const parts = [
|
|
17120
|
+
result.stats.high ? `${result.stats.high} high` : null,
|
|
17121
|
+
result.stats.medium ? `${result.stats.medium} medium` : null,
|
|
17122
|
+
result.stats.low ? `${result.stats.low} low` : null
|
|
17123
|
+
].filter((value) => !!value);
|
|
17124
|
+
return parts.length > 0 ? parts.join(", ") : "no findings";
|
|
17125
|
+
}
|
|
17126
|
+
formatBlockingReason(result) {
|
|
17127
|
+
const finding = result.findings.find((entry) => entry.blocking) || result.findings.find((entry) => entry.severity === "high") || result.findings[0];
|
|
17128
|
+
if (!finding) {
|
|
17129
|
+
return "Security scan failed";
|
|
17130
|
+
}
|
|
17131
|
+
return `Security scan failed: ${finding.title} (${finding.ruleId}) at ${finding.filePath}:${finding.line}`;
|
|
17132
|
+
}
|
|
17133
|
+
async scanDirectory(rootPath) {
|
|
17134
|
+
const findings = [];
|
|
17135
|
+
await this.walk(rootPath, rootPath, findings);
|
|
17136
|
+
return findings;
|
|
17137
|
+
}
|
|
17138
|
+
async walk(rootPath, currentPath, findings) {
|
|
17139
|
+
const entries = await fs22.readdir(currentPath, { withFileTypes: true });
|
|
17140
|
+
for (const entry of entries) {
|
|
17141
|
+
if (entry.name === ".git" || entry.name === "node_modules") {
|
|
17142
|
+
continue;
|
|
17143
|
+
}
|
|
17144
|
+
const entryPath = join4(currentPath, entry.name);
|
|
17145
|
+
if (entry.isDirectory()) {
|
|
17146
|
+
await this.walk(rootPath, entryPath, findings);
|
|
17147
|
+
continue;
|
|
17148
|
+
}
|
|
17149
|
+
const relativePath = relative2(rootPath, entryPath).replace(/\\/g, "/");
|
|
17150
|
+
const content = await this.readTextFile(entryPath);
|
|
17151
|
+
if (content === null) {
|
|
17152
|
+
continue;
|
|
17153
|
+
}
|
|
17154
|
+
findings.push(...this.scanText(content, relativePath, {
|
|
17155
|
+
blockHighRisk: this.isExecutableTextFile(entryPath, content)
|
|
17156
|
+
}));
|
|
17157
|
+
}
|
|
17158
|
+
}
|
|
17159
|
+
async readTextFile(filePath) {
|
|
17160
|
+
const extension = filePath.includes(".") ? filePath.slice(filePath.lastIndexOf(".")).toLowerCase() : "";
|
|
17161
|
+
if (!SCANNED_TEXT_EXTENSIONS.has(extension)) {
|
|
17162
|
+
return null;
|
|
17163
|
+
}
|
|
17164
|
+
const buffer = await fs22.readFile(filePath);
|
|
17165
|
+
if (buffer.length > MAX_TEXT_FILE_BYTES || buffer.includes(0)) {
|
|
17166
|
+
return null;
|
|
17167
|
+
}
|
|
17168
|
+
return buffer.toString("utf8");
|
|
17169
|
+
}
|
|
17170
|
+
isExecutableTextFile(filePath, content) {
|
|
17171
|
+
const extension = filePath.includes(".") ? filePath.slice(filePath.lastIndexOf(".")).toLowerCase() : "";
|
|
17172
|
+
return EXECUTABLE_TEXT_EXTENSIONS.has(extension) || content.startsWith("#!");
|
|
17173
|
+
}
|
|
17174
|
+
scanText(content, filePath, options2 = {}) {
|
|
17175
|
+
const findings = [];
|
|
17176
|
+
const lines = content.split(/\r?\n/);
|
|
17177
|
+
lines.forEach((line, index) => {
|
|
17178
|
+
for (const rule of SCAN_RULES) {
|
|
17179
|
+
rule.regex.lastIndex = 0;
|
|
17180
|
+
if (!rule.regex.test(line)) {
|
|
17181
|
+
continue;
|
|
17182
|
+
}
|
|
17183
|
+
findings.push({
|
|
17184
|
+
ruleId: rule.id,
|
|
17185
|
+
title: rule.title,
|
|
17186
|
+
severity: rule.severity,
|
|
17187
|
+
filePath,
|
|
17188
|
+
line: index + 1,
|
|
17189
|
+
snippet: line.trim().slice(0, 160),
|
|
17190
|
+
blocking: rule.severity === "high" && options2.blockHighRisk === true
|
|
17191
|
+
});
|
|
17192
|
+
}
|
|
17193
|
+
});
|
|
17194
|
+
return findings;
|
|
17195
|
+
}
|
|
17196
|
+
}
|
|
17197
|
+
var SCAN_RULES, MAX_TEXT_FILE_BYTES, SCANNED_TEXT_EXTENSIONS, EXECUTABLE_TEXT_EXTENSIONS;
|
|
17198
|
+
var init_skillSecurityScanner = __esm(() => {
|
|
17199
|
+
SCAN_RULES = [
|
|
17200
|
+
{
|
|
17201
|
+
id: "AI001",
|
|
17202
|
+
title: "Prompt override language",
|
|
17203
|
+
severity: "medium",
|
|
17204
|
+
regex: /\b(ignore|disregard|override|bypass)\b.{0,40}\b(previous|prior|system|safety|guardrails?|instructions?)\b/i
|
|
17205
|
+
},
|
|
17206
|
+
{
|
|
17207
|
+
id: "AI002",
|
|
17208
|
+
title: "Secret or credential exfiltration",
|
|
17209
|
+
severity: "high",
|
|
17210
|
+
regex: /\b(exfiltrat\w*|upload|send|post|curl|wget)\b.{0,80}\b(secret|token|key|credential|cookie|session|\.ssh|id_rsa|env(?:ironment)? variables?)\b/i
|
|
17211
|
+
},
|
|
17212
|
+
{
|
|
17213
|
+
id: "AI003",
|
|
17214
|
+
title: "Destructive shell command",
|
|
17215
|
+
severity: "high",
|
|
17216
|
+
regex: /\b(rm\s+-rf\s+\/|sudo\s+rm\s+-rf|mkfs\b|dd\s+if=\/dev\/zero|chmod\s+-R\s+777\s+\/)\b/i
|
|
17217
|
+
},
|
|
17218
|
+
{
|
|
17219
|
+
id: "AI004",
|
|
17220
|
+
title: "Remote shell execution pipeline",
|
|
17221
|
+
severity: "high",
|
|
17222
|
+
regex: /\b(curl|wget)\b[^\n|]{0,160}\|\s*(sh|bash|zsh)\b/i
|
|
17223
|
+
},
|
|
17224
|
+
{
|
|
17225
|
+
id: "AI005",
|
|
17226
|
+
title: "Hardcoded credential material",
|
|
17227
|
+
severity: "low",
|
|
17228
|
+
regex: /\b(api[_-]?key|token|secret|password)\b\s*[:=]\s*['"][^'"]{8,}['"]/i
|
|
17229
|
+
},
|
|
17230
|
+
{
|
|
17231
|
+
id: "AI006",
|
|
17232
|
+
title: "Unicode bidi control characters",
|
|
17233
|
+
severity: "low",
|
|
17234
|
+
regex: /[\u202A-\u202E\u2066-\u2069]/
|
|
17235
|
+
}
|
|
17236
|
+
];
|
|
17237
|
+
MAX_TEXT_FILE_BYTES = 1024 * 1024;
|
|
17238
|
+
SCANNED_TEXT_EXTENSIONS = new Set([
|
|
17239
|
+
"",
|
|
17240
|
+
".md",
|
|
17241
|
+
".txt",
|
|
17242
|
+
".json",
|
|
17243
|
+
".yaml",
|
|
17244
|
+
".yml",
|
|
17245
|
+
".toml",
|
|
17246
|
+
".js",
|
|
17247
|
+
".ts",
|
|
17248
|
+
".mjs",
|
|
17249
|
+
".cjs",
|
|
17250
|
+
".sh",
|
|
17251
|
+
".bash",
|
|
17252
|
+
".zsh",
|
|
17253
|
+
".py",
|
|
17254
|
+
".ps1"
|
|
17255
|
+
]);
|
|
17256
|
+
EXECUTABLE_TEXT_EXTENSIONS = new Set([
|
|
17257
|
+
".js",
|
|
17258
|
+
".ts",
|
|
17259
|
+
".mjs",
|
|
17260
|
+
".cjs",
|
|
17261
|
+
".sh",
|
|
17262
|
+
".bash",
|
|
17263
|
+
".zsh",
|
|
17264
|
+
".py",
|
|
17265
|
+
".ps1"
|
|
17266
|
+
]);
|
|
17267
|
+
});
|
|
17268
|
+
|
|
16948
17269
|
// dist/types/skills.js
|
|
16949
17270
|
var SHARED_SKILLS_TARGET_ID, SHARED_SKILLS_TARGET_NAME;
|
|
16950
17271
|
var init_skills = __esm(() => {
|
|
@@ -16952,6 +17273,280 @@ var init_skills = __esm(() => {
|
|
|
16952
17273
|
SHARED_SKILLS_TARGET_NAME = "AGENTS.md ecosystem";
|
|
16953
17274
|
});
|
|
16954
17275
|
|
|
17276
|
+
// dist/core/installLock.js
|
|
17277
|
+
import {promises as fs23} from "fs";
|
|
17278
|
+
import {homedir as homedir4} from "os";
|
|
17279
|
+
import {dirname as dirname2, join as join5, resolve as resolve7} from "path";
|
|
17280
|
+
import {createHash, randomUUID} from "crypto";
|
|
17281
|
+
function getLockEntryTargetLabel(entry) {
|
|
17282
|
+
return entry.scope === "global" ? "Global scope" : entry.projectPath;
|
|
17283
|
+
}
|
|
17284
|
+
function logLockWriteWarning(context, error) {
|
|
17285
|
+
const detail = error instanceof Error ? error.message : "unknown error";
|
|
17286
|
+
logger.warn(`${context}, but failed to update the install lock: ${detail}`);
|
|
17287
|
+
}
|
|
17288
|
+
async function hashDirectory(rootPath) {
|
|
17289
|
+
if (!await fileExists(rootPath))
|
|
17290
|
+
return null;
|
|
17291
|
+
const hash = createHash("sha256");
|
|
17292
|
+
const walk = async (currentPath, relativePath) => {
|
|
17293
|
+
const stat = await fs23.stat(currentPath);
|
|
17294
|
+
if (stat.isDirectory()) {
|
|
17295
|
+
hash.update(`dir:${relativePath}\n`);
|
|
17296
|
+
const entries = await fs23.readdir(currentPath);
|
|
17297
|
+
entries.sort();
|
|
17298
|
+
for (const entry of entries) {
|
|
17299
|
+
await walk(join5(currentPath, entry), `${relativePath}/${entry}`);
|
|
17300
|
+
}
|
|
17301
|
+
} else {
|
|
17302
|
+
const content = await fs23.readFile(currentPath);
|
|
17303
|
+
hash.update(`file:${relativePath}\n`);
|
|
17304
|
+
hash.update(content);
|
|
17305
|
+
hash.update("\n");
|
|
17306
|
+
}
|
|
17307
|
+
};
|
|
17308
|
+
await walk(rootPath, ".");
|
|
17309
|
+
return hash.digest("hex");
|
|
17310
|
+
}
|
|
17311
|
+
|
|
17312
|
+
class InstallLock {
|
|
17313
|
+
state = null;
|
|
17314
|
+
async load() {
|
|
17315
|
+
if (this.state)
|
|
17316
|
+
return this.state;
|
|
17317
|
+
const content = await readFileIfExists(getLockPath());
|
|
17318
|
+
if (!content) {
|
|
17319
|
+
this.state = { version: 1, entries: [] };
|
|
17320
|
+
return this.state;
|
|
17321
|
+
}
|
|
17322
|
+
try {
|
|
17323
|
+
const parsed = JSON.parse(content);
|
|
17324
|
+
if (parsed?.version === 1 && Array.isArray(parsed.entries)) {
|
|
17325
|
+
this.state = parsed;
|
|
17326
|
+
} else {
|
|
17327
|
+
this.state = { version: 1, entries: [] };
|
|
17328
|
+
}
|
|
17329
|
+
} catch {
|
|
17330
|
+
this.state = { version: 1, entries: [] };
|
|
17331
|
+
}
|
|
17332
|
+
return this.state;
|
|
17333
|
+
}
|
|
17334
|
+
async save() {
|
|
17335
|
+
if (!this.state)
|
|
17336
|
+
return;
|
|
17337
|
+
const lockPath = getLockPath();
|
|
17338
|
+
await fs23.mkdir(dirname2(lockPath), { recursive: true });
|
|
17339
|
+
await fs23.writeFile(lockPath, JSON.stringify(this.state, null, 2) + "\n", {
|
|
17340
|
+
encoding: "utf8",
|
|
17341
|
+
mode: 384
|
|
17342
|
+
});
|
|
17343
|
+
await fs23.chmod(lockPath, 384).catch(() => {
|
|
17344
|
+
});
|
|
17345
|
+
}
|
|
17346
|
+
async recordSkill(params) {
|
|
17347
|
+
const state = await this.load();
|
|
17348
|
+
const metadata = {
|
|
17349
|
+
kind: "skill",
|
|
17350
|
+
installPath: params.installPath,
|
|
17351
|
+
...params.canonicalPath ? { canonicalPath: params.canonicalPath } : {},
|
|
17352
|
+
mode: params.mode
|
|
17353
|
+
};
|
|
17354
|
+
const entry = createEntry({
|
|
17355
|
+
kind: "skill",
|
|
17356
|
+
action: params.action,
|
|
17357
|
+
name: params.name,
|
|
17358
|
+
projectPath: resolve7(params.projectPath),
|
|
17359
|
+
agents: params.agents,
|
|
17360
|
+
scope: params.scope,
|
|
17361
|
+
source: params.source,
|
|
17362
|
+
...params.contentHash ? { contentHash: params.contentHash } : {},
|
|
17363
|
+
metadata
|
|
17364
|
+
});
|
|
17365
|
+
state.entries.push(entry);
|
|
17366
|
+
await this.save();
|
|
17367
|
+
return entry;
|
|
17368
|
+
}
|
|
17369
|
+
async recordMcp(params) {
|
|
17370
|
+
const state = await this.load();
|
|
17371
|
+
const metadata = {
|
|
17372
|
+
kind: "mcp",
|
|
17373
|
+
configPath: params.configPath,
|
|
17374
|
+
serverType: params.serverType,
|
|
17375
|
+
...params.command ? { command: params.command } : {},
|
|
17376
|
+
...params.url ? { url: sanitizeUrlForLock(params.url) } : {}
|
|
17377
|
+
};
|
|
17378
|
+
const entry = createEntry({
|
|
17379
|
+
kind: "mcp",
|
|
17380
|
+
action: params.action,
|
|
17381
|
+
name: params.name,
|
|
17382
|
+
projectPath: resolve7(params.projectPath),
|
|
17383
|
+
agents: params.agents,
|
|
17384
|
+
scope: params.scope,
|
|
17385
|
+
source: params.source,
|
|
17386
|
+
metadata
|
|
17387
|
+
});
|
|
17388
|
+
state.entries.push(entry);
|
|
17389
|
+
await this.save();
|
|
17390
|
+
return entry;
|
|
17391
|
+
}
|
|
17392
|
+
async recordRules(params) {
|
|
17393
|
+
const state = await this.load();
|
|
17394
|
+
const metadata = {
|
|
17395
|
+
kind: "rules",
|
|
17396
|
+
configPath: params.configPath,
|
|
17397
|
+
templateIds: params.templateIds,
|
|
17398
|
+
ruleCount: params.ruleCount
|
|
17399
|
+
};
|
|
17400
|
+
const entry = createEntry({
|
|
17401
|
+
kind: "rules",
|
|
17402
|
+
action: params.action,
|
|
17403
|
+
name: params.name,
|
|
17404
|
+
projectPath: resolve7(params.projectPath),
|
|
17405
|
+
agents: params.agents,
|
|
17406
|
+
scope: params.scope,
|
|
17407
|
+
source: params.source,
|
|
17408
|
+
metadata
|
|
17409
|
+
});
|
|
17410
|
+
state.entries.push(entry);
|
|
17411
|
+
await this.save();
|
|
17412
|
+
return entry;
|
|
17413
|
+
}
|
|
17414
|
+
async query(options2 = {}) {
|
|
17415
|
+
const state = await this.load();
|
|
17416
|
+
return state.entries.filter((entry) => {
|
|
17417
|
+
if (options2.kind && entry.kind !== options2.kind)
|
|
17418
|
+
return false;
|
|
17419
|
+
if (options2.name && entry.name.toLowerCase() !== options2.name.toLowerCase())
|
|
17420
|
+
return false;
|
|
17421
|
+
if (options2.projectPath && entry.projectPath !== resolve7(options2.projectPath))
|
|
17422
|
+
return false;
|
|
17423
|
+
if (options2.agent && !entry.agents.includes(options2.agent))
|
|
17424
|
+
return false;
|
|
17425
|
+
if (options2.scope && entry.scope !== options2.scope)
|
|
17426
|
+
return false;
|
|
17427
|
+
if (options2.action && entry.action !== options2.action)
|
|
17428
|
+
return false;
|
|
17429
|
+
return true;
|
|
17430
|
+
});
|
|
17431
|
+
}
|
|
17432
|
+
async getCurrentState(options2 = {}) {
|
|
17433
|
+
const entries = await this.query(options2);
|
|
17434
|
+
const groups = new Map;
|
|
17435
|
+
for (const entry of entries) {
|
|
17436
|
+
const key = this.getCurrentStateKey(entry);
|
|
17437
|
+
groups.set(key, entry);
|
|
17438
|
+
}
|
|
17439
|
+
return [...groups.values()].filter((e) => e.action !== "remove");
|
|
17440
|
+
}
|
|
17441
|
+
getCurrentStateKey(entry) {
|
|
17442
|
+
const agents = [...entry.agents].sort().join(",");
|
|
17443
|
+
return [
|
|
17444
|
+
entry.kind,
|
|
17445
|
+
entry.name.toLowerCase(),
|
|
17446
|
+
getEntryTargetKey(entry),
|
|
17447
|
+
entry.scope,
|
|
17448
|
+
agents,
|
|
17449
|
+
this.getLocationKey(entry)
|
|
17450
|
+
].join(":");
|
|
17451
|
+
}
|
|
17452
|
+
getLocationKey(entry) {
|
|
17453
|
+
switch (entry.metadata.kind) {
|
|
17454
|
+
case "skill":
|
|
17455
|
+
return entry.metadata.canonicalPath || entry.metadata.installPath;
|
|
17456
|
+
case "mcp":
|
|
17457
|
+
return entry.metadata.configPath;
|
|
17458
|
+
case "rules":
|
|
17459
|
+
return `${entry.metadata.configPath}:${entry.metadata.templateIds.join(",")}`;
|
|
17460
|
+
}
|
|
17461
|
+
}
|
|
17462
|
+
async getProjectPaths() {
|
|
17463
|
+
const state = await this.load();
|
|
17464
|
+
return [...new Set(state.entries.filter((entry) => entry.scope === "project").map((entry) => entry.projectPath))];
|
|
17465
|
+
}
|
|
17466
|
+
async findProjectsWithSkill(skillName) {
|
|
17467
|
+
return this.getCurrentState({ kind: "skill", name: skillName });
|
|
17468
|
+
}
|
|
17469
|
+
async findStaleProjects() {
|
|
17470
|
+
const projectPaths = await this.getProjectPaths();
|
|
17471
|
+
const stale = [];
|
|
17472
|
+
for (const projectPath of projectPaths) {
|
|
17473
|
+
if (!await fileExists(projectPath)) {
|
|
17474
|
+
stale.push(projectPath);
|
|
17475
|
+
}
|
|
17476
|
+
}
|
|
17477
|
+
return stale;
|
|
17478
|
+
}
|
|
17479
|
+
async pruneStaleEntries() {
|
|
17480
|
+
const stale = await this.findStaleProjects();
|
|
17481
|
+
let entriesRemoved = 0;
|
|
17482
|
+
if (stale.length === 0) {
|
|
17483
|
+
return { prunedProjects: [], entriesRemoved: 0 };
|
|
17484
|
+
}
|
|
17485
|
+
const state = await this.load();
|
|
17486
|
+
const staleSet = new Set(stale);
|
|
17487
|
+
const before = state.entries.length;
|
|
17488
|
+
state.entries = state.entries.filter((e) => !staleSet.has(e.projectPath));
|
|
17489
|
+
entriesRemoved = before - state.entries.length;
|
|
17490
|
+
if (entriesRemoved > 0) {
|
|
17491
|
+
await this.save();
|
|
17492
|
+
}
|
|
17493
|
+
return { prunedProjects: stale, entriesRemoved };
|
|
17494
|
+
}
|
|
17495
|
+
async checkDrift(entry) {
|
|
17496
|
+
if (!entry.contentHash) {
|
|
17497
|
+
return { entry, status: "match" };
|
|
17498
|
+
}
|
|
17499
|
+
if (entry.metadata.kind !== "skill") {
|
|
17500
|
+
return { entry, status: "match" };
|
|
17501
|
+
}
|
|
17502
|
+
const installPath = entry.metadata.installPath;
|
|
17503
|
+
if (!await fileExists(installPath)) {
|
|
17504
|
+
return { entry, status: "missing" };
|
|
17505
|
+
}
|
|
17506
|
+
const currentHash = await hashDirectory(installPath);
|
|
17507
|
+
if (!currentHash) {
|
|
17508
|
+
return { entry, status: "missing" };
|
|
17509
|
+
}
|
|
17510
|
+
return {
|
|
17511
|
+
entry,
|
|
17512
|
+
status: currentHash === entry.contentHash ? "match" : "drift",
|
|
17513
|
+
currentHash
|
|
17514
|
+
};
|
|
17515
|
+
}
|
|
17516
|
+
}
|
|
17517
|
+
var getLockPath, getEntryTargetKey, createEntry, sanitizeUrlForLock, LOCK_FILE, GLOBAL_TARGET_KEY;
|
|
17518
|
+
var init_installLock = __esm(() => {
|
|
17519
|
+
init_fs();
|
|
17520
|
+
init_logger();
|
|
17521
|
+
getLockPath = function() {
|
|
17522
|
+
return join5(homedir4(), ".agentinit", LOCK_FILE);
|
|
17523
|
+
};
|
|
17524
|
+
getEntryTargetKey = function(entry) {
|
|
17525
|
+
return entry.scope === "global" ? GLOBAL_TARGET_KEY : entry.projectPath;
|
|
17526
|
+
};
|
|
17527
|
+
createEntry = function(base) {
|
|
17528
|
+
return {
|
|
17529
|
+
id: randomUUID(),
|
|
17530
|
+
timestamp: new Date().toISOString(),
|
|
17531
|
+
...base
|
|
17532
|
+
};
|
|
17533
|
+
};
|
|
17534
|
+
sanitizeUrlForLock = function(url) {
|
|
17535
|
+
try {
|
|
17536
|
+
const parsed = new URL(url);
|
|
17537
|
+
parsed.username = "";
|
|
17538
|
+
parsed.password = "";
|
|
17539
|
+
parsed.search = "";
|
|
17540
|
+
parsed.hash = "";
|
|
17541
|
+
return parsed.toString();
|
|
17542
|
+
} catch {
|
|
17543
|
+
return url.split(/[?#]/)[0] || url;
|
|
17544
|
+
}
|
|
17545
|
+
};
|
|
17546
|
+
LOCK_FILE = "lock.json";
|
|
17547
|
+
GLOBAL_TARGET_KEY = "__agentinit_global__";
|
|
17548
|
+
});
|
|
17549
|
+
|
|
16955
17550
|
// dist/core/mcpFilter.js
|
|
16956
17551
|
class MCPFilter {
|
|
16957
17552
|
static filterForAgent(agent, servers) {
|
|
@@ -17066,9 +17661,9 @@ __export(exports_pluginManager, {
|
|
|
17066
17661
|
}
|
|
17067
17662
|
}
|
|
17068
17663
|
});
|
|
17069
|
-
import {resolve as
|
|
17070
|
-
import {promises as
|
|
17071
|
-
import {homedir as
|
|
17664
|
+
import {resolve as resolve8, join as join6, basename as basename2, relative as relative3, dirname as dirname3} from "path";
|
|
17665
|
+
import {promises as fs25} from "fs";
|
|
17666
|
+
import {homedir as homedir5} from "os";
|
|
17072
17667
|
|
|
17073
17668
|
class MultipleBundlePluginsError extends Error {
|
|
17074
17669
|
entries;
|
|
@@ -17112,7 +17707,7 @@ class PluginManager {
|
|
|
17112
17707
|
}
|
|
17113
17708
|
async cleanupLoadedPluginContext(context) {
|
|
17114
17709
|
if (context?.tempDir) {
|
|
17115
|
-
await
|
|
17710
|
+
await fs25.rm(context.tempDir, { recursive: true, force: true }).catch(() => {
|
|
17116
17711
|
});
|
|
17117
17712
|
}
|
|
17118
17713
|
}
|
|
@@ -17190,7 +17785,7 @@ class PluginManager {
|
|
|
17190
17785
|
return "unverified";
|
|
17191
17786
|
}
|
|
17192
17787
|
async resolvePreparedPluginDir(pluginDir, source) {
|
|
17193
|
-
const claudeMarketplaceManifestPath =
|
|
17788
|
+
const claudeMarketplaceManifestPath = join6(pluginDir, ".claude-plugin", "marketplace.json");
|
|
17194
17789
|
if (!await fileExists(claudeMarketplaceManifestPath)) {
|
|
17195
17790
|
return { pluginDir, warnings: [] };
|
|
17196
17791
|
}
|
|
@@ -17225,8 +17820,8 @@ class PluginManager {
|
|
|
17225
17820
|
}
|
|
17226
17821
|
selectedEntry = matched;
|
|
17227
17822
|
}
|
|
17228
|
-
const selectedPluginDir =
|
|
17229
|
-
const relativePath =
|
|
17823
|
+
const selectedPluginDir = resolve8(pluginDir, selectedEntry.source);
|
|
17824
|
+
const relativePath = relative3(resolve8(pluginDir), selectedPluginDir);
|
|
17230
17825
|
if (relativePath.startsWith("..") || relativePath.includes("/../") || relativePath.includes("\\..\\")) {
|
|
17231
17826
|
throw new Error(`Invalid bundled plugin source path "${selectedEntry.source}" in ${claudeMarketplaceManifestPath}`);
|
|
17232
17827
|
}
|
|
@@ -17293,7 +17888,7 @@ class PluginManager {
|
|
|
17293
17888
|
tempDir = await this.skillsManager.cloneRepo(resolved.url);
|
|
17294
17889
|
pluginDir = tempDir;
|
|
17295
17890
|
} else {
|
|
17296
|
-
pluginDir =
|
|
17891
|
+
pluginDir = resolve8(resolved.path || source);
|
|
17297
17892
|
if (!await fileExists(pluginDir)) {
|
|
17298
17893
|
throw new Error(`Local path not found: ${pluginDir}`);
|
|
17299
17894
|
}
|
|
@@ -17338,15 +17933,15 @@ class PluginManager {
|
|
|
17338
17933
|
}
|
|
17339
17934
|
async getClaudeNativeFeatureKinds(pluginDir, manifest) {
|
|
17340
17935
|
const featureChecks = await Promise.all([
|
|
17341
|
-
(async () => !!manifest.commands || await isDirectory(
|
|
17342
|
-
(async () => !!manifest.hooks || await isDirectory(
|
|
17343
|
-
(async () => !!manifest.agents || await isDirectory(
|
|
17344
|
-
isDirectory(
|
|
17345
|
-
(async () => !!manifest.mcpServers || await fileExists(
|
|
17346
|
-
isDirectory(
|
|
17347
|
-
isDirectory(
|
|
17348
|
-
isDirectory(
|
|
17349
|
-
isDirectory(
|
|
17936
|
+
(async () => !!manifest.commands || await isDirectory(join6(pluginDir, "commands")))(),
|
|
17937
|
+
(async () => !!manifest.hooks || await isDirectory(join6(pluginDir, "hooks")))(),
|
|
17938
|
+
(async () => !!manifest.agents || await isDirectory(join6(pluginDir, "agents")))(),
|
|
17939
|
+
isDirectory(join6(pluginDir, "skills")),
|
|
17940
|
+
(async () => !!manifest.mcpServers || await fileExists(join6(pluginDir, ".mcp.json")))(),
|
|
17941
|
+
isDirectory(join6(pluginDir, "prompts")),
|
|
17942
|
+
isDirectory(join6(pluginDir, "schemas")),
|
|
17943
|
+
isDirectory(join6(pluginDir, "scripts")),
|
|
17944
|
+
isDirectory(join6(pluginDir, "templates"))
|
|
17350
17945
|
]);
|
|
17351
17946
|
return [
|
|
17352
17947
|
...featureChecks[0] ? ["commands"] : [],
|
|
@@ -17364,7 +17959,7 @@ class PluginManager {
|
|
|
17364
17959
|
if (plugin.format !== "claude") {
|
|
17365
17960
|
return null;
|
|
17366
17961
|
}
|
|
17367
|
-
const manifestContent = await readFileIfExists(
|
|
17962
|
+
const manifestContent = await readFileIfExists(join6(pluginDir, ".claude-plugin", "plugin.json"));
|
|
17368
17963
|
if (!manifestContent) {
|
|
17369
17964
|
return null;
|
|
17370
17965
|
}
|
|
@@ -17384,7 +17979,7 @@ class PluginManager {
|
|
|
17384
17979
|
return {
|
|
17385
17980
|
namespace,
|
|
17386
17981
|
pluginKey: `${plugin.name}@${namespace}`,
|
|
17387
|
-
installPath:
|
|
17982
|
+
installPath: join6(homedir5(), ".claude", "plugins", "cache", namespace, plugin.name, versionDir),
|
|
17388
17983
|
marketplacePath: getClaudeMarketplaceInstallPath(namespace),
|
|
17389
17984
|
features
|
|
17390
17985
|
};
|
|
@@ -17448,12 +18043,12 @@ class PluginManager {
|
|
|
17448
18043
|
await writeFile(getClaudeSettingsPath(), JSON.stringify(state, null, 2));
|
|
17449
18044
|
}
|
|
17450
18045
|
async findClaudeMarketplaceRoot(pluginDir) {
|
|
17451
|
-
let currentDir =
|
|
18046
|
+
let currentDir = resolve8(pluginDir);
|
|
17452
18047
|
while (true) {
|
|
17453
|
-
if (await fileExists(
|
|
18048
|
+
if (await fileExists(join6(currentDir, ".claude-plugin", "marketplace.json"))) {
|
|
17454
18049
|
return currentDir;
|
|
17455
18050
|
}
|
|
17456
|
-
const parentDir =
|
|
18051
|
+
const parentDir = dirname3(currentDir);
|
|
17457
18052
|
if (parentDir === currentDir) {
|
|
17458
18053
|
return null;
|
|
17459
18054
|
}
|
|
@@ -17461,7 +18056,7 @@ class PluginManager {
|
|
|
17461
18056
|
}
|
|
17462
18057
|
}
|
|
17463
18058
|
async readClaudeMarketplaceManifest(marketplaceDir) {
|
|
17464
|
-
const manifestContent = await readFileIfExists(
|
|
18059
|
+
const manifestContent = await readFileIfExists(join6(marketplaceDir, ".claude-plugin", "marketplace.json"));
|
|
17465
18060
|
if (!manifestContent) {
|
|
17466
18061
|
return null;
|
|
17467
18062
|
}
|
|
@@ -17480,19 +18075,19 @@ class PluginManager {
|
|
|
17480
18075
|
}
|
|
17481
18076
|
}
|
|
17482
18077
|
async saveClaudeMarketplaceManifest(marketplaceDir, manifest) {
|
|
17483
|
-
await
|
|
17484
|
-
await writeFile(
|
|
18078
|
+
await fs25.mkdir(join6(marketplaceDir, ".claude-plugin"), { recursive: true });
|
|
18079
|
+
await writeFile(join6(marketplaceDir, ".claude-plugin", "marketplace.json"), JSON.stringify(manifest, null, 2));
|
|
17485
18080
|
}
|
|
17486
18081
|
resolveMarketplaceSourcePath(baseDir, relativePath) {
|
|
17487
|
-
const resolvedPath =
|
|
17488
|
-
const relativePathFromBase =
|
|
18082
|
+
const resolvedPath = resolve8(baseDir, relativePath);
|
|
18083
|
+
const relativePathFromBase = relative3(resolve8(baseDir), resolvedPath);
|
|
17489
18084
|
if (relativePathFromBase.startsWith("..") || relativePathFromBase.includes("/../") || relativePathFromBase.includes("\\..\\")) {
|
|
17490
18085
|
throw new Error(`Invalid marketplace source path "${relativePath}" in ${baseDir}`);
|
|
17491
18086
|
}
|
|
17492
18087
|
return resolvedPath;
|
|
17493
18088
|
}
|
|
17494
18089
|
async readClaudePluginMetadata(pluginDir) {
|
|
17495
|
-
const manifestContent = await readFileIfExists(
|
|
18090
|
+
const manifestContent = await readFileIfExists(join6(pluginDir, ".claude-plugin", "plugin.json"));
|
|
17496
18091
|
if (!manifestContent) {
|
|
17497
18092
|
return {};
|
|
17498
18093
|
}
|
|
@@ -17508,11 +18103,11 @@ class PluginManager {
|
|
|
17508
18103
|
}
|
|
17509
18104
|
}
|
|
17510
18105
|
async copyClaudeMarketplacePlugin(sourcePluginDir, marketplacePath, pluginName) {
|
|
17511
|
-
const marketplacePluginPath =
|
|
17512
|
-
await
|
|
17513
|
-
await
|
|
18106
|
+
const marketplacePluginPath = join6(marketplacePath, "plugins", pluginName);
|
|
18107
|
+
await fs25.mkdir(dirname3(marketplacePluginPath), { recursive: true });
|
|
18108
|
+
await fs25.rm(marketplacePluginPath, { recursive: true, force: true }).catch(() => {
|
|
17514
18109
|
});
|
|
17515
|
-
await
|
|
18110
|
+
await fs25.cp(sourcePluginDir, marketplacePluginPath, { recursive: true, dereference: true });
|
|
17516
18111
|
return marketplacePluginPath;
|
|
17517
18112
|
}
|
|
17518
18113
|
getClaudeMarketplaceSource(plugin, marketplaceRoot, marketplacePath) {
|
|
@@ -17533,7 +18128,7 @@ class PluginManager {
|
|
|
17533
18128
|
if (plugin.source.type === "local") {
|
|
17534
18129
|
return {
|
|
17535
18130
|
source: "directory",
|
|
17536
|
-
path:
|
|
18131
|
+
path: resolve8(marketplaceRoot || plugin.source.path || marketplacePath)
|
|
17537
18132
|
};
|
|
17538
18133
|
}
|
|
17539
18134
|
return {
|
|
@@ -17544,7 +18139,7 @@ class PluginManager {
|
|
|
17544
18139
|
async materializeClaudeMarketplace(plugin, pluginDir, target) {
|
|
17545
18140
|
const marketplaceRoot = await this.findClaudeMarketplaceRoot(pluginDir);
|
|
17546
18141
|
const marketplaceSource = this.getClaudeMarketplaceSource(plugin, marketplaceRoot, target.marketplacePath);
|
|
17547
|
-
await
|
|
18142
|
+
await fs25.mkdir(target.marketplacePath, { recursive: true });
|
|
17548
18143
|
const existingManifest = await this.readClaudeMarketplaceManifest(target.marketplacePath);
|
|
17549
18144
|
const sourceManifest = marketplaceRoot ? await this.readClaudeMarketplaceManifest(marketplaceRoot) : null;
|
|
17550
18145
|
const mergedManifest = {
|
|
@@ -17616,10 +18211,10 @@ class PluginManager {
|
|
|
17616
18211
|
warnings.push(`Skipped native Claude plugin install because Claude already has "${plugin.name}" installed as ${conflictingKey}.`);
|
|
17617
18212
|
return { installed, skipped, warnings };
|
|
17618
18213
|
}
|
|
17619
|
-
await
|
|
18214
|
+
await fs25.rm(nativeTarget.installPath, { recursive: true, force: true }).catch(() => {
|
|
17620
18215
|
});
|
|
17621
|
-
await
|
|
17622
|
-
await
|
|
18216
|
+
await fs25.mkdir(dirname3(nativeTarget.installPath), { recursive: true });
|
|
18217
|
+
await fs25.cp(pluginDir, nativeTarget.installPath, { recursive: true, dereference: true });
|
|
17623
18218
|
const marketplace = await this.materializeClaudeMarketplace(plugin, pluginDir, nativeTarget);
|
|
17624
18219
|
const now = new Date().toISOString();
|
|
17625
18220
|
claudeInstalled.plugins[nativeTarget.pluginKey] = [{
|
|
@@ -17659,7 +18254,7 @@ class PluginManager {
|
|
|
17659
18254
|
};
|
|
17660
18255
|
await this.saveClaudeKnownMarketplaces(knownMarketplaces);
|
|
17661
18256
|
for (const entry of legacyEntries) {
|
|
17662
|
-
await
|
|
18257
|
+
await fs25.rm(entry.installPath, { recursive: true, force: true }).catch(() => {
|
|
17663
18258
|
});
|
|
17664
18259
|
}
|
|
17665
18260
|
for (const legacyKey of legacyKeys) {
|
|
@@ -17707,7 +18302,7 @@ class PluginManager {
|
|
|
17707
18302
|
delete knownMarketplaces[marketplaceNamespace];
|
|
17708
18303
|
await this.saveClaudeKnownMarketplaces(knownMarketplaces);
|
|
17709
18304
|
}
|
|
17710
|
-
await
|
|
18305
|
+
await fs25.rm(getClaudeMarketplaceInstallPath(marketplaceNamespace), { recursive: true, force: true }).catch(() => {
|
|
17711
18306
|
});
|
|
17712
18307
|
} else if (marketplaceNamespace) {
|
|
17713
18308
|
const pluginName = component.pluginKey.split("@")[0] || "";
|
|
@@ -17715,14 +18310,14 @@ class PluginManager {
|
|
|
17715
18310
|
const manifest = await this.readClaudeMarketplaceManifest(marketplacePath);
|
|
17716
18311
|
if (pluginName && manifest) {
|
|
17717
18312
|
manifest.plugins = (manifest.plugins || []).filter((entry) => entry.name !== pluginName);
|
|
17718
|
-
const marketplacePluginPath =
|
|
17719
|
-
await
|
|
18313
|
+
const marketplacePluginPath = join6(marketplacePath, "plugins", pluginName);
|
|
18314
|
+
await fs25.rm(marketplacePluginPath, { recursive: true, force: true }).catch(() => {
|
|
17720
18315
|
});
|
|
17721
18316
|
await this.saveClaudeMarketplaceManifest(marketplacePath, manifest);
|
|
17722
18317
|
}
|
|
17723
18318
|
}
|
|
17724
18319
|
await this.saveClaudeSettings(claudeSettings);
|
|
17725
|
-
await
|
|
18320
|
+
await fs25.rm(component.installPath, { recursive: true, force: true }).catch(() => {
|
|
17726
18321
|
});
|
|
17727
18322
|
return true;
|
|
17728
18323
|
}
|
|
@@ -17795,7 +18390,7 @@ class PluginManager {
|
|
|
17795
18390
|
throw new Error(`Unknown marketplace: ${registryId}. Available: ${this.getMarketplaceIds().join(", ")}`);
|
|
17796
18391
|
}
|
|
17797
18392
|
const cacheDir = getMarketplaceCacheDir(registryId);
|
|
17798
|
-
const cacheMetaPath =
|
|
18393
|
+
const cacheMetaPath = join6(cacheDir, ".agentinit-cache-meta.json");
|
|
17799
18394
|
const cacheMeta = await this.readMarketplaceCacheMeta(cacheMetaPath);
|
|
17800
18395
|
if (cacheMeta?.repoUrl === registry.repoUrl) {
|
|
17801
18396
|
const age = Date.now() - cacheMeta.fetchedAt;
|
|
@@ -17803,10 +18398,10 @@ class PluginManager {
|
|
|
17803
18398
|
return cacheDir;
|
|
17804
18399
|
}
|
|
17805
18400
|
}
|
|
17806
|
-
if (await fileExists(
|
|
18401
|
+
if (await fileExists(join6(cacheDir, ".git"))) {
|
|
17807
18402
|
const originUrl = await this.getMarketplaceCacheOriginUrl(cacheDir);
|
|
17808
18403
|
if (originUrl !== registry.repoUrl) {
|
|
17809
|
-
await
|
|
18404
|
+
await fs25.rm(cacheDir, { recursive: true, force: true });
|
|
17810
18405
|
await this.cloneMarketplace(registry.repoUrl, cacheDir);
|
|
17811
18406
|
} else {
|
|
17812
18407
|
const { execFile } = await import("child_process");
|
|
@@ -17815,15 +18410,15 @@ class PluginManager {
|
|
|
17815
18410
|
try {
|
|
17816
18411
|
await exec("git", ["pull", "--ff-only"], { cwd: cacheDir, timeout: 30000 });
|
|
17817
18412
|
} catch {
|
|
17818
|
-
await
|
|
18413
|
+
await fs25.rm(cacheDir, { recursive: true, force: true });
|
|
17819
18414
|
await this.cloneMarketplace(registry.repoUrl, cacheDir);
|
|
17820
18415
|
}
|
|
17821
18416
|
}
|
|
17822
18417
|
} else {
|
|
17823
18418
|
await this.cloneMarketplace(registry.repoUrl, cacheDir);
|
|
17824
18419
|
}
|
|
17825
|
-
await
|
|
17826
|
-
await
|
|
18420
|
+
await fs25.mkdir(cacheDir, { recursive: true });
|
|
18421
|
+
await fs25.writeFile(cacheMetaPath, JSON.stringify({
|
|
17827
18422
|
fetchedAt: Date.now(),
|
|
17828
18423
|
repoUrl: registry.repoUrl
|
|
17829
18424
|
}));
|
|
@@ -17834,7 +18429,7 @@ class PluginManager {
|
|
|
17834
18429
|
return null;
|
|
17835
18430
|
}
|
|
17836
18431
|
try {
|
|
17837
|
-
const meta = JSON.parse(await
|
|
18432
|
+
const meta = JSON.parse(await fs25.readFile(cacheMetaPath, "utf8"));
|
|
17838
18433
|
if (typeof meta.fetchedAt !== "number") {
|
|
17839
18434
|
return null;
|
|
17840
18435
|
}
|
|
@@ -17862,11 +18457,11 @@ class PluginManager {
|
|
|
17862
18457
|
}
|
|
17863
18458
|
}
|
|
17864
18459
|
async cloneMarketplace(repoUrl, dest) {
|
|
17865
|
-
await
|
|
18460
|
+
await fs25.mkdir(dest, { recursive: true });
|
|
17866
18461
|
const { execFile } = await import("child_process");
|
|
17867
18462
|
const { promisify } = await import("util");
|
|
17868
18463
|
const exec = promisify(execFile);
|
|
17869
|
-
await
|
|
18464
|
+
await fs25.rm(dest, { recursive: true, force: true }).catch(() => {
|
|
17870
18465
|
});
|
|
17871
18466
|
await exec("git", ["clone", "--depth", "1", repoUrl, dest], { timeout: 60000 });
|
|
17872
18467
|
}
|
|
@@ -17876,7 +18471,7 @@ class PluginManager {
|
|
|
17876
18471
|
throw new Error(`Unknown marketplace: ${registryId}`);
|
|
17877
18472
|
const cacheDir = await this.ensureMarketplaceCache(registryId);
|
|
17878
18473
|
for (const dir of registry.pluginDirs) {
|
|
17879
|
-
const pluginPath =
|
|
18474
|
+
const pluginPath = join6(cacheDir, dir, name);
|
|
17880
18475
|
if (await isDirectory(pluginPath)) {
|
|
17881
18476
|
return pluginPath;
|
|
17882
18477
|
}
|
|
@@ -17892,7 +18487,7 @@ class PluginManager {
|
|
|
17892
18487
|
const cacheDir = await this.ensureMarketplaceCache(registryId);
|
|
17893
18488
|
const results = [];
|
|
17894
18489
|
for (const dir of registry.pluginDirs) {
|
|
17895
|
-
const fullDir =
|
|
18490
|
+
const fullDir = join6(cacheDir, dir);
|
|
17896
18491
|
if (!await isDirectory(fullDir))
|
|
17897
18492
|
continue;
|
|
17898
18493
|
const cat = getMarketplaceCategoryForDir(dir);
|
|
@@ -17902,26 +18497,26 @@ class PluginManager {
|
|
|
17902
18497
|
for (const entry of entries) {
|
|
17903
18498
|
if (entry.startsWith("."))
|
|
17904
18499
|
continue;
|
|
17905
|
-
const entryPath =
|
|
18500
|
+
const entryPath = join6(fullDir, entry);
|
|
17906
18501
|
if (!await isDirectory(entryPath))
|
|
17907
18502
|
continue;
|
|
17908
|
-
const manifestPath =
|
|
18503
|
+
const manifestPath = join6(entryPath, ".claude-plugin", "plugin.json");
|
|
17909
18504
|
let name = entry;
|
|
17910
18505
|
let description = "";
|
|
17911
18506
|
let version = "0.0.0";
|
|
17912
18507
|
if (await fileExists(manifestPath)) {
|
|
17913
18508
|
try {
|
|
17914
|
-
const manifest = JSON.parse(await
|
|
18509
|
+
const manifest = JSON.parse(await fs25.readFile(manifestPath, "utf8"));
|
|
17915
18510
|
name = manifest.name || entry;
|
|
17916
18511
|
description = manifest.description || "";
|
|
17917
18512
|
version = manifest.version || "0.0.0";
|
|
17918
18513
|
} catch {
|
|
17919
18514
|
}
|
|
17920
18515
|
} else {
|
|
17921
|
-
const skillMdPath =
|
|
18516
|
+
const skillMdPath = join6(entryPath, "SKILL.md");
|
|
17922
18517
|
if (await fileExists(skillMdPath)) {
|
|
17923
18518
|
try {
|
|
17924
|
-
const parsed = import_gray_matter.default(await
|
|
18519
|
+
const parsed = import_gray_matter.default(await fs25.readFile(skillMdPath, "utf8"));
|
|
17925
18520
|
if (parsed.data.name)
|
|
17926
18521
|
name = parsed.data.name;
|
|
17927
18522
|
if (parsed.data.description)
|
|
@@ -17929,10 +18524,10 @@ class PluginManager {
|
|
|
17929
18524
|
} catch {
|
|
17930
18525
|
}
|
|
17931
18526
|
} else {
|
|
17932
|
-
const mcpPath =
|
|
18527
|
+
const mcpPath = join6(entryPath, ".mcp.json");
|
|
17933
18528
|
if (await fileExists(mcpPath)) {
|
|
17934
18529
|
try {
|
|
17935
|
-
const mcpConfig = JSON.parse(await
|
|
18530
|
+
const mcpConfig = JSON.parse(await fs25.readFile(mcpPath, "utf8"));
|
|
17936
18531
|
const serverNames = Object.keys(mcpConfig.mcpServers || mcpConfig);
|
|
17937
18532
|
if (serverNames.length > 0) {
|
|
17938
18533
|
description = `MCP server(s): ${serverNames.join(", ")}`;
|
|
@@ -17954,10 +18549,10 @@ class PluginManager {
|
|
|
17954
18549
|
return results.sort((a, b) => a.name.localeCompare(b.name));
|
|
17955
18550
|
}
|
|
17956
18551
|
async detectFormat(pluginDir) {
|
|
17957
|
-
if (await fileExists(
|
|
18552
|
+
if (await fileExists(join6(pluginDir, ".claude-plugin", "plugin.json"))) {
|
|
17958
18553
|
return "claude";
|
|
17959
18554
|
}
|
|
17960
|
-
if (await fileExists(
|
|
18555
|
+
if (await fileExists(join6(pluginDir, ".cursor-plugin", "plugin.json"))) {
|
|
17961
18556
|
return "cursor";
|
|
17962
18557
|
}
|
|
17963
18558
|
return "generic";
|
|
@@ -17974,7 +18569,7 @@ class PluginManager {
|
|
|
17974
18569
|
}
|
|
17975
18570
|
}
|
|
17976
18571
|
async parseClaudePlugin(pluginDir, source) {
|
|
17977
|
-
const manifestPath =
|
|
18572
|
+
const manifestPath = join6(pluginDir, ".claude-plugin", "plugin.json");
|
|
17978
18573
|
const manifestContent = await readFileIfExists(manifestPath);
|
|
17979
18574
|
if (!manifestContent) {
|
|
17980
18575
|
throw new Error(`Missing .claude-plugin/plugin.json in ${pluginDir}`);
|
|
@@ -17985,10 +18580,10 @@ class PluginManager {
|
|
|
17985
18580
|
const convertedSkills = await this.convertCommandsToSkills(pluginDir, manifest);
|
|
17986
18581
|
skills.push(...convertedSkills);
|
|
17987
18582
|
const mcpServers = await this.parseMcpJson(pluginDir);
|
|
17988
|
-
if (await isDirectory(
|
|
18583
|
+
if (await isDirectory(join6(pluginDir, "hooks")) || manifest.hooks) {
|
|
17989
18584
|
warnings.push("Hooks (hooks/) are Claude Code-specific");
|
|
17990
18585
|
}
|
|
17991
|
-
if (await isDirectory(
|
|
18586
|
+
if (await isDirectory(join6(pluginDir, "agents")) || manifest.agents) {
|
|
17992
18587
|
warnings.push("Agent definitions (agents/) are Claude Code-specific");
|
|
17993
18588
|
}
|
|
17994
18589
|
return {
|
|
@@ -18003,7 +18598,7 @@ class PluginManager {
|
|
|
18003
18598
|
};
|
|
18004
18599
|
}
|
|
18005
18600
|
async parseCursorPlugin(pluginDir, source) {
|
|
18006
|
-
const manifestPath =
|
|
18601
|
+
const manifestPath = join6(pluginDir, ".cursor-plugin", "plugin.json");
|
|
18007
18602
|
const manifestContent = await readFileIfExists(manifestPath);
|
|
18008
18603
|
if (!manifestContent) {
|
|
18009
18604
|
throw new Error(`Missing .cursor-plugin/plugin.json in ${pluginDir}`);
|
|
@@ -18042,7 +18637,7 @@ class PluginManager {
|
|
|
18042
18637
|
};
|
|
18043
18638
|
}
|
|
18044
18639
|
async parseMcpJson(pluginDir) {
|
|
18045
|
-
const mcpPath =
|
|
18640
|
+
const mcpPath = join6(pluginDir, ".mcp.json");
|
|
18046
18641
|
const content = await readFileIfExists(mcpPath);
|
|
18047
18642
|
if (!content)
|
|
18048
18643
|
return [];
|
|
@@ -18086,10 +18681,10 @@ class PluginManager {
|
|
|
18086
18681
|
if (manifest.commands) {
|
|
18087
18682
|
const cmds = Array.isArray(manifest.commands) ? manifest.commands : [manifest.commands];
|
|
18088
18683
|
for (const cmd of cmds) {
|
|
18089
|
-
commandsDirs.push(
|
|
18684
|
+
commandsDirs.push(resolve8(pluginDir, cmd));
|
|
18090
18685
|
}
|
|
18091
18686
|
} else {
|
|
18092
|
-
commandsDirs.push(
|
|
18687
|
+
commandsDirs.push(join6(pluginDir, "commands"));
|
|
18093
18688
|
}
|
|
18094
18689
|
for (const commandsDir of commandsDirs) {
|
|
18095
18690
|
if (!await isDirectory(commandsDir))
|
|
@@ -18098,7 +18693,7 @@ class PluginManager {
|
|
|
18098
18693
|
for (const entry of entries) {
|
|
18099
18694
|
if (!entry.endsWith(".md"))
|
|
18100
18695
|
continue;
|
|
18101
|
-
const cmdPath =
|
|
18696
|
+
const cmdPath = join6(commandsDir, entry);
|
|
18102
18697
|
const skill = await this.convertSingleCommandToSkill(cmdPath, manifest.name);
|
|
18103
18698
|
if (skill)
|
|
18104
18699
|
skills.push(skill);
|
|
@@ -18412,7 +19007,7 @@ ${body.trim()}
|
|
|
18412
19007
|
}
|
|
18413
19008
|
if (!removedSkillPaths.has(skill.path)) {
|
|
18414
19009
|
try {
|
|
18415
|
-
await
|
|
19010
|
+
await fs25.rm(skill.path, { recursive: true, force: true });
|
|
18416
19011
|
removedSkillPaths.add(skill.path);
|
|
18417
19012
|
} catch {
|
|
18418
19013
|
details.push(`Could not remove skill path: ${skill.path}`);
|
|
@@ -18421,7 +19016,7 @@ ${body.trim()}
|
|
|
18421
19016
|
}
|
|
18422
19017
|
if (skill.canonicalPath && skill.canonicalPath !== skill.path && !removedCanonicalPaths.has(skill.canonicalPath) && !sharedCanonicalPath) {
|
|
18423
19018
|
try {
|
|
18424
|
-
await
|
|
19019
|
+
await fs25.rm(skill.canonicalPath, { recursive: true, force: true });
|
|
18425
19020
|
removedCanonicalPaths.add(skill.canonicalPath);
|
|
18426
19021
|
} catch {
|
|
18427
19022
|
details.push(`Could not remove canonical skill path: ${skill.canonicalPath}`);
|
|
@@ -18527,39 +19122,40 @@ var init_pluginManager = __esm(() => {
|
|
|
18527
19122
|
init_skillsManager();
|
|
18528
19123
|
init_userConfig();
|
|
18529
19124
|
getMarketplaceCacheDir = function(registryId) {
|
|
18530
|
-
return
|
|
19125
|
+
return join6(homedir5(), ".agentinit", "marketplace-cache", registryId);
|
|
18531
19126
|
};
|
|
18532
19127
|
getRegistryPath = function(projectPath, global3) {
|
|
18533
19128
|
if (global3) {
|
|
18534
|
-
return
|
|
19129
|
+
return join6(homedir5(), ".agentinit", "plugins.json");
|
|
18535
19130
|
}
|
|
18536
|
-
return
|
|
19131
|
+
return join6(projectPath, ".agentinit", "plugins.json");
|
|
18537
19132
|
};
|
|
18538
19133
|
getClaudeInstalledPluginsPath = function() {
|
|
18539
|
-
return
|
|
19134
|
+
return join6(homedir5(), ".claude", "plugins", "installed_plugins.json");
|
|
18540
19135
|
};
|
|
18541
19136
|
getClaudeKnownMarketplacesPath = function() {
|
|
18542
|
-
return
|
|
19137
|
+
return join6(homedir5(), ".claude", "plugins", "known_marketplaces.json");
|
|
18543
19138
|
};
|
|
18544
19139
|
getClaudeMarketplaceInstallPath = function(namespace) {
|
|
18545
|
-
return
|
|
19140
|
+
return join6(homedir5(), ".claude", "plugins", "marketplaces", namespace);
|
|
18546
19141
|
};
|
|
18547
19142
|
getClaudeSettingsPath = function() {
|
|
18548
|
-
return
|
|
19143
|
+
return join6(homedir5(), ".claude", "settings.json");
|
|
18549
19144
|
};
|
|
18550
19145
|
});
|
|
18551
19146
|
|
|
18552
19147
|
// dist/core/skillsManager.js
|
|
18553
|
-
import {resolve as
|
|
18554
|
-
import {promises as
|
|
18555
|
-
import {homedir as
|
|
19148
|
+
import {resolve as resolve9, join as join7, relative as relative4, basename as basename3, dirname as dirname4} from "path";
|
|
19149
|
+
import {promises as fs27} from "fs";
|
|
19150
|
+
import {homedir as homedir6, tmpdir} from "os";
|
|
18556
19151
|
import {execFile} from "child_process";
|
|
18557
|
-
import {createHash} from "crypto";
|
|
19152
|
+
import {createHash as createHash2} from "crypto";
|
|
18558
19153
|
import {promisify} from "util";
|
|
18559
19154
|
|
|
18560
19155
|
class SkillsManager {
|
|
18561
19156
|
agentManager;
|
|
18562
19157
|
preparedSourceContexts = new Map;
|
|
19158
|
+
skillScanner = new SkillSecurityScanner;
|
|
18563
19159
|
constructor(agentManager3) {
|
|
18564
19160
|
this.agentManager = agentManager3 || new AgentManager;
|
|
18565
19161
|
}
|
|
@@ -18567,11 +19163,15 @@ class SkillsManager {
|
|
|
18567
19163
|
if (source.startsWith(".") || source.startsWith("/") || source.startsWith("~")) {
|
|
18568
19164
|
return { type: "local", path: source };
|
|
18569
19165
|
}
|
|
18570
|
-
const
|
|
18571
|
-
if (
|
|
18572
|
-
return
|
|
19166
|
+
const httpSource = this.parseHttpRepositorySource(source);
|
|
19167
|
+
if (httpSource) {
|
|
19168
|
+
return httpSource;
|
|
18573
19169
|
}
|
|
18574
|
-
|
|
19170
|
+
const sshSource = this.parseSshRepositorySource(source);
|
|
19171
|
+
if (sshSource) {
|
|
19172
|
+
return sshSource;
|
|
19173
|
+
}
|
|
19174
|
+
if (source.endsWith(".git")) {
|
|
18575
19175
|
return { type: "github", url: source };
|
|
18576
19176
|
}
|
|
18577
19177
|
if (options2?.from) {
|
|
@@ -18584,6 +19184,14 @@ class SkillsManager {
|
|
|
18584
19184
|
pluginName: source
|
|
18585
19185
|
};
|
|
18586
19186
|
}
|
|
19187
|
+
const gitLabShorthandSource = this.parseGitLabShorthandSource(source);
|
|
19188
|
+
if (gitLabShorthandSource) {
|
|
19189
|
+
return gitLabShorthandSource;
|
|
19190
|
+
}
|
|
19191
|
+
const bitbucketShorthandSource = this.parseBitbucketShorthandSource(source);
|
|
19192
|
+
if (bitbucketShorthandSource) {
|
|
19193
|
+
return bitbucketShorthandSource;
|
|
19194
|
+
}
|
|
18587
19195
|
const githubShorthandSource = this.parseGitHubShorthandSource(source);
|
|
18588
19196
|
if (githubShorthandSource?.subpath) {
|
|
18589
19197
|
return githubShorthandSource;
|
|
@@ -18673,6 +19281,106 @@ class SkillsManager {
|
|
|
18673
19281
|
return null;
|
|
18674
19282
|
}
|
|
18675
19283
|
}
|
|
19284
|
+
parseGitLabHttpSource(source) {
|
|
19285
|
+
if (!source.startsWith("https://gitlab.com/") && !source.startsWith("http://gitlab.com/")) {
|
|
19286
|
+
return null;
|
|
19287
|
+
}
|
|
19288
|
+
try {
|
|
19289
|
+
const parsedUrl = new URL(source);
|
|
19290
|
+
const segments = parsedUrl.pathname.replace(/\/+$/, "").split("/").filter(Boolean);
|
|
19291
|
+
const dashIndex = segments.indexOf("-");
|
|
19292
|
+
const repoBoundary = dashIndex >= 0 ? dashIndex : segments.length;
|
|
19293
|
+
if (repoBoundary < 2) {
|
|
19294
|
+
return null;
|
|
19295
|
+
}
|
|
19296
|
+
const repo = segments[repoBoundary - 1];
|
|
19297
|
+
const owner = segments.slice(0, repoBoundary - 1).join("/");
|
|
19298
|
+
if (!owner || !repo) {
|
|
19299
|
+
return null;
|
|
19300
|
+
}
|
|
19301
|
+
let subpath;
|
|
19302
|
+
if (dashIndex >= 0) {
|
|
19303
|
+
const marker = segments[dashIndex + 1];
|
|
19304
|
+
if ((marker === "tree" || marker === "blob") && segments.length > dashIndex + 3) {
|
|
19305
|
+
subpath = segments.slice(dashIndex + 3).join("/");
|
|
19306
|
+
}
|
|
19307
|
+
}
|
|
19308
|
+
return {
|
|
19309
|
+
type: "gitlab",
|
|
19310
|
+
url: `https://gitlab.com/${owner}/${repo}.git`,
|
|
19311
|
+
owner,
|
|
19312
|
+
repo,
|
|
19313
|
+
...subpath ? { subpath } : {}
|
|
19314
|
+
};
|
|
19315
|
+
} catch {
|
|
19316
|
+
return null;
|
|
19317
|
+
}
|
|
19318
|
+
}
|
|
19319
|
+
parseBitbucketHttpSource(source) {
|
|
19320
|
+
if (!source.startsWith("https://bitbucket.org/") && !source.startsWith("http://bitbucket.org/")) {
|
|
19321
|
+
return null;
|
|
19322
|
+
}
|
|
19323
|
+
try {
|
|
19324
|
+
const parsedUrl = new URL(source);
|
|
19325
|
+
const segments = parsedUrl.pathname.replace(/\/+$/, "").split("/").filter(Boolean);
|
|
19326
|
+
if (segments.length < 2) {
|
|
19327
|
+
return null;
|
|
19328
|
+
}
|
|
19329
|
+
const [owner, repo, marker, _commitish, ...rest] = segments;
|
|
19330
|
+
if (!owner || !repo) {
|
|
19331
|
+
return null;
|
|
19332
|
+
}
|
|
19333
|
+
let subpath;
|
|
19334
|
+
if (marker === "src" && rest.length > 0) {
|
|
19335
|
+
subpath = rest.join("/");
|
|
19336
|
+
}
|
|
19337
|
+
return {
|
|
19338
|
+
type: "bitbucket",
|
|
19339
|
+
url: `https://bitbucket.org/${owner}/${repo}.git`,
|
|
19340
|
+
owner,
|
|
19341
|
+
repo,
|
|
19342
|
+
...subpath ? { subpath } : {}
|
|
19343
|
+
};
|
|
19344
|
+
} catch {
|
|
19345
|
+
return null;
|
|
19346
|
+
}
|
|
19347
|
+
}
|
|
19348
|
+
parseHttpRepositorySource(source) {
|
|
19349
|
+
return this.parseGitHubHttpSource(source) || this.parseGitLabHttpSource(source) || this.parseBitbucketHttpSource(source);
|
|
19350
|
+
}
|
|
19351
|
+
parseSshRepositorySource(source) {
|
|
19352
|
+
const githubMatch = source.match(/^git@github\.com:([^/]+)\/([^/]+?)(?:\.git)?$/);
|
|
19353
|
+
if (githubMatch) {
|
|
19354
|
+
const [, owner, repo] = githubMatch;
|
|
19355
|
+
return {
|
|
19356
|
+
type: "github",
|
|
19357
|
+
url: `git@github.com:${owner}/${repo}.git`,
|
|
19358
|
+
owner,
|
|
19359
|
+
repo
|
|
19360
|
+
};
|
|
19361
|
+
}
|
|
19362
|
+
const gitlabMatch = source.match(/^git@gitlab\.com:(.+)\/([^/]+?)(?:\.git)?$/);
|
|
19363
|
+
if (gitlabMatch) {
|
|
19364
|
+
const [, owner, repo] = gitlabMatch;
|
|
19365
|
+
return {
|
|
19366
|
+
type: "gitlab",
|
|
19367
|
+
url: `git@gitlab.com:${owner}/${repo}.git`,
|
|
19368
|
+
owner,
|
|
19369
|
+
repo
|
|
19370
|
+
};
|
|
19371
|
+
}
|
|
19372
|
+
const bitbucketMatch = source.match(/^git@bitbucket\.org:([^/]+)\/([^/]+?)(?:\.git)?$/);
|
|
19373
|
+
if (bitbucketMatch) {
|
|
19374
|
+
const [, owner, repo] = bitbucketMatch;
|
|
19375
|
+
return {
|
|
19376
|
+
type: "bitbucket",
|
|
19377
|
+
url: `git@bitbucket.org:${owner}/${repo}.git`,
|
|
19378
|
+
owner,
|
|
19379
|
+
repo
|
|
19380
|
+
};
|
|
19381
|
+
}
|
|
19382
|
+
return null;
|
|
19383
|
+
}
|
|
18676
19384
|
parseGitHubShorthandSource(source) {
|
|
18677
19385
|
const githubShorthandMatch = source.match(/^([a-zA-Z0-9._-]+)\/([a-zA-Z0-9._-]+)(?:\/(.+))?$/);
|
|
18678
19386
|
if (!githubShorthandMatch) {
|
|
@@ -18687,6 +19395,50 @@ class SkillsManager {
|
|
|
18687
19395
|
...subpath ? { subpath } : {}
|
|
18688
19396
|
};
|
|
18689
19397
|
}
|
|
19398
|
+
parseGitLabShorthandSource(source) {
|
|
19399
|
+
const normalized = source.startsWith("gitlab:") ? source.slice("gitlab:".length) : source.startsWith("gitlab.com/") ? source.slice("gitlab.com/".length) : null;
|
|
19400
|
+
if (!normalized) {
|
|
19401
|
+
return null;
|
|
19402
|
+
}
|
|
19403
|
+
const [repoSpec = normalized, subpathSpec] = normalized.split("//", 2);
|
|
19404
|
+
const segments = repoSpec.split("/").filter(Boolean);
|
|
19405
|
+
if (segments.length < 2) {
|
|
19406
|
+
return null;
|
|
19407
|
+
}
|
|
19408
|
+
const repo = segments[segments.length - 1];
|
|
19409
|
+
const owner = segments.slice(0, segments.length - 1).join("/");
|
|
19410
|
+
if (!owner || !repo) {
|
|
19411
|
+
return null;
|
|
19412
|
+
}
|
|
19413
|
+
return {
|
|
19414
|
+
type: "gitlab",
|
|
19415
|
+
url: `https://gitlab.com/${owner}/${repo}.git`,
|
|
19416
|
+
owner,
|
|
19417
|
+
repo,
|
|
19418
|
+
...subpathSpec ? { subpath: subpathSpec } : {}
|
|
19419
|
+
};
|
|
19420
|
+
}
|
|
19421
|
+
parseBitbucketShorthandSource(source) {
|
|
19422
|
+
const normalized = source.startsWith("bitbucket:") ? source.slice("bitbucket:".length) : source.startsWith("bitbucket.org/") ? source.slice("bitbucket.org/".length) : null;
|
|
19423
|
+
if (!normalized) {
|
|
19424
|
+
return null;
|
|
19425
|
+
}
|
|
19426
|
+
const segments = normalized.split("/").filter(Boolean);
|
|
19427
|
+
if (segments.length < 2) {
|
|
19428
|
+
return null;
|
|
19429
|
+
}
|
|
19430
|
+
const [owner, repo, ...rest] = segments;
|
|
19431
|
+
if (!owner || !repo) {
|
|
19432
|
+
return null;
|
|
19433
|
+
}
|
|
19434
|
+
return {
|
|
19435
|
+
type: "bitbucket",
|
|
19436
|
+
url: `https://bitbucket.org/${owner}/${repo}.git`,
|
|
19437
|
+
owner,
|
|
19438
|
+
repo,
|
|
19439
|
+
...rest.length > 0 ? { subpath: rest.join("/") } : {}
|
|
19440
|
+
};
|
|
19441
|
+
}
|
|
18690
19442
|
async parseSkillMd(filePath) {
|
|
18691
19443
|
const content = await readFileIfExists(filePath);
|
|
18692
19444
|
if (!content)
|
|
@@ -18705,34 +19457,34 @@ class SkillsManager {
|
|
|
18705
19457
|
const skills2 = [];
|
|
18706
19458
|
const seen = new Set;
|
|
18707
19459
|
for (const searchDir of SKILL_SEARCH_DIRS) {
|
|
18708
|
-
const fullDir =
|
|
19460
|
+
const fullDir = resolve9(repoPath, searchDir);
|
|
18709
19461
|
if (!await fileExists(fullDir))
|
|
18710
19462
|
continue;
|
|
18711
|
-
const directSkillMd =
|
|
19463
|
+
const directSkillMd = join7(fullDir, "SKILL.md");
|
|
18712
19464
|
if (await fileExists(directSkillMd)) {
|
|
18713
19465
|
const parsed = await this.parseSkillMd(directSkillMd);
|
|
18714
19466
|
if (parsed && !seen.has(parsed.name)) {
|
|
18715
19467
|
seen.add(parsed.name);
|
|
18716
|
-
skills2.push({ ...parsed, path:
|
|
19468
|
+
skills2.push({ ...parsed, path: resolve9(fullDir) });
|
|
18717
19469
|
}
|
|
18718
19470
|
}
|
|
18719
|
-
const directSkillMdLower =
|
|
19471
|
+
const directSkillMdLower = join7(fullDir, "skill.md");
|
|
18720
19472
|
if (await fileExists(directSkillMdLower)) {
|
|
18721
19473
|
const parsed = await this.parseSkillMd(directSkillMdLower);
|
|
18722
19474
|
if (parsed && !seen.has(parsed.name)) {
|
|
18723
19475
|
seen.add(parsed.name);
|
|
18724
|
-
skills2.push({ ...parsed, path:
|
|
19476
|
+
skills2.push({ ...parsed, path: resolve9(fullDir) });
|
|
18725
19477
|
}
|
|
18726
19478
|
}
|
|
18727
19479
|
if (!await isDirectory(fullDir))
|
|
18728
19480
|
continue;
|
|
18729
19481
|
const entries = await listFiles(fullDir);
|
|
18730
19482
|
for (const entry of entries) {
|
|
18731
|
-
const entryPath =
|
|
19483
|
+
const entryPath = join7(fullDir, entry);
|
|
18732
19484
|
if (!await isDirectory(entryPath))
|
|
18733
19485
|
continue;
|
|
18734
|
-
const skillMdPath =
|
|
18735
|
-
const skillMdPathLower =
|
|
19486
|
+
const skillMdPath = join7(entryPath, "SKILL.md");
|
|
19487
|
+
const skillMdPathLower = join7(entryPath, "skill.md");
|
|
18736
19488
|
const skillFile = await fileExists(skillMdPath) ? skillMdPath : await fileExists(skillMdPathLower) ? skillMdPathLower : null;
|
|
18737
19489
|
if (!skillFile)
|
|
18738
19490
|
continue;
|
|
@@ -18746,14 +19498,14 @@ class SkillsManager {
|
|
|
18746
19498
|
return skills2;
|
|
18747
19499
|
}
|
|
18748
19500
|
async cloneRepo(url) {
|
|
18749
|
-
const tempDir = await
|
|
18750
|
-
await
|
|
19501
|
+
const tempDir = await fs27.mkdtemp(join7(tmpdir(), "agentinit-skills-"));
|
|
19502
|
+
await fs27.rm(tempDir, { recursive: true, force: true });
|
|
18751
19503
|
try {
|
|
18752
19504
|
await execFileAsync("git", ["clone", "--depth", "1", url, tempDir], {
|
|
18753
19505
|
timeout: 60000
|
|
18754
19506
|
});
|
|
18755
19507
|
} catch (error) {
|
|
18756
|
-
await
|
|
19508
|
+
await fs27.rm(tempDir, { recursive: true, force: true }).catch(() => {
|
|
18757
19509
|
});
|
|
18758
19510
|
throw new Error(`Failed to clone ${url}: ${error.message}`);
|
|
18759
19511
|
}
|
|
@@ -18811,15 +19563,15 @@ class SkillsManager {
|
|
|
18811
19563
|
if (!tempDir) {
|
|
18812
19564
|
return;
|
|
18813
19565
|
}
|
|
18814
|
-
await
|
|
19566
|
+
await fs27.rm(tempDir, { recursive: true, force: true }).catch(() => {
|
|
18815
19567
|
});
|
|
18816
19568
|
}
|
|
18817
19569
|
async resolveDiscoveryRoot(repoPath, source, sourceLabel) {
|
|
18818
|
-
const resolvedRepoPath =
|
|
18819
|
-
if (source.type !== "github" || !source.subpath) {
|
|
19570
|
+
const resolvedRepoPath = resolve9(repoPath);
|
|
19571
|
+
if (source.type !== "github" && source.type !== "gitlab" && source.type !== "bitbucket" || !source.subpath) {
|
|
18820
19572
|
return resolvedRepoPath;
|
|
18821
19573
|
}
|
|
18822
|
-
const discoveryRoot =
|
|
19574
|
+
const discoveryRoot = resolve9(resolvedRepoPath, source.subpath);
|
|
18823
19575
|
if (!this.isWithinPath(resolvedRepoPath, discoveryRoot)) {
|
|
18824
19576
|
throw new Error(`Invalid GitHub source path "${source.subpath}" in ${sourceLabel}`);
|
|
18825
19577
|
}
|
|
@@ -18837,7 +19589,7 @@ class SkillsManager {
|
|
|
18837
19589
|
return realDiscoveryRoot;
|
|
18838
19590
|
}
|
|
18839
19591
|
if (basename3(realDiscoveryRoot).toLowerCase() === "skill.md") {
|
|
18840
|
-
return
|
|
19592
|
+
return dirname4(realDiscoveryRoot);
|
|
18841
19593
|
}
|
|
18842
19594
|
throw new Error(`GitHub source must reference a skill directory or SKILL.md: ${sourceLabel}`);
|
|
18843
19595
|
}
|
|
@@ -18861,14 +19613,14 @@ class SkillsManager {
|
|
|
18861
19613
|
};
|
|
18862
19614
|
}
|
|
18863
19615
|
let repoPath;
|
|
18864
|
-
if (resolved.type === "github") {
|
|
19616
|
+
if (resolved.type === "github" || resolved.type === "gitlab" || resolved.type === "bitbucket") {
|
|
18865
19617
|
if (!resolved.url) {
|
|
18866
19618
|
throw new Error(`Invalid source: ${source}`);
|
|
18867
19619
|
}
|
|
18868
19620
|
tempDir = await this.cloneRepo(resolved.url);
|
|
18869
19621
|
repoPath = tempDir;
|
|
18870
19622
|
} else {
|
|
18871
|
-
repoPath =
|
|
19623
|
+
repoPath = resolve9(resolved.path || source);
|
|
18872
19624
|
if (!await fileExists(repoPath)) {
|
|
18873
19625
|
throw this.getMissingLocalPathError(source, repoPath);
|
|
18874
19626
|
}
|
|
@@ -18955,30 +19707,30 @@ class SkillsManager {
|
|
|
18955
19707
|
async installSkill(skillPath, skillName, targetDir, copy = false) {
|
|
18956
19708
|
const normalizedSkillName = this.normalizeSkillName(skillName);
|
|
18957
19709
|
const destPath = this.resolveInstallPath(targetDir, normalizedSkillName);
|
|
18958
|
-
await
|
|
19710
|
+
await fs27.mkdir(resolve9(targetDir), { recursive: true });
|
|
18959
19711
|
if (await fileExists(destPath)) {
|
|
18960
|
-
await
|
|
19712
|
+
await fs27.rm(destPath, { recursive: true, force: true });
|
|
18961
19713
|
}
|
|
18962
19714
|
if (copy) {
|
|
18963
19715
|
await this.copyDir(skillPath, destPath);
|
|
18964
19716
|
} else {
|
|
18965
|
-
await
|
|
19717
|
+
await fs27.symlink(skillPath, destPath, "dir");
|
|
18966
19718
|
}
|
|
18967
19719
|
return destPath;
|
|
18968
19720
|
}
|
|
18969
19721
|
async installSkillFromContent(skillName, skillContent, targetDir) {
|
|
18970
19722
|
const normalizedSkillName = this.normalizeSkillName(skillName);
|
|
18971
19723
|
const destPath = this.resolveInstallPath(targetDir, normalizedSkillName);
|
|
18972
|
-
await
|
|
19724
|
+
await fs27.mkdir(resolve9(targetDir), { recursive: true });
|
|
18973
19725
|
if (await fileExists(destPath)) {
|
|
18974
|
-
await
|
|
19726
|
+
await fs27.rm(destPath, { recursive: true, force: true });
|
|
18975
19727
|
}
|
|
18976
|
-
await
|
|
18977
|
-
await
|
|
19728
|
+
await fs27.mkdir(destPath, { recursive: true });
|
|
19729
|
+
await fs27.writeFile(join7(destPath, "SKILL.md"), skillContent, "utf8");
|
|
18978
19730
|
return destPath;
|
|
18979
19731
|
}
|
|
18980
19732
|
getCanonicalSkillsDir(projectPath, global3 = false) {
|
|
18981
|
-
return global3 ?
|
|
19733
|
+
return global3 ? resolve9(homedir6(), ".agents/skills") : resolve9(projectPath, ".agents/skills");
|
|
18982
19734
|
}
|
|
18983
19735
|
async getInstallPlan(skillName, agent, projectPath, options2 = {}) {
|
|
18984
19736
|
const normalizedSkillName = this.normalizeSkillName(skillName);
|
|
@@ -19021,7 +19773,7 @@ class SkillsManager {
|
|
|
19021
19773
|
...options2.global !== undefined ? { global: options2.global } : {},
|
|
19022
19774
|
...options2.copy !== undefined ? { copy: options2.copy } : {}
|
|
19023
19775
|
});
|
|
19024
|
-
return this.
|
|
19776
|
+
return this.compareSkillInstallStatus(skill, plan);
|
|
19025
19777
|
}
|
|
19026
19778
|
async installSkillForAgent(skillPath, skillName, agent, projectPath, options2 = {}) {
|
|
19027
19779
|
const plan = await this.getInstallPlan(skillName, agent, projectPath, options2);
|
|
@@ -19068,7 +19820,7 @@ class SkillsManager {
|
|
|
19068
19820
|
throw new Error(`Missing canonical path for ${skillName}`);
|
|
19069
19821
|
}
|
|
19070
19822
|
await this.cleanAndCreateDirectory(canonicalPath);
|
|
19071
|
-
await
|
|
19823
|
+
await fs27.writeFile(join7(canonicalPath, "SKILL.md"), skillContent, "utf8");
|
|
19072
19824
|
if (plan.path === canonicalPath) {
|
|
19073
19825
|
return plan;
|
|
19074
19826
|
}
|
|
@@ -19091,7 +19843,7 @@ class SkillsManager {
|
|
|
19091
19843
|
async installSkillFromContentToCanonicalStore(skillName, skillContent, projectPath, options2 = {}) {
|
|
19092
19844
|
const plan = this.getCanonicalInstallPlan(skillName, projectPath, options2);
|
|
19093
19845
|
await this.cleanAndCreateDirectory(plan.path);
|
|
19094
|
-
await
|
|
19846
|
+
await fs27.writeFile(join7(plan.path, "SKILL.md"), skillContent, "utf8");
|
|
19095
19847
|
return plan;
|
|
19096
19848
|
}
|
|
19097
19849
|
getCanonicalInstallPlan(skillName, projectPath, options2 = {}) {
|
|
@@ -19103,6 +19855,76 @@ class SkillsManager {
|
|
|
19103
19855
|
mode: "symlink"
|
|
19104
19856
|
};
|
|
19105
19857
|
}
|
|
19858
|
+
normalizeSkillPrefix(prefix) {
|
|
19859
|
+
const normalized = prefix?.trim() ?? "";
|
|
19860
|
+
if (normalized.includes("/") || normalized.includes("\\")) {
|
|
19861
|
+
throw new Error(`Invalid skill prefix: ${prefix}`);
|
|
19862
|
+
}
|
|
19863
|
+
return normalized;
|
|
19864
|
+
}
|
|
19865
|
+
withSkillPrefix(skillName, prefix) {
|
|
19866
|
+
const normalizedPrefix = this.normalizeSkillPrefix(prefix);
|
|
19867
|
+
return normalizedPrefix ? `${normalizedPrefix}${skillName}` : skillName;
|
|
19868
|
+
}
|
|
19869
|
+
async rewriteSkillFileName(filePath, skillName) {
|
|
19870
|
+
const content = await fs27.readFile(filePath, "utf8");
|
|
19871
|
+
const parsed = import_gray_matter2.default(content);
|
|
19872
|
+
const nextContent = import_gray_matter2.default.stringify(parsed.content, {
|
|
19873
|
+
...parsed.data,
|
|
19874
|
+
name: skillName
|
|
19875
|
+
});
|
|
19876
|
+
await fs27.writeFile(filePath, nextContent, "utf8");
|
|
19877
|
+
}
|
|
19878
|
+
async applyPrefixToSkills(skills2, prefix) {
|
|
19879
|
+
const normalizedPrefix = this.normalizeSkillPrefix(prefix);
|
|
19880
|
+
if (!normalizedPrefix) {
|
|
19881
|
+
return { skills: skills2, cleanup: async () => {
|
|
19882
|
+
} };
|
|
19883
|
+
}
|
|
19884
|
+
const tempDirs = [];
|
|
19885
|
+
try {
|
|
19886
|
+
const prefixedSkills = await Promise.all(skills2.map(async (skill) => {
|
|
19887
|
+
const name = this.withSkillPrefix(skill.name, normalizedPrefix);
|
|
19888
|
+
if (skill.generatedContent) {
|
|
19889
|
+
return {
|
|
19890
|
+
...skill,
|
|
19891
|
+
name,
|
|
19892
|
+
generatedContent: import_gray_matter2.default.stringify(import_gray_matter2.default(skill.generatedContent).content, {
|
|
19893
|
+
...import_gray_matter2.default(skill.generatedContent).data,
|
|
19894
|
+
name
|
|
19895
|
+
})
|
|
19896
|
+
};
|
|
19897
|
+
}
|
|
19898
|
+
const tempRoot = await fs27.mkdtemp(join7(tmpdir(), "agentinit-prefixed-skill-"));
|
|
19899
|
+
const tempSkillPath = join7(tempRoot, basename3(skill.path));
|
|
19900
|
+
tempDirs.push(tempRoot);
|
|
19901
|
+
await this.copyDir(skill.path, tempSkillPath);
|
|
19902
|
+
const skillMdPath = join7(tempSkillPath, "SKILL.md");
|
|
19903
|
+
const skillMdPathLower = join7(tempSkillPath, "skill.md");
|
|
19904
|
+
const skillFile = await fileExists(skillMdPath) ? skillMdPath : await fileExists(skillMdPathLower) ? skillMdPathLower : null;
|
|
19905
|
+
if (!skillFile) {
|
|
19906
|
+
throw new Error(`Skill "${skill.name}" is missing SKILL.md`);
|
|
19907
|
+
}
|
|
19908
|
+
await this.rewriteSkillFileName(skillFile, name);
|
|
19909
|
+
return {
|
|
19910
|
+
...skill,
|
|
19911
|
+
name,
|
|
19912
|
+
path: tempSkillPath
|
|
19913
|
+
};
|
|
19914
|
+
}));
|
|
19915
|
+
return {
|
|
19916
|
+
skills: prefixedSkills,
|
|
19917
|
+
cleanup: async () => {
|
|
19918
|
+
await Promise.all(tempDirs.map((dir) => fs27.rm(dir, { recursive: true, force: true }).catch(() => {
|
|
19919
|
+
})));
|
|
19920
|
+
}
|
|
19921
|
+
};
|
|
19922
|
+
} catch (error) {
|
|
19923
|
+
await Promise.all(tempDirs.map((dir) => fs27.rm(dir, { recursive: true, force: true }).catch(() => {
|
|
19924
|
+
})));
|
|
19925
|
+
throw error;
|
|
19926
|
+
}
|
|
19927
|
+
}
|
|
19106
19928
|
normalizeSkillName(skillName) {
|
|
19107
19929
|
const normalized = skillName.trim();
|
|
19108
19930
|
if (!normalized) {
|
|
@@ -19114,9 +19936,9 @@ class SkillsManager {
|
|
|
19114
19936
|
return normalized;
|
|
19115
19937
|
}
|
|
19116
19938
|
resolveInstallPath(targetDir, skillName) {
|
|
19117
|
-
const resolvedTargetDir =
|
|
19118
|
-
const destPath =
|
|
19119
|
-
const relativePath =
|
|
19939
|
+
const resolvedTargetDir = resolve9(targetDir);
|
|
19940
|
+
const destPath = resolve9(resolvedTargetDir, skillName);
|
|
19941
|
+
const relativePath = relative4(resolvedTargetDir, destPath);
|
|
19120
19942
|
if (relativePath === "" || relativePath.startsWith("..") || relativePath.includes("/../") || relativePath.includes("\\..\\")) {
|
|
19121
19943
|
throw new Error(`Refusing to install skill outside target directory: ${skillName}`);
|
|
19122
19944
|
}
|
|
@@ -19133,18 +19955,18 @@ class SkillsManager {
|
|
|
19133
19955
|
async createDirectorySnapshot(rootPath) {
|
|
19134
19956
|
if (!await fileExists(rootPath))
|
|
19135
19957
|
return null;
|
|
19136
|
-
const hash =
|
|
19958
|
+
const hash = createHash2("sha256");
|
|
19137
19959
|
const walk = async (currentPath, relativePath) => {
|
|
19138
|
-
const stat = await
|
|
19960
|
+
const stat = await fs27.stat(currentPath);
|
|
19139
19961
|
if (!stat.isDirectory()) {
|
|
19140
|
-
const content = await
|
|
19962
|
+
const content = await fs27.readFile(currentPath);
|
|
19141
19963
|
this.updateSnapshotWithFile(hash, relativePath, content);
|
|
19142
19964
|
return;
|
|
19143
19965
|
}
|
|
19144
19966
|
hash.update(`dir:${relativePath || "."}\n`);
|
|
19145
|
-
const entries = (await
|
|
19967
|
+
const entries = (await fs27.readdir(currentPath)).sort((left, right) => left.localeCompare(right));
|
|
19146
19968
|
for (const entry of entries) {
|
|
19147
|
-
await walk(
|
|
19969
|
+
await walk(join7(currentPath, entry), relativePath ? join7(relativePath, entry) : entry);
|
|
19148
19970
|
}
|
|
19149
19971
|
};
|
|
19150
19972
|
await walk(rootPath, "");
|
|
@@ -19155,7 +19977,7 @@ class SkillsManager {
|
|
|
19155
19977
|
}
|
|
19156
19978
|
async getNewSkillSnapshot(skill) {
|
|
19157
19979
|
if (skill.generatedContent) {
|
|
19158
|
-
const hash =
|
|
19980
|
+
const hash = createHash2("sha256");
|
|
19159
19981
|
hash.update("dir:.\n");
|
|
19160
19982
|
this.updateSnapshotWithFile(hash, "SKILL.md", skill.generatedContent.trim());
|
|
19161
19983
|
return hash.digest("hex");
|
|
@@ -19171,23 +19993,43 @@ class SkillsManager {
|
|
|
19171
19993
|
return "new";
|
|
19172
19994
|
return existing === incoming ? "unchanged" : "changed";
|
|
19173
19995
|
}
|
|
19996
|
+
async compareSkillInstallStatus(skill, plan) {
|
|
19997
|
+
const incoming = await this.getNewSkillSnapshot(skill);
|
|
19998
|
+
if (incoming === null)
|
|
19999
|
+
return "new";
|
|
20000
|
+
const existingAtTarget = await this.readExistingSkillSnapshot(plan.path);
|
|
20001
|
+
if (existingAtTarget !== null) {
|
|
20002
|
+
return existingAtTarget === incoming ? "unchanged" : "changed";
|
|
20003
|
+
}
|
|
20004
|
+
if (!plan.canonicalPath || plan.canonicalPath === plan.path) {
|
|
20005
|
+
return "new";
|
|
20006
|
+
}
|
|
20007
|
+
const existingAtCanonical = await this.readExistingSkillSnapshot(plan.canonicalPath);
|
|
20008
|
+
if (existingAtCanonical === null) {
|
|
20009
|
+
return "new";
|
|
20010
|
+
}
|
|
20011
|
+
return existingAtCanonical === incoming ? "new" : "changed";
|
|
20012
|
+
}
|
|
19174
20013
|
async cleanAndCreateDirectory(path) {
|
|
19175
|
-
await
|
|
20014
|
+
await fs27.rm(path, { recursive: true, force: true }).catch(() => {
|
|
19176
20015
|
});
|
|
19177
|
-
await
|
|
20016
|
+
await fs27.mkdir(path, { recursive: true });
|
|
19178
20017
|
}
|
|
19179
20018
|
isWithinPath(basePath, targetPath) {
|
|
19180
|
-
const relativePath =
|
|
20019
|
+
const relativePath = relative4(resolve9(basePath), resolve9(targetPath));
|
|
19181
20020
|
return relativePath === "" || !relativePath.startsWith("..") && !relativePath.includes("/../") && !relativePath.includes("\\..\\");
|
|
19182
20021
|
}
|
|
19183
20022
|
async copyDir(src, dest) {
|
|
19184
|
-
await
|
|
20023
|
+
await fs27.cp(src, dest, { recursive: true, dereference: true });
|
|
19185
20024
|
}
|
|
19186
20025
|
async addFromSource(source, projectPath, options2 = {}) {
|
|
20026
|
+
const normalizedPrefix = this.normalizeSkillPrefix(options2.prefix);
|
|
19187
20027
|
const context = this.takePreparedSourceContext(source, projectPath, options2.from) || await this.loadDiscoveredSkillsContext(source, projectPath, {
|
|
19188
20028
|
...options2.from !== undefined ? { from: options2.from } : {},
|
|
19189
20029
|
...options2.pluginName !== undefined ? { pluginName: options2.pluginName } : {}
|
|
19190
20030
|
});
|
|
20031
|
+
let prefixedCleanup = async () => {
|
|
20032
|
+
};
|
|
19191
20033
|
try {
|
|
19192
20034
|
let skills2 = context.skills;
|
|
19193
20035
|
if (skills2.length === 0) {
|
|
@@ -19195,7 +20037,34 @@ class SkillsManager {
|
|
|
19195
20037
|
}
|
|
19196
20038
|
if (options2.skills && options2.skills.length > 0) {
|
|
19197
20039
|
const names = new Set(options2.skills.map((skill) => skill.toLowerCase()));
|
|
19198
|
-
skills2 = skills2.filter((skill) => names.has(skill.name.toLowerCase()));
|
|
20040
|
+
skills2 = skills2.filter((skill) => names.has(skill.name.toLowerCase()) || names.has(this.withSkillPrefix(skill.name, normalizedPrefix).toLowerCase()));
|
|
20041
|
+
}
|
|
20042
|
+
const prefixed = await this.applyPrefixToSkills(skills2, normalizedPrefix);
|
|
20043
|
+
skills2 = prefixed.skills;
|
|
20044
|
+
prefixedCleanup = prefixed.cleanup;
|
|
20045
|
+
const result = { installed: [], updated: [], unchanged: [], skipped: [], warnings: [...context.warnings] };
|
|
20046
|
+
if (options2.scan !== false) {
|
|
20047
|
+
const scannedWarnings = new Set;
|
|
20048
|
+
const scannableSkills = [];
|
|
20049
|
+
for (const skill of skills2) {
|
|
20050
|
+
const scan = await this.skillScanner.scanSkill(skill);
|
|
20051
|
+
if (scan.findings.length === 0) {
|
|
20052
|
+
scannableSkills.push(skill);
|
|
20053
|
+
continue;
|
|
20054
|
+
}
|
|
20055
|
+
if (scan.blocked && !options2.allowRisky) {
|
|
20056
|
+
result.skipped.push({
|
|
20057
|
+
skill,
|
|
20058
|
+
reason: this.skillScanner.formatBlockingReason(scan)
|
|
20059
|
+
});
|
|
20060
|
+
continue;
|
|
20061
|
+
}
|
|
20062
|
+
const summary = this.skillScanner.formatShortSummary(scan);
|
|
20063
|
+
scannedWarnings.add(scan.blocked ? `Proceeding with "${skill.name}" despite high-risk findings: ${summary}` : `Security warnings for "${skill.name}": ${summary}`);
|
|
20064
|
+
scannableSkills.push(skill);
|
|
20065
|
+
}
|
|
20066
|
+
skills2 = scannableSkills;
|
|
20067
|
+
result.warnings.push(...scannedWarnings);
|
|
19199
20068
|
}
|
|
19200
20069
|
const installToSharedStore = options2.agents?.includes(SHARED_SKILLS_TARGET_ID) ?? false;
|
|
19201
20070
|
const agents = await this.getTargetAgents(projectPath, options2);
|
|
@@ -19204,11 +20073,13 @@ class SkillsManager {
|
|
|
19204
20073
|
installed: [],
|
|
19205
20074
|
updated: [],
|
|
19206
20075
|
unchanged: [],
|
|
19207
|
-
skipped:
|
|
19208
|
-
|
|
20076
|
+
skipped: [
|
|
20077
|
+
...result.skipped,
|
|
20078
|
+
...skills2.map((skill) => ({ skill, reason: "No target agents found" }))
|
|
20079
|
+
],
|
|
20080
|
+
warnings: result.warnings
|
|
19209
20081
|
};
|
|
19210
20082
|
}
|
|
19211
|
-
const result = { installed: [], updated: [], unchanged: [], skipped: [], warnings: context.warnings };
|
|
19212
20083
|
const installableAgents = [];
|
|
19213
20084
|
const comparisonCache = new Map;
|
|
19214
20085
|
const pendingUpdates = [];
|
|
@@ -19260,10 +20131,10 @@ class SkillsManager {
|
|
|
19260
20131
|
...options2.copy !== undefined ? { copy: options2.copy } : {}
|
|
19261
20132
|
};
|
|
19262
20133
|
const plan = await this.getInstallPlan(skill.name, agent, projectPath, installOptions);
|
|
19263
|
-
const comparisonPath = plan.
|
|
20134
|
+
const comparisonPath = plan.path;
|
|
19264
20135
|
let comparison = comparisonCache.get(comparisonPath);
|
|
19265
20136
|
if (comparison === undefined) {
|
|
19266
|
-
comparison = await this.
|
|
20137
|
+
comparison = await this.compareSkillInstallStatus(skill, plan);
|
|
19267
20138
|
comparisonCache.set(comparisonPath, comparison);
|
|
19268
20139
|
}
|
|
19269
20140
|
if (comparison === "unchanged") {
|
|
@@ -19310,8 +20181,47 @@ class SkillsManager {
|
|
|
19310
20181
|
}
|
|
19311
20182
|
}
|
|
19312
20183
|
}
|
|
20184
|
+
try {
|
|
20185
|
+
const lock = new InstallLock;
|
|
20186
|
+
const fromOption = options2.from;
|
|
20187
|
+
const { source: resolvedSource } = this.resolveSourceRequest(source, ...fromOption ? [{ from: fromOption }] : []);
|
|
20188
|
+
const lockSource = {
|
|
20189
|
+
type: resolvedSource.type,
|
|
20190
|
+
...resolvedSource.marketplace ? { marketplace: resolvedSource.marketplace } : {},
|
|
20191
|
+
...resolvedSource.pluginName ? { pluginName: resolvedSource.pluginName } : {},
|
|
20192
|
+
...normalizedPrefix ? { prefix: normalizedPrefix } : {},
|
|
20193
|
+
...resolvedSource.url ? { url: resolvedSource.url } : {},
|
|
20194
|
+
...resolvedSource.path ? { path: resolve9(projectPath, expandTilde(resolvedSource.path)) } : {},
|
|
20195
|
+
...resolvedSource.owner ? { owner: resolvedSource.owner } : {},
|
|
20196
|
+
...resolvedSource.repo ? { repo: resolvedSource.repo } : {},
|
|
20197
|
+
...resolvedSource.subpath ? { subpath: resolvedSource.subpath } : {}
|
|
20198
|
+
};
|
|
20199
|
+
const recordEntries = async (entries, action) => {
|
|
20200
|
+
for (const entry of entries) {
|
|
20201
|
+
const hashPath = entry.canonicalPath || entry.path;
|
|
20202
|
+
const contentHash = await hashDirectory(hashPath);
|
|
20203
|
+
await lock.recordSkill({
|
|
20204
|
+
action,
|
|
20205
|
+
name: entry.skill.name,
|
|
20206
|
+
projectPath: resolve9(projectPath),
|
|
20207
|
+
agents: [entry.agent],
|
|
20208
|
+
scope: options2.global ? "global" : "project",
|
|
20209
|
+
source: lockSource,
|
|
20210
|
+
installPath: entry.path,
|
|
20211
|
+
mode: entry.mode,
|
|
20212
|
+
...entry.canonicalPath ? { canonicalPath: entry.canonicalPath } : {},
|
|
20213
|
+
...contentHash ? { contentHash } : {}
|
|
20214
|
+
});
|
|
20215
|
+
}
|
|
20216
|
+
};
|
|
20217
|
+
await recordEntries(result.installed, "install");
|
|
20218
|
+
await recordEntries(result.updated, "update");
|
|
20219
|
+
} catch (error) {
|
|
20220
|
+
logLockWriteWarning("Skills changed successfully", error);
|
|
20221
|
+
}
|
|
19313
20222
|
return result;
|
|
19314
20223
|
} finally {
|
|
20224
|
+
await prefixedCleanup();
|
|
19315
20225
|
await context.cleanup();
|
|
19316
20226
|
}
|
|
19317
20227
|
}
|
|
@@ -19334,11 +20244,11 @@ class SkillsManager {
|
|
|
19334
20244
|
continue;
|
|
19335
20245
|
const entries = await listFiles(dir);
|
|
19336
20246
|
for (const entry of entries) {
|
|
19337
|
-
const entryPath =
|
|
20247
|
+
const entryPath = join7(dir, entry);
|
|
19338
20248
|
if (!await isDirectory(entryPath))
|
|
19339
20249
|
continue;
|
|
19340
|
-
const skillMdPath =
|
|
19341
|
-
const skillMdPathLower =
|
|
20250
|
+
const skillMdPath = join7(entryPath, "SKILL.md");
|
|
20251
|
+
const skillMdPathLower = join7(entryPath, "skill.md");
|
|
19342
20252
|
const skillFile = await fileExists(skillMdPath) ? skillMdPath : await fileExists(skillMdPathLower) ? skillMdPathLower : null;
|
|
19343
20253
|
if (!skillFile)
|
|
19344
20254
|
continue;
|
|
@@ -19348,7 +20258,7 @@ class SkillsManager {
|
|
|
19348
20258
|
let isSymlink = false;
|
|
19349
20259
|
let canonicalPath;
|
|
19350
20260
|
try {
|
|
19351
|
-
const stat = await
|
|
20261
|
+
const stat = await fs27.lstat(entryPath);
|
|
19352
20262
|
isSymlink = stat.isSymbolicLink();
|
|
19353
20263
|
const canonicalBase = this.getCanonicalSkillsDir(projectPath, scope === "global");
|
|
19354
20264
|
const [resolvedEntryPath, resolvedCanonicalBase] = await Promise.all([
|
|
@@ -19358,7 +20268,7 @@ class SkillsManager {
|
|
|
19358
20268
|
if (this.isWithinPath(resolvedCanonicalBase, resolvedEntryPath)) {
|
|
19359
20269
|
canonicalPath = resolvedEntryPath;
|
|
19360
20270
|
} else if (this.isWithinPath(canonicalBase, entryPath)) {
|
|
19361
|
-
canonicalPath =
|
|
20271
|
+
canonicalPath = resolve9(entryPath);
|
|
19362
20272
|
}
|
|
19363
20273
|
} catch {
|
|
19364
20274
|
}
|
|
@@ -19378,21 +20288,21 @@ class SkillsManager {
|
|
|
19378
20288
|
const includeSharedTarget = !options2.agents || options2.agents.includes(SHARED_SKILLS_TARGET_ID);
|
|
19379
20289
|
if (includeSharedTarget) {
|
|
19380
20290
|
const scopes = options2.global ? ["global"] : ["project", "global"];
|
|
19381
|
-
const referencedCanonicalPaths = new Set(installed.map((entry) => entry.canonicalPath).filter((value) => !!value).map((value) =>
|
|
20291
|
+
const referencedCanonicalPaths = new Set(installed.map((entry) => entry.canonicalPath).filter((value) => !!value).map((value) => resolve9(value)));
|
|
19382
20292
|
for (const scope of scopes) {
|
|
19383
20293
|
const canonicalDir = this.getCanonicalSkillsDir(projectPath, scope === "global");
|
|
19384
20294
|
if (!await fileExists(canonicalDir))
|
|
19385
20295
|
continue;
|
|
19386
20296
|
const entries = await listFiles(canonicalDir);
|
|
19387
20297
|
for (const entry of entries) {
|
|
19388
|
-
const entryPath =
|
|
20298
|
+
const entryPath = join7(canonicalDir, entry);
|
|
19389
20299
|
if (!await isDirectory(entryPath))
|
|
19390
20300
|
continue;
|
|
19391
|
-
const resolvedEntryPath =
|
|
20301
|
+
const resolvedEntryPath = resolve9(entryPath);
|
|
19392
20302
|
if (referencedCanonicalPaths.has(resolvedEntryPath))
|
|
19393
20303
|
continue;
|
|
19394
|
-
const skillMdPath =
|
|
19395
|
-
const skillMdPathLower =
|
|
20304
|
+
const skillMdPath = join7(entryPath, "SKILL.md");
|
|
20305
|
+
const skillMdPathLower = join7(entryPath, "skill.md");
|
|
19396
20306
|
const skillFile = await fileExists(skillMdPath) ? skillMdPath : await fileExists(skillMdPathLower) ? skillMdPathLower : null;
|
|
19397
20307
|
if (!skillFile)
|
|
19398
20308
|
continue;
|
|
@@ -19459,7 +20369,7 @@ class SkillsManager {
|
|
|
19459
20369
|
}
|
|
19460
20370
|
if (!removedPaths.has(entry.path)) {
|
|
19461
20371
|
try {
|
|
19462
|
-
await
|
|
20372
|
+
await fs27.rm(entry.path, { recursive: true, force: true });
|
|
19463
20373
|
removedPaths.add(entry.path);
|
|
19464
20374
|
} catch {
|
|
19465
20375
|
skipped.push({
|
|
@@ -19472,7 +20382,7 @@ class SkillsManager {
|
|
|
19472
20382
|
if (entry.canonicalPath && entry.canonicalPath !== entry.path && !removedCanonicalPaths.has(entry.canonicalPath)) {
|
|
19473
20383
|
const stillReferenced = remainingEntries.some((other) => other.name.toLowerCase() === entry.name.toLowerCase() && other.canonicalPath === entry.canonicalPath);
|
|
19474
20384
|
if (!stillReferenced) {
|
|
19475
|
-
await
|
|
20385
|
+
await fs27.rm(entry.canonicalPath, { recursive: true, force: true }).catch(() => {
|
|
19476
20386
|
});
|
|
19477
20387
|
removedCanonicalPaths.add(entry.canonicalPath);
|
|
19478
20388
|
}
|
|
@@ -19485,6 +20395,29 @@ class SkillsManager {
|
|
|
19485
20395
|
notFound.push(name);
|
|
19486
20396
|
}
|
|
19487
20397
|
}
|
|
20398
|
+
try {
|
|
20399
|
+
if (targetedEntries.length > 0) {
|
|
20400
|
+
const lock = new InstallLock;
|
|
20401
|
+
for (const entry of targetedEntries) {
|
|
20402
|
+
const entryKey = `${entry.agent}:${entry.name}`;
|
|
20403
|
+
if (!removed.includes(entryKey))
|
|
20404
|
+
continue;
|
|
20405
|
+
await lock.recordSkill({
|
|
20406
|
+
action: "remove",
|
|
20407
|
+
name: entry.name,
|
|
20408
|
+
projectPath: resolve9(projectPath),
|
|
20409
|
+
agents: [entry.agent],
|
|
20410
|
+
scope: entry.scope,
|
|
20411
|
+
source: { type: "local", path: entry.path },
|
|
20412
|
+
installPath: entry.path,
|
|
20413
|
+
mode: entry.mode,
|
|
20414
|
+
...entry.canonicalPath ? { canonicalPath: entry.canonicalPath } : {}
|
|
20415
|
+
});
|
|
20416
|
+
}
|
|
20417
|
+
}
|
|
20418
|
+
} catch (error) {
|
|
20419
|
+
logLockWriteWarning("Skills removed successfully", error);
|
|
20420
|
+
}
|
|
19488
20421
|
return { removed, notFound, skipped };
|
|
19489
20422
|
}
|
|
19490
20423
|
}
|
|
@@ -19492,9 +20425,12 @@ var import_gray_matter2, execFileAsync, DEFAULT_SKILLS_CATALOG, SKILL_SEARCH_DIR
|
|
|
19492
20425
|
var init_skillsManager = __esm(() => {
|
|
19493
20426
|
import_gray_matter2 = __toESM(require_gray_matter(), 1);
|
|
19494
20427
|
init_fs();
|
|
20428
|
+
init_paths();
|
|
19495
20429
|
init_agentManager();
|
|
19496
20430
|
init_marketplaceRegistry();
|
|
20431
|
+
init_skillSecurityScanner();
|
|
19497
20432
|
init_skills();
|
|
20433
|
+
init_installLock();
|
|
19498
20434
|
execFileAsync = promisify(execFile);
|
|
19499
20435
|
DEFAULT_SKILLS_CATALOG = {
|
|
19500
20436
|
owner: "vercel-labs",
|
|
@@ -20378,51 +21314,51 @@ var require_uri_all = __commonJS((exports, module) => {
|
|
|
20378
21314
|
}
|
|
20379
21315
|
return uriTokens.join("");
|
|
20380
21316
|
}
|
|
20381
|
-
function resolveComponents(base2,
|
|
21317
|
+
function resolveComponents(base2, relative7) {
|
|
20382
21318
|
var options2 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
20383
21319
|
var skipNormalization = arguments[3];
|
|
20384
21320
|
var target = {};
|
|
20385
21321
|
if (!skipNormalization) {
|
|
20386
21322
|
base2 = parse4(serialize(base2, options2), options2);
|
|
20387
|
-
|
|
21323
|
+
relative7 = parse4(serialize(relative7, options2), options2);
|
|
20388
21324
|
}
|
|
20389
21325
|
options2 = options2 || {};
|
|
20390
|
-
if (!options2.tolerant &&
|
|
20391
|
-
target.scheme =
|
|
20392
|
-
target.userinfo =
|
|
20393
|
-
target.host =
|
|
20394
|
-
target.port =
|
|
20395
|
-
target.path = removeDotSegments(
|
|
20396
|
-
target.query =
|
|
21326
|
+
if (!options2.tolerant && relative7.scheme) {
|
|
21327
|
+
target.scheme = relative7.scheme;
|
|
21328
|
+
target.userinfo = relative7.userinfo;
|
|
21329
|
+
target.host = relative7.host;
|
|
21330
|
+
target.port = relative7.port;
|
|
21331
|
+
target.path = removeDotSegments(relative7.path || "");
|
|
21332
|
+
target.query = relative7.query;
|
|
20397
21333
|
} else {
|
|
20398
|
-
if (
|
|
20399
|
-
target.userinfo =
|
|
20400
|
-
target.host =
|
|
20401
|
-
target.port =
|
|
20402
|
-
target.path = removeDotSegments(
|
|
20403
|
-
target.query =
|
|
21334
|
+
if (relative7.userinfo !== undefined || relative7.host !== undefined || relative7.port !== undefined) {
|
|
21335
|
+
target.userinfo = relative7.userinfo;
|
|
21336
|
+
target.host = relative7.host;
|
|
21337
|
+
target.port = relative7.port;
|
|
21338
|
+
target.path = removeDotSegments(relative7.path || "");
|
|
21339
|
+
target.query = relative7.query;
|
|
20404
21340
|
} else {
|
|
20405
|
-
if (!
|
|
21341
|
+
if (!relative7.path) {
|
|
20406
21342
|
target.path = base2.path;
|
|
20407
|
-
if (
|
|
20408
|
-
target.query =
|
|
21343
|
+
if (relative7.query !== undefined) {
|
|
21344
|
+
target.query = relative7.query;
|
|
20409
21345
|
} else {
|
|
20410
21346
|
target.query = base2.query;
|
|
20411
21347
|
}
|
|
20412
21348
|
} else {
|
|
20413
|
-
if (
|
|
20414
|
-
target.path = removeDotSegments(
|
|
21349
|
+
if (relative7.path.charAt(0) === "/") {
|
|
21350
|
+
target.path = removeDotSegments(relative7.path);
|
|
20415
21351
|
} else {
|
|
20416
21352
|
if ((base2.userinfo !== undefined || base2.host !== undefined || base2.port !== undefined) && !base2.path) {
|
|
20417
|
-
target.path = "/" +
|
|
21353
|
+
target.path = "/" + relative7.path;
|
|
20418
21354
|
} else if (!base2.path) {
|
|
20419
|
-
target.path =
|
|
21355
|
+
target.path = relative7.path;
|
|
20420
21356
|
} else {
|
|
20421
|
-
target.path = base2.path.slice(0, base2.path.lastIndexOf("/") + 1) +
|
|
21357
|
+
target.path = base2.path.slice(0, base2.path.lastIndexOf("/") + 1) + relative7.path;
|
|
20422
21358
|
}
|
|
20423
21359
|
target.path = removeDotSegments(target.path);
|
|
20424
21360
|
}
|
|
20425
|
-
target.query =
|
|
21361
|
+
target.query = relative7.query;
|
|
20426
21362
|
}
|
|
20427
21363
|
target.userinfo = base2.userinfo;
|
|
20428
21364
|
target.host = base2.host;
|
|
@@ -20430,10 +21366,10 @@ var require_uri_all = __commonJS((exports, module) => {
|
|
|
20430
21366
|
}
|
|
20431
21367
|
target.scheme = base2.scheme;
|
|
20432
21368
|
}
|
|
20433
|
-
target.fragment =
|
|
21369
|
+
target.fragment = relative7.fragment;
|
|
20434
21370
|
return target;
|
|
20435
21371
|
}
|
|
20436
|
-
function
|
|
21372
|
+
function resolve13(baseURI, relativeURI, options2) {
|
|
20437
21373
|
var schemelessOptions = assign({ scheme: "null" }, options2);
|
|
20438
21374
|
return serialize(resolveComponents(parse4(baseURI, schemelessOptions), parse4(relativeURI, schemelessOptions), schemelessOptions, true), schemelessOptions);
|
|
20439
21375
|
}
|
|
@@ -20701,7 +21637,7 @@ var require_uri_all = __commonJS((exports, module) => {
|
|
|
20701
21637
|
exports2.removeDotSegments = removeDotSegments;
|
|
20702
21638
|
exports2.serialize = serialize;
|
|
20703
21639
|
exports2.resolveComponents = resolveComponents;
|
|
20704
|
-
exports2.resolve =
|
|
21640
|
+
exports2.resolve = resolve13;
|
|
20705
21641
|
exports2.normalize = normalize;
|
|
20706
21642
|
exports2.equal = equal;
|
|
20707
21643
|
exports2.escapeComponent = escapeComponent;
|
|
@@ -20887,7 +21823,7 @@ var require_util3 = __commonJS((exports, module) => {
|
|
|
20887
21823
|
var path = jsonPointers ? toQuotedString("/" + escapeJsonPointer(prop)) : toQuotedString(getProperty(prop));
|
|
20888
21824
|
return joinPaths(currentPath, path);
|
|
20889
21825
|
};
|
|
20890
|
-
var getData = function($data, lvl,
|
|
21826
|
+
var getData = function($data, lvl, paths6) {
|
|
20891
21827
|
var up, jsonPointer, data, matches;
|
|
20892
21828
|
if ($data === "")
|
|
20893
21829
|
return "rootData";
|
|
@@ -20905,7 +21841,7 @@ var require_util3 = __commonJS((exports, module) => {
|
|
|
20905
21841
|
if (jsonPointer == "#") {
|
|
20906
21842
|
if (up >= lvl)
|
|
20907
21843
|
throw new Error("Cannot access property/index " + up + " levels up, current level is " + lvl);
|
|
20908
|
-
return
|
|
21844
|
+
return paths6[lvl - up];
|
|
20909
21845
|
}
|
|
20910
21846
|
if (up > lvl)
|
|
20911
21847
|
throw new Error("Cannot access data " + up + " levels up, current level is " + lvl);
|
|
@@ -21064,13 +22000,13 @@ var require_json_schema_traverse = __commonJS((exports, module) => {
|
|
|
21064
22000
|
|
|
21065
22001
|
// node_modules/ajv/lib/compile/resolve.js
|
|
21066
22002
|
var require_resolve = __commonJS((exports, module) => {
|
|
21067
|
-
var
|
|
22003
|
+
var resolve13 = function(compile, root, ref) {
|
|
21068
22004
|
var refVal = this._refs[ref];
|
|
21069
22005
|
if (typeof refVal == "string") {
|
|
21070
22006
|
if (this._refs[refVal])
|
|
21071
22007
|
refVal = this._refs[refVal];
|
|
21072
22008
|
else
|
|
21073
|
-
return
|
|
22009
|
+
return resolve13.call(this, compile, root, refVal);
|
|
21074
22010
|
}
|
|
21075
22011
|
refVal = refVal || this._schemas[ref];
|
|
21076
22012
|
if (refVal instanceof SchemaObject) {
|
|
@@ -21275,13 +22211,13 @@ var require_resolve = __commonJS((exports, module) => {
|
|
|
21275
22211
|
var util6 = require_util3();
|
|
21276
22212
|
var SchemaObject = require_schema_obj();
|
|
21277
22213
|
var traverse = require_json_schema_traverse();
|
|
21278
|
-
module.exports =
|
|
21279
|
-
|
|
21280
|
-
|
|
21281
|
-
|
|
21282
|
-
|
|
21283
|
-
|
|
21284
|
-
|
|
22214
|
+
module.exports = resolve13;
|
|
22215
|
+
resolve13.normalizeId = normalizeId;
|
|
22216
|
+
resolve13.fullPath = getFullPath;
|
|
22217
|
+
resolve13.url = resolveUrl;
|
|
22218
|
+
resolve13.ids = resolveIds;
|
|
22219
|
+
resolve13.inlineRef = inlineRef;
|
|
22220
|
+
resolve13.schema = resolveSchema;
|
|
21285
22221
|
var PREVENT_SCOPE_CHANGE = util6.toHash(["properties", "patternProperties", "enum", "dependencies", "definitions"]);
|
|
21286
22222
|
var SIMPLE_INLINED = util6.toHash([
|
|
21287
22223
|
"type",
|
|
@@ -21312,15 +22248,15 @@ var require_error_classes = __commonJS((exports, module) => {
|
|
|
21312
22248
|
};
|
|
21313
22249
|
var MissingRefError = function(baseId, ref, message) {
|
|
21314
22250
|
this.message = message || MissingRefError.message(baseId, ref);
|
|
21315
|
-
this.missingRef =
|
|
21316
|
-
this.missingSchema =
|
|
22251
|
+
this.missingRef = resolve13.url(baseId, ref);
|
|
22252
|
+
this.missingSchema = resolve13.normalizeId(resolve13.fullPath(this.missingRef));
|
|
21317
22253
|
};
|
|
21318
22254
|
var errorSubclass = function(Subclass) {
|
|
21319
22255
|
Subclass.prototype = Object.create(Error.prototype);
|
|
21320
22256
|
Subclass.prototype.constructor = Subclass;
|
|
21321
22257
|
return Subclass;
|
|
21322
22258
|
};
|
|
21323
|
-
var
|
|
22259
|
+
var resolve13 = require_resolve();
|
|
21324
22260
|
module.exports = {
|
|
21325
22261
|
Validation: errorSubclass(ValidationError),
|
|
21326
22262
|
MissingRef: errorSubclass(MissingRefError)
|
|
@@ -21914,7 +22850,7 @@ var require_compile = __commonJS((exports, module) => {
|
|
|
21914
22850
|
RULES,
|
|
21915
22851
|
validate: validateGenerator,
|
|
21916
22852
|
util: util6,
|
|
21917
|
-
resolve:
|
|
22853
|
+
resolve: resolve13,
|
|
21918
22854
|
resolveRef,
|
|
21919
22855
|
usePattern,
|
|
21920
22856
|
useDefault,
|
|
@@ -21953,7 +22889,7 @@ var require_compile = __commonJS((exports, module) => {
|
|
|
21953
22889
|
return validate2;
|
|
21954
22890
|
}
|
|
21955
22891
|
function resolveRef(baseId2, ref, isRoot) {
|
|
21956
|
-
ref =
|
|
22892
|
+
ref = resolve13.url(baseId2, ref);
|
|
21957
22893
|
var refIndex = refs[ref];
|
|
21958
22894
|
var _refVal, refCode;
|
|
21959
22895
|
if (refIndex !== undefined) {
|
|
@@ -21970,11 +22906,11 @@ var require_compile = __commonJS((exports, module) => {
|
|
|
21970
22906
|
}
|
|
21971
22907
|
}
|
|
21972
22908
|
refCode = addLocalRef(ref);
|
|
21973
|
-
var v2 =
|
|
22909
|
+
var v2 = resolve13.call(self, localCompile, root, ref);
|
|
21974
22910
|
if (v2 === undefined) {
|
|
21975
22911
|
var localSchema = localRefs && localRefs[ref];
|
|
21976
22912
|
if (localSchema) {
|
|
21977
|
-
v2 =
|
|
22913
|
+
v2 = resolve13.inlineRef(localSchema, opts.inlineRefs) ? localSchema : compile.call(self, localSchema, root, localRefs, baseId2);
|
|
21978
22914
|
}
|
|
21979
22915
|
}
|
|
21980
22916
|
if (v2 === undefined) {
|
|
@@ -22116,7 +23052,7 @@ var require_compile = __commonJS((exports, module) => {
|
|
|
22116
23052
|
code += statement(i, arr);
|
|
22117
23053
|
return code;
|
|
22118
23054
|
};
|
|
22119
|
-
var
|
|
23055
|
+
var resolve13 = require_resolve();
|
|
22120
23056
|
var util6 = require_util3();
|
|
22121
23057
|
var errorClasses = require_error_classes();
|
|
22122
23058
|
var stableStringify = require_fast_json_stable_stringify();
|
|
@@ -25365,7 +26301,7 @@ var require_ajv = __commonJS((exports, module) => {
|
|
|
25365
26301
|
var id = this._getId(schema2);
|
|
25366
26302
|
if (id !== undefined && typeof id != "string")
|
|
25367
26303
|
throw new Error("schema id must be string");
|
|
25368
|
-
key =
|
|
26304
|
+
key = resolve13.normalizeId(key || id);
|
|
25369
26305
|
checkUnique(this, key);
|
|
25370
26306
|
this._schemas[key] = this._addSchema(schema2, _skipValidation, _meta, true);
|
|
25371
26307
|
return this;
|
|
@@ -25411,7 +26347,7 @@ var require_ajv = __commonJS((exports, module) => {
|
|
|
25411
26347
|
}
|
|
25412
26348
|
};
|
|
25413
26349
|
var _getSchemaFragment = function(self, ref) {
|
|
25414
|
-
var res =
|
|
26350
|
+
var res = resolve13.schema.call(self, { schema: {} }, ref);
|
|
25415
26351
|
if (res) {
|
|
25416
26352
|
var { schema: schema2, root, baseId } = res;
|
|
25417
26353
|
var v = compileSchema.call(self, schema2, root, undefined, baseId);
|
|
@@ -25427,7 +26363,7 @@ var require_ajv = __commonJS((exports, module) => {
|
|
|
25427
26363
|
}
|
|
25428
26364
|
};
|
|
25429
26365
|
var _getSchemaObj = function(self, keyRef) {
|
|
25430
|
-
keyRef =
|
|
26366
|
+
keyRef = resolve13.normalizeId(keyRef);
|
|
25431
26367
|
return self._schemas[keyRef] || self._refs[keyRef] || self._fragments[keyRef];
|
|
25432
26368
|
};
|
|
25433
26369
|
var removeSchema = function(schemaKeyRef) {
|
|
@@ -25455,7 +26391,7 @@ var require_ajv = __commonJS((exports, module) => {
|
|
|
25455
26391
|
this._cache.del(cacheKey);
|
|
25456
26392
|
var id = this._getId(schemaKeyRef);
|
|
25457
26393
|
if (id) {
|
|
25458
|
-
id =
|
|
26394
|
+
id = resolve13.normalizeId(id);
|
|
25459
26395
|
delete this._schemas[id];
|
|
25460
26396
|
delete this._refs[id];
|
|
25461
26397
|
}
|
|
@@ -25480,14 +26416,14 @@ var require_ajv = __commonJS((exports, module) => {
|
|
|
25480
26416
|
if (cached)
|
|
25481
26417
|
return cached;
|
|
25482
26418
|
shouldAddSchema = shouldAddSchema || this._opts.addUsedSchema !== false;
|
|
25483
|
-
var id =
|
|
26419
|
+
var id = resolve13.normalizeId(this._getId(schema2));
|
|
25484
26420
|
if (id && shouldAddSchema)
|
|
25485
26421
|
checkUnique(this, id);
|
|
25486
26422
|
var willValidate = this._opts.validateSchema !== false && !skipValidation;
|
|
25487
26423
|
var recursiveMeta;
|
|
25488
|
-
if (willValidate && !(recursiveMeta = id && id ==
|
|
26424
|
+
if (willValidate && !(recursiveMeta = id && id == resolve13.normalizeId(schema2.$schema)))
|
|
25489
26425
|
this.validateSchema(schema2, true);
|
|
25490
|
-
var localRefs =
|
|
26426
|
+
var localRefs = resolve13.ids.call(this, schema2);
|
|
25491
26427
|
var schemaObj = new SchemaObject({
|
|
25492
26428
|
id,
|
|
25493
26429
|
schema: schema2,
|
|
@@ -25634,21 +26570,21 @@ var require_ajv = __commonJS((exports, module) => {
|
|
|
25634
26570
|
return metaOpts;
|
|
25635
26571
|
};
|
|
25636
26572
|
var setLogger = function(self) {
|
|
25637
|
-
var
|
|
25638
|
-
if (
|
|
26573
|
+
var logger6 = self._opts.logger;
|
|
26574
|
+
if (logger6 === false) {
|
|
25639
26575
|
self.logger = { log: noop, warn: noop, error: noop };
|
|
25640
26576
|
} else {
|
|
25641
|
-
if (
|
|
25642
|
-
|
|
25643
|
-
if (!(typeof
|
|
26577
|
+
if (logger6 === undefined)
|
|
26578
|
+
logger6 = console;
|
|
26579
|
+
if (!(typeof logger6 == "object" && logger6.log && logger6.warn && logger6.error))
|
|
25644
26580
|
throw new Error("logger must implement log, warn and error methods");
|
|
25645
|
-
self.logger =
|
|
26581
|
+
self.logger = logger6;
|
|
25646
26582
|
}
|
|
25647
26583
|
};
|
|
25648
26584
|
var noop = function() {
|
|
25649
26585
|
};
|
|
25650
26586
|
var compileSchema = require_compile();
|
|
25651
|
-
var
|
|
26587
|
+
var resolve13 = require_resolve();
|
|
25652
26588
|
var Cache = require_cache();
|
|
25653
26589
|
var SchemaObject = require_schema_obj();
|
|
25654
26590
|
var stableStringify = require_fast_json_stable_stringify();
|
|
@@ -25709,27 +26645,27 @@ var require_windows = __commonJS((exports, module) => {
|
|
|
25709
26645
|
return checkPathExt(path, options2);
|
|
25710
26646
|
};
|
|
25711
26647
|
var isexe = function(path, options2, cb) {
|
|
25712
|
-
|
|
26648
|
+
fs34.stat(path, function(er, stat) {
|
|
25713
26649
|
cb(er, er ? false : checkStat(stat, path, options2));
|
|
25714
26650
|
});
|
|
25715
26651
|
};
|
|
25716
26652
|
var sync = function(path, options2) {
|
|
25717
|
-
return checkStat(
|
|
26653
|
+
return checkStat(fs34.statSync(path), path, options2);
|
|
25718
26654
|
};
|
|
25719
26655
|
module.exports = isexe;
|
|
25720
26656
|
isexe.sync = sync;
|
|
25721
|
-
var
|
|
26657
|
+
var fs34 = __require("fs");
|
|
25722
26658
|
});
|
|
25723
26659
|
|
|
25724
26660
|
// node_modules/isexe/mode.js
|
|
25725
26661
|
var require_mode = __commonJS((exports, module) => {
|
|
25726
26662
|
var isexe = function(path, options2, cb) {
|
|
25727
|
-
|
|
26663
|
+
fs34.stat(path, function(er, stat) {
|
|
25728
26664
|
cb(er, er ? false : checkStat(stat, options2));
|
|
25729
26665
|
});
|
|
25730
26666
|
};
|
|
25731
26667
|
var sync = function(path, options2) {
|
|
25732
|
-
return checkStat(
|
|
26668
|
+
return checkStat(fs34.statSync(path), options2);
|
|
25733
26669
|
};
|
|
25734
26670
|
var checkStat = function(stat, options2) {
|
|
25735
26671
|
return stat.isFile() && checkMode(stat, options2);
|
|
@@ -25749,7 +26685,7 @@ var require_mode = __commonJS((exports, module) => {
|
|
|
25749
26685
|
};
|
|
25750
26686
|
module.exports = isexe;
|
|
25751
26687
|
isexe.sync = sync;
|
|
25752
|
-
var
|
|
26688
|
+
var fs34 = __require("fs");
|
|
25753
26689
|
});
|
|
25754
26690
|
|
|
25755
26691
|
// node_modules/isexe/index.js
|
|
@@ -25763,12 +26699,12 @@ var require_isexe = __commonJS((exports, module) => {
|
|
|
25763
26699
|
if (typeof Promise !== "function") {
|
|
25764
26700
|
throw new TypeError("callback not provided");
|
|
25765
26701
|
}
|
|
25766
|
-
return new Promise(function(
|
|
26702
|
+
return new Promise(function(resolve13, reject) {
|
|
25767
26703
|
isexe(path, options2 || {}, function(er, is) {
|
|
25768
26704
|
if (er) {
|
|
25769
26705
|
reject(er);
|
|
25770
26706
|
} else {
|
|
25771
|
-
|
|
26707
|
+
resolve13(is);
|
|
25772
26708
|
}
|
|
25773
26709
|
});
|
|
25774
26710
|
});
|
|
@@ -25794,7 +26730,7 @@ var require_isexe = __commonJS((exports, module) => {
|
|
|
25794
26730
|
}
|
|
25795
26731
|
}
|
|
25796
26732
|
};
|
|
25797
|
-
var
|
|
26733
|
+
var fs34 = __require("fs");
|
|
25798
26734
|
var core2;
|
|
25799
26735
|
if (process.platform === "win32" || global.TESTING_WINDOWS) {
|
|
25800
26736
|
core2 = require_windows();
|
|
@@ -25839,27 +26775,27 @@ var require_which = __commonJS((exports, module) => {
|
|
|
25839
26775
|
opt = {};
|
|
25840
26776
|
const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
|
|
25841
26777
|
const found = [];
|
|
25842
|
-
const step = (i) => new Promise((
|
|
26778
|
+
const step = (i) => new Promise((resolve13, reject) => {
|
|
25843
26779
|
if (i === pathEnv.length)
|
|
25844
|
-
return opt.all && found.length ?
|
|
26780
|
+
return opt.all && found.length ? resolve13(found) : reject(getNotFoundError(cmd));
|
|
25845
26781
|
const ppRaw = pathEnv[i];
|
|
25846
26782
|
const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
|
|
25847
26783
|
const pCmd = path.join(pathPart, cmd);
|
|
25848
26784
|
const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
|
|
25849
|
-
|
|
26785
|
+
resolve13(subStep(p, i, 0));
|
|
25850
26786
|
});
|
|
25851
|
-
const subStep = (p, i, ii) => new Promise((
|
|
26787
|
+
const subStep = (p, i, ii) => new Promise((resolve13, reject) => {
|
|
25852
26788
|
if (ii === pathExt.length)
|
|
25853
|
-
return
|
|
26789
|
+
return resolve13(step(i + 1));
|
|
25854
26790
|
const ext = pathExt[ii];
|
|
25855
26791
|
isexe(p + ext, { pathExt: pathExtExe }, (er, is) => {
|
|
25856
26792
|
if (!er && is) {
|
|
25857
26793
|
if (opt.all)
|
|
25858
26794
|
found.push(p + ext);
|
|
25859
26795
|
else
|
|
25860
|
-
return
|
|
26796
|
+
return resolve13(p + ext);
|
|
25861
26797
|
}
|
|
25862
|
-
return
|
|
26798
|
+
return resolve13(subStep(p, i, ii + 1));
|
|
25863
26799
|
});
|
|
25864
26800
|
});
|
|
25865
26801
|
return cb ? step(0).then((res) => cb(null, res), cb) : step(0);
|
|
@@ -26001,14 +26937,14 @@ var require_readShebang = __commonJS((exports, module) => {
|
|
|
26001
26937
|
const buffer = Buffer.alloc(size);
|
|
26002
26938
|
let fd;
|
|
26003
26939
|
try {
|
|
26004
|
-
fd =
|
|
26005
|
-
|
|
26006
|
-
|
|
26940
|
+
fd = fs34.openSync(command, "r");
|
|
26941
|
+
fs34.readSync(fd, buffer, 0, size, 0);
|
|
26942
|
+
fs34.closeSync(fd);
|
|
26007
26943
|
} catch (e) {
|
|
26008
26944
|
}
|
|
26009
26945
|
return shebangCommand(buffer.toString());
|
|
26010
26946
|
};
|
|
26011
|
-
var
|
|
26947
|
+
var fs34 = __require("fs");
|
|
26012
26948
|
var shebangCommand = require_shebang_command();
|
|
26013
26949
|
module.exports = readShebang;
|
|
26014
26950
|
});
|
|
@@ -27461,155 +28397,7 @@ function ora(options2) {
|
|
|
27461
28397
|
|
|
27462
28398
|
// dist/commands/init.js
|
|
27463
28399
|
var import_prompts = __toESM(require_prompts3(), 1);
|
|
27464
|
-
|
|
27465
|
-
// node_modules/kleur/colors.mjs
|
|
27466
|
-
var init = function(x, y) {
|
|
27467
|
-
let rgx = new RegExp(`\\x1b\\[${y}m`, "g");
|
|
27468
|
-
let open = `\x1B[${x}m`, close = `\x1B[${y}m`;
|
|
27469
|
-
return function(txt) {
|
|
27470
|
-
if (!$.enabled || txt == null)
|
|
27471
|
-
return txt;
|
|
27472
|
-
return open + (~("" + txt).indexOf(close) ? txt.replace(rgx, close + open) : txt) + close;
|
|
27473
|
-
};
|
|
27474
|
-
};
|
|
27475
|
-
var FORCE_COLOR;
|
|
27476
|
-
var NODE_DISABLE_COLORS;
|
|
27477
|
-
var NO_COLOR;
|
|
27478
|
-
var TERM;
|
|
27479
|
-
var isTTY = true;
|
|
27480
|
-
if (typeof process !== "undefined") {
|
|
27481
|
-
({ FORCE_COLOR, NODE_DISABLE_COLORS, NO_COLOR, TERM } = process.env || {});
|
|
27482
|
-
isTTY = process.stdout && process.stdout.isTTY;
|
|
27483
|
-
}
|
|
27484
|
-
var $ = {
|
|
27485
|
-
enabled: !NODE_DISABLE_COLORS && NO_COLOR == null && TERM !== "dumb" && (FORCE_COLOR != null && FORCE_COLOR !== "0" || isTTY)
|
|
27486
|
-
};
|
|
27487
|
-
var reset = init(0, 0);
|
|
27488
|
-
var bold = init(1, 22);
|
|
27489
|
-
var dim = init(2, 22);
|
|
27490
|
-
var italic = init(3, 23);
|
|
27491
|
-
var underline = init(4, 24);
|
|
27492
|
-
var inverse = init(7, 27);
|
|
27493
|
-
var hidden = init(8, 28);
|
|
27494
|
-
var strikethrough = init(9, 29);
|
|
27495
|
-
var black = init(30, 39);
|
|
27496
|
-
var red = init(31, 39);
|
|
27497
|
-
var green = init(32, 39);
|
|
27498
|
-
var yellow = init(33, 39);
|
|
27499
|
-
var blue = init(34, 39);
|
|
27500
|
-
var magenta = init(35, 39);
|
|
27501
|
-
var cyan = init(36, 39);
|
|
27502
|
-
var white = init(37, 39);
|
|
27503
|
-
var gray = init(90, 39);
|
|
27504
|
-
var grey = init(90, 39);
|
|
27505
|
-
var bgBlack = init(40, 49);
|
|
27506
|
-
var bgRed = init(41, 49);
|
|
27507
|
-
var bgGreen = init(42, 49);
|
|
27508
|
-
var bgYellow = init(43, 49);
|
|
27509
|
-
var bgBlue = init(44, 49);
|
|
27510
|
-
var bgMagenta = init(45, 49);
|
|
27511
|
-
var bgCyan = init(46, 49);
|
|
27512
|
-
var bgWhite = init(47, 49);
|
|
27513
|
-
|
|
27514
|
-
// dist/utils/symbols.js
|
|
27515
|
-
var STATUS = {
|
|
27516
|
-
success: "\u2713",
|
|
27517
|
-
error: "\u2717",
|
|
27518
|
-
warning: "\u26A0",
|
|
27519
|
-
info: "\u2139",
|
|
27520
|
-
debug: "\u2022"
|
|
27521
|
-
};
|
|
27522
|
-
var TREE = {
|
|
27523
|
-
branch: "\u251C\u2500",
|
|
27524
|
-
last: "\u2514\u2500"
|
|
27525
|
-
};
|
|
27526
|
-
var BOX = {
|
|
27527
|
-
topLeft: "\u250C",
|
|
27528
|
-
topRight: "\u2510",
|
|
27529
|
-
bottomLeft: "\u2514",
|
|
27530
|
-
bottomRight: "\u2518",
|
|
27531
|
-
horizontal: "\u2500",
|
|
27532
|
-
vertical: "\u2502"
|
|
27533
|
-
};
|
|
27534
|
-
|
|
27535
|
-
// dist/utils/logger.js
|
|
27536
|
-
var getTerminalWidth = function() {
|
|
27537
|
-
const columns = process.stdout.columns;
|
|
27538
|
-
return typeof columns === "number" && columns > 0 ? columns : 80;
|
|
27539
|
-
};
|
|
27540
|
-
var truncateText = function(text, maxLength) {
|
|
27541
|
-
if (maxLength <= 0) {
|
|
27542
|
-
return "";
|
|
27543
|
-
}
|
|
27544
|
-
if (text.length <= maxLength) {
|
|
27545
|
-
return text;
|
|
27546
|
-
}
|
|
27547
|
-
if (maxLength <= 3) {
|
|
27548
|
-
return ".".repeat(maxLength);
|
|
27549
|
-
}
|
|
27550
|
-
return `${text.slice(0, maxLength - 3)}...`;
|
|
27551
|
-
};
|
|
27552
|
-
|
|
27553
|
-
class Logger {
|
|
27554
|
-
static instance;
|
|
27555
|
-
static getInstance() {
|
|
27556
|
-
if (!Logger.instance) {
|
|
27557
|
-
Logger.instance = new Logger;
|
|
27558
|
-
}
|
|
27559
|
-
return Logger.instance;
|
|
27560
|
-
}
|
|
27561
|
-
info(message) {
|
|
27562
|
-
console.log(cyan(STATUS.info), message);
|
|
27563
|
-
}
|
|
27564
|
-
success(message) {
|
|
27565
|
-
console.log(green(STATUS.success), message);
|
|
27566
|
-
}
|
|
27567
|
-
warning(message) {
|
|
27568
|
-
console.log(yellow(STATUS.warning), message);
|
|
27569
|
-
}
|
|
27570
|
-
warn(message) {
|
|
27571
|
-
this.warning(message);
|
|
27572
|
-
}
|
|
27573
|
-
error(message) {
|
|
27574
|
-
console.log(red(STATUS.error), message);
|
|
27575
|
-
}
|
|
27576
|
-
debug(message) {
|
|
27577
|
-
console.log(dim(STATUS.debug), dim(message));
|
|
27578
|
-
}
|
|
27579
|
-
title(message) {
|
|
27580
|
-
console.log(bold(cyan(message)));
|
|
27581
|
-
}
|
|
27582
|
-
subtitle(message) {
|
|
27583
|
-
console.log(bold(message));
|
|
27584
|
-
}
|
|
27585
|
-
titleBox(message) {
|
|
27586
|
-
const w = getTerminalWidth();
|
|
27587
|
-
if (w < 8) {
|
|
27588
|
-
console.log(bold(cyan(truncateText(message, w))));
|
|
27589
|
-
return;
|
|
27590
|
-
}
|
|
27591
|
-
const maxInner = Math.max(4, w - 2);
|
|
27592
|
-
const inner = Math.min(Math.max(message.length + 4, 40), maxInner);
|
|
27593
|
-
const visibleMessage = truncateText(message, inner - 2);
|
|
27594
|
-
const padR = Math.max(0, inner - visibleMessage.length - 2);
|
|
27595
|
-
console.log(dim(BOX.topLeft + BOX.horizontal.repeat(inner) + BOX.topRight));
|
|
27596
|
-
console.log(dim(BOX.vertical) + " " + bold(cyan(visibleMessage)) + " ".repeat(padR) + " " + dim(BOX.vertical));
|
|
27597
|
-
console.log(dim(BOX.bottomLeft + BOX.horizontal.repeat(inner) + BOX.bottomRight));
|
|
27598
|
-
}
|
|
27599
|
-
section(title) {
|
|
27600
|
-
const w = getTerminalWidth();
|
|
27601
|
-
const lineLen = Math.max(0, w - title.length - 5);
|
|
27602
|
-
console.log("");
|
|
27603
|
-
console.log(bold(`${BOX.horizontal}${BOX.horizontal} ${title} ${BOX.horizontal.repeat(lineLen)}`));
|
|
27604
|
-
}
|
|
27605
|
-
tree(message, isLast) {
|
|
27606
|
-
const connector = isLast ? TREE.last : TREE.branch;
|
|
27607
|
-
console.log(`${connector} ${message}`);
|
|
27608
|
-
}
|
|
27609
|
-
}
|
|
27610
|
-
var logger = Logger.getInstance();
|
|
27611
|
-
|
|
27612
|
-
// dist/commands/init.js
|
|
28400
|
+
init_logger();
|
|
27613
28401
|
init_fs();
|
|
27614
28402
|
|
|
27615
28403
|
// dist/core/agentDetector.js
|
|
@@ -28270,6 +29058,7 @@ var getProjectName = function(cwd) {
|
|
|
28270
29058
|
};
|
|
28271
29059
|
|
|
28272
29060
|
// dist/commands/detect.js
|
|
29061
|
+
init_logger();
|
|
28273
29062
|
init_skillsManager();
|
|
28274
29063
|
init_agentManager();
|
|
28275
29064
|
async function detectCommand(options2) {
|
|
@@ -28338,12 +29127,13 @@ async function detectCommand(options2) {
|
|
|
28338
29127
|
}
|
|
28339
29128
|
|
|
28340
29129
|
// dist/commands/sync.js
|
|
28341
|
-
|
|
29130
|
+
init_logger();
|
|
29131
|
+
import {relative as relative6} from "path";
|
|
28342
29132
|
|
|
28343
29133
|
// dist/core/propagator.js
|
|
28344
29134
|
var import_gray_matter3 = __toESM(require_gray_matter(), 1);
|
|
28345
|
-
import {promises as
|
|
28346
|
-
import {resolve as
|
|
29135
|
+
import {promises as fs29} from "fs";
|
|
29136
|
+
import {resolve as resolve10} from "path";
|
|
28347
29137
|
|
|
28348
29138
|
// node_modules/js-yaml/dist/js-yaml.mjs
|
|
28349
29139
|
var isNothing = function(subject) {
|
|
@@ -30990,7 +31780,7 @@ class Propagator {
|
|
|
30990
31780
|
warnings: [],
|
|
30991
31781
|
resolvedTargets: []
|
|
30992
31782
|
};
|
|
30993
|
-
const agentsPath =
|
|
31783
|
+
const agentsPath = resolve10(projectPath, "agents.md");
|
|
30994
31784
|
if (!await fileExists(agentsPath)) {
|
|
30995
31785
|
result.success = false;
|
|
30996
31786
|
result.errors.push("agents.md not found. Run `agentinit init` first.");
|
|
@@ -31075,7 +31865,7 @@ class Propagator {
|
|
|
31075
31865
|
return [...generatedFiles.values()];
|
|
31076
31866
|
}
|
|
31077
31867
|
mergeGeneratedFile(projectPath, generatedFiles, output, agentId) {
|
|
31078
|
-
const outputPath =
|
|
31868
|
+
const outputPath = resolve10(projectPath, output.path);
|
|
31079
31869
|
const nextKind = output.kind ?? "file";
|
|
31080
31870
|
const nextContent = nextKind === "file" || output.content !== undefined ? normalizeContent(output.content || "") : undefined;
|
|
31081
31871
|
const existing = generatedFiles.get(outputPath);
|
|
@@ -31110,14 +31900,14 @@ class Propagator {
|
|
|
31110
31900
|
resolvedTargets: []
|
|
31111
31901
|
};
|
|
31112
31902
|
const exists = await fileExists(generatedFile.path);
|
|
31113
|
-
const existingStats = exists ? await
|
|
31903
|
+
const existingStats = exists ? await fs29.lstat(generatedFile.path).catch(() => null) : null;
|
|
31114
31904
|
const existingContent = exists && !existingStats?.isSymbolicLink() ? await readFileIfExists(generatedFile.path) : null;
|
|
31115
31905
|
const existingTarget = existingStats?.isSymbolicLink() ? await readSymlinkTarget(generatedFile.path) : null;
|
|
31116
31906
|
if (options2.managedState && !options2.dryRun) {
|
|
31117
31907
|
await options2.managedState.trackGeneratedPath(generatedFile.path, {
|
|
31118
31908
|
kind: "file",
|
|
31119
31909
|
source: "sync",
|
|
31120
|
-
ignorePath:
|
|
31910
|
+
ignorePath: resolve10(projectPath, generatedFile.ignorePath)
|
|
31121
31911
|
});
|
|
31122
31912
|
}
|
|
31123
31913
|
if (generatedFile.kind === "file" && exists && !existingStats?.isSymbolicLink() && existingContent === generatedFile.content) {
|
|
@@ -31141,12 +31931,12 @@ class Propagator {
|
|
|
31141
31931
|
if (!options2.dryRun) {
|
|
31142
31932
|
if (generatedFile.kind === "file") {
|
|
31143
31933
|
if (existingStats?.isSymbolicLink()) {
|
|
31144
|
-
await
|
|
31934
|
+
await fs29.rm(generatedFile.path, { force: true }).catch(() => {
|
|
31145
31935
|
});
|
|
31146
31936
|
}
|
|
31147
31937
|
await writeFile(generatedFile.path, generatedFile.content || "");
|
|
31148
31938
|
} else {
|
|
31149
|
-
const symlinkCreated = await createRelativeSymlink(
|
|
31939
|
+
const symlinkCreated = await createRelativeSymlink(resolve10(projectPath, generatedFile.target || ""), generatedFile.path);
|
|
31150
31940
|
if (!symlinkCreated) {
|
|
31151
31941
|
await writeFile(generatedFile.path, generatedFile.content || "");
|
|
31152
31942
|
result.warnings.push(`Could not create symlink for ${generatedFile.path}; wrote a copied file instead.`);
|
|
@@ -31251,7 +32041,7 @@ class Propagator {
|
|
|
31251
32041
|
});
|
|
31252
32042
|
}
|
|
31253
32043
|
async buildAiderConfig(projectPath) {
|
|
31254
|
-
const configPath =
|
|
32044
|
+
const configPath = resolve10(projectPath, ".aider.conf.yml");
|
|
31255
32045
|
const existingContent = await readFileIfExists(configPath);
|
|
31256
32046
|
let document = {};
|
|
31257
32047
|
if (existingContent) {
|
|
@@ -31318,14 +32108,14 @@ ${content}
|
|
|
31318
32108
|
|
|
31319
32109
|
// dist/core/managedState.js
|
|
31320
32110
|
init_fs();
|
|
31321
|
-
import {promises as
|
|
31322
|
-
import {dirname as
|
|
32111
|
+
import {promises as fs31} from "fs";
|
|
32112
|
+
import {dirname as dirname5, join as join8, relative as relative5, resolve as resolve11} from "path";
|
|
31323
32113
|
var toPosixPath = function(value) {
|
|
31324
32114
|
return value.replace(/\\/g, "/");
|
|
31325
32115
|
};
|
|
31326
32116
|
async function pathType(targetPath) {
|
|
31327
32117
|
try {
|
|
31328
|
-
const stat = await
|
|
32118
|
+
const stat = await fs31.lstat(targetPath);
|
|
31329
32119
|
if (stat.isSymbolicLink()) {
|
|
31330
32120
|
return "symlink";
|
|
31331
32121
|
}
|
|
@@ -31335,20 +32125,20 @@ async function pathType(targetPath) {
|
|
|
31335
32125
|
}
|
|
31336
32126
|
}
|
|
31337
32127
|
async function copyDirectory(src, dest) {
|
|
31338
|
-
await
|
|
31339
|
-
const entries = await
|
|
32128
|
+
await fs31.mkdir(dest, { recursive: true });
|
|
32129
|
+
const entries = await fs31.readdir(src, { withFileTypes: true });
|
|
31340
32130
|
for (const entry of entries) {
|
|
31341
|
-
const srcPath =
|
|
31342
|
-
const destPath =
|
|
32131
|
+
const srcPath = join8(src, entry.name);
|
|
32132
|
+
const destPath = join8(dest, entry.name);
|
|
31343
32133
|
if (entry.isDirectory()) {
|
|
31344
32134
|
await copyDirectory(srcPath, destPath);
|
|
31345
32135
|
} else if (entry.isSymbolicLink()) {
|
|
31346
|
-
const target = await
|
|
31347
|
-
await
|
|
31348
|
-
await
|
|
32136
|
+
const target = await fs31.readlink(srcPath);
|
|
32137
|
+
await fs31.mkdir(dirname5(destPath), { recursive: true });
|
|
32138
|
+
await fs31.symlink(target, destPath);
|
|
31349
32139
|
} else {
|
|
31350
|
-
await
|
|
31351
|
-
await
|
|
32140
|
+
await fs31.mkdir(dirname5(destPath), { recursive: true });
|
|
32141
|
+
await fs31.copyFile(srcPath, destPath);
|
|
31352
32142
|
}
|
|
31353
32143
|
}
|
|
31354
32144
|
}
|
|
@@ -31357,14 +32147,14 @@ async function copyPath(src, dest) {
|
|
|
31357
32147
|
if (!type2) {
|
|
31358
32148
|
return;
|
|
31359
32149
|
}
|
|
31360
|
-
await
|
|
32150
|
+
await fs31.mkdir(dirname5(dest), { recursive: true });
|
|
31361
32151
|
if (type2 === "symlink") {
|
|
31362
|
-
const target = await
|
|
31363
|
-
await
|
|
32152
|
+
const target = await fs31.readlink(src);
|
|
32153
|
+
await fs31.symlink(target, dest);
|
|
31364
32154
|
} else if (type2 === "directory") {
|
|
31365
32155
|
await copyDirectory(src, dest);
|
|
31366
32156
|
} else {
|
|
31367
|
-
await
|
|
32157
|
+
await fs31.copyFile(src, dest);
|
|
31368
32158
|
}
|
|
31369
32159
|
}
|
|
31370
32160
|
var MANAGED_STATE_FILE = "managed-state.json";
|
|
@@ -31378,11 +32168,11 @@ class ManagedStateStore {
|
|
|
31378
32168
|
this.state = state;
|
|
31379
32169
|
}
|
|
31380
32170
|
static async open(projectPath) {
|
|
31381
|
-
const agentInitDir =
|
|
31382
|
-
const statePath =
|
|
32171
|
+
const agentInitDir = join8(projectPath, ".agentinit");
|
|
32172
|
+
const statePath = join8(agentInitDir, MANAGED_STATE_FILE);
|
|
31383
32173
|
const emptyState = { version: 1, entries: [] };
|
|
31384
32174
|
try {
|
|
31385
|
-
const raw = await
|
|
32175
|
+
const raw = await fs31.readFile(statePath, "utf8");
|
|
31386
32176
|
const parsed = JSON.parse(raw);
|
|
31387
32177
|
if (!parsed || parsed.version !== 1 || !Array.isArray(parsed.entries)) {
|
|
31388
32178
|
return new ManagedStateStore(projectPath, emptyState);
|
|
@@ -31393,17 +32183,17 @@ class ManagedStateStore {
|
|
|
31393
32183
|
}
|
|
31394
32184
|
}
|
|
31395
32185
|
get agentInitDir() {
|
|
31396
|
-
return
|
|
32186
|
+
return join8(this.projectPath, ".agentinit");
|
|
31397
32187
|
}
|
|
31398
32188
|
get stateFilePath() {
|
|
31399
|
-
return
|
|
32189
|
+
return join8(this.agentInitDir, MANAGED_STATE_FILE);
|
|
31400
32190
|
}
|
|
31401
32191
|
get backupsDir() {
|
|
31402
|
-
return
|
|
32192
|
+
return join8(this.agentInitDir, BACKUPS_DIR);
|
|
31403
32193
|
}
|
|
31404
32194
|
normalizeRelativePath(targetPath, preserveTrailingSlash = false) {
|
|
31405
32195
|
const hasTrailingSlash = preserveTrailingSlash && /[\\/]$/.test(targetPath);
|
|
31406
|
-
const relativePath =
|
|
32196
|
+
const relativePath = relative5(this.projectPath, resolve11(targetPath));
|
|
31407
32197
|
const normalizedPath = toPosixPath(relativePath);
|
|
31408
32198
|
if (hasTrailingSlash && normalizedPath) {
|
|
31409
32199
|
return normalizedPath.endsWith("/") ? normalizedPath : `${normalizedPath}/`;
|
|
@@ -31421,14 +32211,14 @@ class ManagedStateStore {
|
|
|
31421
32211
|
}
|
|
31422
32212
|
if (type2 === "symlink") {
|
|
31423
32213
|
try {
|
|
31424
|
-
const backupLinkTarget = await
|
|
32214
|
+
const backupLinkTarget = await fs31.readlink(targetPath);
|
|
31425
32215
|
return { backupLinkTarget };
|
|
31426
32216
|
} catch {
|
|
31427
32217
|
return {};
|
|
31428
32218
|
}
|
|
31429
32219
|
}
|
|
31430
32220
|
const relativeTargetPath = this.normalizeRelativePath(targetPath);
|
|
31431
|
-
const backupPath =
|
|
32221
|
+
const backupPath = join8(this.backupsDir, relativeTargetPath);
|
|
31432
32222
|
if (!await fileExists(backupPath)) {
|
|
31433
32223
|
await copyPath(targetPath, backupPath);
|
|
31434
32224
|
}
|
|
@@ -31463,20 +32253,20 @@ class ManagedStateStore {
|
|
|
31463
32253
|
if (this.state.entries.length === 0) {
|
|
31464
32254
|
return [];
|
|
31465
32255
|
}
|
|
31466
|
-
const
|
|
32256
|
+
const paths6 = new Set([
|
|
31467
32257
|
".agentinit/managed-state.json",
|
|
31468
32258
|
".agentinit/backups/"
|
|
31469
32259
|
]);
|
|
31470
32260
|
for (const entry of this.state.entries) {
|
|
31471
32261
|
if (entry.ignorePath) {
|
|
31472
|
-
|
|
32262
|
+
paths6.add(entry.ignorePath);
|
|
31473
32263
|
}
|
|
31474
32264
|
}
|
|
31475
|
-
return [...
|
|
32265
|
+
return [...paths6];
|
|
31476
32266
|
}
|
|
31477
32267
|
async save() {
|
|
31478
|
-
await
|
|
31479
|
-
await
|
|
32268
|
+
await fs31.mkdir(this.agentInitDir, { recursive: true });
|
|
32269
|
+
await fs31.writeFile(this.stateFilePath, JSON.stringify(this.state, null, 2), "utf8");
|
|
31480
32270
|
}
|
|
31481
32271
|
async revertAll(options2 = {}) {
|
|
31482
32272
|
const summary = {
|
|
@@ -31486,34 +32276,34 @@ class ManagedStateStore {
|
|
|
31486
32276
|
};
|
|
31487
32277
|
const entries = [...this.state.entries].sort((a, b) => b.path.length - a.path.length);
|
|
31488
32278
|
for (const entry of entries) {
|
|
31489
|
-
const absolutePath =
|
|
31490
|
-
const backupPath = entry.backupPath ?
|
|
32279
|
+
const absolutePath = resolve11(this.projectPath, entry.path);
|
|
32280
|
+
const backupPath = entry.backupPath ? resolve11(this.projectPath, entry.backupPath) : null;
|
|
31491
32281
|
const backupLinkTarget = entry.backupLinkTarget;
|
|
31492
32282
|
if (entry.existedBefore && backupLinkTarget !== undefined) {
|
|
31493
32283
|
if (!options2.dryRun) {
|
|
31494
|
-
await
|
|
32284
|
+
await fs31.rm(absolutePath, { recursive: true, force: true }).catch(() => {
|
|
31495
32285
|
});
|
|
31496
|
-
await
|
|
31497
|
-
await
|
|
32286
|
+
await fs31.mkdir(dirname5(absolutePath), { recursive: true });
|
|
32287
|
+
await fs31.symlink(backupLinkTarget, absolutePath);
|
|
31498
32288
|
}
|
|
31499
32289
|
summary.restored++;
|
|
31500
32290
|
} else if (entry.existedBefore && backupPath && await fileExists(backupPath)) {
|
|
31501
32291
|
if (!options2.dryRun) {
|
|
31502
|
-
await
|
|
32292
|
+
await fs31.rm(absolutePath, { recursive: true, force: true }).catch(() => {
|
|
31503
32293
|
});
|
|
31504
32294
|
await copyPath(backupPath, absolutePath);
|
|
31505
32295
|
}
|
|
31506
32296
|
summary.restored++;
|
|
31507
32297
|
} else {
|
|
31508
32298
|
if (!options2.dryRun) {
|
|
31509
|
-
await
|
|
32299
|
+
await fs31.rm(absolutePath, { recursive: true, force: true }).catch(() => {
|
|
31510
32300
|
});
|
|
31511
32301
|
}
|
|
31512
32302
|
summary.removed++;
|
|
31513
32303
|
}
|
|
31514
32304
|
if (!options2.keepBackups && backupPath && await fileExists(backupPath)) {
|
|
31515
32305
|
if (!options2.dryRun) {
|
|
31516
|
-
await
|
|
32306
|
+
await fs31.rm(backupPath, { recursive: true, force: true }).catch(() => {
|
|
31517
32307
|
});
|
|
31518
32308
|
}
|
|
31519
32309
|
summary.backupsRemoved++;
|
|
@@ -31521,16 +32311,16 @@ class ManagedStateStore {
|
|
|
31521
32311
|
}
|
|
31522
32312
|
if (!options2.dryRun) {
|
|
31523
32313
|
this.state.entries.length = 0;
|
|
31524
|
-
await
|
|
32314
|
+
await fs31.rm(this.stateFilePath, { force: true }).catch(() => {
|
|
31525
32315
|
});
|
|
31526
32316
|
if (!options2.keepBackups) {
|
|
31527
|
-
await
|
|
32317
|
+
await fs31.rm(this.backupsDir, { recursive: true, force: true }).catch(() => {
|
|
31528
32318
|
});
|
|
31529
32319
|
}
|
|
31530
32320
|
try {
|
|
31531
|
-
const remainingEntries = await
|
|
32321
|
+
const remainingEntries = await fs31.readdir(this.agentInitDir);
|
|
31532
32322
|
if (remainingEntries.length === 0) {
|
|
31533
|
-
await
|
|
32323
|
+
await fs31.rm(this.agentInitDir, { recursive: true, force: true });
|
|
31534
32324
|
}
|
|
31535
32325
|
} catch {
|
|
31536
32326
|
}
|
|
@@ -31580,7 +32370,7 @@ async function syncCommand(options2) {
|
|
|
31580
32370
|
for (const change of result.changes) {
|
|
31581
32371
|
const action = change.action === "created" ? "\u2795" : change.action === "updated" ? "\uD83D\uDCDD" : "\uD83D\uDCBE";
|
|
31582
32372
|
const names = change.agents.map((id) => agentManager5.getAgentById(id)?.name || id).join(", ");
|
|
31583
|
-
logger.info(` ${action} ${
|
|
32373
|
+
logger.info(` ${action} ${relative6(cwd, change.file) || change.file}`);
|
|
31584
32374
|
logger.info(` Agents: ${names}`);
|
|
31585
32375
|
}
|
|
31586
32376
|
if (options2.backup && result.changes.some((c) => c.action === "backed_up")) {
|
|
@@ -31609,7 +32399,9 @@ async function syncCommand(options2) {
|
|
|
31609
32399
|
}
|
|
31610
32400
|
|
|
31611
32401
|
// dist/commands/apply.js
|
|
31612
|
-
|
|
32402
|
+
init_colors();
|
|
32403
|
+
init_logger();
|
|
32404
|
+
import {relative as relative7} from "path";
|
|
31613
32405
|
|
|
31614
32406
|
// dist/types/index.js
|
|
31615
32407
|
var MCPServerType;
|
|
@@ -31875,12 +32667,12 @@ class MCPParser {
|
|
|
31875
32667
|
// dist/constants/mcp.js
|
|
31876
32668
|
import {readFileSync as readFileSync2} from "fs";
|
|
31877
32669
|
import {fileURLToPath} from "url";
|
|
31878
|
-
import {dirname as
|
|
32670
|
+
import {dirname as dirname6, join as join9} from "path";
|
|
31879
32671
|
var getPackageVersion = function() {
|
|
31880
32672
|
try {
|
|
31881
32673
|
const __filename2 = fileURLToPath(import.meta.url);
|
|
31882
|
-
const __dirname2 =
|
|
31883
|
-
const packageJsonPath =
|
|
32674
|
+
const __dirname2 = dirname6(__filename2);
|
|
32675
|
+
const packageJsonPath = join9(__dirname2, "../../package.json");
|
|
31884
32676
|
const packageJson = JSON.parse(readFileSync2(packageJsonPath, "utf-8"));
|
|
31885
32677
|
return packageJson.version || "1.0.0";
|
|
31886
32678
|
} catch {
|
|
@@ -31911,17 +32703,17 @@ import {readFileSync as readFileSync4} from "fs";
|
|
|
31911
32703
|
|
|
31912
32704
|
// dist/core/rulesTemplateLoader.js
|
|
31913
32705
|
var toml = __toESM(require_toml(), 1);
|
|
31914
|
-
import {resolve as
|
|
32706
|
+
import {resolve as resolve12, dirname as dirname7} from "path";
|
|
31915
32707
|
import {fileURLToPath as fileURLToPath2} from "url";
|
|
31916
32708
|
import {readFileSync as readFileSync3, readdirSync, existsSync as existsSync2} from "fs";
|
|
31917
32709
|
var __filename2 = fileURLToPath2(import.meta.url);
|
|
31918
|
-
var __dirname2 =
|
|
32710
|
+
var __dirname2 = dirname7(__filename2);
|
|
31919
32711
|
|
|
31920
32712
|
class RulesTemplateLoader {
|
|
31921
32713
|
templatesPath;
|
|
31922
32714
|
templates = new Map;
|
|
31923
32715
|
constructor() {
|
|
31924
|
-
this.templatesPath =
|
|
32716
|
+
this.templatesPath = resolve12(__dirname2, "../templates/rules");
|
|
31925
32717
|
this.loadTemplates();
|
|
31926
32718
|
}
|
|
31927
32719
|
loadTemplates() {
|
|
@@ -31931,7 +32723,7 @@ class RulesTemplateLoader {
|
|
|
31931
32723
|
const files = readdirSync(this.templatesPath).filter((file) => file.endsWith(".toml"));
|
|
31932
32724
|
for (const file of files) {
|
|
31933
32725
|
try {
|
|
31934
|
-
const filePath =
|
|
32726
|
+
const filePath = resolve12(this.templatesPath, file);
|
|
31935
32727
|
const content = readFileSync3(filePath, "utf-8");
|
|
31936
32728
|
const parsed = toml.default.parse(content);
|
|
31937
32729
|
const template = {
|
|
@@ -37503,7 +38295,7 @@ class Protocol {
|
|
|
37503
38295
|
}
|
|
37504
38296
|
request(request, resultSchema, options2) {
|
|
37505
38297
|
const { relatedRequestId, resumptionToken, onresumptiontoken } = options2 !== null && options2 !== undefined ? options2 : {};
|
|
37506
|
-
return new Promise((
|
|
38298
|
+
return new Promise((resolve13, reject) => {
|
|
37507
38299
|
var _a, _b, _c, _d, _e, _f;
|
|
37508
38300
|
if (!this._transport) {
|
|
37509
38301
|
reject(new Error("Not connected"));
|
|
@@ -37554,7 +38346,7 @@ class Protocol {
|
|
|
37554
38346
|
}
|
|
37555
38347
|
try {
|
|
37556
38348
|
const result = resultSchema.parse(response.result);
|
|
37557
|
-
|
|
38349
|
+
resolve13(result);
|
|
37558
38350
|
} catch (error) {
|
|
37559
38351
|
reject(error);
|
|
37560
38352
|
}
|
|
@@ -37934,7 +38726,7 @@ class StdioClientTransport {
|
|
|
37934
38726
|
if (this._process) {
|
|
37935
38727
|
throw new Error("StdioClientTransport already started! If using Client class, note that connect() calls start() automatically.");
|
|
37936
38728
|
}
|
|
37937
|
-
return new Promise((
|
|
38729
|
+
return new Promise((resolve13, reject) => {
|
|
37938
38730
|
var _a, _b, _c, _d, _e;
|
|
37939
38731
|
this._process = import_cross_spawn.default(this._serverParams.command, (_a = this._serverParams.args) !== null && _a !== undefined ? _a : [], {
|
|
37940
38732
|
env: {
|
|
@@ -37957,7 +38749,7 @@ class StdioClientTransport {
|
|
|
37957
38749
|
(_b2 = this.onerror) === null || _b2 === undefined || _b2.call(this, error);
|
|
37958
38750
|
});
|
|
37959
38751
|
this._process.on("spawn", () => {
|
|
37960
|
-
|
|
38752
|
+
resolve13();
|
|
37961
38753
|
});
|
|
37962
38754
|
this._process.on("close", (_code) => {
|
|
37963
38755
|
var _a2;
|
|
@@ -38012,16 +38804,16 @@ class StdioClientTransport {
|
|
|
38012
38804
|
this._readBuffer.clear();
|
|
38013
38805
|
}
|
|
38014
38806
|
send(message) {
|
|
38015
|
-
return new Promise((
|
|
38807
|
+
return new Promise((resolve13) => {
|
|
38016
38808
|
var _a;
|
|
38017
38809
|
if (!((_a = this._process) === null || _a === undefined ? undefined : _a.stdin)) {
|
|
38018
38810
|
throw new Error("Not connected");
|
|
38019
38811
|
}
|
|
38020
38812
|
const json2 = serializeMessage(message);
|
|
38021
38813
|
if (this._process.stdin.write(json2)) {
|
|
38022
|
-
|
|
38814
|
+
resolve13();
|
|
38023
38815
|
} else {
|
|
38024
|
-
this._process.stdin.once("drain",
|
|
38816
|
+
this._process.stdin.once("drain", resolve13);
|
|
38025
38817
|
}
|
|
38026
38818
|
});
|
|
38027
38819
|
}
|
|
@@ -39443,7 +40235,7 @@ class SSEClientTransport {
|
|
|
39443
40235
|
_startOrAuth() {
|
|
39444
40236
|
var _a, _b, _c;
|
|
39445
40237
|
const fetchImpl = (_c = (_b = (_a = this === null || this === undefined ? undefined : this._eventSourceInit) === null || _a === undefined ? undefined : _a.fetch) !== null && _b !== undefined ? _b : this._fetch) !== null && _c !== undefined ? _c : fetch;
|
|
39446
|
-
return new Promise((
|
|
40238
|
+
return new Promise((resolve13, reject) => {
|
|
39447
40239
|
this._eventSource = new EventSource(this._url.href, {
|
|
39448
40240
|
...this._eventSourceInit,
|
|
39449
40241
|
fetch: async (url, init2) => {
|
|
@@ -39463,7 +40255,7 @@ class SSEClientTransport {
|
|
|
39463
40255
|
this._eventSource.onerror = (event) => {
|
|
39464
40256
|
var _a2;
|
|
39465
40257
|
if (event.code === 401 && this._authProvider) {
|
|
39466
|
-
this._authThenStart().then(
|
|
40258
|
+
this._authThenStart().then(resolve13, reject);
|
|
39467
40259
|
return;
|
|
39468
40260
|
}
|
|
39469
40261
|
const error = new SseError(event.code, event.message, event);
|
|
@@ -39486,7 +40278,7 @@ class SSEClientTransport {
|
|
|
39486
40278
|
this.close();
|
|
39487
40279
|
return;
|
|
39488
40280
|
}
|
|
39489
|
-
|
|
40281
|
+
resolve13();
|
|
39490
40282
|
});
|
|
39491
40283
|
this._eventSource.onmessage = (event) => {
|
|
39492
40284
|
var _a2, _b2;
|
|
@@ -39563,8 +40355,11 @@ class SSEClientTransport {
|
|
|
39563
40355
|
|
|
39564
40356
|
// dist/core/mcpClient.js
|
|
39565
40357
|
init_lib();
|
|
40358
|
+
init_colors();
|
|
40359
|
+
init_logger();
|
|
39566
40360
|
|
|
39567
40361
|
// dist/utils/packageVersion.js
|
|
40362
|
+
init_logger();
|
|
39568
40363
|
function extractExplicitVersion(packageSpec) {
|
|
39569
40364
|
const versionMatch = packageSpec.match(/@([\d]+\.[\d]+\.[\d]+(?:[-+].+)?$)/);
|
|
39570
40365
|
if (versionMatch && versionMatch[1]) {
|
|
@@ -40150,11 +40945,11 @@ class MCPVerifier {
|
|
|
40150
40945
|
}
|
|
40151
40946
|
|
|
40152
40947
|
// dist/core/gitignoreManager.js
|
|
40153
|
-
import {promises as
|
|
40154
|
-
import {dirname as
|
|
40948
|
+
import {promises as fs34} from "fs";
|
|
40949
|
+
import {dirname as dirname8, join as join10} from "path";
|
|
40155
40950
|
var normalizeIgnorePath = function(projectPath, value) {
|
|
40156
|
-
const
|
|
40157
|
-
const normalized =
|
|
40951
|
+
const relative7 = value.startsWith(projectPath) ? value.slice(projectPath.length + 1) : value;
|
|
40952
|
+
const normalized = relative7.replace(/\\/g, "/").replace(/^\/+/, "");
|
|
40158
40953
|
if (!normalized) {
|
|
40159
40954
|
return normalized;
|
|
40160
40955
|
}
|
|
@@ -40197,13 +40992,13 @@ var updateManagedBlock = function(existingContent, entries) {
|
|
|
40197
40992
|
}
|
|
40198
40993
|
return content;
|
|
40199
40994
|
};
|
|
40200
|
-
async function updateManagedIgnoreFile(projectPath,
|
|
40201
|
-
const ignoreFile = options2.local ?
|
|
40202
|
-
const ignoreFilePath =
|
|
40995
|
+
async function updateManagedIgnoreFile(projectPath, paths6, options2 = {}) {
|
|
40996
|
+
const ignoreFile = options2.local ? join10(".git", "info", "exclude") : ".gitignore";
|
|
40997
|
+
const ignoreFilePath = join10(projectPath, ignoreFile);
|
|
40203
40998
|
if (options2.local) {
|
|
40204
|
-
const gitDir =
|
|
40999
|
+
const gitDir = join10(projectPath, ".git");
|
|
40205
41000
|
try {
|
|
40206
|
-
const stat = await
|
|
41001
|
+
const stat = await fs34.stat(gitDir);
|
|
40207
41002
|
if (!stat.isDirectory()) {
|
|
40208
41003
|
throw new Error;
|
|
40209
41004
|
}
|
|
@@ -40211,24 +41006,24 @@ async function updateManagedIgnoreFile(projectPath, paths5, options2 = {}) {
|
|
|
40211
41006
|
throw new Error("Cannot update .git/info/exclude because this project is not a Git repository");
|
|
40212
41007
|
}
|
|
40213
41008
|
}
|
|
40214
|
-
const normalizedPaths = [...new Set(
|
|
41009
|
+
const normalizedPaths = [...new Set(paths6.map((path) => normalizeIgnorePath(projectPath, path)).filter(Boolean))].sort();
|
|
40215
41010
|
let existingContent = "";
|
|
40216
41011
|
try {
|
|
40217
|
-
existingContent = await
|
|
41012
|
+
existingContent = await fs34.readFile(ignoreFilePath, "utf8");
|
|
40218
41013
|
} catch {
|
|
40219
41014
|
existingContent = "";
|
|
40220
41015
|
}
|
|
40221
41016
|
const updatedContent = updateManagedBlock(existingContent, normalizedPaths);
|
|
40222
|
-
await
|
|
40223
|
-
await
|
|
41017
|
+
await fs34.mkdir(dirname8(ignoreFilePath), { recursive: true });
|
|
41018
|
+
await fs34.writeFile(ignoreFilePath, updatedContent, "utf8");
|
|
40224
41019
|
return ignoreFilePath;
|
|
40225
41020
|
}
|
|
40226
41021
|
async function removeManagedIgnoreBlock(projectPath, options2 = {}) {
|
|
40227
|
-
const ignoreFile = options2.local ?
|
|
40228
|
-
const ignoreFilePath =
|
|
41022
|
+
const ignoreFile = options2.local ? join10(".git", "info", "exclude") : ".gitignore";
|
|
41023
|
+
const ignoreFilePath = join10(projectPath, ignoreFile);
|
|
40229
41024
|
let content;
|
|
40230
41025
|
try {
|
|
40231
|
-
content = await
|
|
41026
|
+
content = await fs34.readFile(ignoreFilePath, "utf8");
|
|
40232
41027
|
} catch {
|
|
40233
41028
|
return false;
|
|
40234
41029
|
}
|
|
@@ -40244,13 +41039,13 @@ async function removeManagedIgnoreBlock(projectPath, options2 = {}) {
|
|
|
40244
41039
|
const afterBlock = content.slice(endIndex + END_MARKER.length).replace(/^\n+/, "");
|
|
40245
41040
|
let nextContent = `${beforeBlock}${afterBlock}`.replace(/\n{3,}/g, "\n\n").replace(/^\n+/, "");
|
|
40246
41041
|
if (nextContent.trim() === "") {
|
|
40247
|
-
await
|
|
41042
|
+
await fs34.rm(ignoreFilePath, { force: true }).catch(() => {
|
|
40248
41043
|
});
|
|
40249
41044
|
} else {
|
|
40250
41045
|
if (!nextContent.endsWith("\n")) {
|
|
40251
41046
|
nextContent += "\n";
|
|
40252
41047
|
}
|
|
40253
|
-
await
|
|
41048
|
+
await fs34.writeFile(ignoreFilePath, nextContent, "utf8");
|
|
40254
41049
|
}
|
|
40255
41050
|
return true;
|
|
40256
41051
|
}
|
|
@@ -40261,12 +41056,12 @@ var END_MARKER = "# END AgentInit Generated Files";
|
|
|
40261
41056
|
init_agentManager();
|
|
40262
41057
|
init_skillsManager();
|
|
40263
41058
|
init_fs();
|
|
40264
|
-
import {dirname as
|
|
41059
|
+
import {dirname as dirname9, join as join11} from "path";
|
|
40265
41060
|
async function discoverProjectSkills(projectPath, skillsManager4) {
|
|
40266
41061
|
const sources = [];
|
|
40267
41062
|
const skills2 = new Map;
|
|
40268
41063
|
for (const sourceDir of PROJECT_SKILL_SOURCE_DIRS) {
|
|
40269
|
-
const absoluteSourceDir =
|
|
41064
|
+
const absoluteSourceDir = join11(projectPath, sourceDir);
|
|
40270
41065
|
if (!await fileExists(absoluteSourceDir)) {
|
|
40271
41066
|
continue;
|
|
40272
41067
|
}
|
|
@@ -40339,7 +41134,7 @@ async function applyProjectSkills(projectPath, targetAgentIds, managedState2, op
|
|
|
40339
41134
|
await managedState2.trackGeneratedPath(generatedPath, {
|
|
40340
41135
|
kind: "directory",
|
|
40341
41136
|
source: "skills",
|
|
40342
|
-
ignorePath: `${
|
|
41137
|
+
ignorePath: `${dirname9(generatedPath)}/`
|
|
40343
41138
|
});
|
|
40344
41139
|
}
|
|
40345
41140
|
}
|
|
@@ -40450,7 +41245,7 @@ async function applyProjectCommand(options2) {
|
|
|
40450
41245
|
if (change.action === "backed_up")
|
|
40451
41246
|
return;
|
|
40452
41247
|
const names = change.agents.map((id) => agentManager7.getAgentById(id)?.name || id).join(", ");
|
|
40453
|
-
logger.info(` ${
|
|
41248
|
+
logger.info(` ${relative7(cwd, change.file) || change.file}`);
|
|
40454
41249
|
logger.info(` Agents: ${names}`);
|
|
40455
41250
|
});
|
|
40456
41251
|
}
|
|
@@ -40468,7 +41263,7 @@ async function applyProjectCommand(options2) {
|
|
|
40468
41263
|
installsByPath.set(item.path, existing);
|
|
40469
41264
|
}
|
|
40470
41265
|
for (const [path, details] of installsByPath) {
|
|
40471
|
-
logger.info(` ${
|
|
41266
|
+
logger.info(` ${relative7(cwd, path) || path}`);
|
|
40472
41267
|
logger.info(` Agents: ${[...details.agents].join(", ")}`);
|
|
40473
41268
|
logger.info(` Skills: ${[...details.skills].join(", ")}`);
|
|
40474
41269
|
}
|
|
@@ -40910,6 +41705,7 @@ var LEGACY_APPLY_FLAGS = new Set([
|
|
|
40910
41705
|
]);
|
|
40911
41706
|
|
|
40912
41707
|
// dist/commands/verifyMcp.js
|
|
41708
|
+
init_logger();
|
|
40913
41709
|
init_agentManager();
|
|
40914
41710
|
async function verifyMcpCommand(args) {
|
|
40915
41711
|
const cwd = process.cwd();
|
|
@@ -41115,6 +41911,7 @@ async function verifyMcpCommand(args) {
|
|
|
41115
41911
|
}
|
|
41116
41912
|
|
|
41117
41913
|
// dist/commands/revert.js
|
|
41914
|
+
init_logger();
|
|
41118
41915
|
async function revertCommand(options2) {
|
|
41119
41916
|
const cwd = process.cwd();
|
|
41120
41917
|
logger.titleBox("AgentInit Revert");
|
|
@@ -41159,6 +41956,7 @@ async function revertCommand(options2) {
|
|
|
41159
41956
|
}
|
|
41160
41957
|
|
|
41161
41958
|
// dist/utils/colors.js
|
|
41959
|
+
init_colors();
|
|
41162
41960
|
var colorsEnabled = function() {
|
|
41163
41961
|
const env2 = process.env || {};
|
|
41164
41962
|
const isTTY2 = !!process.stdout?.isTTY;
|
|
@@ -41172,6 +41970,7 @@ function orange(text) {
|
|
|
41172
41970
|
}
|
|
41173
41971
|
|
|
41174
41972
|
// dist/commands/config.js
|
|
41973
|
+
init_logger();
|
|
41175
41974
|
init_marketplaceRegistry();
|
|
41176
41975
|
init_userConfig();
|
|
41177
41976
|
var sortConfig = function(config) {
|
|
@@ -41348,12 +42147,15 @@ var BUILT_IN_VERIFIED_REPOS = new Set(getBuiltInVerifiedGithubRepos());
|
|
|
41348
42147
|
|
|
41349
42148
|
// dist/commands/skills.js
|
|
41350
42149
|
var import_prompts3 = __toESM(require_prompts3(), 1);
|
|
41351
|
-
|
|
41352
|
-
|
|
42150
|
+
init_colors();
|
|
42151
|
+
init_logger();
|
|
42152
|
+
import {homedir as homedir7} from "os";
|
|
42153
|
+
import {relative as relative8, resolve as resolve13} from "path";
|
|
41353
42154
|
|
|
41354
42155
|
// dist/utils/promptUtils.js
|
|
41355
42156
|
var import_prompts2 = __toESM(require_prompts3(), 1);
|
|
41356
42157
|
import {createRequire as createRequire2} from "module";
|
|
42158
|
+
init_logger();
|
|
41357
42159
|
function enableUppercaseToggleAllForMultiselectPrompt() {
|
|
41358
42160
|
if (uppercaseToggleAllPatched) {
|
|
41359
42161
|
return;
|
|
@@ -41367,7 +42169,22 @@ function enableUppercaseToggleAllForMultiselectPrompt() {
|
|
|
41367
42169
|
}
|
|
41368
42170
|
const originalHandler = prototype._;
|
|
41369
42171
|
prototype._ = function agentinitMultiselectHandler(input, key) {
|
|
41370
|
-
|
|
42172
|
+
if (this.__agentinitHotkeyBusy) {
|
|
42173
|
+
return;
|
|
42174
|
+
}
|
|
42175
|
+
const normalizedInput = input === "A" ? "a" : input;
|
|
42176
|
+
const hotkeyHandler = this.__agentinitHotkeys?.[normalizedInput] || this.__agentinitHotkeys?.[input];
|
|
42177
|
+
if (hotkeyHandler) {
|
|
42178
|
+
this.__agentinitHotkeyBusy = true;
|
|
42179
|
+
Promise.resolve(hotkeyHandler(this, normalizedInput, key)).finally(() => {
|
|
42180
|
+
this.__agentinitHotkeyBusy = false;
|
|
42181
|
+
if (typeof this.render === "function") {
|
|
42182
|
+
this.render();
|
|
42183
|
+
}
|
|
42184
|
+
});
|
|
42185
|
+
return;
|
|
42186
|
+
}
|
|
42187
|
+
return originalHandler.call(this, normalizedInput, key);
|
|
41371
42188
|
};
|
|
41372
42189
|
Object.defineProperty(prototype, "__agentinitUppercaseToggleAllPatched", {
|
|
41373
42190
|
value: true,
|
|
@@ -41380,12 +42197,52 @@ function enableUppercaseToggleAllForMultiselectPrompt() {
|
|
|
41380
42197
|
}
|
|
41381
42198
|
async function promptMultiselect(options2) {
|
|
41382
42199
|
enableUppercaseToggleAllForMultiselectPrompt();
|
|
41383
|
-
|
|
42200
|
+
const userOnRender = options2.onRenderPrompt;
|
|
42201
|
+
const hint = options2.hint;
|
|
42202
|
+
let requestedAction;
|
|
42203
|
+
let promptInstance;
|
|
42204
|
+
const closeWithCurrentSelection = (prompt) => {
|
|
42205
|
+
if (typeof prompt.close !== "function") {
|
|
42206
|
+
return false;
|
|
42207
|
+
}
|
|
42208
|
+
prompt.done = true;
|
|
42209
|
+
prompt.aborted = false;
|
|
42210
|
+
prompt.fire?.();
|
|
42211
|
+
prompt.render?.();
|
|
42212
|
+
prompt.out?.write("\n");
|
|
42213
|
+
prompt.close();
|
|
42214
|
+
return true;
|
|
42215
|
+
};
|
|
42216
|
+
const hotkeys = options2.hotkeys ? Object.fromEntries(Object.entries(options2.hotkeys).map(([key, handler]) => [
|
|
42217
|
+
key,
|
|
42218
|
+
(prompt, input, pressedKey) => handler({
|
|
42219
|
+
prompt,
|
|
42220
|
+
requestAction: (action) => {
|
|
42221
|
+
requestedAction = action;
|
|
42222
|
+
},
|
|
42223
|
+
closeWithCurrentSelection: () => closeWithCurrentSelection(prompt)
|
|
42224
|
+
}, input, pressedKey)
|
|
42225
|
+
])) : undefined;
|
|
42226
|
+
const response = await import_prompts2.default({
|
|
41384
42227
|
...options2,
|
|
41385
42228
|
type: "multiselect",
|
|
41386
42229
|
instructions: options2.instructions ?? false,
|
|
41387
|
-
hint:
|
|
42230
|
+
hint: typeof hint === "function" ? hint() : hint ?? MULTISELECT_TOGGLE_ALL_HINT,
|
|
42231
|
+
onRender() {
|
|
42232
|
+
promptInstance = this;
|
|
42233
|
+
if (hotkeys) {
|
|
42234
|
+
this.__agentinitHotkeys = hotkeys;
|
|
42235
|
+
} else {
|
|
42236
|
+
delete this.__agentinitHotkeys;
|
|
42237
|
+
}
|
|
42238
|
+
this.hint = typeof hint === "function" ? hint() : hint ?? MULTISELECT_TOGGLE_ALL_HINT;
|
|
42239
|
+
userOnRender?.(this);
|
|
42240
|
+
}
|
|
41388
42241
|
});
|
|
42242
|
+
if (requestedAction) {
|
|
42243
|
+
response.__agentinitAction = requestedAction;
|
|
42244
|
+
}
|
|
42245
|
+
return response;
|
|
41389
42246
|
}
|
|
41390
42247
|
async function selectBundlePlugins(entries, actionLabel, options2 = {}) {
|
|
41391
42248
|
if (options2.selectAll) {
|
|
@@ -41418,11 +42275,86 @@ init_skillsManager();
|
|
|
41418
42275
|
init_pluginManager();
|
|
41419
42276
|
init_marketplaceRegistry();
|
|
41420
42277
|
init_agentManager();
|
|
42278
|
+
init_installLock();
|
|
42279
|
+
init_fs();
|
|
42280
|
+
|
|
42281
|
+
// dist/utils/lockSource.js
|
|
42282
|
+
function lockSourceToSpecifier(source) {
|
|
42283
|
+
if (source.type === "marketplace" && source.marketplace && source.pluginName) {
|
|
42284
|
+
return {
|
|
42285
|
+
source: source.pluginName,
|
|
42286
|
+
from: source.marketplace,
|
|
42287
|
+
...source.prefix ? { prefix: source.prefix } : {}
|
|
42288
|
+
};
|
|
42289
|
+
}
|
|
42290
|
+
if (source.type === "github") {
|
|
42291
|
+
if (source.owner && source.repo) {
|
|
42292
|
+
return {
|
|
42293
|
+
source: source.subpath ? `${source.owner}/${source.repo}/${source.subpath}` : `${source.owner}/${source.repo}`,
|
|
42294
|
+
...source.prefix ? { prefix: source.prefix } : {}
|
|
42295
|
+
};
|
|
42296
|
+
}
|
|
42297
|
+
if (source.url) {
|
|
42298
|
+
return { source: source.url, ...source.prefix ? { prefix: source.prefix } : {} };
|
|
42299
|
+
}
|
|
42300
|
+
}
|
|
42301
|
+
if (source.type === "gitlab") {
|
|
42302
|
+
if (source.owner && source.repo) {
|
|
42303
|
+
const prefix = `gitlab:${source.owner}/${source.repo}`;
|
|
42304
|
+
return {
|
|
42305
|
+
source: source.subpath ? `${prefix}//${source.subpath}` : prefix,
|
|
42306
|
+
...source.prefix ? { prefix: source.prefix } : {}
|
|
42307
|
+
};
|
|
42308
|
+
}
|
|
42309
|
+
if (source.url) {
|
|
42310
|
+
return { source: source.url, ...source.prefix ? { prefix: source.prefix } : {} };
|
|
42311
|
+
}
|
|
42312
|
+
}
|
|
42313
|
+
if (source.type === "bitbucket") {
|
|
42314
|
+
if (source.owner && source.repo) {
|
|
42315
|
+
const prefix = `bitbucket:${source.owner}/${source.repo}`;
|
|
42316
|
+
return {
|
|
42317
|
+
source: source.subpath ? `${prefix}/${source.subpath}` : prefix,
|
|
42318
|
+
...source.prefix ? { prefix: source.prefix } : {}
|
|
42319
|
+
};
|
|
42320
|
+
}
|
|
42321
|
+
if (source.url) {
|
|
42322
|
+
return { source: source.url, ...source.prefix ? { prefix: source.prefix } : {} };
|
|
42323
|
+
}
|
|
42324
|
+
}
|
|
42325
|
+
if (source.type === "local" && source.path) {
|
|
42326
|
+
return { source: source.path, ...source.prefix ? { prefix: source.prefix } : {} };
|
|
42327
|
+
}
|
|
42328
|
+
return null;
|
|
42329
|
+
}
|
|
42330
|
+
function formatLockSource(source) {
|
|
42331
|
+
const specifier = lockSourceToSpecifier(source);
|
|
42332
|
+
if (!specifier) {
|
|
42333
|
+
return source.type;
|
|
42334
|
+
}
|
|
42335
|
+
const formatted = specifier.from ? `${specifier.from}/${specifier.source}` : specifier.source;
|
|
42336
|
+
return specifier.prefix ? `${formatted} [prefix: ${specifier.prefix}]` : formatted;
|
|
42337
|
+
}
|
|
42338
|
+
|
|
42339
|
+
// dist/commands/skills.js
|
|
41421
42340
|
init_skills();
|
|
42341
|
+
var normalizeSkillPrefix = function(prefix) {
|
|
42342
|
+
return prefix?.trim() ?? "";
|
|
42343
|
+
};
|
|
42344
|
+
var matchesSelectedSkillName = function(skillName, selectedNames, prefix) {
|
|
42345
|
+
if (selectedNames.has(skillName.toLowerCase())) {
|
|
42346
|
+
return true;
|
|
42347
|
+
}
|
|
42348
|
+
const normalizedPrefix = normalizeSkillPrefix(prefix);
|
|
42349
|
+
if (!normalizedPrefix) {
|
|
42350
|
+
return false;
|
|
42351
|
+
}
|
|
42352
|
+
return selectedNames.has(`${normalizedPrefix}${skillName}`.toLowerCase());
|
|
42353
|
+
};
|
|
41422
42354
|
function registerSkillsCommand(program2) {
|
|
41423
42355
|
const marketplaceHelp = getMarketplaceIds().join(", ");
|
|
41424
42356
|
const skills3 = program2.command("skills").description("Manage agent skills");
|
|
41425
|
-
skills3.command("add <source>").description("Add skills from a marketplace,
|
|
42357
|
+
skills3.command("add <source>").description("Add skills from a marketplace, hosted Git repo, or local path").option("--from <marketplace>", `Marketplace source override (available: ${marketplaceHelp})`).option("-g, --global", "Install skills globally").option("-a, --agent <agents...>", "Target specific agent(s)").option("-s, --skill <names...>", "Install only specific skills by name").option("-l, --list", "List available skills from the source without installing").option("--all", "Select all bundled plugins when the source contains multiple plugins").option("--copy", "Copy skill files instead of symlinking").option("--prefix <prefix>", "Prefix installed skill names").option("--no-scan", "Skip security scanning before installation").option("--allow-risky", "Install even if scanning finds high-risk patterns").option("-y, --yes", "Skip prompts, auto-detect project-configured agents, and apply available skill updates").action(async (source, options2) => {
|
|
41426
42358
|
logger.titleBox("AgentInit Skills");
|
|
41427
42359
|
const agentManager9 = new AgentManager;
|
|
41428
42360
|
const skillsManager5 = new SkillsManager(agentManager9);
|
|
@@ -41501,11 +42433,12 @@ function registerSkillsCommand(program2) {
|
|
|
41501
42433
|
let targetAgents = options2.agent;
|
|
41502
42434
|
let targetGlobal = options2.global;
|
|
41503
42435
|
let selectedSkillNames = options2.skill;
|
|
42436
|
+
let installPrefix = options2.prefix;
|
|
41504
42437
|
if (!options2.yes && (!selectedSkillNames || selectedSkillNames.length === 0) && preparedSkills.length > 1) {
|
|
41505
42438
|
if (selectedPluginNames && selectedPluginNames.length > 1) {
|
|
41506
42439
|
logger.info("Multiple bundled plugins selected; installing all skills from each selected plugin. Use --skill to filter by skill name.");
|
|
41507
42440
|
} else {
|
|
41508
|
-
const skillSelection = await resolveInteractiveSkillSelection(preparedSkills);
|
|
42441
|
+
const skillSelection = await resolveInteractiveSkillSelection(preparedSkills, installPrefix);
|
|
41509
42442
|
if (skillSelection.aborted) {
|
|
41510
42443
|
await skillsManager5.discardPreparedSource(source, process.cwd(), {
|
|
41511
42444
|
from: options2.from
|
|
@@ -41513,11 +42446,12 @@ function registerSkillsCommand(program2) {
|
|
|
41513
42446
|
return;
|
|
41514
42447
|
}
|
|
41515
42448
|
selectedSkillNames = skillSelection.skills;
|
|
42449
|
+
installPrefix = skillSelection.prefix;
|
|
41516
42450
|
}
|
|
41517
42451
|
}
|
|
41518
42452
|
if (!targetAgents && !options2.yes) {
|
|
41519
42453
|
const selectedSkillNameSet = selectedSkillNames && selectedSkillNames.length > 0 ? new Set(selectedSkillNames.map((name) => name.toLowerCase())) : undefined;
|
|
41520
|
-
const filteredPreviewSkills = selectedSkillNameSet ? preparedSkills.filter((skill) =>
|
|
42454
|
+
const filteredPreviewSkills = selectedSkillNameSet ? preparedSkills.filter((skill) => matchesSelectedSkillName(skill.name, selectedSkillNameSet, installPrefix)) : preparedSkills;
|
|
41521
42455
|
const selection = await resolveInteractiveSkillTargets(skillsManager5, agentManager9, source, process.cwd(), {
|
|
41522
42456
|
from: options2.from,
|
|
41523
42457
|
global: options2.global,
|
|
@@ -41550,7 +42484,10 @@ function registerSkillsCommand(program2) {
|
|
|
41550
42484
|
...targetGlobal !== undefined ? { global: targetGlobal } : {},
|
|
41551
42485
|
...targetAgents !== undefined ? { agents: targetAgents } : {},
|
|
41552
42486
|
...selectedSkillNames !== undefined ? { skills: selectedSkillNames } : {},
|
|
42487
|
+
...installPrefix !== undefined ? { prefix: installPrefix } : {},
|
|
41553
42488
|
...options2.copy !== undefined ? { copy: options2.copy } : {},
|
|
42489
|
+
...options2.scan !== undefined ? { scan: options2.scan } : {},
|
|
42490
|
+
...options2.allowRisky !== undefined ? { allowRisky: options2.allowRisky } : {},
|
|
41554
42491
|
...pluginName !== undefined ? { pluginName } : {},
|
|
41555
42492
|
...options2.yes !== undefined ? { yes: options2.yes } : {},
|
|
41556
42493
|
...confirmUpdate !== undefined ? { confirmUpdate } : {}
|
|
@@ -41609,7 +42546,7 @@ function registerSkillsCommand(program2) {
|
|
|
41609
42546
|
const mode = skill.mode === "symlink" ? " (canonical)" : "";
|
|
41610
42547
|
const scope = skill.scope === "global" ? " [global]" : "";
|
|
41611
42548
|
logger.info(`\n ${green(skill.name)} - ${skill.description}${scope}${mode}`);
|
|
41612
|
-
logger.info(` Path: ${
|
|
42549
|
+
logger.info(` Path: ${relative8(process.cwd(), skill.path) || skill.path}`);
|
|
41613
42550
|
logger.info(` Agents: ${[...skill.agents].join(", ")}`);
|
|
41614
42551
|
}
|
|
41615
42552
|
});
|
|
@@ -41648,7 +42585,207 @@ function registerSkillsCommand(program2) {
|
|
|
41648
42585
|
logger.info("Nothing to remove.");
|
|
41649
42586
|
}
|
|
41650
42587
|
});
|
|
42588
|
+
skills3.command("update [name]").description("Update installed skills from their original source").option("--everywhere", "Update across all tracked projects (uses global lockfile)").option("-d, --dry-run", "Show what would be updated without making changes").action(async (name, options2) => {
|
|
42589
|
+
logger.titleBox("AgentInit Skills");
|
|
42590
|
+
const installLock3 = new InstallLock;
|
|
42591
|
+
if (options2.everywhere) {
|
|
42592
|
+
if (!name) {
|
|
42593
|
+
logger.error("Skill name is required with --everywhere.");
|
|
42594
|
+
logger.info("Usage: agentinit skills update <name> --everywhere");
|
|
42595
|
+
return;
|
|
42596
|
+
}
|
|
42597
|
+
const entries = await installLock3.findProjectsWithSkill(name);
|
|
42598
|
+
if (entries.length === 0) {
|
|
42599
|
+
logger.info(`No tracked installations found for skill "${name}".`);
|
|
42600
|
+
logger.info(dim("Install the skill first, then update with --everywhere."));
|
|
42601
|
+
return;
|
|
42602
|
+
}
|
|
42603
|
+
logger.info(`Found ${cyan(String(entries.length))} tracked target(s) with skill "${green(name)}":\n`);
|
|
42604
|
+
const staleProjects = [];
|
|
42605
|
+
const updateTargets = [];
|
|
42606
|
+
for (const entry of entries) {
|
|
42607
|
+
const targetLabel = getLockEntryTargetLabel(entry);
|
|
42608
|
+
if (entry.scope !== "global" && !await fileExists(entry.projectPath)) {
|
|
42609
|
+
staleProjects.push(entry.projectPath);
|
|
42610
|
+
logger.info(` ${red("x")} ${targetLabel} ${dim("(missing)")}`);
|
|
42611
|
+
} else {
|
|
42612
|
+
updateTargets.push(entry);
|
|
42613
|
+
logger.info(` ${green("+")} ${targetLabel} ${dim(`[${entry.agents.join(", ")}]`)}`);
|
|
42614
|
+
}
|
|
42615
|
+
}
|
|
42616
|
+
if (staleProjects.length > 0) {
|
|
42617
|
+
logger.info("");
|
|
42618
|
+
logger.warn(`${staleProjects.length} project(s) no longer exist. Run "agentinit lock prune" to clean up.`);
|
|
42619
|
+
}
|
|
42620
|
+
if (updateTargets.length === 0) {
|
|
42621
|
+
logger.info("\nNo valid projects to update.");
|
|
42622
|
+
return;
|
|
42623
|
+
}
|
|
42624
|
+
if (options2.dryRun) {
|
|
42625
|
+
logger.info(dim(`
|
|
42626
|
+
Dry run \u2014 no changes made.`));
|
|
42627
|
+
return;
|
|
42628
|
+
}
|
|
42629
|
+
logger.info("");
|
|
42630
|
+
const spinner = ora("Updating skills across projects...").start();
|
|
42631
|
+
let updatedCount = 0;
|
|
42632
|
+
let unchangedCount = 0;
|
|
42633
|
+
let failedCount = 0;
|
|
42634
|
+
for (const entry of updateTargets) {
|
|
42635
|
+
spinner.text = `Updating in ${getLockEntryTargetLabel(entry)}...`;
|
|
42636
|
+
try {
|
|
42637
|
+
const sourceString = lockSourceToString(entry.source);
|
|
42638
|
+
if (!sourceString) {
|
|
42639
|
+
failedCount++;
|
|
42640
|
+
logger.info(` ${red("x")} ${getLockEntryTargetLabel(entry)}: cannot reconstruct source`);
|
|
42641
|
+
continue;
|
|
42642
|
+
}
|
|
42643
|
+
const agentManager9 = new AgentManager;
|
|
42644
|
+
const skillsManager5 = new SkillsManager(agentManager9);
|
|
42645
|
+
const result = await skillsManager5.addFromSource(sourceString.source, entry.projectPath, {
|
|
42646
|
+
...sourceString.from ? { from: sourceString.from } : {},
|
|
42647
|
+
...sourceString.prefix ? { prefix: sourceString.prefix } : {},
|
|
42648
|
+
agents: entry.agents,
|
|
42649
|
+
global: entry.scope === "global",
|
|
42650
|
+
skills: [name],
|
|
42651
|
+
yes: true
|
|
42652
|
+
});
|
|
42653
|
+
if (result.updated.length > 0) {
|
|
42654
|
+
updatedCount++;
|
|
42655
|
+
logger.info(` ${green("~")} ${getLockEntryTargetLabel(entry)}: updated`);
|
|
42656
|
+
} else if (result.installed.length > 0) {
|
|
42657
|
+
updatedCount++;
|
|
42658
|
+
logger.info(` ${green("+")} ${getLockEntryTargetLabel(entry)}: installed`);
|
|
42659
|
+
} else {
|
|
42660
|
+
unchangedCount++;
|
|
42661
|
+
logger.info(` ${dim("-")} ${getLockEntryTargetLabel(entry)}: ${dim("unchanged")}`);
|
|
42662
|
+
}
|
|
42663
|
+
} catch (error) {
|
|
42664
|
+
failedCount++;
|
|
42665
|
+
logger.info(` ${red("x")} ${getLockEntryTargetLabel(entry)}: ${error instanceof Error ? error.message : "unknown error"}`);
|
|
42666
|
+
}
|
|
42667
|
+
}
|
|
42668
|
+
if (updatedCount > 0) {
|
|
42669
|
+
spinner.succeed(`Updated "${name}" in ${updatedCount} target(s)`);
|
|
42670
|
+
} else {
|
|
42671
|
+
spinner.info(`"${name}" is already up to date in all tracked targets`);
|
|
42672
|
+
}
|
|
42673
|
+
if (unchangedCount > 0)
|
|
42674
|
+
logger.info(dim(` ${unchangedCount} unchanged`));
|
|
42675
|
+
if (failedCount > 0)
|
|
42676
|
+
logger.info(red(` ${failedCount} failed`));
|
|
42677
|
+
} else {
|
|
42678
|
+
const cwd = process.cwd();
|
|
42679
|
+
const agentManager9 = new AgentManager;
|
|
42680
|
+
const skillsManager5 = new SkillsManager(agentManager9);
|
|
42681
|
+
if (name) {
|
|
42682
|
+
const entries = await installLock3.getCurrentState({
|
|
42683
|
+
kind: "skill",
|
|
42684
|
+
name,
|
|
42685
|
+
projectPath: resolve13(cwd),
|
|
42686
|
+
scope: "project"
|
|
42687
|
+
});
|
|
42688
|
+
if (entries.length === 0) {
|
|
42689
|
+
logger.info(`Skill "${name}" not tracked in the lockfile for this project.`);
|
|
42690
|
+
logger.info(dim("Try: agentinit skills add <source> or use --everywhere for global installs."));
|
|
42691
|
+
return;
|
|
42692
|
+
}
|
|
42693
|
+
if (options2.dryRun) {
|
|
42694
|
+
logger.info(`Would update "${name}" in ${entries.length} tracked target(s):`);
|
|
42695
|
+
for (const entry of entries) {
|
|
42696
|
+
const sourceString = lockSourceToString(entry.source);
|
|
42697
|
+
logger.info(` ${green(entry.name)} ${dim(`[${entry.agents.join(", ")}]`)} ${sourceString ? dim(sourceString.source) : red("unavailable source")}`);
|
|
42698
|
+
}
|
|
42699
|
+
return;
|
|
42700
|
+
}
|
|
42701
|
+
const spinner = ora(`Updating skill "${name}"...`).start();
|
|
42702
|
+
let updatedCount = 0;
|
|
42703
|
+
let unchangedCount = 0;
|
|
42704
|
+
let failedCount = 0;
|
|
42705
|
+
for (const entry of entries) {
|
|
42706
|
+
const sourceString = lockSourceToString(entry.source);
|
|
42707
|
+
if (!sourceString) {
|
|
42708
|
+
failedCount++;
|
|
42709
|
+
continue;
|
|
42710
|
+
}
|
|
42711
|
+
try {
|
|
42712
|
+
const result = await skillsManager5.addFromSource(sourceString.source, cwd, {
|
|
42713
|
+
...sourceString.from ? { from: sourceString.from } : {},
|
|
42714
|
+
...sourceString.prefix ? { prefix: sourceString.prefix } : {},
|
|
42715
|
+
agents: entry.agents,
|
|
42716
|
+
global: entry.scope === "global",
|
|
42717
|
+
skills: [name],
|
|
42718
|
+
yes: true
|
|
42719
|
+
});
|
|
42720
|
+
if (result.updated.length > 0 || result.installed.length > 0) {
|
|
42721
|
+
updatedCount++;
|
|
42722
|
+
} else {
|
|
42723
|
+
unchangedCount++;
|
|
42724
|
+
}
|
|
42725
|
+
} catch {
|
|
42726
|
+
failedCount++;
|
|
42727
|
+
}
|
|
42728
|
+
}
|
|
42729
|
+
if (updatedCount > 0) {
|
|
42730
|
+
spinner.succeed(`Updated "${name}" in ${updatedCount} target(s)`);
|
|
42731
|
+
} else {
|
|
42732
|
+
spinner.info(`"${name}" is already up to date`);
|
|
42733
|
+
}
|
|
42734
|
+
if (unchangedCount > 0)
|
|
42735
|
+
logger.info(dim(` ${unchangedCount} unchanged`));
|
|
42736
|
+
if (failedCount > 0)
|
|
42737
|
+
logger.info(red(` ${failedCount} failed`));
|
|
42738
|
+
} else {
|
|
42739
|
+
const entries = await installLock3.getCurrentState({
|
|
42740
|
+
kind: "skill",
|
|
42741
|
+
projectPath: resolve13(cwd),
|
|
42742
|
+
scope: "project"
|
|
42743
|
+
});
|
|
42744
|
+
if (entries.length === 0) {
|
|
42745
|
+
logger.info("No skills tracked in the lockfile for this project.");
|
|
42746
|
+
return;
|
|
42747
|
+
}
|
|
42748
|
+
if (options2.dryRun) {
|
|
42749
|
+
logger.info(`Would update ${entries.length} skill(s):`);
|
|
42750
|
+
for (const entry of entries) {
|
|
42751
|
+
logger.info(` ${green(entry.name)} ${dim(`[${entry.agents.join(", ")}]`)}`);
|
|
42752
|
+
}
|
|
42753
|
+
return;
|
|
42754
|
+
}
|
|
42755
|
+
const spinner = ora("Updating all skills...").start();
|
|
42756
|
+
let updatedCount = 0;
|
|
42757
|
+
for (const entry of entries) {
|
|
42758
|
+
const sourceString = lockSourceToString(entry.source);
|
|
42759
|
+
if (!sourceString)
|
|
42760
|
+
continue;
|
|
42761
|
+
spinner.text = `Updating "${entry.name}"...`;
|
|
42762
|
+
try {
|
|
42763
|
+
const result = await skillsManager5.addFromSource(sourceString.source, cwd, {
|
|
42764
|
+
...sourceString.from ? { from: sourceString.from } : {},
|
|
42765
|
+
...sourceString.prefix ? { prefix: sourceString.prefix } : {},
|
|
42766
|
+
agents: entry.agents,
|
|
42767
|
+
global: entry.scope === "global",
|
|
42768
|
+
skills: [entry.name],
|
|
42769
|
+
yes: true
|
|
42770
|
+
});
|
|
42771
|
+
if (result.updated.length > 0 || result.installed.length > 0) {
|
|
42772
|
+
updatedCount++;
|
|
42773
|
+
}
|
|
42774
|
+
} catch {
|
|
42775
|
+
}
|
|
42776
|
+
}
|
|
42777
|
+
if (updatedCount > 0) {
|
|
42778
|
+
spinner.succeed(`Updated ${updatedCount} skill(s)`);
|
|
42779
|
+
} else {
|
|
42780
|
+
spinner.info("All skills are up to date");
|
|
42781
|
+
}
|
|
42782
|
+
}
|
|
42783
|
+
}
|
|
42784
|
+
});
|
|
41651
42785
|
}
|
|
42786
|
+
var lockSourceToString = function(source) {
|
|
42787
|
+
return lockSourceToSpecifier(source);
|
|
42788
|
+
};
|
|
41652
42789
|
async function resolveInteractiveSkillTargets(skillsManager5, agentManager9, source, projectPath, options2) {
|
|
41653
42790
|
let installGlobal = !!options2.global;
|
|
41654
42791
|
if (!options2.global) {
|
|
@@ -41721,23 +42858,57 @@ async function resolveInteractiveSkillTargets(skillsManager5, agentManager9, sou
|
|
|
41721
42858
|
}
|
|
41722
42859
|
return selection;
|
|
41723
42860
|
}
|
|
41724
|
-
|
|
41725
|
-
|
|
41726
|
-
|
|
41727
|
-
|
|
41728
|
-
|
|
41729
|
-
|
|
41730
|
-
|
|
41731
|
-
|
|
41732
|
-
|
|
41733
|
-
|
|
41734
|
-
|
|
41735
|
-
|
|
41736
|
-
|
|
41737
|
-
|
|
41738
|
-
|
|
42861
|
+
var formatSkillSelectionHint = function(prefix) {
|
|
42862
|
+
return `Press Space to select, A to select or deselect all, p to edit prefix, then Enter to confirm. Prefix: "${prefix}"`;
|
|
42863
|
+
};
|
|
42864
|
+
async function resolveInteractiveSkillSelection(skills3, initialPrefix) {
|
|
42865
|
+
let prefix = initialPrefix ?? "";
|
|
42866
|
+
let selectedSkills = new Set(skills3.map((skill) => skill.name));
|
|
42867
|
+
const promptForPrefix = async () => {
|
|
42868
|
+
const response = await import_prompts3.default({
|
|
42869
|
+
type: "text",
|
|
42870
|
+
name: "prefix",
|
|
42871
|
+
message: "Prefix to prepend to installed skill names:",
|
|
42872
|
+
initial: prefix
|
|
42873
|
+
});
|
|
42874
|
+
if (typeof response.prefix === "string") {
|
|
42875
|
+
prefix = response.prefix;
|
|
42876
|
+
}
|
|
42877
|
+
};
|
|
42878
|
+
const requestPrefixEdit = (controls) => {
|
|
42879
|
+
controls.requestAction("edit-prefix");
|
|
42880
|
+
controls.closeWithCurrentSelection();
|
|
42881
|
+
};
|
|
42882
|
+
while (true) {
|
|
42883
|
+
const response = await promptMultiselect({
|
|
42884
|
+
name: "skills",
|
|
42885
|
+
message: `Select skills to install (${skills3.length} found):`,
|
|
42886
|
+
min: 1,
|
|
42887
|
+
hint: () => formatSkillSelectionHint(prefix),
|
|
42888
|
+
hotkeys: {
|
|
42889
|
+
p: requestPrefixEdit,
|
|
42890
|
+
P: requestPrefixEdit
|
|
42891
|
+
},
|
|
42892
|
+
choices: skills3.map((skill) => ({
|
|
42893
|
+
title: skill.name,
|
|
42894
|
+
value: skill.name,
|
|
42895
|
+
description: skill.description,
|
|
42896
|
+
selected: selectedSkills.has(skill.name)
|
|
42897
|
+
}))
|
|
42898
|
+
});
|
|
42899
|
+
if (response.skills && response.skills.length > 0) {
|
|
42900
|
+
selectedSkills = new Set(response.skills);
|
|
42901
|
+
}
|
|
42902
|
+
if (response.__agentinitAction === "edit-prefix") {
|
|
42903
|
+
await promptForPrefix();
|
|
42904
|
+
continue;
|
|
42905
|
+
}
|
|
42906
|
+
if (!response.skills || response.skills.length === 0) {
|
|
42907
|
+
logger.info("No skills selected. Aborting.");
|
|
42908
|
+
return { aborted: true };
|
|
42909
|
+
}
|
|
42910
|
+
return { skills: response.skills, prefix };
|
|
41739
42911
|
}
|
|
41740
|
-
return { skills: response.skills };
|
|
41741
42912
|
}
|
|
41742
42913
|
async function getDetectedSkillGroups(agentManager9, projectPath, global3) {
|
|
41743
42914
|
const detectedAgents = (await agentManager9.detectAgents(projectPath)).map((entry) => entry.agent);
|
|
@@ -41772,7 +42943,7 @@ var buildSkillGroups = function(agents, projectPath, global3) {
|
|
|
41772
42943
|
dirToAgents.set(skillsDir, existing);
|
|
41773
42944
|
}
|
|
41774
42945
|
return Array.from(dirToAgents.entries()).map(([dir, groupedAgents]) => {
|
|
41775
|
-
const canonicalShared =
|
|
42946
|
+
const canonicalShared = resolve13(dir) === getCanonicalSkillsDirForScope(projectPath, !!global3) && groupedAgents.every((agent) => agent.getProjectSkillsStandard() === "agents");
|
|
41776
42947
|
return {
|
|
41777
42948
|
dir,
|
|
41778
42949
|
displayDir: formatSkillsDir(projectPath, dir),
|
|
@@ -41795,7 +42966,7 @@ var prependCanonicalGlobalGroup = function(agentManager9, projectPath, groups) {
|
|
|
41795
42966
|
if (sharedAgents.length === 0) {
|
|
41796
42967
|
return groups;
|
|
41797
42968
|
}
|
|
41798
|
-
const existingCanonicalIndex = groups.findIndex((group) =>
|
|
42969
|
+
const existingCanonicalIndex = groups.findIndex((group) => resolve13(group.dir) === canonicalDir);
|
|
41799
42970
|
if (existingCanonicalIndex >= 0) {
|
|
41800
42971
|
const existingCanonical = groups[existingCanonicalIndex];
|
|
41801
42972
|
const remaining = groups.filter((_, index) => index !== existingCanonicalIndex);
|
|
@@ -41831,9 +43002,9 @@ var prependCanonicalGlobalGroup = function(agentManager9, projectPath, groups) {
|
|
|
41831
43002
|
var formatSkillsDir = function(projectPath, dir) {
|
|
41832
43003
|
const normalizedDir = dir.replace(/\\/g, "/").replace(/\/?$/, "/");
|
|
41833
43004
|
const normalizedProjectPath = projectPath.replace(/\\/g, "/");
|
|
41834
|
-
const normalizedHome =
|
|
43005
|
+
const normalizedHome = homedir7().replace(/\\/g, "/");
|
|
41835
43006
|
if (normalizedDir.startsWith(`${normalizedProjectPath}/`)) {
|
|
41836
|
-
return `${
|
|
43007
|
+
return `${relative8(projectPath, dir).replace(/\\/g, "/").replace(/\/?$/, "/")}`;
|
|
41837
43008
|
}
|
|
41838
43009
|
if (normalizedDir.startsWith(`${normalizedHome}/`)) {
|
|
41839
43010
|
return normalizedDir.replace(normalizedHome, "~");
|
|
@@ -41842,7 +43013,7 @@ var formatSkillsDir = function(projectPath, dir) {
|
|
|
41842
43013
|
};
|
|
41843
43014
|
var formatPromptPath = function(path) {
|
|
41844
43015
|
const normalizedPath = path.replace(/\\/g, "/").replace(/\/?$/, "/");
|
|
41845
|
-
const normalizedHome =
|
|
43016
|
+
const normalizedHome = homedir7().replace(/\\/g, "/");
|
|
41846
43017
|
if (normalizedPath === `${normalizedHome}/`) {
|
|
41847
43018
|
return "~/";
|
|
41848
43019
|
}
|
|
@@ -41852,10 +43023,10 @@ var formatPromptPath = function(path) {
|
|
|
41852
43023
|
return normalizedPath;
|
|
41853
43024
|
};
|
|
41854
43025
|
var getCanonicalGlobalSkillsDir = function() {
|
|
41855
|
-
return
|
|
43026
|
+
return resolve13(homedir7(), ".agents/skills");
|
|
41856
43027
|
};
|
|
41857
43028
|
var getCanonicalSkillsDirForScope = function(projectPath, global3) {
|
|
41858
|
-
return global3 ? getCanonicalGlobalSkillsDir() :
|
|
43029
|
+
return global3 ? getCanonicalGlobalSkillsDir() : resolve13(projectPath, ".agents/skills");
|
|
41859
43030
|
};
|
|
41860
43031
|
var getCanonicalGlobalSkillsDisplayPath = function() {
|
|
41861
43032
|
return formatPromptPath(getCanonicalGlobalSkillsDir());
|
|
@@ -42045,7 +43216,7 @@ var displayInstallResult = function(result, spinner, agentManager9, skillsManage
|
|
|
42045
43216
|
byPath.set(path, existing);
|
|
42046
43217
|
}
|
|
42047
43218
|
for (const [path, details] of byPath) {
|
|
42048
|
-
logger.info(` ${
|
|
43219
|
+
logger.info(` ${relative8(process.cwd(), path) || path}`);
|
|
42049
43220
|
logger.info(` Agents: ${[...details.agents].join(", ")}`);
|
|
42050
43221
|
logger.info(` Skills: ${green(String(details.skills.size))} installed (${[...details.skills].join(", ")})`);
|
|
42051
43222
|
}
|
|
@@ -42061,7 +43232,7 @@ var displayInstallResult = function(result, spinner, agentManager9, skillsManage
|
|
|
42061
43232
|
byPathUpdated.set(path, existing);
|
|
42062
43233
|
}
|
|
42063
43234
|
for (const [path, details] of byPathUpdated) {
|
|
42064
|
-
logger.info(` ${
|
|
43235
|
+
logger.info(` ${relative8(process.cwd(), path) || path}`);
|
|
42065
43236
|
logger.info(` Agents: ${[...details.agents].join(", ")}`);
|
|
42066
43237
|
logger.info(` Skills: ${yellow(String(details.skills.size))} updated (${[...details.skills].join(", ")})`);
|
|
42067
43238
|
}
|
|
@@ -42089,8 +43260,11 @@ var displayInstallResult = function(result, spinner, agentManager9, skillsManage
|
|
|
42089
43260
|
};
|
|
42090
43261
|
|
|
42091
43262
|
// dist/commands/mcp.js
|
|
43263
|
+
init_colors();
|
|
43264
|
+
init_logger();
|
|
42092
43265
|
init_mcpFilter();
|
|
42093
43266
|
init_agentManager();
|
|
43267
|
+
init_installLock();
|
|
42094
43268
|
var filterMcpArgs = function(args) {
|
|
42095
43269
|
const filtered = [];
|
|
42096
43270
|
let i = 0;
|
|
@@ -42282,6 +43456,28 @@ var registerAddCommand = function(mcp) {
|
|
|
42282
43456
|
logger.info(` ${cyan(server.name)} (${typeLabel}): ${server.url}`);
|
|
42283
43457
|
}
|
|
42284
43458
|
});
|
|
43459
|
+
try {
|
|
43460
|
+
const lock = new InstallLock;
|
|
43461
|
+
const lockSource2 = { type: "local" };
|
|
43462
|
+
for (const plan of plans) {
|
|
43463
|
+
for (const server of plan.servers) {
|
|
43464
|
+
await lock.recordMcp({
|
|
43465
|
+
action: "install",
|
|
43466
|
+
name: server.name,
|
|
43467
|
+
projectPath: cwd,
|
|
43468
|
+
agents: [plan.agent.id],
|
|
43469
|
+
scope: plan.isGlobal ? "global" : "project",
|
|
43470
|
+
source: lockSource2,
|
|
43471
|
+
configPath: plan.configPath,
|
|
43472
|
+
serverType: server.type,
|
|
43473
|
+
...server.command ? { command: server.command } : {},
|
|
43474
|
+
...server.url ? { url: server.url } : {}
|
|
43475
|
+
});
|
|
43476
|
+
}
|
|
43477
|
+
}
|
|
43478
|
+
} catch (error) {
|
|
43479
|
+
logLockWriteWarning("MCP servers were added successfully", error);
|
|
43480
|
+
}
|
|
42285
43481
|
}
|
|
42286
43482
|
} catch (error) {
|
|
42287
43483
|
spinner.fail("Failed to add MCP servers");
|
|
@@ -42375,8 +43571,12 @@ var registerRemoveCommand = function(mcp) {
|
|
|
42375
43571
|
}
|
|
42376
43572
|
let removedCount = 0;
|
|
42377
43573
|
let failedCount = 0;
|
|
43574
|
+
const removedTargets = [];
|
|
42378
43575
|
for (const { agent, isGlobal: global3 } of targets) {
|
|
42379
43576
|
try {
|
|
43577
|
+
const configPath = global3 ? agent.getGlobalMcpPath() : agent.getNativeMcpPath(cwd);
|
|
43578
|
+
const existingServers = global3 ? await agent.getGlobalMCPServers().catch(() => []) : await agent.getMCPServers(cwd).catch(() => []);
|
|
43579
|
+
const existingServer = existingServers.find((server) => server.name.toLowerCase() === name.toLowerCase());
|
|
42380
43580
|
let removed;
|
|
42381
43581
|
if (global3) {
|
|
42382
43582
|
removed = await agent.removeGlobalMCPServer(name);
|
|
@@ -42385,6 +43585,14 @@ var registerRemoveCommand = function(mcp) {
|
|
|
42385
43585
|
}
|
|
42386
43586
|
if (removed) {
|
|
42387
43587
|
removedCount++;
|
|
43588
|
+
if (configPath) {
|
|
43589
|
+
removedTargets.push({
|
|
43590
|
+
agent,
|
|
43591
|
+
isGlobal: global3,
|
|
43592
|
+
configPath,
|
|
43593
|
+
...existingServer ? { server: existingServer } : {}
|
|
43594
|
+
});
|
|
43595
|
+
}
|
|
42388
43596
|
logger.info(` ${green("-")} ${agent.name}: removed "${name}"`);
|
|
42389
43597
|
} else {
|
|
42390
43598
|
logger.info(` ${yellow("~")} ${agent.name}: "${name}" not found`);
|
|
@@ -42396,6 +43604,25 @@ var registerRemoveCommand = function(mcp) {
|
|
|
42396
43604
|
}
|
|
42397
43605
|
if (removedCount > 0) {
|
|
42398
43606
|
spinner.succeed(`Removed "${name}" from ${removedCount} agent(s)`);
|
|
43607
|
+
try {
|
|
43608
|
+
const lock = new InstallLock;
|
|
43609
|
+
for (const { agent, isGlobal: global3, configPath, server } of removedTargets) {
|
|
43610
|
+
await lock.recordMcp({
|
|
43611
|
+
action: "remove",
|
|
43612
|
+
name,
|
|
43613
|
+
projectPath: cwd,
|
|
43614
|
+
agents: [agent.id],
|
|
43615
|
+
scope: global3 ? "global" : "project",
|
|
43616
|
+
source: { type: "local" },
|
|
43617
|
+
configPath,
|
|
43618
|
+
serverType: server?.type || "stdio",
|
|
43619
|
+
...server?.command ? { command: server.command } : {},
|
|
43620
|
+
...server?.url ? { url: server.url } : {}
|
|
43621
|
+
});
|
|
43622
|
+
}
|
|
43623
|
+
} catch (error) {
|
|
43624
|
+
logLockWriteWarning("MCP servers were removed successfully", error);
|
|
43625
|
+
}
|
|
42399
43626
|
} else if (failedCount > 0) {
|
|
42400
43627
|
spinner.fail(`Failed to remove "${name}"`);
|
|
42401
43628
|
} else {
|
|
@@ -42584,8 +43811,11 @@ var KNOWN_ADD_OPTIONS = {
|
|
|
42584
43811
|
};
|
|
42585
43812
|
|
|
42586
43813
|
// dist/commands/rules.js
|
|
43814
|
+
init_colors();
|
|
43815
|
+
init_logger();
|
|
42587
43816
|
init_agentManager();
|
|
42588
43817
|
init_fs();
|
|
43818
|
+
init_installLock();
|
|
42589
43819
|
var colorizeTokenCount2 = function(tokenCount) {
|
|
42590
43820
|
if (tokenCount <= TOKEN_COUNT_THRESHOLDS.LOW)
|
|
42591
43821
|
return green(tokenCount.toString());
|
|
@@ -42774,6 +44004,29 @@ function registerRulesCommand(program2) {
|
|
|
42774
44004
|
}
|
|
42775
44005
|
}
|
|
42776
44006
|
}
|
|
44007
|
+
try {
|
|
44008
|
+
const lock = new InstallLock;
|
|
44009
|
+
for (const { agent, result } of results) {
|
|
44010
|
+
if (!result.success || result.rulesApplied === 0)
|
|
44011
|
+
continue;
|
|
44012
|
+
const sections = result.mergedSections || uniqueSections;
|
|
44013
|
+
for (const section of sections) {
|
|
44014
|
+
await lock.recordRules({
|
|
44015
|
+
action: "install",
|
|
44016
|
+
name: section.templateId,
|
|
44017
|
+
projectPath: cwd,
|
|
44018
|
+
agents: [agent.id],
|
|
44019
|
+
scope: isGlobal ? "global" : "project",
|
|
44020
|
+
source: { type: "local" },
|
|
44021
|
+
configPath: result.configPath || "",
|
|
44022
|
+
templateIds: [section.templateId],
|
|
44023
|
+
ruleCount: section.rules.length
|
|
44024
|
+
});
|
|
44025
|
+
}
|
|
44026
|
+
}
|
|
44027
|
+
} catch (error) {
|
|
44028
|
+
logLockWriteWarning("Rules were applied successfully", error);
|
|
44029
|
+
}
|
|
42777
44030
|
} catch (error) {
|
|
42778
44031
|
spinner.fail("Failed to apply rules");
|
|
42779
44032
|
logger.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
@@ -42836,6 +44089,7 @@ function registerRulesCommand(program2) {
|
|
|
42836
44089
|
const agents = await resolveTargetAgents(agentManager11, options2, cwd);
|
|
42837
44090
|
const spinner = ora("Removing rules...").start();
|
|
42838
44091
|
let totalRemoved = 0;
|
|
44092
|
+
const removedSections = [];
|
|
42839
44093
|
try {
|
|
42840
44094
|
for (const agent of agents) {
|
|
42841
44095
|
if (!agent.capabilities.rules) {
|
|
@@ -42859,6 +44113,9 @@ function registerRulesCommand(program2) {
|
|
|
42859
44113
|
const updatedContent = await agent.applyRulesConfig(configPath, buildAppliedRules(remaining), content);
|
|
42860
44114
|
await writeFile(configPath, updatedContent);
|
|
42861
44115
|
totalRemoved += removed.length;
|
|
44116
|
+
for (const section of removed) {
|
|
44117
|
+
removedSections.push({ agent, configPath, section });
|
|
44118
|
+
}
|
|
42862
44119
|
for (const s of removed) {
|
|
42863
44120
|
logger.info(` ${agent.name}: removed ${green(s.templateName)} (${s.rules.length} rules)`);
|
|
42864
44121
|
}
|
|
@@ -42868,6 +44125,24 @@ function registerRulesCommand(program2) {
|
|
|
42868
44125
|
logger.info('Run "agentinit rules list" to see current sections.');
|
|
42869
44126
|
} else {
|
|
42870
44127
|
spinner.succeed(`Removed ${totalRemoved} rule section${totalRemoved !== 1 ? "s" : ""}`);
|
|
44128
|
+
try {
|
|
44129
|
+
const lock = new InstallLock;
|
|
44130
|
+
for (const { agent, configPath, section } of removedSections) {
|
|
44131
|
+
await lock.recordRules({
|
|
44132
|
+
action: "remove",
|
|
44133
|
+
name: section.templateId,
|
|
44134
|
+
projectPath: cwd,
|
|
44135
|
+
agents: [agent.id],
|
|
44136
|
+
scope: isGlobal ? "global" : "project",
|
|
44137
|
+
source: { type: "local" },
|
|
44138
|
+
configPath,
|
|
44139
|
+
templateIds: [section.templateId],
|
|
44140
|
+
ruleCount: 0
|
|
44141
|
+
});
|
|
44142
|
+
}
|
|
44143
|
+
} catch (error) {
|
|
44144
|
+
logLockWriteWarning("Rules were removed successfully", error);
|
|
44145
|
+
}
|
|
42871
44146
|
}
|
|
42872
44147
|
} catch (error) {
|
|
42873
44148
|
spinner.fail("Failed to remove rules");
|
|
@@ -42879,8 +44154,9 @@ function registerRulesCommand(program2) {
|
|
|
42879
44154
|
|
|
42880
44155
|
// dist/commands/plugins.js
|
|
42881
44156
|
var import_prompts4 = __toESM(require_prompts3(), 1);
|
|
42882
|
-
import {homedir as
|
|
42883
|
-
import {dirname as
|
|
44157
|
+
import {homedir as homedir8} from "os";
|
|
44158
|
+
import {dirname as dirname10, relative as relative9, resolve as resolve14} from "path";
|
|
44159
|
+
init_logger();
|
|
42884
44160
|
init_pluginManager();
|
|
42885
44161
|
init_agentManager();
|
|
42886
44162
|
init_marketplaceRegistry();
|
|
@@ -43232,7 +44508,7 @@ function registerPluginsCommand(program2) {
|
|
|
43232
44508
|
}
|
|
43233
44509
|
var formatPathForDisplay = function(pathValue, projectPath) {
|
|
43234
44510
|
if (pathValue.startsWith(`${projectPath}/`)) {
|
|
43235
|
-
return
|
|
44511
|
+
return relative9(projectPath, pathValue) || ".";
|
|
43236
44512
|
}
|
|
43237
44513
|
const homePrefix = `${process.env.HOME || ""}/`;
|
|
43238
44514
|
if (homePrefix !== "/" && pathValue.startsWith(homePrefix)) {
|
|
@@ -43422,7 +44698,7 @@ var renderPluginWarnings = function(previewOrResult, projectPath) {
|
|
|
43422
44698
|
var renderInstalledComponents = function(result, agentManager12, projectPath) {
|
|
43423
44699
|
const skillGroups = new Map;
|
|
43424
44700
|
for (const item of result.skills.installed) {
|
|
43425
|
-
const targetDir =
|
|
44701
|
+
const targetDir = dirname10(item.path);
|
|
43426
44702
|
const existing = skillGroups.get(targetDir) || { agents: new Set, skillNames: new Set };
|
|
43427
44703
|
existing.agents.add(item.agent);
|
|
43428
44704
|
existing.skillNames.add(item.name);
|
|
@@ -43500,7 +44776,7 @@ var buildGlobalPluginGroups = function(agentManager12, projectPath) {
|
|
|
43500
44776
|
compatibleAgentNames: [],
|
|
43501
44777
|
kind: "native"
|
|
43502
44778
|
}));
|
|
43503
|
-
const canonicalDir =
|
|
44779
|
+
const canonicalDir = resolve14(homedir8(), ".agents/skills");
|
|
43504
44780
|
const sharedAgents = agentManager12.getAllAgents().filter((agent) => agent.supportsSkills() && agent.getProjectSkillsStandard() === "agents" && !!agent.getSkillsDir(projectPath, true));
|
|
43505
44781
|
const claudeGroups = nativeGroups.filter((group) => group.agents.some((agent) => agent.id === "claude"));
|
|
43506
44782
|
const otherGroups = nativeGroups.filter((group) => !group.agents.some((agent) => agent.id === "claude"));
|
|
@@ -43610,7 +44886,148 @@ async function interactiveAgentSelect(pluginManager3, agentManager12, projectPat
|
|
|
43610
44886
|
} : undefined;
|
|
43611
44887
|
}
|
|
43612
44888
|
|
|
44889
|
+
// dist/commands/lock.js
|
|
44890
|
+
init_colors();
|
|
44891
|
+
init_logger();
|
|
44892
|
+
init_installLock();
|
|
44893
|
+
import {resolve as resolve15} from "path";
|
|
44894
|
+
var formatTimestamp = function(iso) {
|
|
44895
|
+
const date = new Date(iso);
|
|
44896
|
+
return date.toLocaleDateString("en-US", {
|
|
44897
|
+
month: "short",
|
|
44898
|
+
day: "numeric",
|
|
44899
|
+
year: "numeric"
|
|
44900
|
+
});
|
|
44901
|
+
};
|
|
44902
|
+
var formatKind = function(kind) {
|
|
44903
|
+
switch (kind) {
|
|
44904
|
+
case "skill":
|
|
44905
|
+
return cyan("skill");
|
|
44906
|
+
case "mcp":
|
|
44907
|
+
return yellow("mcp");
|
|
44908
|
+
case "rules":
|
|
44909
|
+
return green("rules");
|
|
44910
|
+
}
|
|
44911
|
+
};
|
|
44912
|
+
var formatSource = function(entry) {
|
|
44913
|
+
return formatLockSource(entry.source);
|
|
44914
|
+
};
|
|
44915
|
+
function registerLockCommand(program2) {
|
|
44916
|
+
const lock = program2.command("lock").description("View and manage the global install lockfile");
|
|
44917
|
+
lock.command("list").alias("ls").description("List all tracked installations across projects").option("--kind <kind>", "Filter by kind: skill, mcp, rules").option("--project <path>", "Filter by project path").option("--agent <agent>", "Filter by agent ID").option("--scope <scope>", "Filter by scope: project or global").action(async (options2) => {
|
|
44918
|
+
const installLock6 = new InstallLock;
|
|
44919
|
+
const queryOptions = {};
|
|
44920
|
+
if (options2.kind)
|
|
44921
|
+
queryOptions.kind = options2.kind;
|
|
44922
|
+
if (options2.project)
|
|
44923
|
+
queryOptions.projectPath = resolve15(options2.project);
|
|
44924
|
+
if (options2.agent)
|
|
44925
|
+
queryOptions.agent = options2.agent;
|
|
44926
|
+
if (options2.scope)
|
|
44927
|
+
queryOptions.scope = options2.scope;
|
|
44928
|
+
const entries = await installLock6.getCurrentState(queryOptions);
|
|
44929
|
+
if (entries.length === 0) {
|
|
44930
|
+
logger.info("No installations tracked in the lockfile.");
|
|
44931
|
+
logger.info(dim("Install skills, MCPs, or rules to start tracking."));
|
|
44932
|
+
return;
|
|
44933
|
+
}
|
|
44934
|
+
const byProject = new Map;
|
|
44935
|
+
for (const entry of entries) {
|
|
44936
|
+
const key = entry.scope === "global" ? "global" : entry.projectPath;
|
|
44937
|
+
const group = byProject.get(key) || { label: getLockEntryTargetLabel(entry), entries: [] };
|
|
44938
|
+
group.entries.push(entry);
|
|
44939
|
+
byProject.set(key, group);
|
|
44940
|
+
}
|
|
44941
|
+
for (const { label, entries: projectEntries } of byProject.values()) {
|
|
44942
|
+
logger.info(`\n${cyan(label)}`);
|
|
44943
|
+
for (const entry of projectEntries) {
|
|
44944
|
+
const kind = formatKind(entry.kind);
|
|
44945
|
+
const scope = entry.scope === "global" ? dim(" (global)") : "";
|
|
44946
|
+
const agents = dim(`[${entry.agents.join(", ")}]`);
|
|
44947
|
+
const date = dim(formatTimestamp(entry.timestamp));
|
|
44948
|
+
const source = dim(formatSource(entry));
|
|
44949
|
+
logger.info(` ${kind} ${green(entry.name)} ${agents}${scope} ${source} ${date}`);
|
|
44950
|
+
}
|
|
44951
|
+
}
|
|
44952
|
+
logger.info("");
|
|
44953
|
+
logger.info(dim(`${entries.length} installation(s) across ${byProject.size} target(s)`));
|
|
44954
|
+
});
|
|
44955
|
+
lock.command("status").description("Show summary of tracked installations").option("--check-drift", "Check for modified skill files (compares content hashes)").action(async (options2) => {
|
|
44956
|
+
const installLock6 = new InstallLock;
|
|
44957
|
+
const entries = await installLock6.getCurrentState();
|
|
44958
|
+
if (entries.length === 0) {
|
|
44959
|
+
logger.info("No installations tracked in the lockfile.");
|
|
44960
|
+
return;
|
|
44961
|
+
}
|
|
44962
|
+
const projects = new Set(entries.filter((entry) => entry.scope === "project").map((entry) => entry.projectPath));
|
|
44963
|
+
const globalTargets = entries.filter((entry) => entry.scope === "global");
|
|
44964
|
+
const skills3 = entries.filter((e) => e.kind === "skill");
|
|
44965
|
+
const mcps = entries.filter((e) => e.kind === "mcp");
|
|
44966
|
+
const rules = entries.filter((e) => e.kind === "rules");
|
|
44967
|
+
logger.info(`Projects: ${cyan(projects.size.toString())}`);
|
|
44968
|
+
logger.info(`Global targets: ${cyan(globalTargets.length.toString())}`);
|
|
44969
|
+
logger.info(`Skills: ${green(skills3.length.toString())}`);
|
|
44970
|
+
logger.info(`MCPs: ${yellow(mcps.length.toString())}`);
|
|
44971
|
+
logger.info(`Rules: ${green(rules.length.toString())}`);
|
|
44972
|
+
const stale = await installLock6.findStaleProjects();
|
|
44973
|
+
if (stale.length > 0) {
|
|
44974
|
+
logger.info("");
|
|
44975
|
+
logger.info(`${red("Stale projects:")} ${stale.length}`);
|
|
44976
|
+
for (const path of stale) {
|
|
44977
|
+
logger.info(` ${red("x")} ${path}`);
|
|
44978
|
+
}
|
|
44979
|
+
logger.info(dim('Run "agentinit lock prune" to clean up.'));
|
|
44980
|
+
}
|
|
44981
|
+
if (options2.checkDrift) {
|
|
44982
|
+
logger.info("");
|
|
44983
|
+
logger.info("Checking for drift...");
|
|
44984
|
+
let driftCount = 0;
|
|
44985
|
+
let missingCount = 0;
|
|
44986
|
+
for (const entry of skills3) {
|
|
44987
|
+
if (!entry.contentHash)
|
|
44988
|
+
continue;
|
|
44989
|
+
const result = await installLock6.checkDrift(entry);
|
|
44990
|
+
if (result.status === "drift") {
|
|
44991
|
+
driftCount++;
|
|
44992
|
+
logger.info(` ${yellow("~")} ${entry.name} in ${entry.projectPath}`);
|
|
44993
|
+
} else if (result.status === "missing") {
|
|
44994
|
+
missingCount++;
|
|
44995
|
+
logger.info(` ${red("x")} ${entry.name} in ${entry.projectPath} ${dim("(missing)")}`);
|
|
44996
|
+
}
|
|
44997
|
+
}
|
|
44998
|
+
if (driftCount === 0 && missingCount === 0) {
|
|
44999
|
+
logger.info(` ${green("All skills match their installed hashes.")}`);
|
|
45000
|
+
} else {
|
|
45001
|
+
if (driftCount > 0)
|
|
45002
|
+
logger.info(` ${driftCount} skill(s) modified since install`);
|
|
45003
|
+
if (missingCount > 0)
|
|
45004
|
+
logger.info(` ${missingCount} skill(s) missing from disk`);
|
|
45005
|
+
}
|
|
45006
|
+
}
|
|
45007
|
+
});
|
|
45008
|
+
lock.command("prune").description("Remove entries for projects that no longer exist on disk").option("-d, --dry-run", "Show what would be removed without changing the lockfile").action(async (options2) => {
|
|
45009
|
+
const installLock6 = new InstallLock;
|
|
45010
|
+
const stale = await installLock6.findStaleProjects();
|
|
45011
|
+
if (stale.length === 0) {
|
|
45012
|
+
logger.info("No stale projects found. Lockfile is clean.");
|
|
45013
|
+
return;
|
|
45014
|
+
}
|
|
45015
|
+
logger.info(`Found ${stale.length} stale project(s):`);
|
|
45016
|
+
for (const path of stale) {
|
|
45017
|
+
logger.info(` ${red("x")} ${path}`);
|
|
45018
|
+
}
|
|
45019
|
+
if (options2.dryRun) {
|
|
45020
|
+
logger.info(dim(`
|
|
45021
|
+
Dry run \u2014 no changes made.`));
|
|
45022
|
+
return;
|
|
45023
|
+
}
|
|
45024
|
+
const result = await installLock6.pruneStaleEntries();
|
|
45025
|
+
logger.info(`\nRemoved ${result.entriesRemoved} entries for ${result.prunedProjects.length} stale project(s).`);
|
|
45026
|
+
});
|
|
45027
|
+
}
|
|
45028
|
+
|
|
43613
45029
|
// dist/cli.js
|
|
45030
|
+
init_logger();
|
|
43614
45031
|
var program2 = new Command;
|
|
43615
45032
|
program2.name("agentinit").description("A CLI tool for managing and configuring AI coding agents").version("1.0.1");
|
|
43616
45033
|
registerSkillsCommand(program2);
|
|
@@ -43618,6 +45035,7 @@ registerMcpCommand(program2);
|
|
|
43618
45035
|
registerRulesCommand(program2);
|
|
43619
45036
|
registerPluginsCommand(program2);
|
|
43620
45037
|
registerConfigCommand(program2);
|
|
45038
|
+
registerLockCommand(program2);
|
|
43621
45039
|
program2.command("init").description("Initialize agents.md configuration for the current project").option("-f, --force", "Overwrite existing configuration").option("-t, --template <template>", "Use specific template (web, cli, library)").action(initCommand);
|
|
43622
45040
|
program2.command("detect").description("Detect current project stack and existing agent configurations").option("-v, --verbose", "Show detailed detection results").action(detectCommand);
|
|
43623
45041
|
program2.command("sync").description("Sync agents.md with agent-specific configuration files").option("-a, --agent <agents...>", "Target specific agent(s)").option("-d, --dry-run", "Show what would be changed without making changes").option("-b, --backup", "Create backup before syncing").action(syncCommand);
|