allagents 0.17.2 → 0.19.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.
Files changed (2) hide show
  1. package/dist/index.js +351 -114
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -11382,7 +11382,7 @@ var init_zod = __esm(() => {
11382
11382
  });
11383
11383
 
11384
11384
  // src/models/workspace-config.ts
11385
- var RepositorySchema, WorkspaceFileSchema, WorkspaceSchema, PluginSourceSchema, ClientTypeSchema, VscodeConfigSchema, WorkspaceConfigSchema;
11385
+ var RepositorySchema, WorkspaceFileSchema, WorkspaceSchema, PluginSourceSchema, ClientTypeSchema, VscodeConfigSchema, SyncModeSchema, WorkspaceConfigSchema;
11386
11386
  var init_workspace_config = __esm(() => {
11387
11387
  init_zod();
11388
11388
  RepositorySchema = exports_external.object({
@@ -11417,12 +11417,14 @@ var init_workspace_config = __esm(() => {
11417
11417
  VscodeConfigSchema = exports_external.object({
11418
11418
  output: exports_external.string().optional()
11419
11419
  });
11420
+ SyncModeSchema = exports_external.enum(["symlink", "copy"]);
11420
11421
  WorkspaceConfigSchema = exports_external.object({
11421
11422
  workspace: WorkspaceSchema.optional(),
11422
11423
  repositories: exports_external.array(RepositorySchema),
11423
11424
  plugins: exports_external.array(PluginSourceSchema),
11424
11425
  clients: exports_external.array(ClientTypeSchema),
11425
- vscode: VscodeConfigSchema.optional()
11426
+ vscode: VscodeConfigSchema.optional(),
11427
+ syncMode: SyncModeSchema.optional()
11426
11428
  });
11427
11429
  });
11428
11430
 
@@ -21223,7 +21225,10 @@ var init_glob_patterns = __esm(() => {
21223
21225
  });
21224
21226
 
21225
21227
  // src/models/client-mapping.ts
21226
- var CLIENT_MAPPINGS, USER_CLIENT_MAPPINGS;
21228
+ function isUniversalClient(client) {
21229
+ return CLIENT_MAPPINGS[client].skillsPath === CANONICAL_SKILLS_PATH;
21230
+ }
21231
+ var CLIENT_MAPPINGS, CANONICAL_SKILLS_PATH = ".agents/skills/", USER_CLIENT_MAPPINGS;
21227
21232
  var init_client_mapping = __esm(() => {
21228
21233
  CLIENT_MAPPINGS = {
21229
21234
  claude: {
@@ -24858,10 +24863,72 @@ var init_skill = __esm(() => {
24858
24863
  import_gray_matter = __toESM(require_gray_matter(), 1);
24859
24864
  });
24860
24865
 
24866
+ // src/utils/symlink.ts
24867
+ import { symlink, lstat, readlink, rm as rm2, mkdir as mkdir2 } from "node:fs/promises";
24868
+ import { dirname as dirname2, relative, resolve as resolve4 } from "node:path";
24869
+ import { platform } from "node:os";
24870
+ import { realpath } from "node:fs/promises";
24871
+ async function resolveParentSymlinks(path) {
24872
+ const resolved = resolve4(path);
24873
+ const dir = dirname2(resolved);
24874
+ const base = resolved.substring(dir.length + 1);
24875
+ try {
24876
+ const realDir = await realpath(dir);
24877
+ return `${realDir}/${base}`;
24878
+ } catch {
24879
+ return resolved;
24880
+ }
24881
+ }
24882
+ function resolveSymlinkTarget(linkPath, linkTarget) {
24883
+ return resolve4(dirname2(linkPath), linkTarget);
24884
+ }
24885
+ async function createSymlink(target, linkPath) {
24886
+ try {
24887
+ const resolvedTarget = resolve4(target);
24888
+ const resolvedLinkPath = resolve4(linkPath);
24889
+ if (resolvedTarget === resolvedLinkPath) {
24890
+ return true;
24891
+ }
24892
+ const realTarget = await resolveParentSymlinks(target);
24893
+ const realLinkPath = await resolveParentSymlinks(linkPath);
24894
+ if (realTarget === realLinkPath) {
24895
+ return true;
24896
+ }
24897
+ try {
24898
+ const stats = await lstat(linkPath);
24899
+ if (stats.isSymbolicLink()) {
24900
+ const existingTarget = await readlink(linkPath);
24901
+ if (resolveSymlinkTarget(linkPath, existingTarget) === resolvedTarget) {
24902
+ return true;
24903
+ }
24904
+ await rm2(linkPath);
24905
+ } else {
24906
+ await rm2(linkPath, { recursive: true });
24907
+ }
24908
+ } catch (err) {
24909
+ if (err && typeof err === "object" && "code" in err && err.code === "ELOOP") {
24910
+ try {
24911
+ await rm2(linkPath, { force: true });
24912
+ } catch {}
24913
+ }
24914
+ }
24915
+ const linkDir = dirname2(linkPath);
24916
+ await mkdir2(linkDir, { recursive: true });
24917
+ const realLinkDir = await resolveParentSymlinks(linkDir);
24918
+ const relativePath = relative(realLinkDir, target);
24919
+ const symlinkType = platform() === "win32" ? "junction" : undefined;
24920
+ await symlink(relativePath, linkPath, symlinkType);
24921
+ return true;
24922
+ } catch {
24923
+ return false;
24924
+ }
24925
+ }
24926
+ var init_symlink = () => {};
24927
+
24861
24928
  // src/core/transform.ts
24862
- import { readFile as readFile4, writeFile, mkdir as mkdir2, cp, readdir as readdir2 } from "node:fs/promises";
24929
+ import { readFile as readFile4, writeFile, mkdir as mkdir3, cp, readdir as readdir2 } from "node:fs/promises";
24863
24930
  import { existsSync as existsSync4 } from "node:fs";
24864
- import { join as join6, dirname as dirname2 } from "node:path";
24931
+ import { join as join6, dirname as dirname3 } from "node:path";
24865
24932
  async function ensureWorkspaceRules(filePath, rules) {
24866
24933
  const rulesContent = rules ?? WORKSPACE_RULES;
24867
24934
  const startMarker = "<!-- WORKSPACE-RULES:START -->";
@@ -24898,7 +24965,7 @@ async function copyCommands(pluginPath, workspacePath, client, options2 = {}) {
24898
24965
  }
24899
24966
  const destDir = join6(workspacePath, mapping.commandsPath);
24900
24967
  if (!dryRun) {
24901
- await mkdir2(destDir, { recursive: true });
24968
+ await mkdir3(destDir, { recursive: true });
24902
24969
  }
24903
24970
  const files = await readdir2(sourceDir);
24904
24971
  const mdFiles = files.filter((f) => f.endsWith(".md"));
@@ -24924,7 +24991,7 @@ async function copyCommands(pluginPath, workspacePath, client, options2 = {}) {
24924
24991
  return Promise.all(copyPromises);
24925
24992
  }
24926
24993
  async function copySkills(pluginPath, workspacePath, client, options2 = {}) {
24927
- const { dryRun = false, skillNameMap } = options2;
24994
+ const { dryRun = false, skillNameMap, syncMode = "copy", canonicalSkillsPath } = options2;
24928
24995
  const mapping = getMapping(client, options2);
24929
24996
  const results = [];
24930
24997
  if (!mapping.skillsPath) {
@@ -24936,10 +25003,11 @@ async function copySkills(pluginPath, workspacePath, client, options2 = {}) {
24936
25003
  }
24937
25004
  const destDir = join6(workspacePath, mapping.skillsPath);
24938
25005
  if (!dryRun) {
24939
- await mkdir2(destDir, { recursive: true });
25006
+ await mkdir3(destDir, { recursive: true });
24940
25007
  }
24941
25008
  const entries = await readdir2(sourceDir, { withFileTypes: true });
24942
25009
  const skillDirs = entries.filter((e) => e.isDirectory());
25010
+ const useSymlinks = syncMode === "symlink" && !isUniversalClient(client) && canonicalSkillsPath;
24943
25011
  const copyPromises = skillDirs.map(async (entry) => {
24944
25012
  const skillSourcePath = join6(sourceDir, entry.name);
24945
25013
  const resolvedName = skillNameMap?.get(entry.name) ?? entry.name;
@@ -24960,6 +25028,17 @@ async function copySkills(pluginPath, workspacePath, client, options2 = {}) {
24960
25028
  action: "copied"
24961
25029
  };
24962
25030
  }
25031
+ if (useSymlinks) {
25032
+ const canonicalSkillPath = join6(workspacePath, canonicalSkillsPath, resolvedName);
25033
+ const symlinkCreated = await createSymlink(canonicalSkillPath, skillDestPath);
25034
+ if (symlinkCreated) {
25035
+ return {
25036
+ source: canonicalSkillPath,
25037
+ destination: skillDestPath,
25038
+ action: "copied"
25039
+ };
25040
+ }
25041
+ }
24963
25042
  try {
24964
25043
  await cp(skillSourcePath, skillDestPath, { recursive: true });
24965
25044
  return {
@@ -25008,7 +25087,7 @@ async function copyHooks(pluginPath, workspacePath, client, options2 = {}) {
25008
25087
  results.push({ source: sourceDir, destination: destDir, action: "copied" });
25009
25088
  return results;
25010
25089
  }
25011
- await mkdir2(destDir, { recursive: true });
25090
+ await mkdir3(destDir, { recursive: true });
25012
25091
  try {
25013
25092
  await cp(sourceDir, destDir, { recursive: true });
25014
25093
  results.push({ source: sourceDir, destination: destDir, action: "copied" });
@@ -25035,7 +25114,7 @@ async function copyAgents(pluginPath, workspacePath, client, options2 = {}) {
25035
25114
  }
25036
25115
  const destDir = join6(workspacePath, mapping.agentsPath);
25037
25116
  if (!dryRun) {
25038
- await mkdir2(destDir, { recursive: true });
25117
+ await mkdir3(destDir, { recursive: true });
25039
25118
  }
25040
25119
  const files = await readdir2(sourceDir);
25041
25120
  const mdFiles = files.filter((f) => f.endsWith(".md"));
@@ -25061,10 +25140,15 @@ async function copyAgents(pluginPath, workspacePath, client, options2 = {}) {
25061
25140
  return Promise.all(copyPromises);
25062
25141
  }
25063
25142
  async function copyPluginToWorkspace(pluginPath, workspacePath, client, options2 = {}) {
25064
- const { skillNameMap, ...baseOptions } = options2;
25143
+ const { skillNameMap, syncMode, canonicalSkillsPath, ...baseOptions } = options2;
25065
25144
  const [commandResults, skillResults, hookResults, agentResults] = await Promise.all([
25066
25145
  copyCommands(pluginPath, workspacePath, client, baseOptions),
25067
- copySkills(pluginPath, workspacePath, client, { ...baseOptions, ...skillNameMap && { skillNameMap } }),
25146
+ copySkills(pluginPath, workspacePath, client, {
25147
+ ...baseOptions,
25148
+ ...skillNameMap && { skillNameMap },
25149
+ ...syncMode && { syncMode },
25150
+ ...canonicalSkillsPath && { canonicalSkillsPath }
25151
+ }),
25068
25152
  copyHooks(pluginPath, workspacePath, client, baseOptions),
25069
25153
  copyAgents(pluginPath, workspacePath, client, baseOptions)
25070
25154
  ]);
@@ -25181,7 +25265,7 @@ async function copyWorkspaceFiles(sourcePath, workspacePath, files, options2 = {
25181
25265
  continue;
25182
25266
  }
25183
25267
  try {
25184
- await mkdir2(dirname2(destPath), { recursive: true });
25268
+ await mkdir3(dirname3(destPath), { recursive: true });
25185
25269
  const content = await readFile4(resolved.sourcePath, "utf-8");
25186
25270
  await writeFile(destPath, content, "utf-8");
25187
25271
  results.push({ source: resolved.sourcePath, destination: destPath, action: "copied" });
@@ -25252,7 +25336,7 @@ async function copyWorkspaceFiles(sourcePath, workspacePath, files, options2 = {
25252
25336
  continue;
25253
25337
  }
25254
25338
  try {
25255
- await mkdir2(dirname2(destPath), { recursive: true });
25339
+ await mkdir3(dirname3(destPath), { recursive: true });
25256
25340
  const content = await readFile4(srcPath, "utf-8");
25257
25341
  await writeFile(destPath, content, "utf-8");
25258
25342
  results.push({ source: srcPath, destination: destPath, action: "copied" });
@@ -25292,6 +25376,7 @@ var init_transform = __esm(() => {
25292
25376
  init_skill();
25293
25377
  init_constants();
25294
25378
  init_plugin_path();
25379
+ init_symlink();
25295
25380
  AGENT_FILES2 = ["AGENTS.md", "CLAUDE.md"];
25296
25381
  injectWorkspaceRules = ensureWorkspaceRules;
25297
25382
  });
@@ -25351,7 +25436,7 @@ var init_marketplace_manifest = __esm(() => {
25351
25436
  // src/utils/marketplace-manifest-parser.ts
25352
25437
  import { readFile as readFile5 } from "node:fs/promises";
25353
25438
  import { existsSync as existsSync5 } from "node:fs";
25354
- import { join as join7, resolve as resolve4 } from "node:path";
25439
+ import { join as join7, resolve as resolve5 } from "node:path";
25355
25440
  async function parseMarketplaceManifest(marketplacePath) {
25356
25441
  const manifestPath = join7(marketplacePath, MANIFEST_PATH);
25357
25442
  if (!existsSync5(manifestPath)) {
@@ -25455,7 +25540,7 @@ function resolvePluginSourcePath(source, marketplacePath) {
25455
25540
  if (typeof source === "object") {
25456
25541
  return source.url;
25457
25542
  }
25458
- return resolve4(marketplacePath, source);
25543
+ return resolve5(marketplacePath, source);
25459
25544
  }
25460
25545
  var MANIFEST_PATH = ".claude-plugin/marketplace.json";
25461
25546
  var init_marketplace_manifest_parser = __esm(() => {
@@ -25473,19 +25558,21 @@ __export(exports_user_workspace, {
25473
25558
  getUserWorkspaceConfigPath: () => getUserWorkspaceConfigPath,
25474
25559
  getUserWorkspaceConfig: () => getUserWorkspaceConfig,
25475
25560
  getUserPluginsForMarketplace: () => getUserPluginsForMarketplace,
25561
+ getInstalledUserPlugins: () => getInstalledUserPlugins,
25562
+ getInstalledProjectPlugins: () => getInstalledProjectPlugins,
25476
25563
  ensureUserWorkspace: () => ensureUserWorkspace,
25477
25564
  addUserPlugin: () => addUserPlugin
25478
25565
  });
25479
- import { readFile as readFile6, writeFile as writeFile2, mkdir as mkdir3 } from "node:fs/promises";
25566
+ import { readFile as readFile6, writeFile as writeFile2, mkdir as mkdir4 } from "node:fs/promises";
25480
25567
  import { existsSync as existsSync6 } from "node:fs";
25481
- import { join as join8, resolve as resolve5 } from "node:path";
25568
+ import { join as join8, resolve as resolve6 } from "node:path";
25482
25569
  function getUserWorkspaceConfigPath() {
25483
25570
  return join8(getAllagentsDir(), WORKSPACE_CONFIG_FILE);
25484
25571
  }
25485
25572
  function isUserConfigPath(workspacePath) {
25486
25573
  const projectConfigPath = join8(workspacePath, CONFIG_DIR, WORKSPACE_CONFIG_FILE);
25487
25574
  const userConfigPath = getUserWorkspaceConfigPath();
25488
- return resolve5(projectConfigPath) === resolve5(userConfigPath);
25575
+ return resolve6(projectConfigPath) === resolve6(userConfigPath);
25489
25576
  }
25490
25577
  async function ensureUserWorkspace() {
25491
25578
  const configPath = getUserWorkspaceConfigPath();
@@ -25494,9 +25581,9 @@ async function ensureUserWorkspace() {
25494
25581
  const defaultConfig = {
25495
25582
  repositories: [],
25496
25583
  plugins: [],
25497
- clients: [...ALL_CLIENTS]
25584
+ clients: [...DEFAULT_USER_CLIENTS]
25498
25585
  };
25499
- await mkdir3(getAllagentsDir(), { recursive: true });
25586
+ await mkdir4(getAllagentsDir(), { recursive: true });
25500
25587
  await writeFile2(configPath, dump(defaultConfig, { lineWidth: -1 }), "utf-8");
25501
25588
  }
25502
25589
  async function getUserWorkspaceConfig() {
@@ -25662,7 +25749,51 @@ async function addPluginToUserConfig(plugin, configPath, autoRegistered) {
25662
25749
  };
25663
25750
  }
25664
25751
  }
25665
- var ALL_CLIENTS;
25752
+ async function getInstalledUserPlugins() {
25753
+ const config = await getUserWorkspaceConfig();
25754
+ if (!config)
25755
+ return [];
25756
+ const result = [];
25757
+ for (const plugin of config.plugins) {
25758
+ const parsed = parsePluginSpec(plugin);
25759
+ if (parsed) {
25760
+ result.push({
25761
+ spec: plugin,
25762
+ name: parsed.plugin,
25763
+ marketplace: parsed.marketplaceName,
25764
+ scope: "user"
25765
+ });
25766
+ }
25767
+ }
25768
+ return result;
25769
+ }
25770
+ async function getInstalledProjectPlugins(workspacePath) {
25771
+ const configPath = join8(workspacePath, CONFIG_DIR, WORKSPACE_CONFIG_FILE);
25772
+ if (!existsSync6(configPath))
25773
+ return [];
25774
+ try {
25775
+ const content = await readFile6(configPath, "utf-8");
25776
+ const config = load(content);
25777
+ if (!config?.plugins)
25778
+ return [];
25779
+ const result = [];
25780
+ for (const plugin of config.plugins) {
25781
+ const parsed = parsePluginSpec(plugin);
25782
+ if (parsed) {
25783
+ result.push({
25784
+ spec: plugin,
25785
+ name: parsed.plugin,
25786
+ marketplace: parsed.marketplaceName,
25787
+ scope: "project"
25788
+ });
25789
+ }
25790
+ }
25791
+ return result;
25792
+ } catch {
25793
+ return [];
25794
+ }
25795
+ }
25796
+ var DEFAULT_USER_CLIENTS;
25666
25797
  var init_user_workspace = __esm(() => {
25667
25798
  init_js_yaml();
25668
25799
  init_constants();
@@ -25670,8 +25801,7 @@ var init_user_workspace = __esm(() => {
25670
25801
  init_marketplace();
25671
25802
  init_plugin_path();
25672
25803
  init_marketplace_manifest_parser();
25673
- ALL_CLIENTS = [
25674
- "claude",
25804
+ DEFAULT_USER_CLIENTS = [
25675
25805
  "copilot",
25676
25806
  "codex",
25677
25807
  "cursor",
@@ -25683,16 +25813,16 @@ var init_user_workspace = __esm(() => {
25683
25813
  });
25684
25814
 
25685
25815
  // src/core/marketplace.ts
25686
- import { mkdir as mkdir4, readFile as readFile7, readdir as readdir3, rm as rm2, writeFile as writeFile3 } from "node:fs/promises";
25816
+ import { mkdir as mkdir5, readFile as readFile7, readdir as readdir3, rm as rm3, writeFile as writeFile3 } from "node:fs/promises";
25687
25817
  import { existsSync as existsSync7 } from "node:fs";
25688
- import { basename as basename2, join as join9, resolve as resolve6 } from "node:path";
25818
+ import { basename as basename2, join as join9, resolve as resolve7 } from "node:path";
25689
25819
  function parseLocation(location) {
25690
25820
  const [owner = "", repo = "", ...rest] = location.split("/");
25691
25821
  const branch = rest.length > 0 ? rest.join("/") : undefined;
25692
25822
  return { owner, repo, ...branch !== undefined && { branch } };
25693
25823
  }
25694
25824
  function getAllagentsDir() {
25695
- return resolve6(getHomeDir(), ".allagents");
25825
+ return resolve7(getHomeDir(), ".allagents");
25696
25826
  }
25697
25827
  function getMarketplacesDir() {
25698
25828
  return join9(getAllagentsDir(), "plugins", "marketplaces");
@@ -25716,7 +25846,7 @@ async function saveRegistry(registry) {
25716
25846
  const registryPath = getRegistryPath();
25717
25847
  const dir = getAllagentsDir();
25718
25848
  if (!existsSync7(dir)) {
25719
- await mkdir4(dir, { recursive: true });
25849
+ await mkdir5(dir, { recursive: true });
25720
25850
  }
25721
25851
  await writeFile3(registryPath, `${JSON.stringify(registry, null, 2)}
25722
25852
  `);
@@ -25746,7 +25876,7 @@ function parseMarketplaceSource(source) {
25746
25876
  return null;
25747
25877
  }
25748
25878
  if (source.startsWith("/") || source.startsWith(".")) {
25749
- const absPath = resolve6(source);
25879
+ const absPath = resolve7(source);
25750
25880
  const name = basename2(absPath) || "local";
25751
25881
  return {
25752
25882
  type: "local",
@@ -25806,7 +25936,7 @@ async function addMarketplace(source, customName, branch) {
25806
25936
  if (existsSync7(marketplacePath)) {} else {
25807
25937
  const parentDir = getMarketplacesDir();
25808
25938
  if (!existsSync7(parentDir)) {
25809
- await mkdir4(parentDir, { recursive: true });
25939
+ await mkdir5(parentDir, { recursive: true });
25810
25940
  }
25811
25941
  const { owner, repo } = parseLocation(parsed.location);
25812
25942
  const repoUrl = gitHubUrl(owner, repo);
@@ -25894,6 +26024,9 @@ async function removeMarketplace(name) {
25894
26024
  const entry = registry.marketplaces[name];
25895
26025
  delete registry.marketplaces[name];
25896
26026
  await saveRegistry(registry);
26027
+ if (existsSync7(entry.path)) {
26028
+ await rm3(entry.path, { recursive: true, force: true });
26029
+ }
25897
26030
  const { removeUserPluginsForMarketplace: removeUserPluginsForMarketplace2 } = await Promise.resolve().then(() => (init_user_workspace(), exports_user_workspace));
25898
26031
  const removedUserPlugins = await removeUserPluginsForMarketplace2(name);
25899
26032
  return {
@@ -25997,7 +26130,7 @@ async function getMarketplacePluginsFromManifest(marketplacePath) {
25997
26130
  const resolvedSource = resolvePluginSourcePath(plugin.source, marketplacePath);
25998
26131
  const info = {
25999
26132
  name: plugin.name,
26000
- path: typeof plugin.source === "string" ? resolve6(marketplacePath, plugin.source) : resolvedSource,
26133
+ path: typeof plugin.source === "string" ? resolve7(marketplacePath, plugin.source) : resolvedSource,
26001
26134
  description: plugin.description,
26002
26135
  source: resolvedSource
26003
26136
  };
@@ -26082,7 +26215,7 @@ async function resolvePluginSpec(spec, options2 = {}) {
26082
26215
  const pluginEntry = manifestResult.data.plugins.find((p) => p.name === parsed.plugin);
26083
26216
  if (pluginEntry) {
26084
26217
  if (typeof pluginEntry.source === "string") {
26085
- const resolvedPath = resolve6(marketplacePath, pluginEntry.source);
26218
+ const resolvedPath = resolve7(marketplacePath, pluginEntry.source);
26086
26219
  if (existsSync7(resolvedPath)) {
26087
26220
  return {
26088
26221
  path: resolvedPath,
@@ -26137,7 +26270,7 @@ async function refreshMarketplace(marketplace) {
26137
26270
  delete registry.marketplaces[marketplace.name];
26138
26271
  await saveRegistry(registry);
26139
26272
  if (existsSync7(marketplace.path)) {
26140
- await rm2(marketplace.path, { recursive: true, force: true });
26273
+ await rm3(marketplace.path, { recursive: true, force: true });
26141
26274
  }
26142
26275
  return addMarketplace(`${owner}/${repo}`, marketplace.name, branch);
26143
26276
  }
@@ -26243,6 +26376,18 @@ function isPluginSpec(spec) {
26243
26376
  function getWellKnownMarketplaces() {
26244
26377
  return { ...WELL_KNOWN_MARKETPLACES };
26245
26378
  }
26379
+ async function getMarketplaceVersion(marketplacePath) {
26380
+ if (!existsSync7(marketplacePath)) {
26381
+ return null;
26382
+ }
26383
+ try {
26384
+ const git = esm_default(marketplacePath);
26385
+ const log = await git.log({ maxCount: 1, format: { hash: "%h" } });
26386
+ return log.latest?.hash || null;
26387
+ } catch {
26388
+ return null;
26389
+ }
26390
+ }
26246
26391
  var WELL_KNOWN_MARKETPLACES;
26247
26392
  var init_marketplace = __esm(() => {
26248
26393
  init_esm();
@@ -26257,7 +26402,7 @@ var init_marketplace = __esm(() => {
26257
26402
  });
26258
26403
 
26259
26404
  // src/core/workspace-modify.ts
26260
- import { readFile as readFile8, writeFile as writeFile4, mkdir as mkdir5 } from "node:fs/promises";
26405
+ import { readFile as readFile8, writeFile as writeFile4, mkdir as mkdir6 } from "node:fs/promises";
26261
26406
  import { existsSync as existsSync8 } from "node:fs";
26262
26407
  import { join as join10 } from "node:path";
26263
26408
  async function setClients(clients, workspacePath = process.cwd()) {
@@ -26291,7 +26436,7 @@ async function ensureWorkspace(workspacePath) {
26291
26436
  plugins: [],
26292
26437
  clients: [...DEFAULT_PROJECT_CLIENTS]
26293
26438
  };
26294
- await mkdir5(configDir, { recursive: true });
26439
+ await mkdir6(configDir, { recursive: true });
26295
26440
  await writeFile4(configPath, dump(defaultConfig, { lineWidth: -1 }), "utf-8");
26296
26441
  }
26297
26442
  async function addPlugin(plugin, workspacePath = process.cwd()) {
@@ -26711,9 +26856,9 @@ var init_sync_state = __esm(() => {
26711
26856
  });
26712
26857
 
26713
26858
  // src/core/sync-state.ts
26714
- import { readFile as readFile10, writeFile as writeFile6, mkdir as mkdir6 } from "node:fs/promises";
26859
+ import { readFile as readFile10, writeFile as writeFile6, mkdir as mkdir7 } from "node:fs/promises";
26715
26860
  import { existsSync as existsSync10 } from "node:fs";
26716
- import { join as join12, dirname as dirname3 } from "node:path";
26861
+ import { join as join12, dirname as dirname4 } from "node:path";
26717
26862
  function getSyncStatePath(workspacePath) {
26718
26863
  return join12(workspacePath, CONFIG_DIR, SYNC_STATE_FILE);
26719
26864
  }
@@ -26741,7 +26886,7 @@ async function saveSyncState(workspacePath, files) {
26741
26886
  lastSync: new Date().toISOString(),
26742
26887
  files
26743
26888
  };
26744
- await mkdir6(dirname3(statePath), { recursive: true });
26889
+ await mkdir7(dirname4(statePath), { recursive: true });
26745
26890
  await writeFile6(statePath, JSON.stringify(state, null, 2), "utf-8");
26746
26891
  }
26747
26892
  function getPreviouslySyncedFiles(state, client) {
@@ -26756,11 +26901,11 @@ var init_sync_state2 = __esm(() => {
26756
26901
  });
26757
26902
 
26758
26903
  // src/core/vscode-workspace.ts
26759
- import { resolve as resolve7, basename as basename3, isAbsolute as isAbsolute2 } from "node:path";
26904
+ import { resolve as resolve8, basename as basename3, isAbsolute as isAbsolute2 } from "node:path";
26760
26905
  function buildPathPlaceholderMap(repositories, workspacePath) {
26761
26906
  const map2 = new Map;
26762
26907
  for (const repo of repositories) {
26763
- const absolutePath = resolve7(workspacePath, repo.path);
26908
+ const absolutePath = resolve8(workspacePath, repo.path);
26764
26909
  map2.set(repo.path, absolutePath);
26765
26910
  }
26766
26911
  return map2;
@@ -26795,16 +26940,16 @@ function generateVscodeWorkspace(input) {
26795
26940
  const folders = [];
26796
26941
  const seenPaths = new Set;
26797
26942
  folders.push({ path: "." });
26798
- seenPaths.add(resolve7(workspacePath, "."));
26943
+ seenPaths.add(resolve8(workspacePath, "."));
26799
26944
  for (const repo of repositories) {
26800
- const absolutePath = resolve7(workspacePath, repo.path).replace(/\\/g, "/");
26945
+ const absolutePath = resolve8(workspacePath, repo.path).replace(/\\/g, "/");
26801
26946
  folders.push({ path: absolutePath });
26802
26947
  seenPaths.add(absolutePath);
26803
26948
  }
26804
26949
  if (resolvedTemplate && Array.isArray(resolvedTemplate.folders)) {
26805
26950
  for (const folder of resolvedTemplate.folders) {
26806
26951
  const rawPath = folder.path;
26807
- const normalizedPath = (typeof rawPath === "string" && !isAbsolute2(rawPath) ? resolve7(workspacePath, rawPath) : rawPath).replace(/\\/g, "/");
26952
+ const normalizedPath = (typeof rawPath === "string" && !isAbsolute2(rawPath) ? resolve8(workspacePath, rawPath) : rawPath).replace(/\\/g, "/");
26808
26953
  if (!seenPaths.has(normalizedPath)) {
26809
26954
  const entry = { path: normalizedPath };
26810
26955
  if (folder.name)
@@ -26834,10 +26979,10 @@ function getWorkspaceOutputPath(workspacePath, vscodeConfig) {
26834
26979
  const name = vscodeConfig?.output;
26835
26980
  if (name) {
26836
26981
  const filename = name.endsWith(".code-workspace") ? name : `${name}.code-workspace`;
26837
- return resolve7(workspacePath, filename);
26982
+ return resolve8(workspacePath, filename);
26838
26983
  }
26839
- const dirName = basename3(resolve7(workspacePath));
26840
- return resolve7(workspacePath, `${dirName}.code-workspace`);
26984
+ const dirName = basename3(resolve8(workspacePath));
26985
+ return resolve8(workspacePath, `${dirName}.code-workspace`);
26841
26986
  }
26842
26987
  var DEFAULT_SETTINGS;
26843
26988
  var init_vscode_workspace = __esm(() => {
@@ -26847,9 +26992,9 @@ var init_vscode_workspace = __esm(() => {
26847
26992
  });
26848
26993
 
26849
26994
  // src/core/sync.ts
26850
- import { existsSync as existsSync11, readFileSync, writeFileSync } from "node:fs";
26851
- import { rm as rm3, unlink, rmdir, copyFile } from "node:fs/promises";
26852
- import { join as join13, resolve as resolve8, dirname as dirname4, relative } from "node:path";
26995
+ import { existsSync as existsSync11, readFileSync, writeFileSync, lstatSync } from "node:fs";
26996
+ import { rm as rm4, unlink, rmdir, copyFile } from "node:fs/promises";
26997
+ import { join as join13, resolve as resolve9, dirname as dirname5, relative as relative2 } from "node:path";
26853
26998
  function deduplicateClientsByPath(clients, clientMappings = CLIENT_MAPPINGS) {
26854
26999
  const pathToClients = new Map;
26855
27000
  for (const client of clients) {
@@ -26900,8 +27045,11 @@ async function selectivePurgeWorkspace(workspacePath, state, clients, options2)
26900
27045
  continue;
26901
27046
  }
26902
27047
  try {
26903
- if (filePath.endsWith("/")) {
26904
- await rm3(fullPath, { recursive: true, force: true });
27048
+ const stats = lstatSync(fullPath.replace(/\/$/, ""));
27049
+ if (stats.isSymbolicLink()) {
27050
+ await unlink(fullPath.replace(/\/$/, ""));
27051
+ } else if (filePath.endsWith("/")) {
27052
+ await rm4(fullPath, { recursive: true, force: true });
26905
27053
  } else {
26906
27054
  await unlink(fullPath);
26907
27055
  }
@@ -26916,16 +27064,16 @@ async function selectivePurgeWorkspace(workspacePath, state, clients, options2)
26916
27064
  return result;
26917
27065
  }
26918
27066
  async function cleanupEmptyParents(workspacePath, filePath) {
26919
- let parentPath = dirname4(filePath);
27067
+ let parentPath = dirname5(filePath);
26920
27068
  while (parentPath && parentPath !== "." && parentPath !== "/") {
26921
27069
  const fullParentPath = join13(workspacePath, parentPath);
26922
27070
  if (!existsSync11(fullParentPath)) {
26923
- parentPath = dirname4(parentPath);
27071
+ parentPath = dirname5(parentPath);
26924
27072
  continue;
26925
27073
  }
26926
27074
  try {
26927
27075
  await rmdir(fullParentPath);
26928
- parentPath = dirname4(parentPath);
27076
+ parentPath = dirname5(parentPath);
26929
27077
  } catch {
26930
27078
  break;
26931
27079
  }
@@ -27032,11 +27180,11 @@ function validateFileSources(files, defaultSourcePath, githubCache) {
27032
27180
  if (file.source.startsWith("/")) {
27033
27181
  fullPath = file.source;
27034
27182
  } else if (file.source.startsWith("../")) {
27035
- fullPath = resolve8(file.source);
27183
+ fullPath = resolve9(file.source);
27036
27184
  } else if (defaultSourcePath) {
27037
27185
  fullPath = join13(defaultSourcePath, file.source);
27038
27186
  } else {
27039
- fullPath = resolve8(file.source);
27187
+ fullPath = resolve9(file.source);
27040
27188
  }
27041
27189
  if (!existsSync11(fullPath)) {
27042
27190
  errors2.push(`File source not found: ${fullPath}`);
@@ -27065,7 +27213,7 @@ function collectSyncedPaths(copyResults, workspacePath, clients, clientMappings)
27065
27213
  if (copyResult.action !== "copied" && copyResult.action !== "generated") {
27066
27214
  continue;
27067
27215
  }
27068
- const relativePath = relative(workspacePath, copyResult.destination).replace(/\\/g, "/");
27216
+ const relativePath = relative2(workspacePath, copyResult.destination).replace(/\\/g, "/");
27069
27217
  for (const client of clients) {
27070
27218
  const mapping = mappings[client];
27071
27219
  if (mapping.skillsPath && relativePath.startsWith(mapping.skillsPath)) {
@@ -27121,7 +27269,7 @@ async function validatePlugin(pluginSource, workspacePath, offline) {
27121
27269
  success: true
27122
27270
  };
27123
27271
  }
27124
- const resolvedPath = resolve8(workspacePath, pluginSource);
27272
+ const resolvedPath = resolve9(workspacePath, pluginSource);
27125
27273
  if (!existsSync11(resolvedPath)) {
27126
27274
  return {
27127
27275
  plugin: pluginSource,
@@ -27139,13 +27287,55 @@ async function validatePlugin(pluginSource, workspacePath, offline) {
27139
27287
  async function validateAllPlugins(plugins, workspacePath, offline) {
27140
27288
  return Promise.all(plugins.map((plugin) => validatePlugin(plugin, workspacePath, offline)));
27141
27289
  }
27142
- async function copyValidatedPlugin(validatedPlugin, workspacePath, clients, dryRun, skillNameMap, clientMappings) {
27290
+ async function copyValidatedPlugin(validatedPlugin, workspacePath, clients, dryRun, skillNameMap, clientMappings, syncMode = "symlink") {
27143
27291
  const copyResults = [];
27144
27292
  const mappings = clientMappings ?? CLIENT_MAPPINGS;
27145
- const { representativeClients } = deduplicateClientsByPath(clients, mappings);
27146
- for (const client of representativeClients) {
27147
- const results = await copyPluginToWorkspace(validatedPlugin.resolved, workspacePath, client, { dryRun, ...skillNameMap && { skillNameMap }, ...clientMappings && { clientMappings } });
27148
- copyResults.push(...results);
27293
+ const clientList = clients;
27294
+ if (syncMode === "symlink") {
27295
+ const { representativeClients } = deduplicateClientsByPath(clientList, mappings);
27296
+ const canonicalRepresentative = representativeClients.find((c) => mappings[c]?.skillsPath === CANONICAL_SKILLS_PATH);
27297
+ const needsCanonicalCopy = !canonicalRepresentative;
27298
+ const nonUniversalClients = clientList.filter((c) => !isUniversalClient(c));
27299
+ if (needsCanonicalCopy && nonUniversalClients.length > 0) {
27300
+ const canonicalResults = await copyPluginToWorkspace(validatedPlugin.resolved, workspacePath, "copilot", {
27301
+ dryRun,
27302
+ ...skillNameMap && { skillNameMap },
27303
+ syncMode: "copy"
27304
+ });
27305
+ const skillResults = canonicalResults.filter((r) => r.destination.includes(CANONICAL_SKILLS_PATH) && r.action === "copied");
27306
+ copyResults.push(...skillResults);
27307
+ }
27308
+ for (const representative of representativeClients) {
27309
+ if (isUniversalClient(representative)) {
27310
+ const results = await copyPluginToWorkspace(validatedPlugin.resolved, workspacePath, representative, {
27311
+ dryRun,
27312
+ ...skillNameMap && { skillNameMap },
27313
+ ...clientMappings && { clientMappings },
27314
+ syncMode: "copy"
27315
+ });
27316
+ copyResults.push(...results);
27317
+ } else {
27318
+ const results = await copyPluginToWorkspace(validatedPlugin.resolved, workspacePath, representative, {
27319
+ dryRun,
27320
+ ...skillNameMap && { skillNameMap },
27321
+ ...clientMappings && { clientMappings },
27322
+ syncMode: "symlink",
27323
+ canonicalSkillsPath: CANONICAL_SKILLS_PATH
27324
+ });
27325
+ copyResults.push(...results);
27326
+ }
27327
+ }
27328
+ } else {
27329
+ const { representativeClients } = deduplicateClientsByPath(clientList, mappings);
27330
+ for (const client of representativeClients) {
27331
+ const results = await copyPluginToWorkspace(validatedPlugin.resolved, workspacePath, client, {
27332
+ dryRun,
27333
+ ...skillNameMap && { skillNameMap },
27334
+ ...clientMappings && { clientMappings },
27335
+ syncMode: "copy"
27336
+ });
27337
+ copyResults.push(...results);
27338
+ }
27149
27339
  }
27150
27340
  const hasFailures = copyResults.some((r) => r.action === "failed");
27151
27341
  return {
@@ -27309,9 +27499,10 @@ ${failedValidations.map((v) => ` - ${v.plugin}: ${v.error}`).join(`
27309
27499
  }
27310
27500
  const allSkills = await collectAllSkills(validPlugins);
27311
27501
  const pluginSkillMaps = buildPluginSkillNameMaps(allSkills);
27502
+ const syncMode = config.syncMode ?? "symlink";
27312
27503
  const pluginResults = await Promise.all(validPlugins.map((validatedPlugin) => {
27313
27504
  const skillNameMap = pluginSkillMaps.get(validatedPlugin.resolved);
27314
- return copyValidatedPlugin(validatedPlugin, workspacePath, clients, dryRun, skillNameMap);
27505
+ return copyValidatedPlugin(validatedPlugin, workspacePath, clients, dryRun, skillNameMap, undefined, syncMode);
27315
27506
  }));
27316
27507
  let workspaceFileResults = [];
27317
27508
  if (config.workspace) {
@@ -27437,7 +27628,7 @@ ${fileValidationErrors.map((e) => ` - ${e}`).join(`
27437
27628
  };
27438
27629
  }
27439
27630
  async function syncUserWorkspace(options2 = {}) {
27440
- const homeDir = resolve8(getHomeDir());
27631
+ const homeDir = resolve9(getHomeDir());
27441
27632
  const config = await getUserWorkspaceConfig();
27442
27633
  if (!config) {
27443
27634
  return {
@@ -27475,9 +27666,10 @@ ${failedValidations.map((v) => ` - ${v.plugin}: ${v.error}`).join(`
27475
27666
  }
27476
27667
  const allSkills = await collectAllSkills(validPlugins);
27477
27668
  const pluginSkillMaps = buildPluginSkillNameMaps(allSkills);
27669
+ const syncMode = config.syncMode ?? "symlink";
27478
27670
  const pluginResults = await Promise.all(validPlugins.map((vp) => {
27479
27671
  const skillNameMap = pluginSkillMaps.get(vp.resolved);
27480
- return copyValidatedPlugin(vp, homeDir, clients, dryRun, skillNameMap, USER_CLIENT_MAPPINGS);
27672
+ return copyValidatedPlugin(vp, homeDir, clients, dryRun, skillNameMap, USER_CLIENT_MAPPINGS, syncMode);
27481
27673
  }));
27482
27674
  let totalCopied = 0;
27483
27675
  let totalFailed = 0;
@@ -27631,12 +27823,12 @@ var init_github_fetch = __esm(() => {
27631
27823
  });
27632
27824
 
27633
27825
  // src/core/workspace.ts
27634
- import { mkdir as mkdir7, readFile as readFile11, writeFile as writeFile7, copyFile as copyFile2 } from "node:fs/promises";
27826
+ import { mkdir as mkdir8, readFile as readFile11, writeFile as writeFile7, copyFile as copyFile2 } from "node:fs/promises";
27635
27827
  import { existsSync as existsSync13 } from "node:fs";
27636
- import { join as join15, resolve as resolve9, dirname as dirname5, relative as relative2, sep as sep2, isAbsolute as isAbsolute3 } from "node:path";
27828
+ import { join as join15, resolve as resolve10, dirname as dirname6, relative as relative3, sep as sep2, isAbsolute as isAbsolute3 } from "node:path";
27637
27829
  import { fileURLToPath } from "node:url";
27638
27830
  async function initWorkspace(targetPath = ".", options2 = {}) {
27639
- const absoluteTarget = resolve9(targetPath);
27831
+ const absoluteTarget = resolve10(targetPath);
27640
27832
  const configDir = join15(absoluteTarget, CONFIG_DIR);
27641
27833
  const configPath = join15(configDir, WORKSPACE_CONFIG_FILE);
27642
27834
  if (existsSync13(configPath)) {
@@ -27644,13 +27836,13 @@ async function initWorkspace(targetPath = ".", options2 = {}) {
27644
27836
  Found existing ${CONFIG_DIR}/${WORKSPACE_CONFIG_FILE}`);
27645
27837
  }
27646
27838
  const currentFilePath = fileURLToPath(import.meta.url);
27647
- const currentFileDir = dirname5(currentFilePath);
27839
+ const currentFileDir = dirname6(currentFilePath);
27648
27840
  const isProduction = currentFilePath.includes(`${sep2}dist${sep2}`);
27649
27841
  const defaultTemplatePath = isProduction ? join15(currentFileDir, "templates", "default") : join15(currentFileDir, "..", "templates", "default");
27650
27842
  let githubTempDir;
27651
27843
  try {
27652
- await mkdir7(absoluteTarget, { recursive: true });
27653
- await mkdir7(configDir, { recursive: true });
27844
+ await mkdir8(absoluteTarget, { recursive: true });
27845
+ await mkdir8(configDir, { recursive: true });
27654
27846
  let workspaceYamlContent;
27655
27847
  let sourceDir;
27656
27848
  if (options2.from) {
@@ -27682,7 +27874,7 @@ async function initWorkspace(targetPath = ".", options2 = {}) {
27682
27874
  }
27683
27875
  console.log(`✓ Using workspace.yaml from: ${options2.from}`);
27684
27876
  } else {
27685
- const fromPath = resolve9(options2.from);
27877
+ const fromPath = resolve10(options2.from);
27686
27878
  if (!existsSync13(fromPath)) {
27687
27879
  throw new Error(`Template not found: ${fromPath}`);
27688
27880
  }
@@ -27704,9 +27896,9 @@ async function initWorkspace(targetPath = ".", options2 = {}) {
27704
27896
  }
27705
27897
  } else {
27706
27898
  sourceYamlPath = fromPath;
27707
- const parentDir = dirname5(fromPath);
27899
+ const parentDir = dirname6(fromPath);
27708
27900
  if (parentDir.endsWith(CONFIG_DIR)) {
27709
- sourceDir = dirname5(parentDir);
27901
+ sourceDir = dirname6(parentDir);
27710
27902
  } else {
27711
27903
  sourceDir = parentDir;
27712
27904
  }
@@ -27718,7 +27910,7 @@ async function initWorkspace(targetPath = ".", options2 = {}) {
27718
27910
  if (workspace?.source) {
27719
27911
  const source = workspace.source;
27720
27912
  if (!isGitHubUrl(source) && !isAbsolute3(source)) {
27721
- workspace.source = resolve9(sourceDir, source);
27913
+ workspace.source = resolve10(sourceDir, source);
27722
27914
  workspaceYamlContent = dump(parsed2, { lineWidth: -1 });
27723
27915
  }
27724
27916
  }
@@ -27834,7 +28026,7 @@ Syncing plugins...`);
27834
28026
  if (targetPath !== ".") {
27835
28027
  console.log(`
27836
28028
  Next steps:`);
27837
- console.log(` cd ${relative2(process.cwd(), absoluteTarget)}`);
28029
+ console.log(` cd ${relative3(process.cwd(), absoluteTarget)}`);
27838
28030
  }
27839
28031
  return {
27840
28032
  path: absoluteTarget,
@@ -28045,12 +28237,12 @@ var require_isexe = __commonJS((exports, module) => {
28045
28237
  if (typeof Promise !== "function") {
28046
28238
  throw new TypeError("callback not provided");
28047
28239
  }
28048
- return new Promise(function(resolve11, reject) {
28240
+ return new Promise(function(resolve12, reject) {
28049
28241
  isexe(path, options2 || {}, function(er, is) {
28050
28242
  if (er) {
28051
28243
  reject(er);
28052
28244
  } else {
28053
- resolve11(is);
28245
+ resolve12(is);
28054
28246
  }
28055
28247
  });
28056
28248
  });
@@ -28112,27 +28304,27 @@ var require_which = __commonJS((exports, module) => {
28112
28304
  opt = {};
28113
28305
  const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
28114
28306
  const found = [];
28115
- const step = (i2) => new Promise((resolve11, reject) => {
28307
+ const step = (i2) => new Promise((resolve12, reject) => {
28116
28308
  if (i2 === pathEnv.length)
28117
- return opt.all && found.length ? resolve11(found) : reject(getNotFoundError(cmd));
28309
+ return opt.all && found.length ? resolve12(found) : reject(getNotFoundError(cmd));
28118
28310
  const ppRaw = pathEnv[i2];
28119
28311
  const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
28120
28312
  const pCmd = path.join(pathPart, cmd);
28121
28313
  const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
28122
- resolve11(subStep(p, i2, 0));
28314
+ resolve12(subStep(p, i2, 0));
28123
28315
  });
28124
- const subStep = (p, i2, ii) => new Promise((resolve11, reject) => {
28316
+ const subStep = (p, i2, ii) => new Promise((resolve12, reject) => {
28125
28317
  if (ii === pathExt.length)
28126
- return resolve11(step(i2 + 1));
28318
+ return resolve12(step(i2 + 1));
28127
28319
  const ext = pathExt[ii];
28128
28320
  isexe(p + ext, { pathExt: pathExtExe }, (er, is) => {
28129
28321
  if (!er && is) {
28130
28322
  if (opt.all)
28131
28323
  found.push(p + ext);
28132
28324
  else
28133
- return resolve11(p + ext);
28325
+ return resolve12(p + ext);
28134
28326
  }
28135
- return resolve11(subStep(p, i2, ii + 1));
28327
+ return resolve12(subStep(p, i2, ii + 1));
28136
28328
  });
28137
28329
  });
28138
28330
  return cb ? step(0).then((res) => cb(null, res), cb) : step(0);
@@ -28173,8 +28365,8 @@ var require_which = __commonJS((exports, module) => {
28173
28365
  var require_path_key = __commonJS((exports, module) => {
28174
28366
  var pathKey = (options2 = {}) => {
28175
28367
  const environment = options2.env || process.env;
28176
- const platform = options2.platform || process.platform;
28177
- if (platform !== "win32") {
28368
+ const platform2 = options2.platform || process.platform;
28369
+ if (platform2 !== "win32") {
28178
28370
  return "PATH";
28179
28371
  }
28180
28372
  return Object.keys(environment).reverse().find((key) => key.toUpperCase() === "PATH") || "Path";
@@ -28431,9 +28623,9 @@ function stripFinalNewline(input) {
28431
28623
  function pathKey(options2 = {}) {
28432
28624
  const {
28433
28625
  env: env2 = process.env,
28434
- platform = process.platform
28626
+ platform: platform2 = process.platform
28435
28627
  } = options2;
28436
- if (platform !== "win32") {
28628
+ if (platform2 !== "win32") {
28437
28629
  return "PATH";
28438
28630
  }
28439
28631
  return Object.keys(env2).reverse().find((key) => key.toUpperCase() === "PATH") || "Path";
@@ -29265,7 +29457,7 @@ var DEFAULT_FORCE_KILL_TIMEOUT, spawnedKill = (kill, signal = "SIGTERM", options
29265
29457
  return spawnedPromise;
29266
29458
  }
29267
29459
  let timeoutId;
29268
- const timeoutPromise = new Promise((resolve11, reject) => {
29460
+ const timeoutPromise = new Promise((resolve12, reject) => {
29269
29461
  timeoutId = setTimeout(() => {
29270
29462
  timeoutKill(spawned, killSignal, reject);
29271
29463
  }, timeout);
@@ -29655,9 +29847,9 @@ var nativePromisePrototype, descriptors, mergePromise = (spawned, promise) => {
29655
29847
  const value = typeof promise === "function" ? (...args) => Reflect.apply(descriptor.value, promise(), args) : descriptor.value.bind(promise);
29656
29848
  Reflect.defineProperty(spawned, property, { ...descriptor, value });
29657
29849
  }
29658
- }, getSpawnedPromise = (spawned) => new Promise((resolve11, reject) => {
29850
+ }, getSpawnedPromise = (spawned) => new Promise((resolve12, reject) => {
29659
29851
  spawned.on("exit", (exitCode, signal) => {
29660
- resolve11({ exitCode, signal });
29852
+ resolve12({ exitCode, signal });
29661
29853
  });
29662
29854
  spawned.on("error", (error) => {
29663
29855
  reject(error);
@@ -29973,7 +30165,7 @@ var package_default;
29973
30165
  var init_package = __esm(() => {
29974
30166
  package_default = {
29975
30167
  name: "allagents",
29976
- version: "0.17.2",
30168
+ version: "0.19.1",
29977
30169
  description: "CLI tool for managing multi-repo AI agent workspaces with plugin synchronization",
29978
30170
  type: "module",
29979
30171
  bin: {
@@ -32563,7 +32755,7 @@ __export(exports_wizard, {
32563
32755
  runWizard: () => runWizard,
32564
32756
  buildMenuOptions: () => buildMenuOptions
32565
32757
  });
32566
- import { relative as relative3 } from "node:path";
32758
+ import { relative as relative4 } from "node:path";
32567
32759
  function buildMenuOptions(context) {
32568
32760
  const options2 = [];
32569
32761
  if (!context.hasWorkspace) {
@@ -32598,7 +32790,7 @@ function buildMenuOptions(context) {
32598
32790
  function buildSummary(context) {
32599
32791
  const lines = [];
32600
32792
  if (context.hasWorkspace && context.workspacePath) {
32601
- const relPath = relative3(process.cwd(), context.workspacePath) || ".";
32793
+ const relPath = relative4(process.cwd(), context.workspacePath) || ".";
32602
32794
  lines.push(`Workspace: ${relPath}`);
32603
32795
  lines.push(`Project plugins: ${context.projectPluginCount}`);
32604
32796
  } else {
@@ -32737,7 +32929,7 @@ init_sync();
32737
32929
  init_status2();
32738
32930
  var import_cmd_ts2 = __toESM(require_cjs(), 1);
32739
32931
  import { existsSync as existsSync16 } from "node:fs";
32740
- import { join as join18, resolve as resolve10 } from "node:path";
32932
+ import { join as join18, resolve as resolve11 } from "node:path";
32741
32933
 
32742
32934
  // src/core/prune.ts
32743
32935
  init_js_yaml();
@@ -33304,7 +33496,7 @@ var repoAddCmd = import_cmd_ts2.command({
33304
33496
  },
33305
33497
  handler: async ({ path: repoPath, description }) => {
33306
33498
  try {
33307
- const resolvedPath = resolve10(process.cwd(), repoPath);
33499
+ const resolvedPath = resolve11(process.cwd(), repoPath);
33308
33500
  const remote = await detectRemote(resolvedPath);
33309
33501
  const result = await addRepository(repoPath, {
33310
33502
  source: remote?.source,
@@ -33877,14 +34069,13 @@ var marketplaceRemoveCmd = import_cmd_ts3.command({
33877
34069
  });
33878
34070
  return;
33879
34071
  }
33880
- console.log(`✓ Marketplace '${name}' removed from registry`);
34072
+ console.log(`✓ Marketplace '${name}' removed`);
33881
34073
  if (result.removedUserPlugins && result.removedUserPlugins.length > 0) {
33882
34074
  console.log(` Removed ${result.removedUserPlugins.length} user plugin(s):`);
33883
34075
  for (const p of result.removedUserPlugins) {
33884
34076
  console.log(` - ${p}`);
33885
34077
  }
33886
34078
  }
33887
- console.log(` Note: Files at ${result.marketplace?.path} were not deleted`);
33888
34079
  } catch (error) {
33889
34080
  if (error instanceof Error) {
33890
34081
  if (isJsonMode()) {
@@ -34001,13 +34192,36 @@ var pluginListCmd = import_cmd_ts3.command({
34001
34192
  console.error(`Marketplace '${marketplace}' not found`);
34002
34193
  process.exit(1);
34003
34194
  }
34195
+ const userPlugins = await getInstalledUserPlugins();
34196
+ const projectPlugins = await getInstalledProjectPlugins(process.cwd());
34197
+ const installedMap = new Map;
34198
+ for (const p of userPlugins) {
34199
+ installedMap.set(`${p.name}@${p.marketplace}`, p);
34200
+ }
34201
+ for (const p of projectPlugins) {
34202
+ installedMap.set(`${p.name}@${p.marketplace}`, p);
34203
+ }
34204
+ const versionMap = new Map;
34205
+ for (const mp of toList) {
34206
+ const version = await getMarketplaceVersion(mp.path);
34207
+ versionMap.set(mp.name, version);
34208
+ }
34004
34209
  if (isJsonMode()) {
34005
34210
  const allPlugins = [];
34006
34211
  const allWarnings = [];
34007
34212
  for (const mp of toList) {
34008
34213
  const result = await listMarketplacePlugins(mp.name);
34214
+ const version = versionMap.get(mp.name) ?? null;
34009
34215
  for (const plugin of result.plugins) {
34010
- allPlugins.push({ name: plugin.name, marketplace: mp.name });
34216
+ const key = `${plugin.name}@${mp.name}`;
34217
+ const installed = installedMap.get(key);
34218
+ allPlugins.push({
34219
+ name: plugin.name,
34220
+ marketplace: mp.name,
34221
+ version,
34222
+ scope: installed?.scope ?? null,
34223
+ enabled: !!installed
34224
+ });
34011
34225
  }
34012
34226
  for (const warning of result.warnings) {
34013
34227
  allWarnings.push(`${mp.name}: ${warning}`);
@@ -34025,29 +34239,52 @@ var pluginListCmd = import_cmd_ts3.command({
34025
34239
  return;
34026
34240
  }
34027
34241
  let totalPlugins = 0;
34242
+ const allPluginEntries = [];
34028
34243
  for (const mp of toList) {
34029
34244
  const result = await listMarketplacePlugins(mp.name);
34030
- if (result.plugins.length === 0 && result.warnings.length === 0) {
34031
- console.log(`${mp.name}: (no plugins found)`);
34032
- continue;
34033
- }
34034
- console.log(`${mp.name}:`);
34245
+ const version = versionMap.get(mp.name) ?? null;
34035
34246
  for (const warning of result.warnings) {
34036
- console.log(` Warning: ${warning}`);
34037
- }
34038
- if (result.plugins.length === 0) {
34039
- console.log(" (no plugins found)");
34247
+ allPluginEntries.push({
34248
+ name: "",
34249
+ marketplace: mp.name,
34250
+ version,
34251
+ installed: undefined,
34252
+ warning
34253
+ });
34040
34254
  }
34041
34255
  for (const plugin of result.plugins) {
34042
- console.log(` - ${plugin.name}@${mp.name}`);
34256
+ const key = `${plugin.name}@${mp.name}`;
34257
+ const installed = installedMap.get(key);
34258
+ allPluginEntries.push({
34259
+ name: plugin.name,
34260
+ marketplace: mp.name,
34261
+ version,
34262
+ installed
34263
+ });
34043
34264
  totalPlugins++;
34044
34265
  }
34045
- console.log();
34046
34266
  }
34047
34267
  if (totalPlugins === 0) {
34048
34268
  console.log("No plugins found in registered marketplaces.");
34049
- } else {
34050
- console.log(`Total: ${totalPlugins} plugin(s)`);
34269
+ return;
34270
+ }
34271
+ console.log(`Installed plugins:
34272
+ `);
34273
+ for (const entry of allPluginEntries) {
34274
+ if (entry.warning) {
34275
+ console.log(` Warning: ${entry.warning}`);
34276
+ continue;
34277
+ }
34278
+ const isEnabled = !!entry.installed;
34279
+ const statusIcon = isEnabled ? "✓" : "✗";
34280
+ const statusText = isEnabled ? "enabled" : "disabled";
34281
+ console.log(` ❯ ${entry.name}@${entry.marketplace}`);
34282
+ console.log(` Version: ${entry.version ?? "unknown"}`);
34283
+ if (entry.installed) {
34284
+ console.log(` Scope: ${entry.installed.scope}`);
34285
+ }
34286
+ console.log(` Status: ${statusIcon} ${statusText}`);
34287
+ console.log();
34051
34288
  }
34052
34289
  } catch (error) {
34053
34290
  if (error instanceof Error) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "allagents",
3
- "version": "0.17.2",
3
+ "version": "0.19.1",
4
4
  "description": "CLI tool for managing multi-repo AI agent workspaces with plugin synchronization",
5
5
  "type": "module",
6
6
  "bin": {