allagents 0.23.0 → 0.24.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 +166 -92
  2. package/package.json +3 -2
package/dist/index.js CHANGED
@@ -11453,7 +11453,13 @@ var init_zod = __esm(() => {
11453
11453
  });
11454
11454
 
11455
11455
  // src/models/workspace-config.ts
11456
- var RepositorySchema, WorkspaceFileSchema, WorkspaceSchema, PluginSourceSchema, ClientTypeSchema, VscodeConfigSchema, SyncModeSchema, WorkspaceConfigSchema;
11456
+ function getPluginSource(plugin) {
11457
+ return typeof plugin === "string" ? plugin : plugin.source;
11458
+ }
11459
+ function getPluginClients(plugin) {
11460
+ return typeof plugin === "string" ? undefined : plugin.clients;
11461
+ }
11462
+ var RepositorySchema, WorkspaceFileSchema, WorkspaceSchema, PluginSourceSchema, ClientTypeSchema, PluginEntrySchema, VscodeConfigSchema, SyncModeSchema, WorkspaceConfigSchema;
11457
11463
  var init_workspace_config = __esm(() => {
11458
11464
  init_zod();
11459
11465
  RepositorySchema = exports_external.object({
@@ -11497,7 +11503,15 @@ var init_workspace_config = __esm(() => {
11497
11503
  "openhands",
11498
11504
  "kiro",
11499
11505
  "replit",
11500
- "kimi"
11506
+ "kimi",
11507
+ "universal"
11508
+ ]);
11509
+ PluginEntrySchema = exports_external.union([
11510
+ PluginSourceSchema,
11511
+ exports_external.object({
11512
+ source: PluginSourceSchema,
11513
+ clients: exports_external.array(ClientTypeSchema).optional()
11514
+ })
11501
11515
  ]);
11502
11516
  VscodeConfigSchema = exports_external.object({
11503
11517
  output: exports_external.string().optional()
@@ -11506,7 +11520,7 @@ var init_workspace_config = __esm(() => {
11506
11520
  WorkspaceConfigSchema = exports_external.object({
11507
11521
  workspace: WorkspaceSchema.optional(),
11508
11522
  repositories: exports_external.array(RepositorySchema),
11509
- plugins: exports_external.array(PluginSourceSchema),
11523
+ plugins: exports_external.array(PluginEntrySchema),
11510
11524
  clients: exports_external.array(ClientTypeSchema),
11511
11525
  vscode: VscodeConfigSchema.optional(),
11512
11526
  syncMode: SyncModeSchema.optional(),
@@ -21386,7 +21400,7 @@ var init_glob_patterns = __esm(() => {
21386
21400
 
21387
21401
  // src/models/client-mapping.ts
21388
21402
  function isUniversalClient(client) {
21389
- return CLIENT_MAPPINGS[client].skillsPath === CANONICAL_SKILLS_PATH;
21403
+ return client === "universal";
21390
21404
  }
21391
21405
  var CLIENT_MAPPINGS, CANONICAL_SKILLS_PATH = ".agents/skills/", USER_CLIENT_MAPPINGS;
21392
21406
  var init_client_mapping = __esm(() => {
@@ -21400,12 +21414,12 @@ var init_client_mapping = __esm(() => {
21400
21414
  hooksPath: ".claude/hooks/"
21401
21415
  },
21402
21416
  copilot: {
21403
- skillsPath: ".agents/skills/",
21417
+ skillsPath: ".github/skills/",
21404
21418
  agentFile: "AGENTS.md",
21405
21419
  githubPath: ".github/"
21406
21420
  },
21407
21421
  codex: {
21408
- skillsPath: ".agents/skills/",
21422
+ skillsPath: ".codex/skills/",
21409
21423
  agentFile: "AGENTS.md"
21410
21424
  },
21411
21425
  cursor: {
@@ -21414,11 +21428,11 @@ var init_client_mapping = __esm(() => {
21414
21428
  },
21415
21429
  opencode: {
21416
21430
  commandsPath: ".opencode/commands/",
21417
- skillsPath: ".agents/skills/",
21431
+ skillsPath: ".opencode/skills/",
21418
21432
  agentFile: "AGENTS.md"
21419
21433
  },
21420
21434
  gemini: {
21421
- skillsPath: ".agents/skills/",
21435
+ skillsPath: ".gemini/skills/",
21422
21436
  agentFile: "GEMINI.md",
21423
21437
  agentFileFallback: "AGENTS.md"
21424
21438
  },
@@ -21428,11 +21442,11 @@ var init_client_mapping = __esm(() => {
21428
21442
  hooksPath: ".factory/hooks/"
21429
21443
  },
21430
21444
  ampcode: {
21431
- skillsPath: ".agents/skills/",
21445
+ skillsPath: ".ampcode/skills/",
21432
21446
  agentFile: "AGENTS.md"
21433
21447
  },
21434
21448
  vscode: {
21435
- skillsPath: ".agents/skills/",
21449
+ skillsPath: ".github/skills/",
21436
21450
  agentFile: "AGENTS.md",
21437
21451
  githubPath: ".github/"
21438
21452
  },
@@ -21485,10 +21499,14 @@ var init_client_mapping = __esm(() => {
21485
21499
  agentFile: "AGENTS.md"
21486
21500
  },
21487
21501
  replit: {
21488
- skillsPath: ".agents/skills/",
21502
+ skillsPath: ".replit/skills/",
21489
21503
  agentFile: "AGENTS.md"
21490
21504
  },
21491
21505
  kimi: {
21506
+ skillsPath: ".kimi/skills/",
21507
+ agentFile: "AGENTS.md"
21508
+ },
21509
+ universal: {
21492
21510
  skillsPath: ".agents/skills/",
21493
21511
  agentFile: "AGENTS.md"
21494
21512
  }
@@ -21503,12 +21521,12 @@ var init_client_mapping = __esm(() => {
21503
21521
  hooksPath: ".claude/hooks/"
21504
21522
  },
21505
21523
  copilot: {
21506
- skillsPath: ".agents/skills/",
21524
+ skillsPath: ".copilot/skills/",
21507
21525
  agentFile: "AGENTS.md",
21508
21526
  githubPath: ".copilot/"
21509
21527
  },
21510
21528
  codex: {
21511
- skillsPath: ".agents/skills/",
21529
+ skillsPath: ".codex/skills/",
21512
21530
  agentFile: "AGENTS.md"
21513
21531
  },
21514
21532
  cursor: {
@@ -21517,11 +21535,11 @@ var init_client_mapping = __esm(() => {
21517
21535
  },
21518
21536
  opencode: {
21519
21537
  commandsPath: ".opencode/commands/",
21520
- skillsPath: ".agents/skills/",
21538
+ skillsPath: ".opencode/skills/",
21521
21539
  agentFile: "AGENTS.md"
21522
21540
  },
21523
21541
  gemini: {
21524
- skillsPath: ".agents/skills/",
21542
+ skillsPath: ".gemini/skills/",
21525
21543
  agentFile: "GEMINI.md",
21526
21544
  agentFileFallback: "AGENTS.md"
21527
21545
  },
@@ -21531,11 +21549,11 @@ var init_client_mapping = __esm(() => {
21531
21549
  hooksPath: ".factory/hooks/"
21532
21550
  },
21533
21551
  ampcode: {
21534
- skillsPath: ".agents/skills/",
21552
+ skillsPath: ".ampcode/skills/",
21535
21553
  agentFile: "AGENTS.md"
21536
21554
  },
21537
21555
  vscode: {
21538
- skillsPath: ".agents/skills/",
21556
+ skillsPath: ".copilot/skills/",
21539
21557
  agentFile: "AGENTS.md",
21540
21558
  githubPath: ".copilot/"
21541
21559
  },
@@ -21588,10 +21606,14 @@ var init_client_mapping = __esm(() => {
21588
21606
  agentFile: "AGENTS.md"
21589
21607
  },
21590
21608
  replit: {
21591
- skillsPath: ".agents/skills/",
21609
+ skillsPath: ".replit/skills/",
21592
21610
  agentFile: "AGENTS.md"
21593
21611
  },
21594
21612
  kimi: {
21613
+ skillsPath: ".kimi/skills/",
21614
+ agentFile: "AGENTS.md"
21615
+ },
21616
+ universal: {
21595
21617
  skillsPath: ".agents/skills/",
21596
21618
  agentFile: "AGENTS.md"
21597
21619
  }
@@ -26059,9 +26081,12 @@ async function hasUserPlugin(plugin) {
26059
26081
  const config = await getUserWorkspaceConfig();
26060
26082
  if (!config)
26061
26083
  return false;
26062
- if (config.plugins.indexOf(plugin) !== -1)
26084
+ if (config.plugins.some((entry) => getPluginSource(entry) === plugin))
26063
26085
  return true;
26064
- return config.plugins.some((p) => p.startsWith(`${plugin}@`) || p === plugin);
26086
+ return config.plugins.some((entry) => {
26087
+ const source = getPluginSource(entry);
26088
+ return source.startsWith(`${plugin}@`) || source === plugin;
26089
+ });
26065
26090
  }
26066
26091
  async function removeUserPlugin(plugin) {
26067
26092
  await ensureUserWorkspace();
@@ -26069,9 +26094,12 @@ async function removeUserPlugin(plugin) {
26069
26094
  try {
26070
26095
  const content = await readFile6(configPath, "utf-8");
26071
26096
  const config = load(content);
26072
- let index = config.plugins.indexOf(plugin);
26097
+ let index = config.plugins.findIndex((entry) => getPluginSource(entry) === plugin);
26073
26098
  if (index === -1) {
26074
- index = config.plugins.findIndex((p) => p.startsWith(`${plugin}@`) || p === plugin);
26099
+ index = config.plugins.findIndex((entry) => {
26100
+ const source = getPluginSource(entry);
26101
+ return source.startsWith(`${plugin}@`) || source === plugin;
26102
+ });
26075
26103
  }
26076
26104
  if (index === -1) {
26077
26105
  const identity = await resolveGitHubIdentity(plugin);
@@ -26080,7 +26108,7 @@ async function removeUserPlugin(plugin) {
26080
26108
  const p = config.plugins[i2];
26081
26109
  if (!p)
26082
26110
  continue;
26083
- const existing = await resolveGitHubIdentity(p);
26111
+ const existing = await resolveGitHubIdentity(getPluginSource(p));
26084
26112
  if (existing === identity) {
26085
26113
  index = i2;
26086
26114
  break;
@@ -26094,7 +26122,7 @@ async function removeUserPlugin(plugin) {
26094
26122
  error: `Plugin not found in user config: ${plugin}`
26095
26123
  };
26096
26124
  }
26097
- const removedEntry = config.plugins[index];
26125
+ const removedEntry = getPluginSource(config.plugins[index]);
26098
26126
  config.plugins.splice(index, 1);
26099
26127
  pruneDisabledSkillsForPlugin(config, removedEntry);
26100
26128
  await writeFile2(configPath, dump(config, { lineWidth: -1 }), "utf-8");
@@ -26110,8 +26138,8 @@ async function getUserPluginsForMarketplace(marketplaceName) {
26110
26138
  const config = await getUserWorkspaceConfig();
26111
26139
  if (!config)
26112
26140
  return [];
26113
- return config.plugins.filter((p) => {
26114
- const parsed = parsePluginSpec(p);
26141
+ return config.plugins.map((entry) => getPluginSource(entry)).filter((source) => {
26142
+ const parsed = parsePluginSpec(source);
26115
26143
  return parsed?.marketplaceName === marketplaceName;
26116
26144
  });
26117
26145
  }
@@ -26119,16 +26147,16 @@ async function removeUserPluginsForMarketplace(marketplaceName) {
26119
26147
  const config = await getUserWorkspaceConfig();
26120
26148
  if (!config)
26121
26149
  return [];
26122
- const matching = config.plugins.filter((p) => {
26123
- const parsed = parsePluginSpec(p);
26150
+ const matching = config.plugins.filter((entry) => {
26151
+ const parsed = parsePluginSpec(getPluginSource(entry));
26124
26152
  return parsed?.marketplaceName === marketplaceName;
26125
26153
  });
26126
26154
  if (matching.length === 0)
26127
26155
  return [];
26128
26156
  const configPath = getUserWorkspaceConfigPath();
26129
- config.plugins = config.plugins.filter((p) => !matching.includes(p));
26157
+ config.plugins = config.plugins.filter((entry) => !matching.includes(entry));
26130
26158
  await writeFile2(configPath, dump(config, { lineWidth: -1 }), "utf-8");
26131
- return matching;
26159
+ return matching.map((entry) => getPluginSource(entry));
26132
26160
  }
26133
26161
  async function resolveGitHubIdentity(pluginSource) {
26134
26162
  if (isGitHubUrl(pluginSource)) {
@@ -26157,7 +26185,7 @@ async function addPluginToUserConfig(plugin, configPath, autoRegistered) {
26157
26185
  try {
26158
26186
  const content = await readFile6(configPath, "utf-8");
26159
26187
  const config = load(content);
26160
- if (config.plugins.includes(plugin)) {
26188
+ if (config.plugins.some((entry) => getPluginSource(entry) === plugin)) {
26161
26189
  return {
26162
26190
  success: false,
26163
26191
  error: `Plugin already exists in user config: ${plugin}`
@@ -26166,11 +26194,12 @@ async function addPluginToUserConfig(plugin, configPath, autoRegistered) {
26166
26194
  const newIdentity = await resolveGitHubIdentity(plugin);
26167
26195
  if (newIdentity) {
26168
26196
  for (const existing of config.plugins) {
26169
- const existingIdentity = await resolveGitHubIdentity(existing);
26197
+ const existingSource = getPluginSource(existing);
26198
+ const existingIdentity = await resolveGitHubIdentity(existingSource);
26170
26199
  if (existingIdentity === newIdentity) {
26171
26200
  return {
26172
26201
  success: false,
26173
- error: `Plugin duplicates existing entry '${existing}': both resolve to ${newIdentity}`
26202
+ error: `Plugin duplicates existing entry '${existingSource}': both resolve to ${newIdentity}`
26174
26203
  };
26175
26204
  }
26176
26205
  }
@@ -26263,7 +26292,8 @@ async function getInstalledUserPlugins() {
26263
26292
  if (!config)
26264
26293
  return [];
26265
26294
  const result = [];
26266
- for (const plugin of config.plugins) {
26295
+ for (const pluginEntry of config.plugins) {
26296
+ const plugin = getPluginSource(pluginEntry);
26267
26297
  const parsed = parsePluginSpec(plugin);
26268
26298
  if (parsed) {
26269
26299
  result.push({
@@ -26286,7 +26316,8 @@ async function getInstalledProjectPlugins(workspacePath) {
26286
26316
  if (!config?.plugins)
26287
26317
  return [];
26288
26318
  const result = [];
26289
- for (const plugin of config.plugins) {
26319
+ for (const pluginEntry of config.plugins) {
26320
+ const plugin = getPluginSource(pluginEntry);
26290
26321
  const parsed = parsePluginSpec(plugin);
26291
26322
  if (parsed) {
26292
26323
  result.push({
@@ -26306,6 +26337,7 @@ var DEFAULT_USER_CLIENTS;
26306
26337
  var init_user_workspace = __esm(() => {
26307
26338
  init_js_yaml();
26308
26339
  init_constants();
26340
+ init_workspace_config();
26309
26341
  init_marketplace_manifest_parser();
26310
26342
  init_plugin_path();
26311
26343
  init_marketplace();
@@ -27015,7 +27047,7 @@ async function addPluginToConfig(plugin, configPath, autoRegistered) {
27015
27047
  try {
27016
27048
  const content = await readFile8(configPath, "utf-8");
27017
27049
  const config = load(content);
27018
- if (config.plugins.includes(plugin)) {
27050
+ if (config.plugins.some((entry) => getPluginSource(entry) === plugin)) {
27019
27051
  return {
27020
27052
  success: false,
27021
27053
  error: `Plugin already exists in .allagents/workspace.yaml: ${plugin}`
@@ -27043,10 +27075,13 @@ async function hasPlugin(plugin, workspacePath = process.cwd()) {
27043
27075
  try {
27044
27076
  const content = await readFile8(configPath, "utf-8");
27045
27077
  const config = load(content);
27046
- if (config.plugins.indexOf(plugin) !== -1)
27078
+ if (config.plugins.some((entry) => getPluginSource(entry) === plugin))
27047
27079
  return true;
27048
27080
  if (!isPluginSpec(plugin)) {
27049
- return config.plugins.some((p) => p.startsWith(`${plugin}@`) || p === plugin);
27081
+ return config.plugins.some((entry) => {
27082
+ const source = getPluginSource(entry);
27083
+ return source.startsWith(`${plugin}@`) || source === plugin;
27084
+ });
27050
27085
  }
27051
27086
  return false;
27052
27087
  } catch {
@@ -27065,9 +27100,12 @@ async function removePlugin(plugin, workspacePath = process.cwd()) {
27065
27100
  try {
27066
27101
  const content = await readFile8(configPath, "utf-8");
27067
27102
  const config = load(content);
27068
- let index = config.plugins.indexOf(plugin);
27103
+ let index = config.plugins.findIndex((entry) => getPluginSource(entry) === plugin);
27069
27104
  if (index === -1 && isPluginSpec(plugin) === false) {
27070
- index = config.plugins.findIndex((p) => p.startsWith(`${plugin}@`) || p === plugin);
27105
+ index = config.plugins.findIndex((entry) => {
27106
+ const source = getPluginSource(entry);
27107
+ return source.startsWith(`${plugin}@`) || source === plugin;
27108
+ });
27071
27109
  }
27072
27110
  if (index === -1) {
27073
27111
  return {
@@ -27075,7 +27113,7 @@ async function removePlugin(plugin, workspacePath = process.cwd()) {
27075
27113
  error: `Plugin not found in .allagents/workspace.yaml: ${plugin}`
27076
27114
  };
27077
27115
  }
27078
- const removedEntry = config.plugins[index];
27116
+ const removedEntry = getPluginSource(config.plugins[index]);
27079
27117
  config.plugins.splice(index, 1);
27080
27118
  pruneDisabledSkillsForPlugin(config, removedEntry);
27081
27119
  const newContent = dump(config, { lineWidth: -1 });
@@ -27173,6 +27211,7 @@ var DEFAULT_PROJECT_CLIENTS;
27173
27211
  var init_workspace_modify = __esm(() => {
27174
27212
  init_js_yaml();
27175
27213
  init_constants();
27214
+ init_workspace_config();
27176
27215
  init_plugin_path();
27177
27216
  init_marketplace();
27178
27217
  DEFAULT_PROJECT_CLIENTS = [
@@ -27837,6 +27876,9 @@ function mergeSyncResults(a, b) {
27837
27876
  ...mcpResult && { mcpResult }
27838
27877
  };
27839
27878
  }
27879
+ function collectSyncClients(workspaceClients, plans) {
27880
+ return [...new Set([...workspaceClients, ...plans.flatMap((plan) => plan.clients)])];
27881
+ }
27840
27882
  async function selectivePurgeWorkspace(workspacePath, state, clients, options2) {
27841
27883
  if (!state) {
27842
27884
  return [];
@@ -28048,6 +28090,7 @@ async function validatePlugin(pluginSource, workspacePath, offline) {
28048
28090
  plugin: pluginSource,
28049
28091
  resolved: "",
28050
28092
  success: false,
28093
+ clients: [],
28051
28094
  error: resolved.error || "Unknown error"
28052
28095
  };
28053
28096
  }
@@ -28055,6 +28098,7 @@ async function validatePlugin(pluginSource, workspacePath, offline) {
28055
28098
  plugin: pluginSource,
28056
28099
  resolved: resolved.path ?? "",
28057
28100
  success: true,
28101
+ clients: [],
28058
28102
  ...resolved.pluginName && { pluginName: resolved.pluginName }
28059
28103
  };
28060
28104
  }
@@ -28069,6 +28113,7 @@ async function validatePlugin(pluginSource, workspacePath, offline) {
28069
28113
  plugin: pluginSource,
28070
28114
  resolved: "",
28071
28115
  success: false,
28116
+ clients: [],
28072
28117
  ...fetchResult.error && { error: fetchResult.error }
28073
28118
  };
28074
28119
  }
@@ -28076,7 +28121,8 @@ async function validatePlugin(pluginSource, workspacePath, offline) {
28076
28121
  return {
28077
28122
  plugin: pluginSource,
28078
28123
  resolved: resolvedPath2,
28079
- success: true
28124
+ success: true,
28125
+ clients: []
28080
28126
  };
28081
28127
  }
28082
28128
  const resolvedPath = resolve9(workspacePath, pluginSource);
@@ -28085,36 +28131,39 @@ async function validatePlugin(pluginSource, workspacePath, offline) {
28085
28131
  plugin: pluginSource,
28086
28132
  resolved: resolvedPath,
28087
28133
  success: false,
28134
+ clients: [],
28088
28135
  error: `Plugin not found at ${resolvedPath}`
28089
28136
  };
28090
28137
  }
28091
28138
  return {
28092
28139
  plugin: pluginSource,
28093
28140
  resolved: resolvedPath,
28094
- success: true
28141
+ success: true,
28142
+ clients: []
28095
28143
  };
28096
28144
  }
28097
- async function validateAllPlugins(plugins, workspacePath, offline) {
28098
- return Promise.all(plugins.map((plugin) => validatePlugin(plugin, workspacePath, offline)));
28145
+ function buildPluginSyncPlans(plugins, workspaceClients, selectedClients) {
28146
+ const selected = selectedClients ? new Set(selectedClients) : null;
28147
+ return plugins.map((plugin) => {
28148
+ const source = getPluginSource(plugin);
28149
+ const configuredClients = getPluginClients(plugin) ?? workspaceClients;
28150
+ const clients = selected ? configuredClients.filter((client) => selected.has(client)) : configuredClients;
28151
+ return { source, clients };
28152
+ });
28153
+ }
28154
+ async function validateAllPlugins(plans, workspacePath, offline) {
28155
+ return Promise.all(plans.map(async ({ source, clients }) => {
28156
+ const validated = await validatePlugin(source, workspacePath, offline);
28157
+ return { ...validated, clients };
28158
+ }));
28099
28159
  }
28100
28160
  async function copyValidatedPlugin(validatedPlugin, workspacePath, clients, dryRun, skillNameMap, clientMappings, syncMode = "symlink") {
28101
28161
  const copyResults = [];
28102
28162
  const mappings = clientMappings ?? CLIENT_MAPPINGS;
28103
28163
  const clientList = clients;
28104
- if (syncMode === "symlink") {
28164
+ const hasUniversalClient = clientList.some((c) => isUniversalClient(c));
28165
+ if (syncMode === "symlink" && hasUniversalClient) {
28105
28166
  const { representativeClients } = deduplicateClientsByPath(clientList, mappings);
28106
- const canonicalRepresentative = representativeClients.find((c) => mappings[c]?.skillsPath === CANONICAL_SKILLS_PATH);
28107
- const needsCanonicalCopy = !canonicalRepresentative;
28108
- const nonUniversalClients = clientList.filter((c) => !isUniversalClient(c));
28109
- if (needsCanonicalCopy && nonUniversalClients.length > 0) {
28110
- const canonicalResults = await copyPluginToWorkspace(validatedPlugin.resolved, workspacePath, "copilot", {
28111
- dryRun,
28112
- ...skillNameMap && { skillNameMap },
28113
- syncMode: "copy"
28114
- });
28115
- const skillResults = canonicalResults.filter((r) => r.destination.includes(CANONICAL_SKILLS_PATH) && r.action === "copied");
28116
- copyResults.push(...skillResults);
28117
- }
28118
28167
  for (const representative of representativeClients) {
28119
28168
  if (isUniversalClient(representative)) {
28120
28169
  const results = await copyPluginToWorkspace(validatedPlugin.resolved, workspacePath, representative, {
@@ -28247,9 +28296,15 @@ async function syncWorkspace(workspacePath = process.cwd(), options2 = {}) {
28247
28296
  };
28248
28297
  }
28249
28298
  const hasRepositories = (config.repositories?.length ?? 0) > 0;
28250
- const clients = options2.clients ? config.clients.filter((c) => options2.clients?.includes(c)) : config.clients;
28299
+ const workspaceClients = options2.clients ? config.clients.filter((c) => options2.clients?.includes(c)) : config.clients;
28251
28300
  if (options2.clients) {
28252
- const invalidClients = options2.clients.filter((c) => !config.clients.includes(c));
28301
+ const availableClients = new Set(config.clients);
28302
+ for (const plugin of config.plugins) {
28303
+ for (const client of getPluginClients(plugin) ?? []) {
28304
+ availableClients.add(client);
28305
+ }
28306
+ }
28307
+ const invalidClients = options2.clients.filter((c) => !availableClients.has(c));
28253
28308
  if (invalidClients.length > 0) {
28254
28309
  return {
28255
28310
  success: false,
@@ -28259,12 +28314,15 @@ async function syncWorkspace(workspacePath = process.cwd(), options2 = {}) {
28259
28314
  totalSkipped: 0,
28260
28315
  totalGenerated: 0,
28261
28316
  error: `Client(s) not configured in workspace.yaml: ${invalidClients.join(", ")}
28262
- Configured clients: ${config.clients.join(", ")}`
28317
+ Configured clients: ${Array.from(availableClients).join(", ")}`
28263
28318
  };
28264
28319
  }
28265
28320
  }
28266
- await ensureMarketplacesRegistered(config.plugins);
28267
- const validatedPlugins = await validateAllPlugins(config.plugins, workspacePath, offline);
28321
+ const selectedClients = options2.clients;
28322
+ const pluginPlans = buildPluginSyncPlans(config.plugins, config.clients, selectedClients).filter((plan) => plan.clients.length > 0);
28323
+ const syncClients = collectSyncClients(workspaceClients, pluginPlans);
28324
+ await ensureMarketplacesRegistered(pluginPlans.map((plan) => plan.source));
28325
+ const validatedPlugins = await validateAllPlugins(pluginPlans, workspacePath, offline);
28268
28326
  let validatedWorkspaceSource = null;
28269
28327
  if (config.workspace?.source) {
28270
28328
  const sourceBasePath = workspaceSourceBase ?? workspacePath;
@@ -28284,7 +28342,7 @@ async function syncWorkspace(workspacePath = process.cwd(), options2 = {}) {
28284
28342
  const failedValidations = validatedPlugins.filter((v) => !v.success);
28285
28343
  const validPlugins = validatedPlugins.filter((v) => v.success);
28286
28344
  const warnings = failedValidations.map((v) => `${v.plugin}: ${v.error} (skipped)`);
28287
- if (validPlugins.length === 0 && config.plugins.length > 0) {
28345
+ if (validPlugins.length === 0 && pluginPlans.length > 0) {
28288
28346
  return {
28289
28347
  success: false,
28290
28348
  pluginResults: [],
@@ -28299,12 +28357,12 @@ ${failedValidations.map((v) => ` - ${v.plugin}: ${v.error}`).join(`
28299
28357
  };
28300
28358
  }
28301
28359
  const previousState = await loadSyncState(workspacePath);
28302
- const purgedPaths = previousState ? clients.map((client) => ({
28360
+ const purgedPaths = previousState ? syncClients.map((client) => ({
28303
28361
  client,
28304
28362
  paths: getPreviouslySyncedFiles(previousState, client)
28305
28363
  })).filter((p) => p.paths.length > 0) : [];
28306
28364
  if (!dryRun) {
28307
- await selectivePurgeWorkspace(workspacePath, previousState, clients, {
28365
+ await selectivePurgeWorkspace(workspacePath, previousState, syncClients, {
28308
28366
  partialSync: !!options2.clients
28309
28367
  });
28310
28368
  }
@@ -28314,7 +28372,7 @@ ${failedValidations.map((v) => ` - ${v.plugin}: ${v.error}`).join(`
28314
28372
  const syncMode = config.syncMode ?? "symlink";
28315
28373
  const pluginResults = await Promise.all(validPlugins.map((validatedPlugin) => {
28316
28374
  const skillNameMap = pluginSkillMaps.get(validatedPlugin.resolved);
28317
- return copyValidatedPlugin(validatedPlugin, workspacePath, clients, dryRun, skillNameMap, undefined, syncMode);
28375
+ return copyValidatedPlugin(validatedPlugin, workspacePath, validatedPlugin.clients, dryRun, skillNameMap, undefined, syncMode);
28318
28376
  }));
28319
28377
  let workspaceFileResults = [];
28320
28378
  if (config.workspace) {
@@ -28362,7 +28420,7 @@ ${fileValidationErrors.map((e) => ` - ${e}`).join(`
28362
28420
  };
28363
28421
  }
28364
28422
  workspaceFileResults = await copyWorkspaceFiles(sourcePath, workspacePath, filesToCopy, { dryRun, githubCache, repositories: config.repositories });
28365
- if (hasRepositories && !dryRun && clients.includes("claude") && sourcePath) {
28423
+ if (hasRepositories && !dryRun && syncClients.includes("claude") && sourcePath) {
28366
28424
  const claudePath = join15(workspacePath, "CLAUDE.md");
28367
28425
  const agentsPath = join15(workspacePath, "AGENTS.md");
28368
28426
  const claudeExistsInSource = existsSync12(join15(sourcePath, "CLAUDE.md"));
@@ -28374,7 +28432,7 @@ ${fileValidationErrors.map((e) => ` - ${e}`).join(`
28374
28432
  if (!config.workspace && !dryRun && !skipAgentFiles) {
28375
28433
  await updateAgentFiles(workspacePath);
28376
28434
  }
28377
- if (clients.includes("vscode") && !dryRun) {
28435
+ if (syncClients.includes("vscode") && !dryRun) {
28378
28436
  generateVscodeWorkspaceFile(workspacePath, config);
28379
28437
  }
28380
28438
  let totalCopied = 0;
@@ -28418,10 +28476,10 @@ ${fileValidationErrors.map((e) => ` - ${e}`).join(`
28418
28476
  ...pluginResults.flatMap((r) => r.copyResults),
28419
28477
  ...workspaceFileResults
28420
28478
  ];
28421
- const syncedFiles = collectSyncedPaths(allCopyResults, workspacePath, clients);
28479
+ const syncedFiles = collectSyncedPaths(allCopyResults, workspacePath, syncClients);
28422
28480
  if (options2.clients && previousState) {
28423
28481
  for (const [client, files] of Object.entries(previousState.files)) {
28424
- if (!clients.includes(client)) {
28482
+ if (!syncClients.includes(client)) {
28425
28483
  syncedFiles[client] = files;
28426
28484
  }
28427
28485
  }
@@ -28452,14 +28510,16 @@ async function syncUserWorkspace(options2 = {}) {
28452
28510
  totalGenerated: 0
28453
28511
  };
28454
28512
  }
28455
- const clients = config.clients;
28513
+ const workspaceClients = config.clients;
28456
28514
  const { offline = false, dryRun = false, force = false } = options2;
28457
- await ensureMarketplacesRegistered(config.plugins);
28458
- const validatedPlugins = await validateAllPlugins(config.plugins, homeDir, offline);
28515
+ const pluginPlans = buildPluginSyncPlans(config.plugins, workspaceClients).filter((plan) => plan.clients.length > 0);
28516
+ const syncClients = collectSyncClients(workspaceClients, pluginPlans);
28517
+ await ensureMarketplacesRegistered(pluginPlans.map((plan) => plan.source));
28518
+ const validatedPlugins = await validateAllPlugins(pluginPlans, homeDir, offline);
28459
28519
  const failedValidations = validatedPlugins.filter((v) => !v.success);
28460
28520
  const validPlugins = validatedPlugins.filter((v) => v.success);
28461
28521
  const warnings = failedValidations.map((v) => `${v.plugin}: ${v.error} (skipped)`);
28462
- if (validPlugins.length === 0 && config.plugins.length > 0) {
28522
+ if (validPlugins.length === 0 && pluginPlans.length > 0) {
28463
28523
  return {
28464
28524
  success: false,
28465
28525
  pluginResults: [],
@@ -28475,7 +28535,7 @@ ${failedValidations.map((v) => ` - ${v.plugin}: ${v.error}`).join(`
28475
28535
  }
28476
28536
  const previousState = await loadSyncState(homeDir);
28477
28537
  if (!dryRun) {
28478
- await selectivePurgeWorkspace(homeDir, previousState, clients);
28538
+ await selectivePurgeWorkspace(homeDir, previousState, syncClients);
28479
28539
  }
28480
28540
  const disabledSkillsSet = new Set(config.disabledSkills ?? []);
28481
28541
  const allSkills = await collectAllSkills(validPlugins, disabledSkillsSet);
@@ -28483,7 +28543,7 @@ ${failedValidations.map((v) => ` - ${v.plugin}: ${v.error}`).join(`
28483
28543
  const syncMode = config.syncMode ?? "symlink";
28484
28544
  const pluginResults = await Promise.all(validPlugins.map((vp) => {
28485
28545
  const skillNameMap = pluginSkillMaps.get(vp.resolved);
28486
- return copyValidatedPlugin(vp, homeDir, clients, dryRun, skillNameMap, USER_CLIENT_MAPPINGS, syncMode);
28546
+ return copyValidatedPlugin(vp, homeDir, vp.clients, dryRun, skillNameMap, USER_CLIENT_MAPPINGS, syncMode);
28487
28547
  }));
28488
28548
  let totalCopied = 0;
28489
28549
  let totalFailed = 0;
@@ -28508,7 +28568,7 @@ ${failedValidations.map((v) => ` - ${v.plugin}: ${v.error}`).join(`
28508
28568
  }
28509
28569
  }
28510
28570
  let mcpResult;
28511
- if (clients.includes("vscode")) {
28571
+ if (syncClients.includes("vscode")) {
28512
28572
  const trackedMcpServers = getPreviouslySyncedMcpServers(previousState, "vscode");
28513
28573
  mcpResult = syncVscodeMcpConfig(validPlugins, { dryRun, force, trackedServers: trackedMcpServers });
28514
28574
  if (mcpResult.warnings.length > 0) {
@@ -28517,7 +28577,7 @@ ${failedValidations.map((v) => ` - ${v.plugin}: ${v.error}`).join(`
28517
28577
  }
28518
28578
  if (!dryRun) {
28519
28579
  const allCopyResults = pluginResults.flatMap((r) => r.copyResults);
28520
- const syncedFiles = collectSyncedPaths(allCopyResults, homeDir, clients, USER_CLIENT_MAPPINGS);
28580
+ const syncedFiles = collectSyncedPaths(allCopyResults, homeDir, syncClients, USER_CLIENT_MAPPINGS);
28521
28581
  await saveSyncState(homeDir, {
28522
28582
  files: syncedFiles,
28523
28583
  ...mcpResult && { mcpServers: { vscode: mcpResult.trackedServers } }
@@ -28538,6 +28598,7 @@ var import_json52, VSCODE_TEMPLATE_FILE = "template.code-workspace";
28538
28598
  var init_sync = __esm(() => {
28539
28599
  init_constants();
28540
28600
  init_workspace_parser();
28601
+ init_workspace_config();
28541
28602
  init_plugin_path();
28542
28603
  init_plugin();
28543
28604
  init_transform();
@@ -28896,7 +28957,8 @@ async function getWorkspaceStatus(workspacePath = process.cwd()) {
28896
28957
  try {
28897
28958
  const config = await parseWorkspaceConfig(configPath);
28898
28959
  const plugins = [];
28899
- for (const pluginSource of config.plugins) {
28960
+ for (const pluginEntry of config.plugins) {
28961
+ const pluginSource = getPluginSource(pluginEntry);
28900
28962
  if (isPluginSpec(pluginSource)) {
28901
28963
  const status = await getMarketplacePluginStatus(pluginSource);
28902
28964
  plugins.push(status);
@@ -28948,7 +29010,8 @@ async function getUserPluginStatuses() {
28948
29010
  if (!config)
28949
29011
  return [];
28950
29012
  const statuses = [];
28951
- for (const pluginSource of config.plugins) {
29013
+ for (const pluginEntry of config.plugins) {
29014
+ const pluginSource = getPluginSource(pluginEntry);
28952
29015
  if (isPluginSpec(pluginSource)) {
28953
29016
  statuses.push(await getMarketplacePluginStatus(pluginSource));
28954
29017
  } else {
@@ -28970,6 +29033,7 @@ async function getMarketplacePluginStatus(spec) {
28970
29033
  var init_status2 = __esm(() => {
28971
29034
  init_constants();
28972
29035
  init_workspace_parser();
29036
+ init_workspace_config();
28973
29037
  init_plugin_path();
28974
29038
  init_marketplace();
28975
29039
  init_user_workspace();
@@ -29069,7 +29133,8 @@ async function getAllSkillsFromPlugins(workspacePath = process.cwd()) {
29069
29133
  const config = load(content);
29070
29134
  const disabledSkills = new Set(config.disabledSkills ?? []);
29071
29135
  const skills = [];
29072
- for (const pluginSource of config.plugins) {
29136
+ for (const pluginEntry of config.plugins) {
29137
+ const pluginSource = getPluginSource(pluginEntry);
29073
29138
  const pluginPath = await resolvePluginPath(pluginSource, workspacePath);
29074
29139
  if (!pluginPath)
29075
29140
  continue;
@@ -29099,6 +29164,7 @@ async function findSkillByName(skillName, workspacePath = process.cwd()) {
29099
29164
  var init_skills = __esm(() => {
29100
29165
  init_js_yaml();
29101
29166
  init_constants();
29167
+ init_workspace_config();
29102
29168
  init_plugin();
29103
29169
  init_plugin_path();
29104
29170
  init_marketplace();
@@ -29602,7 +29668,7 @@ var package_default;
29602
29668
  var init_package = __esm(() => {
29603
29669
  package_default = {
29604
29670
  name: "allagents",
29605
- version: "0.23.0",
29671
+ version: "0.24.1",
29606
29672
  description: "CLI tool for managing multi-repo AI agent workspaces with plugin synchronization",
29607
29673
  type: "module",
29608
29674
  bin: {
@@ -29627,7 +29693,8 @@ var init_package = __esm(() => {
29627
29693
  check: "biome check src",
29628
29694
  "check:fix": "biome check --write src",
29629
29695
  prepare: "bun run build && (test -d .git && bunx prek install -t pre-push || true)",
29630
- release: "bun run scripts/release.ts"
29696
+ release: "bun run scripts/release.ts",
29697
+ "publish:next": "bun run build && bun publish --tag next"
29631
29698
  },
29632
29699
  keywords: [
29633
29700
  "cli",
@@ -32723,6 +32790,7 @@ init_js_yaml();
32723
32790
  init_constants();
32724
32791
  init_marketplace();
32725
32792
  init_user_workspace();
32793
+ init_workspace_config();
32726
32794
  import { readFile as readFile12, writeFile as writeFile8 } from "node:fs/promises";
32727
32795
  import { existsSync as existsSync16 } from "node:fs";
32728
32796
  import { join as join19 } from "node:path";
@@ -32738,33 +32806,36 @@ async function isOrphanedPlugin(pluginSpec) {
32738
32806
  async function prunePlugins(plugins) {
32739
32807
  const removed = [];
32740
32808
  const kept = [];
32741
- for (const plugin of plugins) {
32809
+ const keptEntries = [];
32810
+ for (const pluginEntry of plugins) {
32811
+ const plugin = getPluginSource(pluginEntry);
32742
32812
  if (await isOrphanedPlugin(plugin)) {
32743
32813
  removed.push(plugin);
32744
32814
  } else {
32745
32815
  kept.push(plugin);
32816
+ keptEntries.push(pluginEntry);
32746
32817
  }
32747
32818
  }
32748
- return { removed, kept };
32819
+ return { removed, kept, keptEntries };
32749
32820
  }
32750
32821
  async function pruneOrphanedPlugins(workspacePath) {
32751
- let projectResult = { removed: [], kept: [] };
32822
+ let projectResult = { removed: [], kept: [], keptEntries: [] };
32752
32823
  const projectConfigPath = join19(workspacePath, CONFIG_DIR, WORKSPACE_CONFIG_FILE);
32753
32824
  if (existsSync16(projectConfigPath) && !isUserConfigPath(workspacePath)) {
32754
32825
  const content = await readFile12(projectConfigPath, "utf-8");
32755
32826
  const config = load(content);
32756
32827
  projectResult = await prunePlugins(config.plugins);
32757
32828
  if (projectResult.removed.length > 0) {
32758
- config.plugins = projectResult.kept;
32829
+ config.plugins = projectResult.keptEntries;
32759
32830
  await writeFile8(projectConfigPath, dump(config, { lineWidth: -1 }), "utf-8");
32760
32831
  }
32761
32832
  }
32762
- let userResult = { removed: [], kept: [] };
32833
+ let userResult = { removed: [], kept: [], keptEntries: [] };
32763
32834
  const userConfig = await getUserWorkspaceConfig();
32764
32835
  if (userConfig) {
32765
32836
  userResult = await prunePlugins(userConfig.plugins);
32766
32837
  if (userResult.removed.length > 0) {
32767
- userConfig.plugins = userResult.kept;
32838
+ userConfig.plugins = userResult.keptEntries;
32768
32839
  const userConfigPath = getUserWorkspaceConfigPath();
32769
32840
  await writeFile8(userConfigPath, dump(userConfig, { lineWidth: -1 }), "utf-8");
32770
32841
  }
@@ -34072,6 +34143,7 @@ var skillsCmd = conciseSubcommands({
34072
34143
  });
34073
34144
 
34074
34145
  // src/cli/commands/plugin.ts
34146
+ init_workspace_config();
34075
34147
  async function runSyncAndPrint(options2) {
34076
34148
  if (!isJsonMode()) {
34077
34149
  console.log(`
@@ -34806,7 +34878,8 @@ var pluginUpdateCmd = import_cmd_ts4.command({
34806
34878
  if (existsSync20(configPath)) {
34807
34879
  const content = await readFile14(configPath, "utf-8");
34808
34880
  const config = load2(content);
34809
- for (const p of config.plugins ?? []) {
34881
+ for (const entry of config.plugins ?? []) {
34882
+ const p = getPluginSource(entry);
34810
34883
  if (!pluginsToUpdate.includes(p)) {
34811
34884
  pluginsToUpdate.push(p);
34812
34885
  }
@@ -34816,7 +34889,8 @@ var pluginUpdateCmd = import_cmd_ts4.command({
34816
34889
  if (updateUser) {
34817
34890
  const userConfig = await getUserWorkspaceConfig();
34818
34891
  if (userConfig) {
34819
- for (const p of userConfig.plugins ?? []) {
34892
+ for (const entry of userConfig.plugins ?? []) {
34893
+ const p = getPluginSource(entry);
34820
34894
  if (!pluginsToUpdate.includes(p)) {
34821
34895
  pluginsToUpdate.push(p);
34822
34896
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "allagents",
3
- "version": "0.23.0",
3
+ "version": "0.24.1",
4
4
  "description": "CLI tool for managing multi-repo AI agent workspaces with plugin synchronization",
5
5
  "type": "module",
6
6
  "bin": {
@@ -25,7 +25,8 @@
25
25
  "check": "biome check src",
26
26
  "check:fix": "biome check --write src",
27
27
  "prepare": "bun run build && (test -d .git && bunx prek install -t pre-push || true)",
28
- "release": "bun run scripts/release.ts"
28
+ "release": "bun run scripts/release.ts",
29
+ "publish:next": "bun run build && bun publish --tag next"
29
30
  },
30
31
  "keywords": [
31
32
  "cli",