allagents 0.5.2 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +280 -43
- package/package.json +4 -3
package/dist/index.js
CHANGED
|
@@ -5324,8 +5324,8 @@ var require_pattern = __commonJS((exports) => {
|
|
|
5324
5324
|
}
|
|
5325
5325
|
exports.endsWithSlashGlobStar = endsWithSlashGlobStar;
|
|
5326
5326
|
function isAffectDepthOfReadingPattern(pattern) {
|
|
5327
|
-
const
|
|
5328
|
-
return endsWithSlashGlobStar(pattern) || isStaticPattern(
|
|
5327
|
+
const basename2 = path3.basename(pattern);
|
|
5328
|
+
return endsWithSlashGlobStar(pattern) || isStaticPattern(basename2);
|
|
5329
5329
|
}
|
|
5330
5330
|
exports.isAffectDepthOfReadingPattern = isAffectDepthOfReadingPattern;
|
|
5331
5331
|
function expandPatternsWithBraceExpansion(patterns) {
|
|
@@ -11059,7 +11059,7 @@ import { dirname as dirname7, join as join12 } from "node:path";
|
|
|
11059
11059
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
11060
11060
|
|
|
11061
11061
|
// src/core/workspace.ts
|
|
11062
|
-
import { mkdir as mkdir5, readFile as
|
|
11062
|
+
import { mkdir as mkdir5, readFile as readFile7, writeFile as writeFile4, copyFile as copyFile2 } from "node:fs/promises";
|
|
11063
11063
|
import { existsSync as existsSync7 } from "node:fs";
|
|
11064
11064
|
import { join as join8, resolve as resolve5, dirname as dirname5, relative as relative2, sep, isAbsolute as isAbsolute2 } from "node:path";
|
|
11065
11065
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
@@ -19558,11 +19558,27 @@ async function verifyGitHubUrlExists(source) {
|
|
|
19558
19558
|
}
|
|
19559
19559
|
|
|
19560
19560
|
// src/core/plugin.ts
|
|
19561
|
-
import { mkdir, readdir, stat } from "node:fs/promises";
|
|
19561
|
+
import { mkdir, readdir, stat, readFile as readFile2 } from "node:fs/promises";
|
|
19562
19562
|
import { existsSync } from "node:fs";
|
|
19563
|
-
import { dirname, join, resolve as resolve2 } from "node:path";
|
|
19564
|
-
|
|
19563
|
+
import { basename, dirname, join, resolve as resolve2 } from "node:path";
|
|
19564
|
+
|
|
19565
|
+
// src/models/plugin-config.ts
|
|
19566
|
+
var PluginManifestSchema = exports_external.object({
|
|
19567
|
+
name: exports_external.string(),
|
|
19568
|
+
version: exports_external.string(),
|
|
19569
|
+
description: exports_external.string(),
|
|
19570
|
+
author: exports_external.string().optional(),
|
|
19571
|
+
license: exports_external.string().optional()
|
|
19572
|
+
});
|
|
19573
|
+
|
|
19574
|
+
// src/core/plugin.ts
|
|
19575
|
+
async function fetchPlugin(url, options2 = {}, deps = {}) {
|
|
19565
19576
|
const { force = false, branch } = options2;
|
|
19577
|
+
const {
|
|
19578
|
+
execa: execaFn = execa,
|
|
19579
|
+
existsSync: existsSyncFn = existsSync,
|
|
19580
|
+
mkdir: mkdirFn = mkdir
|
|
19581
|
+
} = deps;
|
|
19566
19582
|
const validation = validatePluginSource(url);
|
|
19567
19583
|
if (!validation.valid) {
|
|
19568
19584
|
return {
|
|
@@ -19584,7 +19600,7 @@ async function fetchPlugin(url, options2 = {}) {
|
|
|
19584
19600
|
const { owner, repo } = parsed;
|
|
19585
19601
|
const cachePath = getPluginCachePath(owner, repo, branch);
|
|
19586
19602
|
try {
|
|
19587
|
-
await
|
|
19603
|
+
await execaFn("gh", ["--version"]);
|
|
19588
19604
|
} catch {
|
|
19589
19605
|
return {
|
|
19590
19606
|
success: false,
|
|
@@ -19594,7 +19610,7 @@ async function fetchPlugin(url, options2 = {}) {
|
|
|
19594
19610
|
Install: https://cli.github.com`
|
|
19595
19611
|
};
|
|
19596
19612
|
}
|
|
19597
|
-
const isCached =
|
|
19613
|
+
const isCached = existsSyncFn(cachePath);
|
|
19598
19614
|
if (isCached && !force) {
|
|
19599
19615
|
return {
|
|
19600
19616
|
success: true,
|
|
@@ -19604,7 +19620,7 @@ async function fetchPlugin(url, options2 = {}) {
|
|
|
19604
19620
|
}
|
|
19605
19621
|
try {
|
|
19606
19622
|
if (isCached && force) {
|
|
19607
|
-
await
|
|
19623
|
+
await execaFn("git", ["pull"], { cwd: cachePath });
|
|
19608
19624
|
return {
|
|
19609
19625
|
success: true,
|
|
19610
19626
|
action: "updated",
|
|
@@ -19612,11 +19628,11 @@ async function fetchPlugin(url, options2 = {}) {
|
|
|
19612
19628
|
};
|
|
19613
19629
|
}
|
|
19614
19630
|
const parentDir = dirname(cachePath);
|
|
19615
|
-
await
|
|
19631
|
+
await mkdirFn(parentDir, { recursive: true });
|
|
19616
19632
|
if (branch) {
|
|
19617
|
-
await
|
|
19633
|
+
await execaFn("gh", ["repo", "clone", `${owner}/${repo}`, cachePath, "--", "--branch", branch]);
|
|
19618
19634
|
} else {
|
|
19619
|
-
await
|
|
19635
|
+
await execaFn("gh", ["repo", "clone", `${owner}/${repo}`, cachePath]);
|
|
19620
19636
|
}
|
|
19621
19637
|
return {
|
|
19622
19638
|
success: true,
|
|
@@ -19666,9 +19682,23 @@ async function fetchPlugin(url, options2 = {}) {
|
|
|
19666
19682
|
};
|
|
19667
19683
|
}
|
|
19668
19684
|
}
|
|
19685
|
+
async function getPluginName(pluginPath) {
|
|
19686
|
+
const manifestPath = join(pluginPath, "plugin.json");
|
|
19687
|
+
if (existsSync(manifestPath)) {
|
|
19688
|
+
try {
|
|
19689
|
+
const content = await readFile2(manifestPath, "utf-8");
|
|
19690
|
+
const manifest = JSON.parse(content);
|
|
19691
|
+
const result = PluginManifestSchema.safeParse(manifest);
|
|
19692
|
+
if (result.success && result.data.name) {
|
|
19693
|
+
return result.data.name;
|
|
19694
|
+
}
|
|
19695
|
+
} catch {}
|
|
19696
|
+
}
|
|
19697
|
+
return basename(pluginPath);
|
|
19698
|
+
}
|
|
19669
19699
|
|
|
19670
19700
|
// src/core/transform.ts
|
|
19671
|
-
import { readFile as
|
|
19701
|
+
import { readFile as readFile4, writeFile, mkdir as mkdir2, cp, readdir as readdir2 } from "node:fs/promises";
|
|
19672
19702
|
import { existsSync as existsSync3 } from "node:fs";
|
|
19673
19703
|
import { join as join4, dirname as dirname2 } from "node:path";
|
|
19674
19704
|
|
|
@@ -19752,7 +19782,7 @@ var CLIENT_MAPPINGS = {
|
|
|
19752
19782
|
|
|
19753
19783
|
// src/validators/skill.ts
|
|
19754
19784
|
var import_gray_matter = __toESM(require_gray_matter(), 1);
|
|
19755
|
-
import { readFile as
|
|
19785
|
+
import { readFile as readFile3 } from "node:fs/promises";
|
|
19756
19786
|
import { existsSync as existsSync2 } from "node:fs";
|
|
19757
19787
|
import { join as join3 } from "node:path";
|
|
19758
19788
|
|
|
@@ -19776,7 +19806,7 @@ async function validateSkill(skillDir) {
|
|
|
19776
19806
|
};
|
|
19777
19807
|
}
|
|
19778
19808
|
try {
|
|
19779
|
-
const content = await
|
|
19809
|
+
const content = await readFile3(skillMdPath, "utf-8");
|
|
19780
19810
|
const { data: frontmatter } = import_gray_matter.default(content);
|
|
19781
19811
|
if (!frontmatter || Object.keys(frontmatter).length === 0) {
|
|
19782
19812
|
return {
|
|
@@ -19826,7 +19856,7 @@ async function ensureWorkspaceRules(filePath, rules) {
|
|
|
19826
19856
|
`, "utf-8");
|
|
19827
19857
|
return;
|
|
19828
19858
|
}
|
|
19829
|
-
const content = await
|
|
19859
|
+
const content = await readFile4(filePath, "utf-8");
|
|
19830
19860
|
const startIndex = content.indexOf(startMarker);
|
|
19831
19861
|
const endIndex = content.indexOf(endMarker);
|
|
19832
19862
|
if (startIndex !== -1 && endIndex !== -1 && endIndex > startIndex) {
|
|
@@ -19862,7 +19892,7 @@ async function copyCommands(pluginPath, workspacePath, client, options2 = {}) {
|
|
|
19862
19892
|
return { source: sourcePath, destination: destPath, action: "copied" };
|
|
19863
19893
|
}
|
|
19864
19894
|
try {
|
|
19865
|
-
const content = await
|
|
19895
|
+
const content = await readFile4(sourcePath, "utf-8");
|
|
19866
19896
|
await writeFile(destPath, content, "utf-8");
|
|
19867
19897
|
return { source: sourcePath, destination: destPath, action: "copied" };
|
|
19868
19898
|
} catch (error) {
|
|
@@ -19877,7 +19907,7 @@ async function copyCommands(pluginPath, workspacePath, client, options2 = {}) {
|
|
|
19877
19907
|
return Promise.all(copyPromises);
|
|
19878
19908
|
}
|
|
19879
19909
|
async function copySkills(pluginPath, workspacePath, client, options2 = {}) {
|
|
19880
|
-
const { dryRun = false } = options2;
|
|
19910
|
+
const { dryRun = false, skillNameMap } = options2;
|
|
19881
19911
|
const mapping = CLIENT_MAPPINGS[client];
|
|
19882
19912
|
const results = [];
|
|
19883
19913
|
if (!mapping.skillsPath) {
|
|
@@ -19895,7 +19925,8 @@ async function copySkills(pluginPath, workspacePath, client, options2 = {}) {
|
|
|
19895
19925
|
const skillDirs = entries.filter((e) => e.isDirectory());
|
|
19896
19926
|
const copyPromises = skillDirs.map(async (entry) => {
|
|
19897
19927
|
const skillSourcePath = join4(sourceDir, entry.name);
|
|
19898
|
-
const
|
|
19928
|
+
const resolvedName = skillNameMap?.get(entry.name) ?? entry.name;
|
|
19929
|
+
const skillDestPath = join4(destDir, resolvedName);
|
|
19899
19930
|
const validation = await validateSkill(skillSourcePath);
|
|
19900
19931
|
if (!validation.valid) {
|
|
19901
19932
|
return {
|
|
@@ -19930,6 +19961,20 @@ async function copySkills(pluginPath, workspacePath, client, options2 = {}) {
|
|
|
19930
19961
|
});
|
|
19931
19962
|
return Promise.all(copyPromises);
|
|
19932
19963
|
}
|
|
19964
|
+
async function collectPluginSkills(pluginPath, pluginSource) {
|
|
19965
|
+
const skillsDir = join4(pluginPath, "skills");
|
|
19966
|
+
if (!existsSync3(skillsDir)) {
|
|
19967
|
+
return [];
|
|
19968
|
+
}
|
|
19969
|
+
const entries = await readdir2(skillsDir, { withFileTypes: true });
|
|
19970
|
+
const skillDirs = entries.filter((e) => e.isDirectory());
|
|
19971
|
+
return skillDirs.map((entry) => ({
|
|
19972
|
+
folderName: entry.name,
|
|
19973
|
+
skillPath: join4(skillsDir, entry.name),
|
|
19974
|
+
pluginPath,
|
|
19975
|
+
pluginSource
|
|
19976
|
+
}));
|
|
19977
|
+
}
|
|
19933
19978
|
async function copyHooks(pluginPath, workspacePath, client, options2 = {}) {
|
|
19934
19979
|
const { dryRun = false } = options2;
|
|
19935
19980
|
const mapping = CLIENT_MAPPINGS[client];
|
|
@@ -19984,7 +20029,7 @@ async function copyAgents(pluginPath, workspacePath, client, options2 = {}) {
|
|
|
19984
20029
|
return { source: sourcePath, destination: destPath, action: "copied" };
|
|
19985
20030
|
}
|
|
19986
20031
|
try {
|
|
19987
|
-
const content = await
|
|
20032
|
+
const content = await readFile4(sourcePath, "utf-8");
|
|
19988
20033
|
await writeFile(destPath, content, "utf-8");
|
|
19989
20034
|
return { source: sourcePath, destination: destPath, action: "copied" };
|
|
19990
20035
|
} catch (error) {
|
|
@@ -19999,11 +20044,12 @@ async function copyAgents(pluginPath, workspacePath, client, options2 = {}) {
|
|
|
19999
20044
|
return Promise.all(copyPromises);
|
|
20000
20045
|
}
|
|
20001
20046
|
async function copyPluginToWorkspace(pluginPath, workspacePath, client, options2 = {}) {
|
|
20047
|
+
const { skillNameMap, ...baseOptions } = options2;
|
|
20002
20048
|
const [commandResults, skillResults, hookResults, agentResults] = await Promise.all([
|
|
20003
|
-
copyCommands(pluginPath, workspacePath, client,
|
|
20004
|
-
copySkills(pluginPath, workspacePath, client,
|
|
20005
|
-
copyHooks(pluginPath, workspacePath, client,
|
|
20006
|
-
copyAgents(pluginPath, workspacePath, client,
|
|
20049
|
+
copyCommands(pluginPath, workspacePath, client, baseOptions),
|
|
20050
|
+
copySkills(pluginPath, workspacePath, client, { ...baseOptions, ...skillNameMap && { skillNameMap } }),
|
|
20051
|
+
copyHooks(pluginPath, workspacePath, client, baseOptions),
|
|
20052
|
+
copyAgents(pluginPath, workspacePath, client, baseOptions)
|
|
20007
20053
|
]);
|
|
20008
20054
|
return [...commandResults, ...skillResults, ...hookResults, ...agentResults];
|
|
20009
20055
|
}
|
|
@@ -20119,7 +20165,7 @@ async function copyWorkspaceFiles(sourcePath, workspacePath, files, options2 = {
|
|
|
20119
20165
|
}
|
|
20120
20166
|
try {
|
|
20121
20167
|
await mkdir2(dirname2(destPath), { recursive: true });
|
|
20122
|
-
const content = await
|
|
20168
|
+
const content = await readFile4(resolved.sourcePath, "utf-8");
|
|
20123
20169
|
await writeFile(destPath, content, "utf-8");
|
|
20124
20170
|
results.push({ source: resolved.sourcePath, destination: destPath, action: "copied" });
|
|
20125
20171
|
if (AGENT_FILES2.includes(resolved.relativePath)) {
|
|
@@ -20190,7 +20236,7 @@ async function copyWorkspaceFiles(sourcePath, workspacePath, files, options2 = {
|
|
|
20190
20236
|
}
|
|
20191
20237
|
try {
|
|
20192
20238
|
await mkdir2(dirname2(destPath), { recursive: true });
|
|
20193
|
-
const content = await
|
|
20239
|
+
const content = await readFile4(srcPath, "utf-8");
|
|
20194
20240
|
await writeFile(destPath, content, "utf-8");
|
|
20195
20241
|
results.push({ source: srcPath, destination: destPath, action: "copied" });
|
|
20196
20242
|
if (AGENT_FILES2.includes(entry.dest)) {
|
|
@@ -20223,10 +20269,153 @@ async function copyWorkspaceFiles(sourcePath, workspacePath, files, options2 = {
|
|
|
20223
20269
|
return results;
|
|
20224
20270
|
}
|
|
20225
20271
|
|
|
20272
|
+
// src/utils/hash.ts
|
|
20273
|
+
import { createHash } from "node:crypto";
|
|
20274
|
+
function getShortId(input) {
|
|
20275
|
+
return createHash("sha256").update(input).digest("hex").substring(0, 6);
|
|
20276
|
+
}
|
|
20277
|
+
|
|
20278
|
+
// src/utils/source-parser.ts
|
|
20279
|
+
function extractOrgFromSource(source) {
|
|
20280
|
+
if (!source || source.trim() === "") {
|
|
20281
|
+
return null;
|
|
20282
|
+
}
|
|
20283
|
+
const trimmedSource = source.trim();
|
|
20284
|
+
if (isLocalPath(trimmedSource)) {
|
|
20285
|
+
return null;
|
|
20286
|
+
}
|
|
20287
|
+
if (trimmedSource.startsWith("github:")) {
|
|
20288
|
+
return parseOrgFromPrefix(trimmedSource.slice("github:".length));
|
|
20289
|
+
}
|
|
20290
|
+
if (trimmedSource.startsWith("gh:")) {
|
|
20291
|
+
return parseOrgFromPrefix(trimmedSource.slice("gh:".length));
|
|
20292
|
+
}
|
|
20293
|
+
const urlMatch = trimmedSource.match(/^(?:https?:\/\/)?(?:www\.)?github\.com\/([^/]+)(?:\/|$)/);
|
|
20294
|
+
if (urlMatch?.[1]) {
|
|
20295
|
+
return validateOrg(urlMatch[1]);
|
|
20296
|
+
}
|
|
20297
|
+
if (trimmedSource.includes("/") && !trimmedSource.includes("://")) {
|
|
20298
|
+
const firstSlashIndex = trimmedSource.indexOf("/");
|
|
20299
|
+
const potentialOrg = trimmedSource.slice(0, firstSlashIndex);
|
|
20300
|
+
return validateOrg(potentialOrg);
|
|
20301
|
+
}
|
|
20302
|
+
return null;
|
|
20303
|
+
}
|
|
20304
|
+
function isLocalPath(source) {
|
|
20305
|
+
if (source.startsWith(".")) {
|
|
20306
|
+
return true;
|
|
20307
|
+
}
|
|
20308
|
+
if (source.startsWith("/")) {
|
|
20309
|
+
return true;
|
|
20310
|
+
}
|
|
20311
|
+
if (/^[a-zA-Z]:[\\/]/.test(source)) {
|
|
20312
|
+
return true;
|
|
20313
|
+
}
|
|
20314
|
+
if (source.includes("\\")) {
|
|
20315
|
+
return true;
|
|
20316
|
+
}
|
|
20317
|
+
return false;
|
|
20318
|
+
}
|
|
20319
|
+
function parseOrgFromPrefix(prefixContent) {
|
|
20320
|
+
const withoutBranch = prefixContent.split("#")[0] || "";
|
|
20321
|
+
const slashIndex = withoutBranch.indexOf("/");
|
|
20322
|
+
if (slashIndex === -1) {
|
|
20323
|
+
return null;
|
|
20324
|
+
}
|
|
20325
|
+
const org = withoutBranch.slice(0, slashIndex);
|
|
20326
|
+
return validateOrg(org);
|
|
20327
|
+
}
|
|
20328
|
+
function validateOrg(org) {
|
|
20329
|
+
if (!org || org.trim() === "") {
|
|
20330
|
+
return null;
|
|
20331
|
+
}
|
|
20332
|
+
const trimmedOrg = org.trim();
|
|
20333
|
+
const validOrgPattern = /^[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?$/;
|
|
20334
|
+
if (!validOrgPattern.test(trimmedOrg)) {
|
|
20335
|
+
if (trimmedOrg.length === 1 && /^[a-zA-Z0-9]$/.test(trimmedOrg)) {
|
|
20336
|
+
return trimmedOrg;
|
|
20337
|
+
}
|
|
20338
|
+
return null;
|
|
20339
|
+
}
|
|
20340
|
+
if (trimmedOrg.includes("--")) {
|
|
20341
|
+
return null;
|
|
20342
|
+
}
|
|
20343
|
+
return trimmedOrg;
|
|
20344
|
+
}
|
|
20345
|
+
|
|
20346
|
+
// src/utils/skill-name-resolver.ts
|
|
20347
|
+
function getSkillKey(entry) {
|
|
20348
|
+
return `${entry.pluginSource}::${entry.pluginName}::${entry.folderName}`;
|
|
20349
|
+
}
|
|
20350
|
+
function getDisambiguatorPrefix(pluginSource) {
|
|
20351
|
+
const org = extractOrgFromSource(pluginSource);
|
|
20352
|
+
if (org) {
|
|
20353
|
+
return org;
|
|
20354
|
+
}
|
|
20355
|
+
return getShortId(pluginSource);
|
|
20356
|
+
}
|
|
20357
|
+
function resolveSkillNames(skills) {
|
|
20358
|
+
const resolved = [];
|
|
20359
|
+
const nameMap = new Map;
|
|
20360
|
+
const byFolderName = new Map;
|
|
20361
|
+
for (const skill of skills) {
|
|
20362
|
+
const existing = byFolderName.get(skill.folderName) || [];
|
|
20363
|
+
existing.push(skill);
|
|
20364
|
+
byFolderName.set(skill.folderName, existing);
|
|
20365
|
+
}
|
|
20366
|
+
for (const [folderName, group] of byFolderName) {
|
|
20367
|
+
if (group.length === 1) {
|
|
20368
|
+
const skill = group[0];
|
|
20369
|
+
if (skill) {
|
|
20370
|
+
const resolvedEntry = {
|
|
20371
|
+
original: skill,
|
|
20372
|
+
resolvedName: folderName,
|
|
20373
|
+
wasRenamed: false
|
|
20374
|
+
};
|
|
20375
|
+
resolved.push(resolvedEntry);
|
|
20376
|
+
nameMap.set(getSkillKey(skill), folderName);
|
|
20377
|
+
}
|
|
20378
|
+
} else {
|
|
20379
|
+
const byPluginName = new Map;
|
|
20380
|
+
for (const skill of group) {
|
|
20381
|
+
const existing = byPluginName.get(skill.pluginName) || [];
|
|
20382
|
+
existing.push(skill);
|
|
20383
|
+
byPluginName.set(skill.pluginName, existing);
|
|
20384
|
+
}
|
|
20385
|
+
const hasPluginNameConflict = Array.from(byPluginName.values()).some((pluginGroup) => pluginGroup.length > 1);
|
|
20386
|
+
if (!hasPluginNameConflict) {
|
|
20387
|
+
for (const skill of group) {
|
|
20388
|
+
const resolvedName = `${skill.pluginName}_${folderName}`;
|
|
20389
|
+
const resolvedEntry = {
|
|
20390
|
+
original: skill,
|
|
20391
|
+
resolvedName,
|
|
20392
|
+
wasRenamed: true
|
|
20393
|
+
};
|
|
20394
|
+
resolved.push(resolvedEntry);
|
|
20395
|
+
nameMap.set(getSkillKey(skill), resolvedName);
|
|
20396
|
+
}
|
|
20397
|
+
} else {
|
|
20398
|
+
for (const skill of group) {
|
|
20399
|
+
const prefix = getDisambiguatorPrefix(skill.pluginSource);
|
|
20400
|
+
const resolvedName = `${prefix}_${skill.pluginName}_${folderName}`;
|
|
20401
|
+
const resolvedEntry = {
|
|
20402
|
+
original: skill,
|
|
20403
|
+
resolvedName,
|
|
20404
|
+
wasRenamed: true
|
|
20405
|
+
};
|
|
20406
|
+
resolved.push(resolvedEntry);
|
|
20407
|
+
nameMap.set(getSkillKey(skill), resolvedName);
|
|
20408
|
+
}
|
|
20409
|
+
}
|
|
20410
|
+
}
|
|
20411
|
+
}
|
|
20412
|
+
return { resolved, nameMap };
|
|
20413
|
+
}
|
|
20414
|
+
|
|
20226
20415
|
// src/core/marketplace.ts
|
|
20227
|
-
import { mkdir as mkdir3, readFile as
|
|
20416
|
+
import { mkdir as mkdir3, readFile as readFile5, readdir as readdir3, writeFile as writeFile2 } from "node:fs/promises";
|
|
20228
20417
|
import { existsSync as existsSync4 } from "node:fs";
|
|
20229
|
-
import { basename, join as join5, resolve as resolve3 } from "node:path";
|
|
20418
|
+
import { basename as basename2, join as join5, resolve as resolve3 } from "node:path";
|
|
20230
20419
|
var WELL_KNOWN_MARKETPLACES = {
|
|
20231
20420
|
"claude-plugins-official": "anthropics/claude-plugins-official"
|
|
20232
20421
|
};
|
|
@@ -20246,7 +20435,7 @@ async function loadRegistry() {
|
|
|
20246
20435
|
return { version: 1, marketplaces: {} };
|
|
20247
20436
|
}
|
|
20248
20437
|
try {
|
|
20249
|
-
const content = await
|
|
20438
|
+
const content = await readFile5(registryPath, "utf-8");
|
|
20250
20439
|
return JSON.parse(content);
|
|
20251
20440
|
} catch {
|
|
20252
20441
|
return { version: 1, marketplaces: {} };
|
|
@@ -20285,7 +20474,7 @@ function parseMarketplaceSource(source) {
|
|
|
20285
20474
|
}
|
|
20286
20475
|
if (source.startsWith("/") || source.startsWith(".")) {
|
|
20287
20476
|
const absPath = resolve3(source);
|
|
20288
|
-
const name =
|
|
20477
|
+
const name = basename2(absPath) || "local";
|
|
20289
20478
|
return {
|
|
20290
20479
|
type: "local",
|
|
20291
20480
|
location: absPath,
|
|
@@ -20526,7 +20715,7 @@ function getWellKnownMarketplaces() {
|
|
|
20526
20715
|
}
|
|
20527
20716
|
|
|
20528
20717
|
// src/core/sync-state.ts
|
|
20529
|
-
import { readFile as
|
|
20718
|
+
import { readFile as readFile6, writeFile as writeFile3, mkdir as mkdir4 } from "node:fs/promises";
|
|
20530
20719
|
import { existsSync as existsSync5 } from "node:fs";
|
|
20531
20720
|
import { join as join6, dirname as dirname3 } from "node:path";
|
|
20532
20721
|
|
|
@@ -20547,7 +20736,7 @@ async function loadSyncState(workspacePath) {
|
|
|
20547
20736
|
return null;
|
|
20548
20737
|
}
|
|
20549
20738
|
try {
|
|
20550
|
-
const content = await
|
|
20739
|
+
const content = await readFile6(statePath, "utf-8");
|
|
20551
20740
|
const parsed = JSON.parse(content);
|
|
20552
20741
|
const result = SyncStateSchema.safeParse(parsed);
|
|
20553
20742
|
if (!result.success) {
|
|
@@ -20581,7 +20770,9 @@ async function selectivePurgeWorkspace(workspacePath, state, clients) {
|
|
|
20581
20770
|
return [];
|
|
20582
20771
|
}
|
|
20583
20772
|
const result = [];
|
|
20584
|
-
|
|
20773
|
+
const previousClients = Object.keys(state.files);
|
|
20774
|
+
const clientsToProcess = [...new Set([...clients, ...previousClients])];
|
|
20775
|
+
for (const client of clientsToProcess) {
|
|
20585
20776
|
const previousFiles = getPreviouslySyncedFiles(state, client);
|
|
20586
20777
|
const purgedPaths = [];
|
|
20587
20778
|
for (const filePath of previousFiles) {
|
|
@@ -20828,10 +21019,10 @@ async function validatePlugin(pluginSource, workspacePath, force) {
|
|
|
20828
21019
|
async function validateAllPlugins(plugins, workspacePath, force) {
|
|
20829
21020
|
return Promise.all(plugins.map((plugin) => validatePlugin(plugin, workspacePath, force)));
|
|
20830
21021
|
}
|
|
20831
|
-
async function copyValidatedPlugin(validatedPlugin, workspacePath, clients, dryRun) {
|
|
21022
|
+
async function copyValidatedPlugin(validatedPlugin, workspacePath, clients, dryRun, skillNameMap) {
|
|
20832
21023
|
const copyResults = [];
|
|
20833
21024
|
for (const client of clients) {
|
|
20834
|
-
const results = await copyPluginToWorkspace(validatedPlugin.resolved, workspacePath, client, { dryRun });
|
|
21025
|
+
const results = await copyPluginToWorkspace(validatedPlugin.resolved, workspacePath, client, { dryRun, ...skillNameMap && { skillNameMap } });
|
|
20835
21026
|
copyResults.push(...results);
|
|
20836
21027
|
}
|
|
20837
21028
|
const hasFailures = copyResults.some((r) => r.action === "failed");
|
|
@@ -20842,6 +21033,47 @@ async function copyValidatedPlugin(validatedPlugin, workspacePath, clients, dryR
|
|
|
20842
21033
|
copyResults
|
|
20843
21034
|
};
|
|
20844
21035
|
}
|
|
21036
|
+
async function collectAllSkills(validatedPlugins) {
|
|
21037
|
+
const allSkills = [];
|
|
21038
|
+
for (const plugin of validatedPlugins) {
|
|
21039
|
+
const pluginName = await getPluginName(plugin.resolved);
|
|
21040
|
+
const skills = await collectPluginSkills(plugin.resolved, plugin.plugin);
|
|
21041
|
+
for (const skill of skills) {
|
|
21042
|
+
allSkills.push({
|
|
21043
|
+
folderName: skill.folderName,
|
|
21044
|
+
pluginName,
|
|
21045
|
+
pluginSource: plugin.plugin,
|
|
21046
|
+
pluginPath: plugin.resolved
|
|
21047
|
+
});
|
|
21048
|
+
}
|
|
21049
|
+
}
|
|
21050
|
+
return allSkills;
|
|
21051
|
+
}
|
|
21052
|
+
function buildPluginSkillNameMaps(allSkills) {
|
|
21053
|
+
const skillEntries = allSkills.map((skill) => ({
|
|
21054
|
+
folderName: skill.folderName,
|
|
21055
|
+
pluginName: skill.pluginName,
|
|
21056
|
+
pluginSource: skill.pluginSource
|
|
21057
|
+
}));
|
|
21058
|
+
const resolution = resolveSkillNames(skillEntries);
|
|
21059
|
+
const pluginMaps = new Map;
|
|
21060
|
+
for (let i2 = 0;i2 < allSkills.length; i2++) {
|
|
21061
|
+
const skill = allSkills[i2];
|
|
21062
|
+
const entry = skillEntries[i2];
|
|
21063
|
+
if (!skill || !entry)
|
|
21064
|
+
continue;
|
|
21065
|
+
const resolvedName = resolution.nameMap.get(getSkillKey(entry));
|
|
21066
|
+
if (resolvedName) {
|
|
21067
|
+
let pluginMap = pluginMaps.get(skill.pluginPath);
|
|
21068
|
+
if (!pluginMap) {
|
|
21069
|
+
pluginMap = new Map;
|
|
21070
|
+
pluginMaps.set(skill.pluginPath, pluginMap);
|
|
21071
|
+
}
|
|
21072
|
+
pluginMap.set(skill.folderName, resolvedName);
|
|
21073
|
+
}
|
|
21074
|
+
}
|
|
21075
|
+
return pluginMaps;
|
|
21076
|
+
}
|
|
20845
21077
|
async function syncWorkspace(workspacePath = process.cwd(), options2 = {}) {
|
|
20846
21078
|
const { force = false, dryRun = false, workspaceSourceBase } = options2;
|
|
20847
21079
|
const configDir = join7(workspacePath, CONFIG_DIR);
|
|
@@ -20918,7 +21150,12 @@ ${errors2}`
|
|
|
20918
21150
|
if (!dryRun) {
|
|
20919
21151
|
await selectivePurgeWorkspace(workspacePath, previousState, config.clients);
|
|
20920
21152
|
}
|
|
20921
|
-
const
|
|
21153
|
+
const allSkills = await collectAllSkills(validatedPlugins);
|
|
21154
|
+
const pluginSkillMaps = buildPluginSkillNameMaps(allSkills);
|
|
21155
|
+
const pluginResults = await Promise.all(validatedPlugins.map((validatedPlugin) => {
|
|
21156
|
+
const skillNameMap = pluginSkillMaps.get(validatedPlugin.resolved);
|
|
21157
|
+
return copyValidatedPlugin(validatedPlugin, workspacePath, config.clients, dryRun, skillNameMap);
|
|
21158
|
+
}));
|
|
20922
21159
|
let workspaceFileResults = [];
|
|
20923
21160
|
if (config.workspace) {
|
|
20924
21161
|
const sourcePath = validatedWorkspaceSource?.resolved;
|
|
@@ -21010,7 +21247,7 @@ ${fileValidationErrors.map((e) => ` - ${e}`).join(`
|
|
|
21010
21247
|
}
|
|
21011
21248
|
}
|
|
21012
21249
|
const hasFailures = pluginResults.some((r) => !r.success) || totalFailed > 0;
|
|
21013
|
-
if (!
|
|
21250
|
+
if (!dryRun) {
|
|
21014
21251
|
const allCopyResults = [
|
|
21015
21252
|
...pluginResults.flatMap((r) => r.copyResults),
|
|
21016
21253
|
...workspaceFileResults
|
|
@@ -21298,7 +21535,7 @@ async function initWorkspace(targetPath = ".", options2 = {}) {
|
|
|
21298
21535
|
sourceDir = parentDir;
|
|
21299
21536
|
}
|
|
21300
21537
|
}
|
|
21301
|
-
workspaceYamlContent = await
|
|
21538
|
+
workspaceYamlContent = await readFile7(sourceYamlPath, "utf-8");
|
|
21302
21539
|
if (sourceDir) {
|
|
21303
21540
|
const parsed2 = load(workspaceYamlContent);
|
|
21304
21541
|
const workspace = parsed2?.workspace;
|
|
@@ -21317,7 +21554,7 @@ async function initWorkspace(targetPath = ".", options2 = {}) {
|
|
|
21317
21554
|
if (!existsSync7(defaultYamlPath)) {
|
|
21318
21555
|
throw new Error(`Default template not found at: ${defaultTemplatePath}`);
|
|
21319
21556
|
}
|
|
21320
|
-
workspaceYamlContent = await
|
|
21557
|
+
workspaceYamlContent = await readFile7(defaultYamlPath, "utf-8");
|
|
21321
21558
|
}
|
|
21322
21559
|
await writeFile4(configPath, workspaceYamlContent, "utf-8");
|
|
21323
21560
|
const copiedAgentFiles = [];
|
|
@@ -21339,7 +21576,7 @@ async function initWorkspace(targetPath = ".", options2 = {}) {
|
|
|
21339
21576
|
for (const agentFile of AGENT_FILES) {
|
|
21340
21577
|
const sourcePath = join8(effectiveSourceDir, agentFile);
|
|
21341
21578
|
if (existsSync7(sourcePath)) {
|
|
21342
|
-
const content = await
|
|
21579
|
+
const content = await readFile7(sourcePath, "utf-8");
|
|
21343
21580
|
await writeFile4(join8(absoluteTarget, agentFile), content, "utf-8");
|
|
21344
21581
|
copiedAgentFiles.push(agentFile);
|
|
21345
21582
|
}
|
|
@@ -21449,7 +21686,7 @@ function getPluginStatus(parsed) {
|
|
|
21449
21686
|
}
|
|
21450
21687
|
|
|
21451
21688
|
// src/core/workspace-modify.ts
|
|
21452
|
-
import { readFile as
|
|
21689
|
+
import { readFile as readFile8, writeFile as writeFile5 } from "node:fs/promises";
|
|
21453
21690
|
import { existsSync as existsSync9 } from "node:fs";
|
|
21454
21691
|
import { join as join10 } from "node:path";
|
|
21455
21692
|
async function addPlugin(plugin, workspacePath = process.cwd()) {
|
|
@@ -21565,7 +21802,7 @@ async function ensureMarketplaceRegistered(spec) {
|
|
|
21565
21802
|
}
|
|
21566
21803
|
async function addPluginToConfig(plugin, configPath, autoRegistered) {
|
|
21567
21804
|
try {
|
|
21568
|
-
const content = await
|
|
21805
|
+
const content = await readFile8(configPath, "utf-8");
|
|
21569
21806
|
const config = load(content);
|
|
21570
21807
|
if (config.plugins.includes(plugin)) {
|
|
21571
21808
|
return {
|
|
@@ -21597,7 +21834,7 @@ async function removePlugin(plugin, workspacePath = process.cwd()) {
|
|
|
21597
21834
|
};
|
|
21598
21835
|
}
|
|
21599
21836
|
try {
|
|
21600
|
-
const content = await
|
|
21837
|
+
const content = await readFile8(configPath, "utf-8");
|
|
21601
21838
|
const config = load(content);
|
|
21602
21839
|
let index = config.plugins.indexOf(plugin);
|
|
21603
21840
|
if (index === -1 && isPluginSpec(plugin) === false) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "allagents",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "CLI tool for managing multi-repo AI agent workspaces with plugin synchronization",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"docs:install": "bun install --cwd docs",
|
|
15
15
|
"docs:build": "bun run --cwd docs build",
|
|
16
16
|
"dev": "bun run src/cli/index.ts",
|
|
17
|
-
"test": "bun test
|
|
17
|
+
"test": "bun test",
|
|
18
18
|
"test:watch": "bun test --watch",
|
|
19
19
|
"test:coverage": "bun test --coverage",
|
|
20
20
|
"test:integration": "bats tests/integration/*.bats",
|
|
@@ -24,7 +24,8 @@
|
|
|
24
24
|
"format": "biome format --write src",
|
|
25
25
|
"check": "biome check src",
|
|
26
26
|
"check:fix": "biome check --write src",
|
|
27
|
-
"prepare": "bun run build && (test -d .git && bunx prek install -t pre-push || true)"
|
|
27
|
+
"prepare": "bun run build && (test -d .git && bunx prek install -t pre-push || true)",
|
|
28
|
+
"release": "bun run scripts/release.ts"
|
|
28
29
|
},
|
|
29
30
|
"keywords": [
|
|
30
31
|
"cli",
|