allagents 0.33.1 → 0.34.0-next.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 +293 -97
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -13440,7 +13440,7 @@ function gitInstanceFactory(baseDir, options) {
13440
13440
  }
13441
13441
  var import_file_exists, import_debug, import_promise_deferred, import_promise_deferred2, __defProp2, __getOwnPropDesc2, __getOwnPropNames2, __hasOwnProp2, __esm2 = (fn, res) => function __init() {
13442
13442
  return fn && (res = (0, fn[__getOwnPropNames2(fn)[0]])(fn = 0)), res;
13443
- }, __commonJS2 = (cb, mod) => function __require() {
13443
+ }, __commonJS2 = (cb, mod) => function __require2() {
13444
13444
  return mod || (0, cb[__getOwnPropNames2(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
13445
13445
  }, __export2 = (target, all) => {
13446
13446
  for (var name in all)
@@ -22907,7 +22907,7 @@ var init_user_workspace = __esm(() => {
22907
22907
  // src/core/marketplace.ts
22908
22908
  import { existsSync as existsSync6 } from "node:fs";
22909
22909
  import { mkdir as mkdir5, readFile as readFile5, readdir as readdir3, rm as rm3, writeFile as writeFile3 } from "node:fs/promises";
22910
- import { basename as basename3, join as join9, resolve as resolve7 } from "node:path";
22910
+ import { basename as basename3, dirname as dirname5, join as join9, resolve as resolve7 } from "node:path";
22911
22911
  function parseLocation(location) {
22912
22912
  const [owner = "", repo = "", ...rest] = location.split("/");
22913
22913
  const branch = rest.length > 0 ? rest.join("/") : undefined;
@@ -22922,8 +22922,10 @@ function getMarketplacesDir() {
22922
22922
  function getRegistryPath() {
22923
22923
  return join9(getAllagentsDir(), "marketplaces.json");
22924
22924
  }
22925
- async function loadRegistry() {
22926
- const registryPath = getRegistryPath();
22925
+ function getProjectRegistryPath(workspacePath) {
22926
+ return join9(workspacePath, ".allagents", "marketplaces.json");
22927
+ }
22928
+ async function loadRegistryFromPath(registryPath) {
22927
22929
  if (!existsSync6(registryPath)) {
22928
22930
  return { version: 1, marketplaces: {} };
22929
22931
  }
@@ -22934,15 +22936,20 @@ async function loadRegistry() {
22934
22936
  return { version: 1, marketplaces: {} };
22935
22937
  }
22936
22938
  }
22937
- async function saveRegistry(registry) {
22938
- const registryPath = getRegistryPath();
22939
- const dir = getAllagentsDir();
22939
+ async function saveRegistryToPath(registry, registryPath) {
22940
+ const dir = dirname5(registryPath);
22940
22941
  if (!existsSync6(dir)) {
22941
22942
  await mkdir5(dir, { recursive: true });
22942
22943
  }
22943
22944
  await writeFile3(registryPath, `${JSON.stringify(registry, null, 2)}
22944
22945
  `);
22945
22946
  }
22947
+ async function loadRegistry() {
22948
+ return loadRegistryFromPath(getRegistryPath());
22949
+ }
22950
+ async function saveRegistry(registry) {
22951
+ return saveRegistryToPath(registry, getRegistryPath());
22952
+ }
22946
22953
  function getSourceLocationKey(source) {
22947
22954
  return source.location;
22948
22955
  }
@@ -22993,7 +23000,7 @@ function parseMarketplaceSource(source) {
22993
23000
  name
22994
23001
  };
22995
23002
  }
22996
- async function addMarketplace(source, customName, branch) {
23003
+ async function addMarketplace(source, customName, branch, scopeOptions) {
22997
23004
  const parsed = parseMarketplaceSource(source);
22998
23005
  if (!parsed) {
22999
23006
  return {
@@ -23020,7 +23027,8 @@ async function addMarketplace(source, customName, branch) {
23020
23027
  }
23021
23028
  }
23022
23029
  let name = customName || parsed.name;
23023
- const registry = await loadRegistry();
23030
+ const registryPath = scopeOptions?.scope === "project" && scopeOptions?.workspacePath ? getProjectRegistryPath(scopeOptions.workspacePath) : getRegistryPath();
23031
+ const registry = await loadRegistryFromPath(registryPath);
23024
23032
  if (registry.marketplaces[name]) {
23025
23033
  return {
23026
23034
  success: false,
@@ -23118,32 +23126,59 @@ async function addMarketplace(source, customName, branch) {
23118
23126
  lastUpdated: new Date().toISOString()
23119
23127
  };
23120
23128
  registry.marketplaces[name] = entry;
23121
- await saveRegistry(registry);
23129
+ await saveRegistryToPath(registry, registryPath);
23122
23130
  return {
23123
23131
  success: true,
23124
23132
  marketplace: entry
23125
23133
  };
23126
23134
  }
23127
23135
  async function removeMarketplace(name, options = {}) {
23128
- const registry = await loadRegistry();
23129
- if (!registry.marketplaces[name]) {
23136
+ const scope = options.scope ?? "all";
23137
+ if ((scope === "project" || scope === "all") && !options.workspacePath && !options.userRegistryPath) {
23138
+ if (scope === "project") {
23139
+ return {
23140
+ success: false,
23141
+ error: 'workspacePath is required when scope is "project"'
23142
+ };
23143
+ }
23144
+ }
23145
+ const userRegPath = options.userRegistryPath ?? getRegistryPath();
23146
+ let removedEntry;
23147
+ if (scope === "user" || scope === "all") {
23148
+ const userRegistry = await loadRegistryFromPath(userRegPath);
23149
+ if (userRegistry.marketplaces[name]) {
23150
+ removedEntry = userRegistry.marketplaces[name];
23151
+ delete userRegistry.marketplaces[name];
23152
+ await saveRegistryToPath(userRegistry, userRegPath);
23153
+ if (removedEntry.source.type !== "local" && existsSync6(removedEntry.path)) {
23154
+ await rm3(removedEntry.path, { recursive: true, force: true });
23155
+ }
23156
+ }
23157
+ }
23158
+ if ((scope === "project" || scope === "all") && options.workspacePath) {
23159
+ const projectRegPath = getProjectRegistryPath(options.workspacePath);
23160
+ const projectRegistry = await loadRegistryFromPath(projectRegPath);
23161
+ if (projectRegistry.marketplaces[name]) {
23162
+ removedEntry = projectRegistry.marketplaces[name];
23163
+ delete projectRegistry.marketplaces[name];
23164
+ await saveRegistryToPath(projectRegistry, projectRegPath);
23165
+ if (removedEntry.source.type !== "local" && existsSync6(removedEntry.path)) {
23166
+ await rm3(removedEntry.path, { recursive: true, force: true });
23167
+ }
23168
+ }
23169
+ }
23170
+ if (!removedEntry) {
23130
23171
  return {
23131
23172
  success: false,
23132
23173
  error: `Marketplace '${name}' not found in registry`
23133
23174
  };
23134
23175
  }
23135
- const entry = registry.marketplaces[name];
23136
- delete registry.marketplaces[name];
23137
- await saveRegistry(registry);
23138
- if (entry.source.type !== "local" && existsSync6(entry.path)) {
23139
- await rm3(entry.path, { recursive: true, force: true });
23140
- }
23141
23176
  if (options.cascade) {
23142
23177
  const { removeUserPluginsForMarketplace: removeUserPluginsForMarketplace2 } = await Promise.resolve().then(() => (init_user_workspace(), exports_user_workspace));
23143
23178
  const removedUserPlugins = await removeUserPluginsForMarketplace2(name);
23144
23179
  return {
23145
23180
  success: true,
23146
- marketplace: entry,
23181
+ marketplace: removedEntry,
23147
23182
  removedUserPlugins
23148
23183
  };
23149
23184
  }
@@ -23151,7 +23186,7 @@ async function removeMarketplace(name, options = {}) {
23151
23186
  const retainedUserPlugins = await getUserPluginsForMarketplace2(name);
23152
23187
  return {
23153
23188
  success: true,
23154
- marketplace: entry,
23189
+ marketplace: removedEntry,
23155
23190
  retainedUserPlugins
23156
23191
  };
23157
23192
  }
@@ -23159,12 +23194,16 @@ async function listMarketplaces() {
23159
23194
  const registry = await loadRegistry();
23160
23195
  return Object.values(registry.marketplaces).sort((a, b) => a.name.localeCompare(b.name));
23161
23196
  }
23162
- async function getMarketplace(name) {
23197
+ async function getMarketplace(name, workspacePath) {
23198
+ if (workspacePath) {
23199
+ const { registry: registry2 } = await loadMergedRegistries(getRegistryPath(), getProjectRegistryPath(workspacePath));
23200
+ return registry2.marketplaces[name] || null;
23201
+ }
23163
23202
  const registry = await loadRegistry();
23164
23203
  return registry.marketplaces[name] || null;
23165
23204
  }
23166
- async function findMarketplace(name, sourceLocation) {
23167
- const registry = await loadRegistry();
23205
+ async function findMarketplace(name, sourceLocation, workspacePath) {
23206
+ const registry = workspacePath ? (await loadMergedRegistries(getRegistryPath(), getProjectRegistryPath(workspacePath))).registry : await loadRegistry();
23168
23207
  if (registry.marketplaces[name]) {
23169
23208
  return registry.marketplaces[name];
23170
23209
  }
@@ -23173,10 +23212,27 @@ async function findMarketplace(name, sourceLocation) {
23173
23212
  }
23174
23213
  return null;
23175
23214
  }
23176
- async function updateMarketplace(name) {
23177
- const registry = await loadRegistry();
23215
+ async function updateMarketplace(name, workspacePath) {
23216
+ const userRegistry = await loadRegistry();
23217
+ let projectRegistry;
23218
+ if (workspacePath) {
23219
+ const projectPath = getProjectRegistryPath(workspacePath);
23220
+ if (existsSync6(projectPath)) {
23221
+ projectRegistry = await loadRegistryFromPath(projectPath);
23222
+ }
23223
+ }
23224
+ const mergedEntries = new Map;
23225
+ for (const entry of Object.values(userRegistry.marketplaces)) {
23226
+ mergedEntries.set(entry.name, { entry, scope: "user" });
23227
+ }
23228
+ if (projectRegistry) {
23229
+ for (const entry of Object.values(projectRegistry.marketplaces)) {
23230
+ mergedEntries.set(entry.name, { entry, scope: "project" });
23231
+ }
23232
+ }
23233
+ const toUpdateScoped = name ? mergedEntries.has(name) ? [mergedEntries.get(name)] : [] : Array.from(mergedEntries.values());
23234
+ const toUpdate = toUpdateScoped.map((s) => s.entry);
23178
23235
  const results = [];
23179
- const toUpdate = name ? registry.marketplaces[name] ? [registry.marketplaces[name]] : [] : Object.values(registry.marketplaces);
23180
23236
  if (name && toUpdate.length === 0) {
23181
23237
  return [{ name, success: false, error: `Marketplace '${name}' not found` }];
23182
23238
  }
@@ -23225,7 +23281,6 @@ async function updateMarketplace(name) {
23225
23281
  await git.checkout(targetBranch);
23226
23282
  await pull(marketplace.path);
23227
23283
  marketplace.lastUpdated = new Date().toISOString();
23228
- registry.marketplaces[marketplace.name] = marketplace;
23229
23284
  results.push({
23230
23285
  name: marketplace.name,
23231
23286
  success: true
@@ -23238,7 +23293,23 @@ async function updateMarketplace(name) {
23238
23293
  });
23239
23294
  }
23240
23295
  }
23241
- await saveRegistry(registry);
23296
+ let userDirty = false;
23297
+ let projectDirty = false;
23298
+ for (const { entry, scope } of toUpdateScoped) {
23299
+ if (scope === "user") {
23300
+ userRegistry.marketplaces[entry.name] = entry;
23301
+ userDirty = true;
23302
+ } else if (projectRegistry) {
23303
+ projectRegistry.marketplaces[entry.name] = entry;
23304
+ projectDirty = true;
23305
+ }
23306
+ }
23307
+ if (userDirty) {
23308
+ await saveRegistry(userRegistry);
23309
+ }
23310
+ if (projectDirty && projectRegistry && workspacePath) {
23311
+ await saveRegistryToPath(projectRegistry, getProjectRegistryPath(workspacePath));
23312
+ }
23242
23313
  return results;
23243
23314
  }
23244
23315
  async function getMarketplacePluginsFromManifest(marketplacePath) {
@@ -23262,8 +23333,8 @@ async function getMarketplacePluginsFromManifest(marketplacePath) {
23262
23333
  });
23263
23334
  return { plugins, warnings: result.warnings };
23264
23335
  }
23265
- async function listMarketplacePlugins(name) {
23266
- const marketplace = await getMarketplace(name);
23336
+ async function listMarketplacePlugins(name, workspacePath) {
23337
+ const marketplace = await getMarketplace(name, workspacePath);
23267
23338
  if (!marketplace) {
23268
23339
  return { plugins: [], warnings: [] };
23269
23340
  }
@@ -23324,7 +23395,7 @@ async function resolvePluginSpec(spec, options = {}) {
23324
23395
  const marketplaceName = options.marketplaceNameOverride ?? parsed.marketplaceName;
23325
23396
  let marketplacePath = options.marketplacePathOverride ?? null;
23326
23397
  if (!marketplacePath) {
23327
- const marketplace = await getMarketplace(marketplaceName);
23398
+ const marketplace = await getMarketplace(marketplaceName, options.workspacePath);
23328
23399
  if (!marketplace) {
23329
23400
  return null;
23330
23401
  }
@@ -23408,7 +23479,7 @@ async function resolvePluginSpecWithAutoRegister(spec, options = {}) {
23408
23479
  }
23409
23480
  const { plugin: pluginName, marketplaceName, owner, repo, subpath } = parsed;
23410
23481
  const sourceLocation = owner && repo ? `${owner}/${repo}` : undefined;
23411
- let marketplace = await findMarketplace(marketplaceName, sourceLocation);
23482
+ let marketplace = await findMarketplace(marketplaceName, sourceLocation, options.workspacePath);
23412
23483
  let didAutoRegister = false;
23413
23484
  if (!marketplace) {
23414
23485
  const sourceToRegister = owner && repo ? `${owner}/${repo}` : marketplaceName;
@@ -23419,7 +23490,7 @@ async function resolvePluginSpecWithAutoRegister(spec, options = {}) {
23419
23490
  error: autoRegResult.error || "Unknown error"
23420
23491
  };
23421
23492
  }
23422
- marketplace = await getMarketplace(autoRegResult.name ?? marketplaceName);
23493
+ marketplace = await getMarketplace(autoRegResult.name ?? marketplaceName, options.workspacePath);
23423
23494
  didAutoRegister = true;
23424
23495
  }
23425
23496
  if (!marketplace) {
@@ -23429,7 +23500,7 @@ async function resolvePluginSpecWithAutoRegister(spec, options = {}) {
23429
23500
  };
23430
23501
  }
23431
23502
  if (!didAutoRegister && !options.offline && marketplace.source.type !== "local" && !updatedMarketplaceCache.has(marketplace.name)) {
23432
- const results = await updateMarketplace(marketplace.name);
23503
+ const results = await updateMarketplace(marketplace.name, options.workspacePath);
23433
23504
  const result = results[0];
23434
23505
  if (result?.success) {
23435
23506
  updatedMarketplaceCache.add(marketplace.name);
@@ -23442,7 +23513,8 @@ async function resolvePluginSpecWithAutoRegister(spec, options = {}) {
23442
23513
  const resolveOpts = {
23443
23514
  ...subpath && { subpath },
23444
23515
  marketplaceNameOverride: marketplace.name,
23445
- ...options.offline != null && { offline: options.offline }
23516
+ ...options.offline != null && { offline: options.offline },
23517
+ ...options.workspacePath && { workspacePath: options.workspacePath }
23446
23518
  };
23447
23519
  let resolved = await resolvePluginSpec(spec, resolveOpts);
23448
23520
  if (!resolved && !options.offline && marketplace.source.type !== "local") {
@@ -23452,7 +23524,8 @@ async function resolvePluginSpecWithAutoRegister(spec, options = {}) {
23452
23524
  marketplace = refreshResult.marketplace;
23453
23525
  resolved = await resolvePluginSpec(spec, {
23454
23526
  ...subpath && { subpath },
23455
- marketplaceNameOverride: marketplace.name
23527
+ marketplaceNameOverride: marketplace.name,
23528
+ ...options.workspacePath && { workspacePath: options.workspacePath }
23456
23529
  });
23457
23530
  }
23458
23531
  }
@@ -23534,6 +23607,54 @@ async function ensureMarketplacesRegistered(plugins) {
23534
23607
  }
23535
23608
  return results;
23536
23609
  }
23610
+ async function loadMergedRegistries(userRegistryPath, projectRegistryPath) {
23611
+ const [userRegistry, projectRegistry] = await Promise.all([
23612
+ loadRegistryFromPath(userRegistryPath),
23613
+ loadRegistryFromPath(projectRegistryPath)
23614
+ ]);
23615
+ const merged = {
23616
+ version: 1,
23617
+ marketplaces: { ...userRegistry.marketplaces }
23618
+ };
23619
+ const overrides = [];
23620
+ for (const [name, entry] of Object.entries(projectRegistry.marketplaces)) {
23621
+ if (merged.marketplaces[name]) {
23622
+ overrides.push(name);
23623
+ }
23624
+ merged.marketplaces[name] = entry;
23625
+ }
23626
+ return { registry: merged, overrides };
23627
+ }
23628
+ async function getMarketplaceOverrides(userRegistryPath, projectRegistryPath) {
23629
+ if (!existsSync6(projectRegistryPath)) {
23630
+ return [];
23631
+ }
23632
+ const { overrides } = await loadMergedRegistries(userRegistryPath, projectRegistryPath);
23633
+ return overrides;
23634
+ }
23635
+ async function listMarketplacesWithScope(userRegistryPath, projectRegistryPath) {
23636
+ const [userRegistry, projectRegistry] = await Promise.all([
23637
+ loadRegistryFromPath(userRegistryPath),
23638
+ loadRegistryFromPath(projectRegistryPath)
23639
+ ]);
23640
+ const projectNames = new Set(Object.keys(projectRegistry.marketplaces));
23641
+ const entries = [];
23642
+ const overrides = [];
23643
+ for (const entry of Object.values(userRegistry.marketplaces)) {
23644
+ if (projectNames.has(entry.name)) {
23645
+ overrides.push(entry.name);
23646
+ } else {
23647
+ entries.push({ ...entry, scope: "user" });
23648
+ }
23649
+ }
23650
+ for (const entry of Object.values(projectRegistry.marketplaces)) {
23651
+ entries.push({ ...entry, scope: "project" });
23652
+ }
23653
+ return {
23654
+ entries: entries.sort((a, b) => a.name.localeCompare(b.name)),
23655
+ overrides
23656
+ };
23657
+ }
23537
23658
  async function getMarketplaceVersion(marketplacePath) {
23538
23659
  if (!existsSync6(marketplacePath)) {
23539
23660
  return null;
@@ -24262,7 +24383,7 @@ var init_sync_state = __esm(() => {
24262
24383
  // src/core/sync-state.ts
24263
24384
  import { readFile as readFile8, writeFile as writeFile6, mkdir as mkdir7 } from "node:fs/promises";
24264
24385
  import { existsSync as existsSync9 } from "node:fs";
24265
- import { join as join12, dirname as dirname5 } from "node:path";
24386
+ import { join as join12, dirname as dirname6 } from "node:path";
24266
24387
  function getSyncStatePath(workspacePath) {
24267
24388
  return join12(workspacePath, CONFIG_DIR, SYNC_STATE_FILE);
24268
24389
  }
@@ -24295,7 +24416,7 @@ async function saveSyncState(workspacePath, data) {
24295
24416
  ...normalizedData.vscodeWorkspaceHash && { vscodeWorkspaceHash: normalizedData.vscodeWorkspaceHash },
24296
24417
  ...normalizedData.vscodeWorkspaceRepos && { vscodeWorkspaceRepos: normalizedData.vscodeWorkspaceRepos }
24297
24418
  };
24298
- await mkdir7(dirname5(statePath), { recursive: true });
24419
+ await mkdir7(dirname6(statePath), { recursive: true });
24299
24420
  await writeFile6(statePath, JSON.stringify(state, null, 2), "utf-8");
24300
24421
  }
24301
24422
  function getPreviouslySyncedFiles(state, client) {
@@ -24456,7 +24577,7 @@ var init_vscode_workspace = __esm(() => {
24456
24577
 
24457
24578
  // src/core/vscode-mcp.ts
24458
24579
  import { existsSync as existsSync10, readFileSync, writeFileSync, mkdirSync } from "node:fs";
24459
- import { join as join13, dirname as dirname6 } from "node:path";
24580
+ import { join as join13, dirname as dirname7 } from "node:path";
24460
24581
  function deepEqual(a, b) {
24461
24582
  if (a === b)
24462
24583
  return true;
@@ -24599,7 +24720,7 @@ function syncVscodeMcpConfig(validatedPlugins, options) {
24599
24720
  const hasChanges = result.added > 0 || result.overwritten > 0 || result.removed > 0;
24600
24721
  if (hasChanges && !dryRun) {
24601
24722
  existingConfig.servers = existingServers;
24602
- const dir = dirname6(configPath);
24723
+ const dir = dirname7(configPath);
24603
24724
  if (!existsSync10(dir)) {
24604
24725
  mkdirSync(dir, { recursive: true });
24605
24726
  }
@@ -24617,7 +24738,7 @@ function syncVscodeMcpConfig(validatedPlugins, options) {
24617
24738
  }
24618
24739
  if (result.removed > 0 && !dryRun) {
24619
24740
  existingConfig.servers = existingServers;
24620
- const dir = dirname6(configPath);
24741
+ const dir = dirname7(configPath);
24621
24742
  if (!existsSync10(dir)) {
24622
24743
  mkdirSync(dir, { recursive: true });
24623
24744
  }
@@ -25013,7 +25134,7 @@ var init_native = __esm(() => {
25013
25134
  // src/core/sync.ts
25014
25135
  import { existsSync as existsSync11, readFileSync as readFileSync2, writeFileSync as writeFileSync2, lstatSync } from "node:fs";
25015
25136
  import { rm as rm4, unlink as unlink2, rmdir, copyFile } from "node:fs/promises";
25016
- import { join as join14, resolve as resolve9, dirname as dirname7, relative as relative4 } from "node:path";
25137
+ import { join as join14, resolve as resolve9, dirname as dirname8, relative as relative4 } from "node:path";
25017
25138
  function deduplicateClientsByPath(clients, clientMappings = CLIENT_MAPPINGS) {
25018
25139
  const pathToClients = new Map;
25019
25140
  for (const client of clients) {
@@ -25139,16 +25260,16 @@ async function selectivePurgeWorkspace(workspacePath, state, clients, options) {
25139
25260
  return result;
25140
25261
  }
25141
25262
  async function cleanupEmptyParents(workspacePath, filePath) {
25142
- let parentPath = dirname7(filePath);
25263
+ let parentPath = dirname8(filePath);
25143
25264
  while (parentPath && parentPath !== "." && parentPath !== "/") {
25144
25265
  const fullParentPath = join14(workspacePath, parentPath);
25145
25266
  if (!existsSync11(fullParentPath)) {
25146
- parentPath = dirname7(parentPath);
25267
+ parentPath = dirname8(parentPath);
25147
25268
  continue;
25148
25269
  }
25149
25270
  try {
25150
25271
  await rmdir(fullParentPath);
25151
- parentPath = dirname7(parentPath);
25272
+ parentPath = dirname8(parentPath);
25152
25273
  } catch {
25153
25274
  break;
25154
25275
  }
@@ -25308,7 +25429,8 @@ function collectSyncedPaths(copyResults, workspacePath, clients, clientMappings)
25308
25429
  async function validatePlugin(pluginSource, workspacePath, offline) {
25309
25430
  if (isPluginSpec(pluginSource)) {
25310
25431
  const resolved = await resolvePluginSpecWithAutoRegister(pluginSource, {
25311
- offline
25432
+ offline,
25433
+ workspacePath
25312
25434
  });
25313
25435
  if (!resolved.success) {
25314
25436
  return {
@@ -25753,6 +25875,10 @@ async function syncWorkspace(workspacePath = process.cwd(), options = {}) {
25753
25875
  } catch (error) {
25754
25876
  return failedSyncResult(error instanceof Error ? error.message : `Failed to parse ${CONFIG_DIR}/${WORKSPACE_CONFIG_FILE}`);
25755
25877
  }
25878
+ const overrides = await getMarketplaceOverrides(getRegistryPath(), getProjectRegistryPath(workspacePath));
25879
+ for (const name of overrides) {
25880
+ console.warn(`Warning: Workspace marketplace '${name}' overrides user marketplace of the same name.`);
25881
+ }
25756
25882
  const hasRepositories = (config.repositories?.length ?? 0) > 0;
25757
25883
  const configClientTypes = getClientTypes(config.clients);
25758
25884
  const workspaceClients = options.clients ? config.clients.filter((c) => {
@@ -26023,13 +26149,18 @@ async function fetchWorkspaceFromGitHub(url) {
26023
26149
  const repoUrl = gitHubUrl(owner, repo);
26024
26150
  let effectiveBranch = branch;
26025
26151
  let effectiveSubpath = subpath;
26026
- if (branch && subpath && !branch.includes("/")) {
26152
+ if (branch && subpath) {
26027
26153
  const resolved = await resolveBranchAndSubpath(repoUrl, `${branch}/${subpath}`);
26028
26154
  if (resolved && resolved.branch !== branch) {
26029
26155
  effectiveBranch = resolved.branch;
26030
26156
  effectiveSubpath = resolved.subpath;
26031
26157
  }
26032
26158
  }
26159
+ if (effectiveSubpath === CONFIG_DIR) {
26160
+ effectiveSubpath = undefined;
26161
+ } else if (effectiveSubpath?.endsWith(`/${CONFIG_DIR}`)) {
26162
+ effectiveSubpath = effectiveSubpath.slice(0, -(CONFIG_DIR.length + 1));
26163
+ }
26033
26164
  let tempDir;
26034
26165
  try {
26035
26166
  tempDir = await cloneToTemp(repoUrl, effectiveBranch);
@@ -26066,11 +26197,12 @@ async function fetchWorkspaceFromGitHub(url) {
26066
26197
  for (const filePath of pathsToTry) {
26067
26198
  const content = readFileFromClone(tempDir, filePath);
26068
26199
  if (content) {
26069
- return {
26070
- success: true,
26071
- content,
26072
- tempDir
26073
- };
26200
+ const result = { success: true, content, tempDir };
26201
+ if (basePath)
26202
+ result.resolvedSubpath = basePath;
26203
+ if (effectiveBranch)
26204
+ result.resolvedBranch = effectiveBranch;
26205
+ return result;
26074
26206
  }
26075
26207
  }
26076
26208
  await cleanupTempDir(tempDir);
@@ -26089,7 +26221,7 @@ var init_github_fetch = __esm(() => {
26089
26221
  // src/core/workspace.ts
26090
26222
  import { mkdir as mkdir8, readFile as readFile9, writeFile as writeFile7, copyFile as copyFile2, unlink as unlink3 } from "node:fs/promises";
26091
26223
  import { existsSync as existsSync13 } from "node:fs";
26092
- import { join as join16, resolve as resolve10, dirname as dirname8, relative as relative5, sep as sep2, isAbsolute as isAbsolute4 } from "node:path";
26224
+ import { join as join16, resolve as resolve10, dirname as dirname9, relative as relative5, sep as sep2, isAbsolute as isAbsolute4 } from "node:path";
26093
26225
  import { fileURLToPath } from "node:url";
26094
26226
  async function initWorkspace(targetPath = ".", options = {}) {
26095
26227
  const absoluteTarget = resolve10(targetPath);
@@ -26104,10 +26236,13 @@ async function initWorkspace(targetPath = ".", options = {}) {
26104
26236
  }
26105
26237
  }
26106
26238
  const currentFilePath = fileURLToPath(import.meta.url);
26107
- const currentFileDir = dirname8(currentFilePath);
26239
+ const currentFileDir = dirname9(currentFilePath);
26108
26240
  const isProduction = currentFilePath.includes(`${sep2}dist${sep2}`);
26109
26241
  const defaultTemplatePath = isProduction ? join16(currentFileDir, "templates", "default") : join16(currentFileDir, "..", "templates", "default");
26110
26242
  let githubTempDir;
26243
+ let parsedFromUrl;
26244
+ let githubBasePath = "";
26245
+ let githubBranch = "main";
26111
26246
  try {
26112
26247
  await mkdir8(absoluteTarget, { recursive: true });
26113
26248
  await mkdir8(configDir, { recursive: true });
@@ -26124,18 +26259,17 @@ async function initWorkspace(targetPath = ".", options = {}) {
26124
26259
  }
26125
26260
  githubTempDir = fetchResult.tempDir;
26126
26261
  workspaceYamlContent = fetchResult.content;
26262
+ parsedFromUrl = parseGitHubUrl(options.from);
26263
+ githubBasePath = fetchResult.resolvedSubpath || "";
26264
+ githubBranch = fetchResult.resolvedBranch || parsedFromUrl?.branch || "main";
26127
26265
  const parsed2 = load(workspaceYamlContent);
26128
26266
  const workspace = parsed2?.workspace;
26129
26267
  if (workspace?.source) {
26130
26268
  const source = workspace.source;
26131
26269
  if (!isGitHubUrl(source) && !isAbsolute4(source)) {
26132
- const parsedUrl = parseGitHubUrl(options.from);
26133
- if (parsedUrl) {
26134
- const basePath = parsedUrl.subpath || "";
26135
- const baseDir = basePath.replace(/\/?\.allagents\/workspace\.yaml$/, "").replace(/\/?workspace\.yaml$/, "");
26136
- const sourcePath = source === "." ? baseDir : baseDir ? `${baseDir}/${source}` : source;
26137
- const branch = parsedUrl.branch || "main";
26138
- workspace.source = `https://github.com/${parsedUrl.owner}/${parsedUrl.repo}/tree/${branch}/${sourcePath}`;
26270
+ if (parsedFromUrl) {
26271
+ const sourcePath = source === "." ? githubBasePath : githubBasePath ? `${githubBasePath}/${source}` : source;
26272
+ workspace.source = `https://github.com/${parsedFromUrl.owner}/${parsedFromUrl.repo}/tree/${githubBranch}/${sourcePath}`;
26139
26273
  workspaceYamlContent = dump(parsed2, { lineWidth: -1 });
26140
26274
  }
26141
26275
  }
@@ -26164,9 +26298,9 @@ async function initWorkspace(targetPath = ".", options = {}) {
26164
26298
  }
26165
26299
  } else {
26166
26300
  sourceYamlPath = fromPath;
26167
- const parentDir = dirname8(fromPath);
26301
+ const parentDir = dirname9(fromPath);
26168
26302
  if (parentDir.endsWith(CONFIG_DIR)) {
26169
- sourceDir = dirname8(parentDir);
26303
+ sourceDir = dirname9(parentDir);
26170
26304
  } else {
26171
26305
  sourceDir = parentDir;
26172
26306
  }
@@ -26206,11 +26340,8 @@ async function initWorkspace(targetPath = ".", options = {}) {
26206
26340
  const targetTemplatePath = join16(configDir, VSCODE_TEMPLATE_FILE2);
26207
26341
  if (!existsSync13(targetTemplatePath)) {
26208
26342
  if (isGitHubUrl(options.from) && githubTempDir) {
26209
- const parsedUrl = parseGitHubUrl(options.from);
26210
- if (parsedUrl) {
26211
- const basePath = parsedUrl.subpath || "";
26212
- const baseDir = basePath.replace(/\/?\.allagents\/workspace\.yaml$/, "").replace(/\/?workspace\.yaml$/, "");
26213
- const templatePath = baseDir ? `${baseDir}/${CONFIG_DIR}/${VSCODE_TEMPLATE_FILE2}` : `${CONFIG_DIR}/${VSCODE_TEMPLATE_FILE2}`;
26343
+ if (parsedFromUrl) {
26344
+ const templatePath = githubBasePath ? `${githubBasePath}/${CONFIG_DIR}/${VSCODE_TEMPLATE_FILE2}` : `${CONFIG_DIR}/${VSCODE_TEMPLATE_FILE2}`;
26214
26345
  const templateContent = readFileFromClone(githubTempDir, templatePath);
26215
26346
  if (templateContent) {
26216
26347
  await writeFile7(targetTemplatePath, templateContent, "utf-8");
@@ -26229,16 +26360,14 @@ async function initWorkspace(targetPath = ".", options = {}) {
26229
26360
  if (hasRepositories) {
26230
26361
  const copiedAgentFiles = [];
26231
26362
  if (options.from && isGitHubUrl(options.from) && githubTempDir) {
26232
- const parsedUrl = parseGitHubUrl(options.from);
26233
- if (parsedUrl) {
26234
- const basePath = parsedUrl.subpath || "";
26363
+ if (parsedFromUrl) {
26235
26364
  for (const agentFile of AGENT_FILES) {
26236
26365
  const targetFilePath = join16(absoluteTarget, agentFile);
26237
26366
  if (existsSync13(targetFilePath)) {
26238
26367
  copiedAgentFiles.push(agentFile);
26239
26368
  continue;
26240
26369
  }
26241
- const filePath = basePath ? `${basePath}/${agentFile}` : agentFile;
26370
+ const filePath = githubBasePath ? `${githubBasePath}/${agentFile}` : agentFile;
26242
26371
  const content = readFileFromClone(githubTempDir, filePath);
26243
26372
  if (content) {
26244
26373
  await writeFile7(targetFilePath, content, "utf-8");
@@ -29012,7 +29141,7 @@ var package_default;
29012
29141
  var init_package = __esm(() => {
29013
29142
  package_default = {
29014
29143
  name: "allagents",
29015
- version: "0.33.1",
29144
+ version: "0.34.0-next.1",
29016
29145
  description: "CLI tool for managing multi-repo AI agent workspaces with plugin synchronization",
29017
29146
  type: "module",
29018
29147
  bin: {
@@ -29123,8 +29252,8 @@ function buildNotice(currentVersion, latestVersion) {
29123
29252
  return null;
29124
29253
  if (!isNewer(latestVersion, currentVersion))
29125
29254
  return null;
29126
- return ` Update available: ${currentVersion} → ${latestVersion}
29127
- Run \`allagents self update\` to upgrade.`;
29255
+ return source_default.yellow(`Update available: ${currentVersion} → ${latestVersion}
29256
+ Run \`allagents self update\` to upgrade.`);
29128
29257
  }
29129
29258
  function backgroundUpdateCheck() {
29130
29259
  const dir = join23(getHomeDir(), CONFIG_DIR);
@@ -29168,6 +29297,7 @@ async function getUpdateNotice(currentVersion) {
29168
29297
  }
29169
29298
  var CHECK_INTERVAL_MS, CACHE_FILE = "version-check.json", NPM_REGISTRY_URL = "https://registry.npmjs.org/allagents/latest";
29170
29299
  var init_update_check = __esm(() => {
29300
+ init_source();
29171
29301
  init_constants();
29172
29302
  CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
29173
29303
  });
@@ -31963,10 +32093,33 @@ native:`);
31963
32093
  var marketplaceListCmd = import_cmd_ts4.command({
31964
32094
  name: "list",
31965
32095
  description: buildDescription(marketplaceListMeta),
31966
- args: {},
31967
- handler: async () => {
32096
+ args: {
32097
+ scope: import_cmd_ts4.option({ type: import_cmd_ts4.optional(import_cmd_ts4.string), long: "scope", short: "s", description: "Filter by scope: user or project" })
32098
+ },
32099
+ handler: async ({ scope }) => {
31968
32100
  try {
31969
- const marketplaces = await listMarketplaces();
32101
+ if (scope && scope !== "user" && scope !== "project") {
32102
+ const msg = `Invalid scope '${scope}'. Must be 'user' or 'project'.`;
32103
+ if (isJsonMode()) {
32104
+ jsonOutput({ success: false, command: "plugin marketplace list", error: msg });
32105
+ process.exit(1);
32106
+ }
32107
+ console.error(`Error: ${msg}`);
32108
+ process.exit(1);
32109
+ }
32110
+ let marketplaces;
32111
+ let overrideNames = [];
32112
+ if (!scope) {
32113
+ const scopedResult = await listMarketplacesWithScope(getRegistryPath(), getProjectRegistryPath(process.cwd()));
32114
+ marketplaces = scopedResult.entries;
32115
+ overrideNames = scopedResult.overrides;
32116
+ } else if (scope === "user") {
32117
+ const registry = await loadRegistryFromPath(getRegistryPath());
32118
+ marketplaces = Object.values(registry.marketplaces).map((mp) => ({ ...mp, scope: "user" }));
32119
+ } else {
32120
+ const registry = await loadRegistryFromPath(getProjectRegistryPath(process.cwd()));
32121
+ marketplaces = Object.values(registry.marketplaces).map((mp) => ({ ...mp, scope: "project" }));
32122
+ }
31970
32123
  if (isJsonMode()) {
31971
32124
  const enriched = await Promise.all(marketplaces.map(async (mp) => {
31972
32125
  const version = await getMarketplaceVersion(mp.path);
@@ -31985,6 +32138,9 @@ var marketplaceListCmd = import_cmd_ts4.command({
31985
32138
  });
31986
32139
  return;
31987
32140
  }
32141
+ for (const overrideName of overrideNames) {
32142
+ console.warn(`Warning: Workspace marketplace '${overrideName}' overrides user marketplace of the same name.`);
32143
+ }
31988
32144
  if (marketplaces.length === 0) {
31989
32145
  console.log(`No marketplaces registered.
31990
32146
  `);
@@ -32010,7 +32166,7 @@ var marketplaceListCmd = import_cmd_ts4.command({
32010
32166
  default:
32011
32167
  sourceLabel = `Local: ${mp.source.location}`;
32012
32168
  }
32013
- console.log(` ❯ ${mp.name}`);
32169
+ console.log(` ❯ ${mp.name} (${mp.scope})`);
32014
32170
  console.log(` Source: ${sourceLabel}`);
32015
32171
  const version = await getMarketplaceVersion(mp.path);
32016
32172
  if (version) {
@@ -32039,14 +32195,39 @@ var marketplaceAddCmd = import_cmd_ts4.command({
32039
32195
  args: {
32040
32196
  source: import_cmd_ts4.positional({ type: import_cmd_ts4.string, displayName: "source" }),
32041
32197
  name: import_cmd_ts4.option({ type: import_cmd_ts4.optional(import_cmd_ts4.string), long: "name", short: "n", description: "Custom name for the marketplace" }),
32042
- branch: import_cmd_ts4.option({ type: import_cmd_ts4.optional(import_cmd_ts4.string), long: "branch", short: "b", description: "Branch to checkout after cloning" })
32198
+ branch: import_cmd_ts4.option({ type: import_cmd_ts4.optional(import_cmd_ts4.string), long: "branch", short: "b", description: "Branch to checkout after cloning" }),
32199
+ scope: import_cmd_ts4.option({ type: import_cmd_ts4.optional(import_cmd_ts4.string), long: "scope", short: "s", description: "Scope: user (default) or project" })
32043
32200
  },
32044
- handler: async ({ source, name, branch }) => {
32201
+ handler: async ({ source, name, branch, scope }) => {
32045
32202
  try {
32203
+ const effectiveScope = scope ?? "user";
32204
+ if (effectiveScope !== "user" && effectiveScope !== "project") {
32205
+ const msg = `Invalid scope '${scope}'. Must be 'user' or 'project'.`;
32206
+ if (isJsonMode()) {
32207
+ jsonOutput({ success: false, command: "plugin marketplace add", error: msg });
32208
+ process.exit(1);
32209
+ }
32210
+ console.error(`Error: ${msg}`);
32211
+ process.exit(1);
32212
+ }
32213
+ if (effectiveScope === "project") {
32214
+ if (!existsSync19(join22(process.cwd(), CONFIG_DIR, WORKSPACE_CONFIG_FILE))) {
32215
+ const msg = 'No workspace found in current directory. Run "allagents workspace init" first.';
32216
+ if (isJsonMode()) {
32217
+ jsonOutput({ success: false, command: "plugin marketplace add", error: msg });
32218
+ process.exit(1);
32219
+ }
32220
+ console.error(`Error: ${msg}`);
32221
+ process.exit(1);
32222
+ }
32223
+ }
32046
32224
  if (!isJsonMode()) {
32047
32225
  console.log(`Adding marketplace: ${source}...`);
32048
32226
  }
32049
- const result = await addMarketplace(source, name, branch);
32227
+ const result = await addMarketplace(source, name, branch, {
32228
+ scope: effectiveScope,
32229
+ workspacePath: process.cwd()
32230
+ });
32050
32231
  if (!result.success) {
32051
32232
  if (isJsonMode()) {
32052
32233
  jsonOutput({ success: false, command: "plugin marketplace add", error: result.error ?? "Unknown error" });
@@ -32088,11 +32269,25 @@ var marketplaceRemoveCmd = import_cmd_ts4.command({
32088
32269
  name: "remove",
32089
32270
  description: buildDescription(marketplaceRemoveMeta),
32090
32271
  args: {
32091
- name: import_cmd_ts4.positional({ type: import_cmd_ts4.string, displayName: "name" })
32272
+ name: import_cmd_ts4.positional({ type: import_cmd_ts4.string, displayName: "name" }),
32273
+ scope: import_cmd_ts4.option({ type: import_cmd_ts4.optional(import_cmd_ts4.string), long: "scope", short: "s", description: "Filter by scope: user or project (default: removes from both)" })
32092
32274
  },
32093
- handler: async ({ name }) => {
32275
+ handler: async ({ name, scope }) => {
32094
32276
  try {
32095
- const result = await removeMarketplace(name);
32277
+ if (scope && scope !== "user" && scope !== "project") {
32278
+ const msg = `Invalid scope '${scope}'. Must be 'user' or 'project'.`;
32279
+ if (isJsonMode()) {
32280
+ jsonOutput({ success: false, command: "plugin marketplace remove", error: msg });
32281
+ process.exit(1);
32282
+ }
32283
+ console.error(`Error: ${msg}`);
32284
+ process.exit(1);
32285
+ }
32286
+ const effectiveScope = scope ?? "all";
32287
+ const result = await removeMarketplace(name, {
32288
+ scope: effectiveScope,
32289
+ workspacePath: process.cwd()
32290
+ });
32096
32291
  if (!result.success) {
32097
32292
  if (isJsonMode()) {
32098
32293
  jsonOutput({ success: false, command: "plugin marketplace remove", error: result.error ?? "Unknown error" });
@@ -32148,7 +32343,7 @@ var marketplaceUpdateCmd = import_cmd_ts4.command({
32148
32343
  console.log(name ? `Updating marketplace: ${name}...` : "Updating all marketplaces...");
32149
32344
  console.log();
32150
32345
  }
32151
- const results = await updateMarketplace(name);
32346
+ const results = await updateMarketplace(name, process.cwd());
32152
32347
  if (isJsonMode()) {
32153
32348
  const succeeded = results.filter((r) => r.success).length;
32154
32349
  const failed = results.filter((r) => !r.success).length;
@@ -32204,7 +32399,7 @@ var marketplaceBrowseCmd = import_cmd_ts4.command({
32204
32399
  },
32205
32400
  handler: async ({ name }) => {
32206
32401
  try {
32207
- if (!await findMarketplace(name)) {
32402
+ if (!await findMarketplace(name, undefined, process.cwd())) {
32208
32403
  const error = `Marketplace '${name}' not found`;
32209
32404
  if (isJsonMode()) {
32210
32405
  jsonOutput({ success: false, command: "plugin marketplace browse", error });
@@ -32216,7 +32411,7 @@ To see registered marketplaces:`);
32216
32411
  console.log(" allagents plugin marketplace list");
32217
32412
  process.exit(1);
32218
32413
  }
32219
- const result = await listMarketplacePlugins(name);
32414
+ const result = await listMarketplacePlugins(name, process.cwd());
32220
32415
  const userPlugins = await getInstalledUserPlugins();
32221
32416
  const projectPlugins = await getInstalledProjectPlugins(process.cwd());
32222
32417
  const installedMap = new Map;
@@ -32486,6 +32681,12 @@ var pluginInstallCmd = import_cmd_ts4.command({
32486
32681
  await ensureWorkspace(process.cwd(), clients);
32487
32682
  }
32488
32683
  }
32684
+ if (!isUser) {
32685
+ const overrideNames = await getMarketplaceOverrides(getRegistryPath(), getProjectRegistryPath(process.cwd()));
32686
+ for (const name of overrideNames) {
32687
+ console.warn(`Warning: Workspace marketplace '${name}' overrides user marketplace of the same name.`);
32688
+ }
32689
+ }
32489
32690
  const result = isUser ? await addUserPlugin(plugin) : await addPlugin(plugin);
32490
32691
  if (!result.success) {
32491
32692
  if (isJsonMode()) {
@@ -34668,17 +34869,12 @@ var { args: argsNoJson, json: json2 } = extractJsonFlag(rawArgs);
34668
34869
  var { args: finalArgs, agentHelp } = extractAgentHelpFlag(argsNoJson);
34669
34870
  setJsonMode(json2);
34670
34871
  var isWizard = finalArgs.length === 0 && process.stdout.isTTY && !json2;
34671
- var updateNotice = null;
34672
34872
  if (!agentHelp && !json2 && !isWizard) {
34673
- process.on("exit", () => {
34674
- if (updateNotice)
34675
- process.stderr.write(`
34676
- ${updateNotice}
34873
+ const notice = await getUpdateNotice(package_default.version);
34874
+ if (notice)
34875
+ process.stderr.write(`${notice}
34876
+
34677
34877
  `);
34678
- });
34679
- getUpdateNotice(package_default.version).then((n) => {
34680
- updateNotice = n;
34681
- });
34682
34878
  }
34683
34879
  if (agentHelp) {
34684
34880
  printAgentHelp(finalArgs, package_default.version);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "allagents",
3
- "version": "0.33.1",
3
+ "version": "0.34.0-next.1",
4
4
  "description": "CLI tool for managing multi-repo AI agent workspaces with plugin synchronization",
5
5
  "type": "module",
6
6
  "bin": {