@packmind/cli 0.25.0 → 0.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/main.cjs +1499 -1429
  2. package/package.json +2 -2
package/main.cjs CHANGED
@@ -3852,7 +3852,7 @@ var require_package = __commonJS({
3852
3852
  "apps/cli/package.json"(exports2, module2) {
3853
3853
  module2.exports = {
3854
3854
  name: "@packmind/cli",
3855
- version: "0.25.0",
3855
+ version: "0.26.0",
3856
3856
  description: "A command-line interface for Packmind linting and code quality checks",
3857
3857
  private: false,
3858
3858
  bin: {
@@ -4427,6 +4427,34 @@ var SpaceCreatedEvent = class extends UserEvent {
4427
4427
  }
4428
4428
  };
4429
4429
 
4430
+ // packages/types/src/spaces/events/SpaceMembersAddedEvent.ts
4431
+ var SpaceMembersAddedEvent = class extends UserEvent {
4432
+ static {
4433
+ this.eventName = "spaces.space.members-added";
4434
+ }
4435
+ };
4436
+
4437
+ // packages/types/src/spaces/events/SpaceMembersRemovedEvent.ts
4438
+ var SpaceMembersRemovedEvent = class extends UserEvent {
4439
+ static {
4440
+ this.eventName = "spaces.space.members-removed";
4441
+ }
4442
+ };
4443
+
4444
+ // packages/types/src/spaces/events/SpaceMembersRoleUpdatedEvent.ts
4445
+ var SpaceMembersRoleUpdatedEvent = class extends UserEvent {
4446
+ static {
4447
+ this.eventName = "spaces.space.members-role-updated";
4448
+ }
4449
+ };
4450
+
4451
+ // packages/types/src/spaces/events/SpaceVisibilityUpdatedEvent.ts
4452
+ var SpaceVisibilityUpdatedEvent = class extends UserEvent {
4453
+ static {
4454
+ this.eventName = "spaces.space.visibility-updated";
4455
+ }
4456
+ };
4457
+
4430
4458
  // packages/types/src/spaces-management/events/PlaybookArtefactMovedEvent.ts
4431
4459
  var PlaybookArtefactMovedEvent = class extends UserEvent {
4432
4460
  static {
@@ -5335,30 +5363,30 @@ var GitService = class {
5335
5363
  this.gitRunner = gitRunner;
5336
5364
  this.logger = logger2;
5337
5365
  }
5338
- getGitRepositoryRoot(path36) {
5366
+ getGitRepositoryRoot(path37) {
5339
5367
  try {
5340
5368
  const { stdout } = this.gitRunner("rev-parse --show-toplevel", {
5341
- cwd: path36
5369
+ cwd: path37
5342
5370
  });
5343
5371
  const gitRoot = stdout.trim();
5344
5372
  this.logger.debug("Resolved git repository root", {
5345
- inputPath: path36,
5373
+ inputPath: path37,
5346
5374
  gitRoot
5347
5375
  });
5348
5376
  return gitRoot;
5349
5377
  } catch (error) {
5350
5378
  if (error instanceof Error) {
5351
5379
  throw new Error(
5352
- `Failed to get Git repository root. The path '${path36}' does not appear to be inside a Git repository.
5380
+ `Failed to get Git repository root. The path '${path37}' does not appear to be inside a Git repository.
5353
5381
  ${error.message}`
5354
5382
  );
5355
5383
  }
5356
5384
  throw new Error("Failed to get Git repository root: Unknown error");
5357
5385
  }
5358
5386
  }
5359
- tryGetGitRepositoryRoot(path36) {
5387
+ tryGetGitRepositoryRoot(path37) {
5360
5388
  try {
5361
- return this.getGitRepositoryRoot(path36);
5389
+ return this.getGitRepositoryRoot(path37);
5362
5390
  } catch {
5363
5391
  return null;
5364
5392
  }
@@ -6623,10 +6651,10 @@ var PackmindHttpClient = class {
6623
6651
  return null;
6624
6652
  }
6625
6653
  }
6626
- async request(path36, options = {}) {
6654
+ async request(path37, options = {}) {
6627
6655
  const { host } = this.getAuthContext();
6628
6656
  const { method = "GET", body } = options;
6629
- const url = `${host}${path36}`;
6657
+ const url = `${host}${path37}`;
6630
6658
  try {
6631
6659
  const response = await fetch(url, {
6632
6660
  method,
@@ -6838,6 +6866,21 @@ var SpacesGateway = class {
6838
6866
  );
6839
6867
  };
6840
6868
  }
6869
+ async getSpaceBySlug(slug3) {
6870
+ const { organizationId } = this.httpClient.getAuthContext();
6871
+ try {
6872
+ return await this.httpClient.request(
6873
+ `/api/v0/organizations/${organizationId}/spaces/${slug3}`
6874
+ );
6875
+ } catch (error) {
6876
+ if (error.statusCode === 404) return null;
6877
+ throw error;
6878
+ }
6879
+ }
6880
+ getApiContext() {
6881
+ const { host, organizationId } = this.httpClient.getAuthContext();
6882
+ return { host, organizationId };
6883
+ }
6841
6884
  };
6842
6885
 
6843
6886
  // apps/cli/src/infra/repositories/SkillsGateway.ts
@@ -7026,6 +7069,21 @@ var DeploymentGateway = class {
7026
7069
  `/api/v0/organizations/${organizationId}/pull?${queryParams.toString()}`
7027
7070
  );
7028
7071
  };
7072
+ this.install = async (command33) => {
7073
+ const { organizationId } = this.httpClient.getAuthContext();
7074
+ return this.httpClient.request(
7075
+ `/api/v0/organizations/${organizationId}/install`,
7076
+ {
7077
+ method: "POST",
7078
+ body: {
7079
+ packagesSlugs: command33.packagesSlugs,
7080
+ packmindLockFile: command33.packmindLockFile,
7081
+ ...command33.relativePath && { relativePath: command33.relativePath },
7082
+ ...command33.agents !== void 0 && { agents: command33.agents }
7083
+ }
7084
+ }
7085
+ );
7086
+ };
7029
7087
  this.getDeployed = async (command33) => {
7030
7088
  const { organizationId } = this.httpClient.getAuthContext();
7031
7089
  return this.httpClient.request(
@@ -7065,6 +7123,21 @@ var DeploymentGateway = class {
7065
7123
  }
7066
7124
  );
7067
7125
  };
7126
+ this.notifyArtefactsDistribution = async (command33) => {
7127
+ const { organizationId } = this.httpClient.getAuthContext();
7128
+ return this.httpClient.request(
7129
+ `/api/v0/organizations/${organizationId}/deployments/notify-artifacts-distribution`,
7130
+ {
7131
+ method: "POST",
7132
+ body: {
7133
+ gitRemoteUrl: command33.gitRemoteUrl,
7134
+ gitBranch: command33.gitBranch,
7135
+ relativePath: command33.relativePath,
7136
+ packmindLockFile: command33.packmindLockFile
7137
+ }
7138
+ }
7139
+ );
7140
+ };
7068
7141
  this.getRenderModeConfiguration = async () => {
7069
7142
  const { organizationId } = this.httpClient.getAuthContext();
7070
7143
  return this.httpClient.request(
@@ -7086,6 +7159,24 @@ var DeploymentGateway = class {
7086
7159
  }
7087
7160
  };
7088
7161
 
7162
+ // apps/cli/src/infra/repositories/OrganizationGateway.ts
7163
+ var OrganizationGateway = class {
7164
+ constructor(httpClient) {
7165
+ this.httpClient = httpClient;
7166
+ }
7167
+ async getOrganization() {
7168
+ const { organizationId } = this.httpClient.getAuthContext();
7169
+ const organizations = await this.httpClient.request(
7170
+ "/api/v0/organizations"
7171
+ );
7172
+ const org = organizations.find((o) => o.id === organizationId);
7173
+ if (!org) {
7174
+ throw new Error(`Organization ${organizationId} not found`);
7175
+ }
7176
+ return org;
7177
+ }
7178
+ };
7179
+
7089
7180
  // apps/cli/src/infra/repositories/PackmindGateway.ts
7090
7181
  var PackmindGateway = class {
7091
7182
  constructor(apiKey) {
@@ -7100,6 +7191,7 @@ var PackmindGateway = class {
7100
7191
  this.standards = new StandardsGateway(this.httpClient);
7101
7192
  this.packages = new PackagesGateway(apiKey, this.httpClient);
7102
7193
  this.deployment = new DeploymentGateway(this.httpClient);
7194
+ this.organization = new OrganizationGateway(this.httpClient);
7103
7195
  }
7104
7196
  };
7105
7197
 
@@ -9927,69 +10019,150 @@ ${endMarker}`;
9927
10019
  }
9928
10020
  };
9929
10021
 
9930
- // apps/cli/src/application/useCases/InstallDefaultSkillsUseCase.ts
10022
+ // apps/cli/src/application/useCases/InstallUseCase.ts
9931
10023
  var fs5 = __toESM(require("fs/promises"));
9932
10024
  var path7 = __toESM(require("path"));
9933
- var import_semver = __toESM(require("semver"));
9934
- var InstallDefaultSkillsUseCase = class {
9935
- constructor(repositories) {
9936
- this.repositories = repositories;
10025
+
10026
+ // apps/cli/src/application/utils/normalizePackageSlugs.ts
10027
+ async function normalizePackageSlugs(slugs, spaceService) {
10028
+ const hasUnprefixed = slugs.some((s) => !s.startsWith("@"));
10029
+ if (!hasUnprefixed) return slugs;
10030
+ const spaces = await spaceService.getSpaces();
10031
+ if (spaces.length > 1) {
10032
+ throw new Error(
10033
+ `Your organization has multiple spaces. Please specify the space for each package using the @space/package format (e.g. @${spaces[0].slug}/my-package).`
10034
+ );
10035
+ }
10036
+ const defaultSpace = await spaceService.getDefaultSpace();
10037
+ return slugs.map(
10038
+ (slug3) => slug3.startsWith("@") ? slug3 : `@${defaultSpace.slug}/${slug3}`
10039
+ );
10040
+ }
10041
+
10042
+ // apps/cli/src/application/useCases/InstallUseCase.ts
10043
+ var InstallUseCase = class {
10044
+ constructor(packmindGateway, lockFileRepository, configFileRepository, spaceService) {
10045
+ this.packmindGateway = packmindGateway;
10046
+ this.lockFileRepository = lockFileRepository;
10047
+ this.configFileRepository = configFileRepository;
10048
+ this.spaceService = spaceService;
9937
10049
  }
9938
10050
  async execute(command33) {
9939
10051
  const baseDirectory = command33.baseDirectory || process.cwd();
9940
10052
  const result = {
9941
10053
  filesCreated: 0,
9942
10054
  filesUpdated: 0,
10055
+ filesDeleted: 0,
10056
+ contentFilesChanged: 0,
9943
10057
  errors: [],
9944
- skippedSkillsCount: 0,
9945
- skippedIncompatibleSkillNames: [],
9946
- incompatibleInstalledSkills: []
10058
+ recipesCount: 0,
10059
+ standardsCount: 0,
10060
+ commandsCount: 0,
10061
+ skillsCount: 0,
10062
+ recipesRemoved: 0,
10063
+ standardsRemoved: 0,
10064
+ commandsRemoved: 0,
10065
+ skillsRemoved: 0,
10066
+ skillDirectoriesDeleted: 0,
10067
+ missingAccess: []
9947
10068
  };
9948
- const config = await this.repositories.configFileRepository.readConfig(baseDirectory);
9949
- const agents = config?.agents;
9950
- const response = await this.repositories.packmindGateway.skills.getDefaults(
9951
- {
9952
- cliVersion: command33.cliVersion,
9953
- includeBeta: command33.includeBeta,
9954
- agents
10069
+ const hasExplicitPackages = command33.packages && command33.packages.length > 0;
10070
+ const lockFile = await this.lockFileRepository.read(baseDirectory);
10071
+ const config = await this.configFileRepository.readConfig(baseDirectory);
10072
+ if (!config && !hasExplicitPackages) {
10073
+ const configFileExists = await this.configFileRepository.configExists(baseDirectory);
10074
+ if (configFileExists) {
10075
+ throw new Error(
10076
+ "packmind.json exists but could not be parsed. Please fix the JSON syntax errors and try again."
10077
+ );
9955
10078
  }
9956
- );
9957
- result.skippedSkillsCount = response.skippedSkillsCount;
9958
- const incompatibleInstalledMap = /* @__PURE__ */ new Map();
9959
- const incompatibleSkillDirs = /* @__PURE__ */ new Map();
9960
- if (command33.cliVersion) {
9961
- for (const file of response.fileUpdates.createOrUpdate) {
9962
- if (path7.basename(file.path) === "SKILL.md" && file.content && this.isVersionConstraintViolated(file.content, command33.cliVersion)) {
9963
- const dir = path7.dirname(file.path);
9964
- const skillName = this.getSkillName(file.content) ?? path7.basename(dir);
9965
- incompatibleSkillDirs.set(dir, skillName);
10079
+ throw new Error(
10080
+ "No packmind.json found in this directory. Run `packmind-cli install <@space/package>` first to install your packages."
10081
+ );
10082
+ }
10083
+ const effectiveLockFile = lockFile ?? {
10084
+ lockfileVersion: 1,
10085
+ packageSlugs: [],
10086
+ agents: [],
10087
+ installedAt: (/* @__PURE__ */ new Date()).toISOString(),
10088
+ artifacts: {}
10089
+ };
10090
+ let packagesSlugs;
10091
+ let normalizedPackages = [];
10092
+ if (hasExplicitPackages) {
10093
+ normalizedPackages = await this.normalizePackageSlugs(command33.packages);
10094
+ await this.validatePackageAccess(normalizedPackages);
10095
+ const normalizedConfigPackages = config ? await this.normalizeAndSaveConfigPackages(baseDirectory, config) : [];
10096
+ packagesSlugs = [
10097
+ .../* @__PURE__ */ new Set([...normalizedConfigPackages, ...normalizedPackages])
10098
+ ];
10099
+ } else {
10100
+ packagesSlugs = await this.normalizeAndSaveConfigPackages(
10101
+ baseDirectory,
10102
+ config
10103
+ );
10104
+ }
10105
+ if (packagesSlugs.length === 0) {
10106
+ try {
10107
+ for (const entry of Object.values(effectiveLockFile.artifacts)) {
10108
+ for (const file of entry.files) {
10109
+ await this.deleteFile(baseDirectory, file.path, result);
10110
+ }
9966
10111
  }
10112
+ await this.deleteFile(baseDirectory, "packmind-lock.json", result);
10113
+ } catch (error) {
10114
+ const errorMsg = error instanceof Error ? error.message : String(error);
10115
+ result.errors.push(`Failed to clean up artifacts: ${errorMsg}`);
10116
+ }
10117
+ return result;
10118
+ }
10119
+ const response = await this.packmindGateway.deployment.install({
10120
+ packagesSlugs,
10121
+ packmindLockFile: effectiveLockFile,
10122
+ agents: config?.agents
10123
+ });
10124
+ result.missingAccess = response.missingAccess;
10125
+ if (result.missingAccess.length > 0) {
10126
+ result.joinSpaceUrl = await this.computeJoinSpaceUrl(
10127
+ result.missingAccess
10128
+ );
10129
+ }
10130
+ const filteredCreateOrUpdate = response.fileUpdates.createOrUpdate.filter(
10131
+ (file) => file.path !== "packmind.json"
10132
+ );
10133
+ const uniqueFilesMap = /* @__PURE__ */ new Map();
10134
+ for (const file of filteredCreateOrUpdate) {
10135
+ uniqueFilesMap.set(file.path, file);
10136
+ }
10137
+ const uniqueFiles = Array.from(uniqueFilesMap.values());
10138
+ for (const file of uniqueFiles) {
10139
+ if (file.path.includes(".packmind/recipes/") && file.path.endsWith(".md")) {
10140
+ result.recipesCount++;
10141
+ } else if (file.path.includes(".packmind/standards/") && file.path.endsWith(".md")) {
10142
+ result.standardsCount++;
10143
+ } else if (file.path.includes(".packmind/commands/") && file.path.endsWith(".md")) {
10144
+ result.commandsCount++;
10145
+ } else if (file.path.includes(".packmind/skills/") && file.path.endsWith(".md")) {
10146
+ result.skillsCount++;
9967
10147
  }
9968
10148
  }
9969
10149
  try {
9970
- for (const file of response.fileUpdates.createOrUpdate) {
10150
+ result.skillDirectoriesDeleted = await this.deleteSkillFolders(
10151
+ baseDirectory,
10152
+ response.skillFolders
10153
+ );
10154
+ for (const file of uniqueFiles) {
9971
10155
  try {
9972
- if (!file.content) continue;
9973
- const isIncompatible = command33.cliVersion && (this.isVersionConstraintViolated(
9974
- file.content,
9975
- command33.cliVersion
9976
- ) || incompatibleSkillDirs.has(path7.dirname(file.path)));
9977
- if (isIncompatible) {
9978
- const skillName = this.getSkillName(file.content) ?? incompatibleSkillDirs.get(path7.dirname(file.path)) ?? path7.basename(file.path);
9979
- const fullPath = path7.join(baseDirectory, file.path);
9980
- const fileAlreadyInstalled = await this.fileExists(fullPath);
9981
- if (fileAlreadyInstalled) {
9982
- const paths = incompatibleInstalledMap.get(skillName) ?? [];
9983
- paths.push(file.path);
9984
- incompatibleInstalledMap.set(skillName, paths);
9985
- } else {
9986
- if (!result.skippedIncompatibleSkillNames.includes(skillName)) {
9987
- result.skippedIncompatibleSkillNames.push(skillName);
9988
- }
9989
- }
9990
- continue;
10156
+ const changesBefore = result.filesCreated + result.filesUpdated;
10157
+ await this.createOrUpdateFile(
10158
+ baseDirectory,
10159
+ file,
10160
+ result,
10161
+ file.skillFilePermissions
10162
+ );
10163
+ if (result.filesCreated + result.filesUpdated > changesBefore && this.isContentFile(file.path)) {
10164
+ result.contentFilesChanged++;
9991
10165
  }
9992
- await this.createOrUpdateFile(baseDirectory, file, result);
9993
10166
  } catch (error) {
9994
10167
  const errorMsg = error instanceof Error ? error.message : String(error);
9995
10168
  result.errors.push(
@@ -9997,46 +10170,469 @@ var InstallDefaultSkillsUseCase = class {
9997
10170
  );
9998
10171
  }
9999
10172
  }
10173
+ for (const file of response.fileUpdates.delete) {
10174
+ try {
10175
+ const deletedBefore = result.filesDeleted;
10176
+ await this.deleteFile(baseDirectory, file.path, result);
10177
+ if (result.filesDeleted > deletedBefore) {
10178
+ if (file.path.includes(".packmind/standards/") && file.path.endsWith(".md")) {
10179
+ result.standardsRemoved++;
10180
+ result.contentFilesChanged++;
10181
+ } else if (file.path.includes(".packmind/commands/") && file.path.endsWith(".md")) {
10182
+ result.commandsRemoved++;
10183
+ result.contentFilesChanged++;
10184
+ } else if (file.path.includes(".packmind/skills/") && file.path.endsWith(".md")) {
10185
+ result.skillsRemoved++;
10186
+ result.contentFilesChanged++;
10187
+ } else if (file.path.includes(".packmind/recipes/") && file.path.endsWith(".md")) {
10188
+ result.recipesRemoved++;
10189
+ result.contentFilesChanged++;
10190
+ }
10191
+ }
10192
+ } catch (error) {
10193
+ const errorMsg = error instanceof Error ? error.message : String(error);
10194
+ result.errors.push(`Failed to delete ${file.path}: ${errorMsg}`);
10195
+ }
10196
+ }
10000
10197
  } catch (error) {
10001
10198
  const errorMsg = error instanceof Error ? error.message : String(error);
10002
- result.errors.push(`Failed to install default skills: ${errorMsg}`);
10199
+ result.errors.push(`Failed to install packages: ${errorMsg}`);
10200
+ }
10201
+ if (normalizedPackages.length > 0) {
10202
+ await this.configFileRepository.addPackagesToConfig(
10203
+ baseDirectory,
10204
+ normalizedPackages
10205
+ );
10003
10206
  }
10004
- result.incompatibleInstalledSkills = Array.from(
10005
- incompatibleInstalledMap.entries()
10006
- ).map(
10007
- ([skillName, filePaths]) => ({
10008
- skillName,
10009
- filePaths
10010
- })
10011
- );
10012
10207
  return result;
10013
10208
  }
10014
- async createOrUpdateFile(baseDirectory, file, result) {
10209
+ async normalizePackageSlugs(slugs) {
10210
+ return normalizePackageSlugs(slugs, this.spaceService);
10211
+ }
10212
+ async normalizeAndSaveConfigPackages(baseDirectory, config) {
10213
+ const originalSlugs = Object.keys(config.packages);
10214
+ if (originalSlugs.length === 0) return [];
10215
+ const normalizedSlugs = await this.normalizePackageSlugs(originalSlugs);
10216
+ const hasChanges = normalizedSlugs.some(
10217
+ (slug3, i) => slug3 !== originalSlugs[i]
10218
+ );
10219
+ if (hasChanges) {
10220
+ const normalizedPackagesMap = {};
10221
+ for (let i = 0; i < normalizedSlugs.length; i++) {
10222
+ normalizedPackagesMap[normalizedSlugs[i]] = config.packages[originalSlugs[i]];
10223
+ }
10224
+ await this.configFileRepository.updateConfig(
10225
+ baseDirectory,
10226
+ "packages",
10227
+ normalizedPackagesMap
10228
+ );
10229
+ }
10230
+ return normalizedSlugs;
10231
+ }
10232
+ async validatePackageAccess(packages) {
10233
+ const userSpaces = await this.spaceService.getSpaces();
10234
+ const userSpaceSlugs = new Set(userSpaces.map((s) => s.slug));
10235
+ const { host } = this.spaceService.getApiContext();
10236
+ const errors = [];
10237
+ for (const pkg of packages) {
10238
+ const spaceSlug = pkg.startsWith("@") ? pkg.slice(1).split("/")[0] : null;
10239
+ if (!spaceSlug || userSpaceSlugs.has(spaceSlug)) continue;
10240
+ const space = await this.spaceService.getSpaceBySlug(spaceSlug);
10241
+ if (!space || space.type === "private" /* private */) {
10242
+ errors.push(`Package ${pkg} does not exist.`);
10243
+ } else {
10244
+ const organization = await this.packmindGateway.organization.getOrganization();
10245
+ const joinUrl = `${host}/org/${organization.slug}/spaces/${spaceSlug}/join`;
10246
+ errors.push(
10247
+ `You don't have access to space @${spaceSlug}. It is a public space \u2014 you can join at: ${joinUrl}`
10248
+ );
10249
+ }
10250
+ }
10251
+ if (errors.length > 0) {
10252
+ throw new Error(errors.join("\n"));
10253
+ }
10254
+ }
10255
+ async computeJoinSpaceUrl(missingAccessSlugs) {
10256
+ const spaceSlugs = /* @__PURE__ */ new Set();
10257
+ for (const slug3 of missingAccessSlugs) {
10258
+ if (slug3.startsWith("@")) {
10259
+ const spaceSlug2 = slug3.slice(1).split("/")[0];
10260
+ spaceSlugs.add(spaceSlug2);
10261
+ }
10262
+ }
10263
+ if (spaceSlugs.size !== 1) return void 0;
10264
+ const [spaceSlug] = spaceSlugs;
10265
+ const space = await this.spaceService.getSpaceBySlug(spaceSlug);
10266
+ if (!space || space.type !== "open" /* open */) return void 0;
10267
+ const organization = await this.packmindGateway.organization.getOrganization();
10268
+ const { host } = this.spaceService.getApiContext();
10269
+ return `${host}/org/${organization.slug}/spaces/${spaceSlug}/join`;
10270
+ }
10271
+ async createOrUpdateFile(baseDirectory, file, result, skillFilePermissions) {
10015
10272
  const fullPath = path7.join(baseDirectory, file.path);
10016
10273
  const directory = path7.dirname(fullPath);
10017
10274
  await fs5.mkdir(directory, { recursive: true });
10018
10275
  const fileExists = await this.fileExists(fullPath);
10276
+ if (file.content !== void 0) {
10277
+ await this.handleFullContentUpdate(
10278
+ fullPath,
10279
+ file.content,
10280
+ fileExists,
10281
+ result,
10282
+ file.isBase64
10283
+ );
10284
+ } else if (file.sections !== void 0) {
10285
+ await this.handleSectionsUpdate(
10286
+ fullPath,
10287
+ file.sections,
10288
+ fileExists,
10289
+ result,
10290
+ baseDirectory
10291
+ );
10292
+ }
10293
+ if (skillFilePermissions && supportsUnixPermissions()) {
10294
+ await fs5.chmod(fullPath, parsePermissionString(skillFilePermissions));
10295
+ }
10296
+ }
10297
+ async handleFullContentUpdate(fullPath, content, fileExists, result, isBase64) {
10298
+ if (isBase64) {
10299
+ const buffer = Buffer.from(content, "base64");
10300
+ await fs5.writeFile(fullPath, buffer);
10301
+ if (fileExists) {
10302
+ result.filesUpdated++;
10303
+ } else {
10304
+ result.filesCreated++;
10305
+ }
10306
+ return;
10307
+ }
10019
10308
  if (fileExists) {
10020
10309
  const existingContent = await fs5.readFile(fullPath, "utf-8");
10021
- if (existingContent !== file.content) {
10022
- await fs5.writeFile(fullPath, file.content, "utf-8");
10310
+ const commentMarker = this.extractCommentMarker(content);
10311
+ let finalContent;
10312
+ if (!commentMarker) {
10313
+ finalContent = content;
10314
+ } else {
10315
+ finalContent = this.mergeContentWithMarkers(
10316
+ existingContent,
10317
+ content,
10318
+ commentMarker
10319
+ );
10320
+ }
10321
+ if (existingContent !== finalContent) {
10322
+ await fs5.writeFile(fullPath, finalContent, "utf-8");
10023
10323
  result.filesUpdated++;
10024
10324
  }
10025
10325
  } else {
10026
- await fs5.writeFile(fullPath, file.content, "utf-8");
10326
+ await fs5.writeFile(fullPath, content, "utf-8");
10027
10327
  result.filesCreated++;
10028
10328
  }
10029
10329
  }
10030
- async fileExists(filePath) {
10031
- try {
10032
- await fs5.access(filePath);
10033
- return true;
10034
- } catch {
10035
- return false;
10330
+ async handleSectionsUpdate(fullPath, sections, fileExists, result, baseDirectory) {
10331
+ let currentContent = "";
10332
+ if (fileExists) {
10333
+ currentContent = await fs5.readFile(fullPath, "utf-8");
10036
10334
  }
10037
- }
10038
- /**
10039
- * Returns true if the skill's `metadata.packmind-cli-version` constraint
10335
+ const mergedContent = mergeSectionsIntoFileContent(
10336
+ currentContent,
10337
+ sections
10338
+ );
10339
+ if (currentContent !== mergedContent) {
10340
+ if (this.isEffectivelyEmpty(mergedContent) && fileExists) {
10341
+ await fs5.unlink(fullPath);
10342
+ result.filesDeleted++;
10343
+ await this.removeEmptyParentDirectories(fullPath, baseDirectory);
10344
+ } else {
10345
+ await fs5.writeFile(fullPath, mergedContent, "utf-8");
10346
+ if (fileExists) {
10347
+ result.filesUpdated++;
10348
+ } else {
10349
+ result.filesCreated++;
10350
+ }
10351
+ }
10352
+ }
10353
+ }
10354
+ async deleteFile(baseDirectory, filePath, result) {
10355
+ const fullPath = path7.join(baseDirectory, filePath);
10356
+ const stat9 = await fs5.stat(fullPath).catch(() => null);
10357
+ if (stat9?.isDirectory()) {
10358
+ await fs5.rm(fullPath, { recursive: true, force: true });
10359
+ result.filesDeleted++;
10360
+ await this.removeEmptyParentDirectories(fullPath, baseDirectory);
10361
+ } else if (stat9?.isFile()) {
10362
+ await fs5.unlink(fullPath);
10363
+ result.filesDeleted++;
10364
+ await this.removeEmptyParentDirectories(fullPath, baseDirectory);
10365
+ }
10366
+ }
10367
+ isContentFile(filePath) {
10368
+ return (filePath.includes(".packmind/standards/") || filePath.includes(".packmind/commands/") || filePath.includes(".packmind/skills/") || filePath.includes(".packmind/recipes/")) && filePath.endsWith(".md");
10369
+ }
10370
+ async fileExists(filePath) {
10371
+ try {
10372
+ await fs5.access(filePath);
10373
+ return true;
10374
+ } catch {
10375
+ return false;
10376
+ }
10377
+ }
10378
+ extractCommentMarker(content) {
10379
+ const startMarkerPattern = /<!--\s*start:\s*([^-]+?)\s*-->/;
10380
+ const match = content.match(startMarkerPattern);
10381
+ return match ? match[1].trim() : null;
10382
+ }
10383
+ mergeContentWithMarkers(existingContent, newContent, commentMarker) {
10384
+ const startMarker = `<!-- start: ${commentMarker} -->`;
10385
+ const endMarker = `<!-- end: ${commentMarker} -->`;
10386
+ const newSectionPattern = new RegExp(
10387
+ `${this.escapeRegex(startMarker)}([\\s\\S]*?)${this.escapeRegex(endMarker)}`
10388
+ );
10389
+ const newSectionMatch = newContent.match(newSectionPattern);
10390
+ const newSectionContent = newSectionMatch ? newSectionMatch[1].trim() : newContent;
10391
+ const existingSectionPattern = new RegExp(
10392
+ `${this.escapeRegex(startMarker)}[\\s\\S]*?${this.escapeRegex(endMarker)}`,
10393
+ "g"
10394
+ );
10395
+ if (existingSectionPattern.test(existingContent)) {
10396
+ return existingContent.replace(
10397
+ existingSectionPattern,
10398
+ `${startMarker}
10399
+ ${newSectionContent}
10400
+ ${endMarker}`
10401
+ );
10402
+ } else {
10403
+ return `${existingContent}
10404
+ ${startMarker}
10405
+ ${newSectionContent}
10406
+ ${endMarker}`;
10407
+ }
10408
+ }
10409
+ isEffectivelyEmpty(content) {
10410
+ const withoutEmptySections = content.replace(
10411
+ /<!--\s*start:\s*[^-]+?\s*-->\s*<!--\s*end:\s*[^-]+?\s*-->/g,
10412
+ ""
10413
+ );
10414
+ return withoutEmptySections.trim() === "";
10415
+ }
10416
+ escapeRegex(str) {
10417
+ return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
10418
+ }
10419
+ async deleteSkillFolders(baseDirectory, folders) {
10420
+ let deletedFilesCount = 0;
10421
+ for (const folder of folders) {
10422
+ const fullPath = path7.join(baseDirectory, folder);
10423
+ try {
10424
+ await fs5.access(fullPath);
10425
+ const fileCount = await this.countFilesInDirectory(fullPath);
10426
+ await fs5.rm(fullPath, { recursive: true, force: true });
10427
+ deletedFilesCount += fileCount;
10428
+ await this.removeEmptyParentDirectories(fullPath, baseDirectory);
10429
+ } catch {
10430
+ }
10431
+ }
10432
+ return deletedFilesCount;
10433
+ }
10434
+ async countFilesInDirectory(dirPath) {
10435
+ let count = 0;
10436
+ const entries = await fs5.readdir(dirPath, { withFileTypes: true });
10437
+ for (const entry of entries) {
10438
+ const entryPath = path7.join(dirPath, entry.name);
10439
+ if (entry.isDirectory()) {
10440
+ count += await this.countFilesInDirectory(entryPath);
10441
+ } else {
10442
+ count++;
10443
+ }
10444
+ }
10445
+ return count;
10446
+ }
10447
+ async isDirectoryEmpty(dirPath) {
10448
+ try {
10449
+ const entries = await fs5.readdir(dirPath);
10450
+ return entries.length === 0;
10451
+ } catch {
10452
+ return false;
10453
+ }
10454
+ }
10455
+ async removeEmptyParentDirectories(fullPath, baseDirectory) {
10456
+ const normalizedBase = path7.resolve(baseDirectory);
10457
+ let currentDir = path7.dirname(path7.resolve(fullPath));
10458
+ while (currentDir.startsWith(normalizedBase + path7.sep) && currentDir !== normalizedBase) {
10459
+ const isEmpty = await this.isDirectoryEmpty(currentDir);
10460
+ if (!isEmpty) break;
10461
+ try {
10462
+ await fs5.rmdir(currentDir);
10463
+ } catch {
10464
+ break;
10465
+ }
10466
+ currentDir = path7.dirname(currentDir);
10467
+ }
10468
+ }
10469
+ };
10470
+
10471
+ // apps/cli/src/application/useCases/UninstallUseCase.ts
10472
+ var UninstallUseCase = class {
10473
+ constructor(configFileRepository, spaceService, installUseCase) {
10474
+ this.configFileRepository = configFileRepository;
10475
+ this.spaceService = spaceService;
10476
+ this.installUseCase = installUseCase;
10477
+ }
10478
+ async execute(command33) {
10479
+ const baseDirectory = command33.baseDirectory || process.cwd();
10480
+ const config = await this.configFileRepository.readConfig(baseDirectory);
10481
+ if (!config) {
10482
+ const configFileExists = await this.configFileRepository.configExists(baseDirectory);
10483
+ if (configFileExists) {
10484
+ throw new Error(
10485
+ "packmind.json exists but could not be parsed. Please fix the JSON syntax errors and try again."
10486
+ );
10487
+ }
10488
+ throw new Error(
10489
+ "No packmind.json found in this directory. Run `packmind-cli install <@space/package>` first to install your packages."
10490
+ );
10491
+ }
10492
+ const normalized = await normalizePackageSlugs(
10493
+ command33.packages,
10494
+ this.spaceService
10495
+ );
10496
+ const notInstalled = normalized.filter((pkg) => !(pkg in config.packages));
10497
+ if (notInstalled.length > 0) {
10498
+ const pkgList = notInstalled.map((p) => ` - ${p}`).join("\n");
10499
+ throw new Error(
10500
+ `The following package${notInstalled.length > 1 ? "s are" : " is"} not installed:
10501
+ ${pkgList}`
10502
+ );
10503
+ }
10504
+ const updatedPackages = { ...config.packages };
10505
+ for (const pkg of normalized) {
10506
+ delete updatedPackages[pkg];
10507
+ }
10508
+ await this.configFileRepository.updateConfig(
10509
+ baseDirectory,
10510
+ "packages",
10511
+ updatedPackages
10512
+ );
10513
+ try {
10514
+ return await this.installUseCase.execute({ baseDirectory });
10515
+ } catch (error) {
10516
+ await this.configFileRepository.updateConfig(
10517
+ baseDirectory,
10518
+ "packages",
10519
+ config.packages
10520
+ );
10521
+ throw error;
10522
+ }
10523
+ }
10524
+ };
10525
+
10526
+ // apps/cli/src/application/useCases/InstallDefaultSkillsUseCase.ts
10527
+ var fs6 = __toESM(require("fs/promises"));
10528
+ var path8 = __toESM(require("path"));
10529
+ var import_semver = __toESM(require("semver"));
10530
+ var InstallDefaultSkillsUseCase = class {
10531
+ constructor(repositories) {
10532
+ this.repositories = repositories;
10533
+ }
10534
+ async execute(command33) {
10535
+ const baseDirectory = command33.baseDirectory || process.cwd();
10536
+ const result = {
10537
+ filesCreated: 0,
10538
+ filesUpdated: 0,
10539
+ errors: [],
10540
+ skippedSkillsCount: 0,
10541
+ skippedIncompatibleSkillNames: [],
10542
+ incompatibleInstalledSkills: []
10543
+ };
10544
+ const config = await this.repositories.configFileRepository.readConfig(baseDirectory);
10545
+ const agents = config?.agents;
10546
+ const response = await this.repositories.packmindGateway.skills.getDefaults(
10547
+ {
10548
+ cliVersion: command33.cliVersion,
10549
+ includeBeta: command33.includeBeta,
10550
+ agents
10551
+ }
10552
+ );
10553
+ result.skippedSkillsCount = response.skippedSkillsCount;
10554
+ const incompatibleInstalledMap = /* @__PURE__ */ new Map();
10555
+ const incompatibleSkillDirs = /* @__PURE__ */ new Map();
10556
+ if (command33.cliVersion) {
10557
+ for (const file of response.fileUpdates.createOrUpdate) {
10558
+ if (path8.basename(file.path) === "SKILL.md" && file.content && this.isVersionConstraintViolated(file.content, command33.cliVersion)) {
10559
+ const dir = path8.dirname(file.path);
10560
+ const skillName = this.getSkillName(file.content) ?? path8.basename(dir);
10561
+ incompatibleSkillDirs.set(dir, skillName);
10562
+ }
10563
+ }
10564
+ }
10565
+ try {
10566
+ for (const file of response.fileUpdates.createOrUpdate) {
10567
+ try {
10568
+ if (!file.content) continue;
10569
+ const isIncompatible = command33.cliVersion && (this.isVersionConstraintViolated(
10570
+ file.content,
10571
+ command33.cliVersion
10572
+ ) || incompatibleSkillDirs.has(path8.dirname(file.path)));
10573
+ if (isIncompatible) {
10574
+ const skillName = this.getSkillName(file.content) ?? incompatibleSkillDirs.get(path8.dirname(file.path)) ?? path8.basename(file.path);
10575
+ const fullPath = path8.join(baseDirectory, file.path);
10576
+ const fileAlreadyInstalled = await this.fileExists(fullPath);
10577
+ if (fileAlreadyInstalled) {
10578
+ const paths = incompatibleInstalledMap.get(skillName) ?? [];
10579
+ paths.push(file.path);
10580
+ incompatibleInstalledMap.set(skillName, paths);
10581
+ } else {
10582
+ if (!result.skippedIncompatibleSkillNames.includes(skillName)) {
10583
+ result.skippedIncompatibleSkillNames.push(skillName);
10584
+ }
10585
+ }
10586
+ continue;
10587
+ }
10588
+ await this.createOrUpdateFile(baseDirectory, file, result);
10589
+ } catch (error) {
10590
+ const errorMsg = error instanceof Error ? error.message : String(error);
10591
+ result.errors.push(
10592
+ `Failed to create/update ${file.path}: ${errorMsg}`
10593
+ );
10594
+ }
10595
+ }
10596
+ } catch (error) {
10597
+ const errorMsg = error instanceof Error ? error.message : String(error);
10598
+ result.errors.push(`Failed to install default skills: ${errorMsg}`);
10599
+ }
10600
+ result.incompatibleInstalledSkills = Array.from(
10601
+ incompatibleInstalledMap.entries()
10602
+ ).map(
10603
+ ([skillName, filePaths]) => ({
10604
+ skillName,
10605
+ filePaths
10606
+ })
10607
+ );
10608
+ return result;
10609
+ }
10610
+ async createOrUpdateFile(baseDirectory, file, result) {
10611
+ const fullPath = path8.join(baseDirectory, file.path);
10612
+ const directory = path8.dirname(fullPath);
10613
+ await fs6.mkdir(directory, { recursive: true });
10614
+ const fileExists = await this.fileExists(fullPath);
10615
+ if (fileExists) {
10616
+ const existingContent = await fs6.readFile(fullPath, "utf-8");
10617
+ if (existingContent !== file.content) {
10618
+ await fs6.writeFile(fullPath, file.content, "utf-8");
10619
+ result.filesUpdated++;
10620
+ }
10621
+ } else {
10622
+ await fs6.writeFile(fullPath, file.content, "utf-8");
10623
+ result.filesCreated++;
10624
+ }
10625
+ }
10626
+ async fileExists(filePath) {
10627
+ try {
10628
+ await fs6.access(filePath);
10629
+ return true;
10630
+ } catch {
10631
+ return false;
10632
+ }
10633
+ }
10634
+ /**
10635
+ * Returns true if the skill's `metadata.packmind-cli-version` constraint
10040
10636
  * is present AND the given CLI version does NOT satisfy it (i.e. the skill
10041
10637
  * is meant for an older CLI version than the one running).
10042
10638
  */
@@ -10148,13 +10744,13 @@ var EnvCredentialsProvider = class {
10148
10744
  };
10149
10745
 
10150
10746
  // apps/cli/src/infra/utils/credentials/FileCredentialsProvider.ts
10151
- var fs6 = __toESM(require("fs"));
10152
- var path8 = __toESM(require("path"));
10747
+ var fs7 = __toESM(require("fs"));
10748
+ var path9 = __toESM(require("path"));
10153
10749
  var os2 = __toESM(require("os"));
10154
10750
  var CREDENTIALS_DIR = ".packmind";
10155
10751
  var CREDENTIALS_FILE = "credentials.json";
10156
10752
  function getCredentialsPath() {
10157
- return path8.join(os2.homedir(), CREDENTIALS_DIR, CREDENTIALS_FILE);
10753
+ return path9.join(os2.homedir(), CREDENTIALS_DIR, CREDENTIALS_FILE);
10158
10754
  }
10159
10755
  var FileCredentialsProvider = class {
10160
10756
  getSourceName() {
@@ -10162,11 +10758,11 @@ var FileCredentialsProvider = class {
10162
10758
  }
10163
10759
  hasCredentials() {
10164
10760
  const credentialsPath = getCredentialsPath();
10165
- if (!fs6.existsSync(credentialsPath)) {
10761
+ if (!fs7.existsSync(credentialsPath)) {
10166
10762
  return false;
10167
10763
  }
10168
10764
  try {
10169
- const content = fs6.readFileSync(credentialsPath, "utf-8");
10765
+ const content = fs7.readFileSync(credentialsPath, "utf-8");
10170
10766
  const credentials = JSON.parse(content);
10171
10767
  return !!credentials.apiKey;
10172
10768
  } catch {
@@ -10175,11 +10771,11 @@ var FileCredentialsProvider = class {
10175
10771
  }
10176
10772
  loadCredentials() {
10177
10773
  const credentialsPath = getCredentialsPath();
10178
- if (!fs6.existsSync(credentialsPath)) {
10774
+ if (!fs7.existsSync(credentialsPath)) {
10179
10775
  return null;
10180
10776
  }
10181
10777
  try {
10182
- const content = fs6.readFileSync(credentialsPath, "utf-8");
10778
+ const content = fs7.readFileSync(credentialsPath, "utf-8");
10183
10779
  const credentials = JSON.parse(content);
10184
10780
  if (!credentials.apiKey) {
10185
10781
  return null;
@@ -10202,13 +10798,13 @@ var FileCredentialsProvider = class {
10202
10798
  }
10203
10799
  };
10204
10800
  function saveCredentials(apiKey) {
10205
- const credentialsDir = path8.join(os2.homedir(), CREDENTIALS_DIR);
10206
- if (!fs6.existsSync(credentialsDir)) {
10207
- fs6.mkdirSync(credentialsDir, { recursive: true, mode: 448 });
10801
+ const credentialsDir = path9.join(os2.homedir(), CREDENTIALS_DIR);
10802
+ if (!fs7.existsSync(credentialsDir)) {
10803
+ fs7.mkdirSync(credentialsDir, { recursive: true, mode: 448 });
10208
10804
  }
10209
10805
  const credentialsPath = getCredentialsPath();
10210
10806
  const credentials = { apiKey };
10211
- fs6.writeFileSync(credentialsPath, JSON.stringify(credentials, null, 2), {
10807
+ fs7.writeFileSync(credentialsPath, JSON.stringify(credentials, null, 2), {
10212
10808
  mode: 384
10213
10809
  });
10214
10810
  }
@@ -10279,10 +10875,10 @@ async function defaultPromptForCode() {
10279
10875
  input: process.stdin,
10280
10876
  output: process.stdout
10281
10877
  });
10282
- return new Promise((resolve14) => {
10878
+ return new Promise((resolve15) => {
10283
10879
  rl.question("Enter the login code from the browser: ", (answer) => {
10284
10880
  rl.close();
10285
- resolve14(answer.trim());
10881
+ resolve15(answer.trim());
10286
10882
  });
10287
10883
  });
10288
10884
  }
@@ -10316,7 +10912,7 @@ async function defaultExchangeCodeForApiKey(code, host) {
10316
10912
  return await response.json();
10317
10913
  }
10318
10914
  function defaultStartCallbackServer() {
10319
- return new Promise((resolve14, reject) => {
10915
+ return new Promise((resolve15, reject) => {
10320
10916
  let timeoutId = null;
10321
10917
  const server = http.createServer((req, res) => {
10322
10918
  res.setHeader("Access-Control-Allow-Origin", "*");
@@ -10329,7 +10925,7 @@ function defaultStartCallbackServer() {
10329
10925
  if (timeoutId) {
10330
10926
  clearTimeout(timeoutId);
10331
10927
  }
10332
- resolve14(code);
10928
+ resolve15(code);
10333
10929
  setImmediate(() => {
10334
10930
  server.close();
10335
10931
  });
@@ -10400,14 +10996,14 @@ var LoginUseCase = class {
10400
10996
  };
10401
10997
 
10402
10998
  // apps/cli/src/application/useCases/LogoutUseCase.ts
10403
- var fs7 = __toESM(require("fs"));
10999
+ var fs8 = __toESM(require("fs"));
10404
11000
  var ENV_VAR_NAME2 = "PACKMIND_API_KEY_V3";
10405
11001
  var LogoutUseCase = class {
10406
11002
  constructor(deps) {
10407
11003
  this.deps = {
10408
11004
  getCredentialsPath: deps?.getCredentialsPath ?? getCredentialsPath,
10409
- fileExists: deps?.fileExists ?? ((path36) => fs7.existsSync(path36)),
10410
- deleteFile: deps?.deleteFile ?? ((path36) => fs7.unlinkSync(path36)),
11005
+ fileExists: deps?.fileExists ?? ((path37) => fs8.existsSync(path37)),
11006
+ deleteFile: deps?.deleteFile ?? ((path37) => fs8.unlinkSync(path37)),
10411
11007
  hasEnvVar: deps?.hasEnvVar ?? (() => !!process.env[ENV_VAR_NAME2])
10412
11008
  };
10413
11009
  }
@@ -10756,8 +11352,8 @@ var SetupMcpUseCase = class {
10756
11352
  };
10757
11353
 
10758
11354
  // apps/cli/src/application/services/McpConfigService.ts
10759
- var fs8 = __toESM(require("fs"));
10760
- var path10 = __toESM(require("path"));
11355
+ var fs9 = __toESM(require("fs"));
11356
+ var path11 = __toESM(require("path"));
10761
11357
  var os3 = __toESM(require("os"));
10762
11358
  var import_child_process3 = require("child_process");
10763
11359
  var McpConfigService = class {
@@ -10804,11 +11400,11 @@ var McpConfigService = class {
10804
11400
  }
10805
11401
  installCursorMcp(config) {
10806
11402
  try {
10807
- const cursorConfigPath = path10.join(os3.homedir(), ".cursor", "mcp.json");
11403
+ const cursorConfigPath = path11.join(os3.homedir(), ".cursor", "mcp.json");
10808
11404
  const cursorConfig = this.buildCursorConfig(config);
10809
11405
  const existingConfig = this.readExistingJsonConfig(cursorConfigPath);
10810
11406
  const mergedConfig = this.mergeConfig(existingConfig, cursorConfig);
10811
- fs8.writeFileSync(cursorConfigPath, JSON.stringify(mergedConfig, null, 2));
11407
+ fs9.writeFileSync(cursorConfigPath, JSON.stringify(mergedConfig, null, 2));
10812
11408
  return { success: true };
10813
11409
  } catch (error) {
10814
11410
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -10817,15 +11413,15 @@ var McpConfigService = class {
10817
11413
  }
10818
11414
  installVSCodeMcp(config) {
10819
11415
  try {
10820
- const vscodeDir = path10.join(this.projectDir, ".vscode");
10821
- if (!fs8.existsSync(vscodeDir)) {
10822
- fs8.mkdirSync(vscodeDir, { recursive: true });
11416
+ const vscodeDir = path11.join(this.projectDir, ".vscode");
11417
+ if (!fs9.existsSync(vscodeDir)) {
11418
+ fs9.mkdirSync(vscodeDir, { recursive: true });
10823
11419
  }
10824
- const vscodeConfigPath = path10.join(vscodeDir, "mcp.json");
11420
+ const vscodeConfigPath = path11.join(vscodeDir, "mcp.json");
10825
11421
  const vscodeConfig = this.buildVSCodeConfig(config);
10826
11422
  const existingConfig = this.readExistingJsonConfig(vscodeConfigPath);
10827
11423
  const mergedConfig = this.mergeVSCodeConfig(existingConfig, vscodeConfig);
10828
- fs8.writeFileSync(vscodeConfigPath, JSON.stringify(mergedConfig, null, 2));
11424
+ fs9.writeFileSync(vscodeConfigPath, JSON.stringify(mergedConfig, null, 2));
10829
11425
  return { success: true };
10830
11426
  } catch (error) {
10831
11427
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -10834,14 +11430,14 @@ var McpConfigService = class {
10834
11430
  }
10835
11431
  installContinueMcp(config) {
10836
11432
  try {
10837
- const continueDir = path10.join(this.projectDir, ".continue");
10838
- const mcpServersDir = path10.join(continueDir, "mcpServers");
10839
- if (!fs8.existsSync(mcpServersDir)) {
10840
- fs8.mkdirSync(mcpServersDir, { recursive: true });
11433
+ const continueDir = path11.join(this.projectDir, ".continue");
11434
+ const mcpServersDir = path11.join(continueDir, "mcpServers");
11435
+ if (!fs9.existsSync(mcpServersDir)) {
11436
+ fs9.mkdirSync(mcpServersDir, { recursive: true });
10841
11437
  }
10842
- const continueConfigPath = path10.join(mcpServersDir, "packmind.yaml");
11438
+ const continueConfigPath = path11.join(mcpServersDir, "packmind.yaml");
10843
11439
  const continueConfig = this.buildContinueYamlConfig(config);
10844
- fs8.writeFileSync(continueConfigPath, continueConfig);
11440
+ fs9.writeFileSync(continueConfigPath, continueConfig);
10845
11441
  return { success: true };
10846
11442
  } catch (error) {
10847
11443
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -10889,8 +11485,8 @@ mcpServers:
10889
11485
  }
10890
11486
  readExistingJsonConfig(filePath) {
10891
11487
  try {
10892
- if (fs8.existsSync(filePath)) {
10893
- const content = fs8.readFileSync(filePath, "utf-8");
11488
+ if (fs9.existsSync(filePath)) {
11489
+ const content = fs9.readFileSync(filePath, "utf-8");
10894
11490
  return JSON.parse(content);
10895
11491
  }
10896
11492
  } catch {
@@ -10923,8 +11519,8 @@ mcpServers:
10923
11519
  };
10924
11520
 
10925
11521
  // apps/cli/src/infra/repositories/ConfigFileRepository.ts
10926
- var fs9 = __toESM(require("fs/promises"));
10927
- var path11 = __toESM(require("path"));
11522
+ var fs10 = __toESM(require("fs/promises"));
11523
+ var path12 = __toESM(require("path"));
10928
11524
  var ConfigFileRepository = class {
10929
11525
  constructor() {
10930
11526
  this.CONFIG_FILENAME = "packmind.json";
@@ -10945,7 +11541,7 @@ var ConfigFileRepository = class {
10945
11541
  async configExists(baseDirectory) {
10946
11542
  const configPath = this.getConfigPath(baseDirectory);
10947
11543
  try {
10948
- await fs9.access(configPath);
11544
+ await fs10.access(configPath);
10949
11545
  return true;
10950
11546
  } catch {
10951
11547
  return false;
@@ -10954,7 +11550,7 @@ var ConfigFileRepository = class {
10954
11550
  async readConfig(baseDirectory) {
10955
11551
  const configPath = this.getConfigPath(baseDirectory);
10956
11552
  try {
10957
- const configContent = await fs9.readFile(configPath, "utf-8");
11553
+ const configContent = await fs10.readFile(configPath, "utf-8");
10958
11554
  const rawConfig = JSON.parse(configContent);
10959
11555
  if (!rawConfig.packages || typeof rawConfig.packages !== "object") {
10960
11556
  throw new Error(
@@ -10988,18 +11584,18 @@ var ConfigFileRepository = class {
10988
11584
  }
10989
11585
  }
10990
11586
  getConfigPath(directory) {
10991
- return path11.join(directory, this.CONFIG_FILENAME);
11587
+ return path12.join(directory, this.CONFIG_FILENAME);
10992
11588
  }
10993
11589
  async writeConfigToPath(configPath, config) {
10994
11590
  const configContent = JSON.stringify(config, null, 2) + "\n";
10995
- await fs9.writeFile(configPath, configContent, "utf-8");
11591
+ await fs10.writeFile(configPath, configContent, "utf-8");
10996
11592
  }
10997
11593
  /**
10998
11594
  * Recursively finds all directories containing packmind.json in descendant folders.
10999
11595
  * Excludes common build/dependency directories (node_modules, .git, dist, etc.)
11000
11596
  */
11001
11597
  async findDescendantConfigs(directory) {
11002
- const normalizedDir = normalizePath2(path11.resolve(directory));
11598
+ const normalizedDir = normalizePath2(path12.resolve(directory));
11003
11599
  return this.searchDescendantsRecursively(normalizedDir);
11004
11600
  }
11005
11601
  async searchDescendantsRecursively(currentDir) {
@@ -11012,7 +11608,7 @@ var ConfigFileRepository = class {
11012
11608
  if (!entry.isDirectory() || this.isExcludedDirectory(entry.name)) {
11013
11609
  continue;
11014
11610
  }
11015
- const entryPath = normalizePath2(path11.join(currentDir, entry.name));
11611
+ const entryPath = normalizePath2(path12.join(currentDir, entry.name));
11016
11612
  const config = await this.readConfig(entryPath);
11017
11613
  if (config) {
11018
11614
  results.push(entryPath);
@@ -11024,7 +11620,7 @@ var ConfigFileRepository = class {
11024
11620
  }
11025
11621
  async tryReadDirectory(directory) {
11026
11622
  try {
11027
- return await fs9.readdir(directory, { withFileTypes: true });
11623
+ return await fs10.readdir(directory, { withFileTypes: true });
11028
11624
  } catch {
11029
11625
  return null;
11030
11626
  }
@@ -11043,21 +11639,21 @@ var ConfigFileRepository = class {
11043
11639
  async readHierarchicalConfig(startDirectory, stopDirectory) {
11044
11640
  const configs = [];
11045
11641
  const configPaths = [];
11046
- const normalizedStart = normalizePath2(path11.resolve(startDirectory));
11047
- const normalizedStop = stopDirectory ? normalizePath2(path11.resolve(stopDirectory)) : null;
11642
+ const normalizedStart = normalizePath2(path12.resolve(startDirectory));
11643
+ const normalizedStop = stopDirectory ? normalizePath2(path12.resolve(stopDirectory)) : null;
11048
11644
  let currentDir = normalizedStart;
11049
11645
  while (true) {
11050
11646
  const config = await this.readConfig(currentDir);
11051
11647
  if (config) {
11052
11648
  configs.push(config);
11053
11649
  configPaths.push(
11054
- normalizePath2(path11.join(currentDir, this.CONFIG_FILENAME))
11650
+ normalizePath2(path12.join(currentDir, this.CONFIG_FILENAME))
11055
11651
  );
11056
11652
  }
11057
11653
  if (normalizedStop !== null && currentDir === normalizedStop) {
11058
11654
  break;
11059
11655
  }
11060
- const parentDir = normalizePath2(path11.dirname(currentDir));
11656
+ const parentDir = normalizePath2(path12.dirname(currentDir));
11061
11657
  if (parentDir === currentDir) {
11062
11658
  break;
11063
11659
  }
@@ -11082,8 +11678,8 @@ var ConfigFileRepository = class {
11082
11678
  * and returns each config with its target path.
11083
11679
  */
11084
11680
  async findAllConfigsInTree(startDirectory, stopDirectory) {
11085
- const normalizedStart = normalizePath2(path11.resolve(startDirectory));
11086
- const normalizedStop = stopDirectory ? normalizePath2(path11.resolve(stopDirectory)) : null;
11681
+ const normalizedStart = normalizePath2(path12.resolve(startDirectory));
11682
+ const normalizedStop = stopDirectory ? normalizePath2(path12.resolve(stopDirectory)) : null;
11087
11683
  const basePath = normalizedStop ?? normalizedStart;
11088
11684
  const searchRoot = normalizedStop ?? normalizedStart;
11089
11685
  const configsMap = /* @__PURE__ */ new Map();
@@ -11109,7 +11705,7 @@ var ConfigFileRepository = class {
11109
11705
  if (stopDir !== null && currentDir === stopDir) {
11110
11706
  break;
11111
11707
  }
11112
- const parentDir = normalizePath2(path11.dirname(currentDir));
11708
+ const parentDir = normalizePath2(path12.dirname(currentDir));
11113
11709
  if (parentDir === currentDir) {
11114
11710
  break;
11115
11711
  }
@@ -11240,7 +11836,7 @@ var ConfigFileRepository = class {
11240
11836
  }
11241
11837
  async tryReadFile(filePath) {
11242
11838
  try {
11243
- return await fs9.readFile(filePath, "utf-8");
11839
+ return await fs10.readFile(filePath, "utf-8");
11244
11840
  } catch (error) {
11245
11841
  if (error.code === "ENOENT") {
11246
11842
  return null;
@@ -11258,8 +11854,8 @@ var ConfigFileRepository = class {
11258
11854
  };
11259
11855
 
11260
11856
  // apps/cli/src/infra/repositories/LockFileRepository.ts
11261
- var fs10 = __toESM(require("fs/promises"));
11262
- var path12 = __toESM(require("path"));
11857
+ var fs11 = __toESM(require("fs/promises"));
11858
+ var path13 = __toESM(require("path"));
11263
11859
  var LockFileRepository = class {
11264
11860
  constructor() {
11265
11861
  this.LOCK_FILENAME = "packmind-lock.json";
@@ -11267,7 +11863,7 @@ var LockFileRepository = class {
11267
11863
  async read(baseDirectory) {
11268
11864
  const lockFilePath = this.getLockFilePath(baseDirectory);
11269
11865
  try {
11270
- const content = await fs10.readFile(lockFilePath, "utf-8");
11866
+ const content = await fs11.readFile(lockFilePath, "utf-8");
11271
11867
  const parsed = JSON.parse(content);
11272
11868
  if (!this.isValidLockFile(parsed)) {
11273
11869
  logWarningConsole(`Malformed lock file: ${lockFilePath}`);
@@ -11293,7 +11889,7 @@ var LockFileRepository = class {
11293
11889
  return typeof obj.installedAt === "string" && Array.isArray(obj.packageSlugs) && Array.isArray(obj.agents) && (obj.targetId === void 0 || typeof obj.targetId === "string") && typeof obj.artifacts === "object" && obj.artifacts !== null && !Array.isArray(obj.artifacts);
11294
11890
  }
11295
11891
  getLockFilePath(baseDirectory) {
11296
- return path12.join(baseDirectory, this.LOCK_FILENAME);
11892
+ return path13.join(baseDirectory, this.LOCK_FILENAME);
11297
11893
  }
11298
11894
  };
11299
11895
 
@@ -11394,7 +11990,7 @@ function normalizeLineEndings(content) {
11394
11990
  }
11395
11991
 
11396
11992
  // apps/cli/src/infra/utils/binaryDetection.ts
11397
- var path13 = __toESM(require("path"));
11993
+ var path14 = __toESM(require("path"));
11398
11994
  var BINARY_EXTENSIONS = /* @__PURE__ */ new Set([
11399
11995
  // Images
11400
11996
  ".png",
@@ -11452,7 +12048,7 @@ var BINARY_EXTENSIONS = /* @__PURE__ */ new Set([
11452
12048
  ".sqlite3"
11453
12049
  ]);
11454
12050
  function isBinaryExtension(filePath) {
11455
- const ext = path13.extname(filePath).toLowerCase();
12051
+ const ext = path14.extname(filePath).toLowerCase();
11456
12052
  return BINARY_EXTENSIONS.has(ext);
11457
12053
  }
11458
12054
  function isBinaryBuffer(buffer) {
@@ -11594,17 +12190,17 @@ ${spaceList}`
11594
12190
 
11595
12191
  // apps/cli/src/application/useCases/diffStrategies/CommandDiffStrategy.ts
11596
12192
  var import_diff2 = require("diff");
11597
- var fs12 = __toESM(require("fs/promises"));
11598
- var path15 = __toESM(require("path"));
12193
+ var fs13 = __toESM(require("fs/promises"));
12194
+ var path16 = __toESM(require("path"));
11599
12195
  var CommandDiffStrategy = class {
11600
12196
  supports(file) {
11601
12197
  return file.artifactType === "command";
11602
12198
  }
11603
12199
  async diff(file, baseDirectory) {
11604
- const fullPath = path15.join(baseDirectory, file.path);
12200
+ const fullPath = path16.join(baseDirectory, file.path);
11605
12201
  let localContent;
11606
12202
  try {
11607
- localContent = await fs12.readFile(fullPath, "utf-8");
12203
+ localContent = await fs13.readFile(fullPath, "utf-8");
11608
12204
  } catch {
11609
12205
  return [];
11610
12206
  }
@@ -11634,8 +12230,8 @@ var CommandDiffStrategy = class {
11634
12230
 
11635
12231
  // apps/cli/src/application/useCases/diffStrategies/SkillDiffStrategy.ts
11636
12232
  var import_diff3 = require("diff");
11637
- var fs13 = __toESM(require("fs/promises"));
11638
- var path16 = __toESM(require("path"));
12233
+ var fs14 = __toESM(require("fs/promises"));
12234
+ var path17 = __toESM(require("path"));
11639
12235
 
11640
12236
  // apps/cli/src/application/utils/stripFrontmatter.ts
11641
12237
  var FRONTMATTER_DELIMITER2 = "---";
@@ -11670,7 +12266,7 @@ var SkillDiffStrategy = class {
11670
12266
  async diffNewFiles(skillFolders, serverFiles, baseDirectory) {
11671
12267
  const diffs = [];
11672
12268
  for (const folder of skillFolders) {
11673
- const folderPath = path16.join(baseDirectory, folder);
12269
+ const folderPath = path17.join(baseDirectory, folder);
11674
12270
  const localFiles = await this.listFilesRecursively(folderPath);
11675
12271
  const serverPathsInFolder = new Set(
11676
12272
  serverFiles.filter((f) => f.path.startsWith(folder + "/")).map((f) => f.path)
@@ -11689,7 +12285,7 @@ var SkillDiffStrategy = class {
11689
12285
  if (serverPathsInFolder.has(filePath)) {
11690
12286
  continue;
11691
12287
  }
11692
- const fullPath = path16.join(baseDirectory, filePath);
12288
+ const fullPath = path17.join(baseDirectory, filePath);
11693
12289
  const localRead = await this.tryReadFileBinaryAware(fullPath);
11694
12290
  if (localRead === null) {
11695
12291
  continue;
@@ -11716,7 +12312,7 @@ var SkillDiffStrategy = class {
11716
12312
  return diffs;
11717
12313
  }
11718
12314
  async diffSkillMd(file, baseDirectory) {
11719
- const fullPath = path16.join(baseDirectory, file.path);
12315
+ const fullPath = path17.join(baseDirectory, file.path);
11720
12316
  const localContent = await this.tryReadFile(fullPath);
11721
12317
  if (localContent === null) {
11722
12318
  return [];
@@ -11773,7 +12369,7 @@ var SkillDiffStrategy = class {
11773
12369
  return [];
11774
12370
  }
11775
12371
  const skillFileId = createSkillFileId(file.skillFileId);
11776
- const fullPath = path16.join(baseDirectory, file.path);
12372
+ const fullPath = path17.join(baseDirectory, file.path);
11777
12373
  const localRead = await this.tryReadFileBinaryAware(fullPath);
11778
12374
  const fileRelativePath = this.computeRelativePath(file.path, skillFolders);
11779
12375
  if (localRead === null) {
@@ -11983,14 +12579,14 @@ var SkillDiffStrategy = class {
11983
12579
  }
11984
12580
  async tryReadFile(filePath) {
11985
12581
  try {
11986
- return await fs13.readFile(filePath, "utf-8");
12582
+ return await fs14.readFile(filePath, "utf-8");
11987
12583
  } catch {
11988
12584
  return null;
11989
12585
  }
11990
12586
  }
11991
12587
  async tryReadFileBinaryAware(filePath) {
11992
12588
  try {
11993
- const buffer = await fs13.readFile(filePath);
12589
+ const buffer = await fs14.readFile(filePath);
11994
12590
  if (isBinaryFile(filePath, buffer)) {
11995
12591
  return { content: buffer.toString("base64"), isBase64: true };
11996
12592
  }
@@ -12002,13 +12598,13 @@ var SkillDiffStrategy = class {
12002
12598
  async listFilesRecursively(dirPath, prefix = "") {
12003
12599
  let entries;
12004
12600
  try {
12005
- entries = await fs13.readdir(dirPath);
12601
+ entries = await fs14.readdir(dirPath);
12006
12602
  } catch {
12007
12603
  return [];
12008
12604
  }
12009
12605
  const files = [];
12010
12606
  for (const entry of entries) {
12011
- const fullPath = path16.join(dirPath, entry);
12607
+ const fullPath = path17.join(dirPath, entry);
12012
12608
  const stat9 = await this.tryStatFile(fullPath);
12013
12609
  if (!stat9) {
12014
12610
  continue;
@@ -12028,7 +12624,7 @@ var SkillDiffStrategy = class {
12028
12624
  }
12029
12625
  async tryStatFile(filePath) {
12030
12626
  try {
12031
- const stat9 = await fs13.stat(filePath);
12627
+ const stat9 = await fs14.stat(filePath);
12032
12628
  return { isDirectory: stat9.isDirectory() };
12033
12629
  } catch {
12034
12630
  return null;
@@ -12036,7 +12632,7 @@ var SkillDiffStrategy = class {
12036
12632
  }
12037
12633
  async tryGetPermissions(filePath) {
12038
12634
  try {
12039
- const stat9 = await fs13.stat(filePath);
12635
+ const stat9 = await fs14.stat(filePath);
12040
12636
  return modeToPermissionStringOrDefault(stat9.mode);
12041
12637
  } catch {
12042
12638
  return null;
@@ -12052,8 +12648,8 @@ var SkillDiffStrategy = class {
12052
12648
  };
12053
12649
 
12054
12650
  // apps/cli/src/application/useCases/diffStrategies/StandardDiffStrategy.ts
12055
- var fs14 = __toESM(require("fs/promises"));
12056
- var path17 = __toESM(require("path"));
12651
+ var fs15 = __toESM(require("fs/promises"));
12652
+ var path18 = __toESM(require("path"));
12057
12653
 
12058
12654
  // apps/cli/src/application/utils/parseStandardMd.ts
12059
12655
  var DEPLOYER_PARSERS = [
@@ -12361,10 +12957,10 @@ var StandardDiffStrategy = class {
12361
12957
  return file.artifactType === "standard";
12362
12958
  }
12363
12959
  async diff(file, baseDirectory) {
12364
- const fullPath = path17.join(baseDirectory, file.path);
12960
+ const fullPath = path18.join(baseDirectory, file.path);
12365
12961
  let localContent;
12366
12962
  try {
12367
- localContent = await fs14.readFile(fullPath, "utf-8");
12963
+ localContent = await fs15.readFile(fullPath, "utf-8");
12368
12964
  } catch {
12369
12965
  return [];
12370
12966
  }
@@ -12728,6 +13324,12 @@ var SpaceService = class {
12728
13324
  }
12729
13325
  return defaultSpace;
12730
13326
  }
13327
+ async getSpaceBySlug(slug3) {
13328
+ return this.spaceGateway.getSpaceBySlug(slug3);
13329
+ }
13330
+ getApiContext() {
13331
+ return this.spaceGateway.getApiContext();
13332
+ }
12731
13333
  };
12732
13334
 
12733
13335
  // apps/cli/src/PackmindCliHexaFactory.ts
@@ -12745,6 +13347,12 @@ var PackmindCliHexaFactory = class {
12745
13347
  diffViolationFilterService: new DiffViolationFilterService(),
12746
13348
  spaceService: new SpaceService(this.repositories.packmindGateway.spaces)
12747
13349
  };
13350
+ const installUseCase = new InstallUseCase(
13351
+ this.repositories.packmindGateway,
13352
+ this.repositories.lockFileRepository,
13353
+ this.repositories.configFileRepository,
13354
+ this.services.spaceService
13355
+ );
12748
13356
  this.useCases = {
12749
13357
  executeSingleFileAst: new ExecuteSingleFileAstUseCase(
12750
13358
  this.services.linterExecutionUseCase
@@ -12762,6 +13370,12 @@ var PackmindCliHexaFactory = class {
12762
13370
  installPackages: new InstallPackagesUseCase(
12763
13371
  this.repositories.packmindGateway
12764
13372
  ),
13373
+ install: installUseCase,
13374
+ uninstall: new UninstallUseCase(
13375
+ this.repositories.configFileRepository,
13376
+ this.services.spaceService,
13377
+ installUseCase
13378
+ ),
12765
13379
  installDefaultSkills: new InstallDefaultSkillsUseCase(this.repositories),
12766
13380
  listPackages: new ListPackagesUseCase(
12767
13381
  this.repositories.packmindGateway,
@@ -12813,6 +13427,11 @@ var PackmindCliHexa = class {
12813
13427
  command33
12814
13428
  );
12815
13429
  };
13430
+ this.notifyArtefactsDistribution = async (command33) => {
13431
+ return this.hexa.repositories.packmindGateway.deployment.notifyArtefactsDistribution(
13432
+ command33
13433
+ );
13434
+ };
12816
13435
  this.logger = logger2;
12817
13436
  try {
12818
13437
  this.hexa = new PackmindCliHexaFactory();
@@ -12845,6 +13464,12 @@ var PackmindCliHexa = class {
12845
13464
  async installPackages(command33) {
12846
13465
  return this.hexa.useCases.installPackages.execute(command33);
12847
13466
  }
13467
+ async install(command33) {
13468
+ return this.hexa.useCases.install.execute(command33);
13469
+ }
13470
+ async uninstall(command33) {
13471
+ return this.hexa.useCases.uninstall.execute(command33);
13472
+ }
12848
13473
  async diffArtefacts(command33) {
12849
13474
  return this.hexa.useCases.diffArtefacts.execute(command33);
12850
13475
  }
@@ -13103,31 +13728,31 @@ var HumanReadableLogger = class {
13103
13728
  var pathModule2 = __toESM(require("path"));
13104
13729
 
13105
13730
  // apps/cli/src/infra/commands/lintHandler.ts
13106
- var fs16 = __toESM(require("fs/promises"));
13731
+ var fs17 = __toESM(require("fs/promises"));
13107
13732
  var pathModule = __toESM(require("path"));
13108
13733
 
13109
13734
  // apps/cli/src/application/services/PackmindIgnoreReader.ts
13110
- var fs15 = __toESM(require("fs/promises"));
13111
- var path18 = __toESM(require("path"));
13735
+ var fs16 = __toESM(require("fs/promises"));
13736
+ var path19 = __toESM(require("path"));
13112
13737
  var IGNORE_FILENAME = ".packmindignore";
13113
13738
  var PackmindIgnoreReader = class {
13114
13739
  async readIgnorePatterns(startDirectory, stopDirectory) {
13115
13740
  const patterns = [];
13116
- const normalizedStart = path18.resolve(startDirectory);
13117
- const normalizedStop = stopDirectory ? path18.resolve(stopDirectory) : null;
13741
+ const normalizedStart = path19.resolve(startDirectory);
13742
+ const normalizedStop = stopDirectory ? path19.resolve(stopDirectory) : null;
13118
13743
  if (normalizedStop === null) {
13119
- const ignoreFile = path18.join(normalizedStart, IGNORE_FILENAME);
13744
+ const ignoreFile = path19.join(normalizedStart, IGNORE_FILENAME);
13120
13745
  return this.parseIgnoreFile(ignoreFile);
13121
13746
  }
13122
13747
  let currentDir = normalizedStart;
13123
13748
  while (true) {
13124
- const ignoreFile = path18.join(currentDir, IGNORE_FILENAME);
13749
+ const ignoreFile = path19.join(currentDir, IGNORE_FILENAME);
13125
13750
  const filePatterns = await this.parseIgnoreFile(ignoreFile);
13126
13751
  patterns.push(...filePatterns);
13127
13752
  if (currentDir === normalizedStop) {
13128
13753
  break;
13129
13754
  }
13130
- const parentDir = path18.dirname(currentDir);
13755
+ const parentDir = path19.dirname(currentDir);
13131
13756
  if (parentDir === currentDir) {
13132
13757
  break;
13133
13758
  }
@@ -13138,7 +13763,7 @@ var PackmindIgnoreReader = class {
13138
13763
  async parseIgnoreFile(filePath) {
13139
13764
  let content;
13140
13765
  try {
13141
- content = await fs15.readFile(filePath, "utf-8");
13766
+ content = await fs16.readFile(filePath, "utf-8");
13142
13767
  } catch (err) {
13143
13768
  if (err.code === "ENOENT") {
13144
13769
  return [];
@@ -13159,7 +13784,7 @@ function isNotLoggedInError(error) {
13159
13784
  }
13160
13785
  async function lintHandler(args2, deps) {
13161
13786
  const {
13162
- path: path36,
13787
+ path: path37,
13163
13788
  draft,
13164
13789
  rule,
13165
13790
  language,
@@ -13181,11 +13806,11 @@ async function lintHandler(args2, deps) {
13181
13806
  throw new Error("option --rule is required to use --draft mode");
13182
13807
  }
13183
13808
  const startedAt = Date.now();
13184
- const targetPath = path36 ?? ".";
13809
+ const targetPath = path37 ?? ".";
13185
13810
  const absolutePath = resolvePath(targetPath);
13186
13811
  let stats;
13187
13812
  try {
13188
- stats = await fs16.stat(absolutePath);
13813
+ stats = await fs17.stat(absolutePath);
13189
13814
  } catch (err) {
13190
13815
  const isNotFound = err.code === "ENOENT";
13191
13816
  const message = isNotFound ? `File or directory "${absolutePath}" does not exist` : `Cannot access "${absolutePath}": ${err.message}`;
@@ -13503,72 +14128,15 @@ function extractWasmFiles() {
13503
14128
 
13504
14129
  // apps/cli/src/main.ts
13505
14130
  var import_dotenv = require("dotenv");
13506
- var fs27 = __toESM(require("fs"));
13507
- var path35 = __toESM(require("path"));
14131
+ var fs28 = __toESM(require("fs"));
14132
+ var path36 = __toESM(require("path"));
13508
14133
 
13509
14134
  // apps/cli/src/infra/commands/InstallCommand.ts
13510
14135
  var import_cmd_ts2 = __toESM(require_cjs());
14136
+ var path20 = __toESM(require("path"));
14137
+ var fs18 = __toESM(require("fs"));
13511
14138
 
13512
14139
  // apps/cli/src/infra/commands/installPackagesHandler.ts
13513
- var fs17 = __toESM(require("fs/promises"));
13514
- var path19 = __toESM(require("path"));
13515
- var { version: CLI_VERSION } = require_package();
13516
- async function notifyDistributionIfInGitRepo(params) {
13517
- const { packmindCliHexa, cwd, packages, log, agents } = params;
13518
- const resolvedGitRoot = params.gitRoot ?? await packmindCliHexa.tryGetGitRepositoryRoot(cwd);
13519
- if (!resolvedGitRoot) {
13520
- return false;
13521
- }
13522
- try {
13523
- const gitRemoteUrl = packmindCliHexa.getGitRemoteUrlFromPath(resolvedGitRoot);
13524
- const gitBranch = packmindCliHexa.getCurrentBranch(resolvedGitRoot);
13525
- let relativePath = cwd.startsWith(resolvedGitRoot) ? cwd.slice(resolvedGitRoot.length) : "/";
13526
- if (!relativePath.startsWith("/")) {
13527
- relativePath = "/" + relativePath;
13528
- }
13529
- if (!relativePath.endsWith("/")) {
13530
- relativePath = relativePath + "/";
13531
- }
13532
- await packmindCliHexa.notifyDistribution({
13533
- distributedPackages: packages,
13534
- gitRemoteUrl,
13535
- gitBranch,
13536
- relativePath,
13537
- agents
13538
- });
13539
- log("Successfully notified Packmind of the new distribution");
13540
- return true;
13541
- } catch {
13542
- return false;
13543
- }
13544
- }
13545
- async function installDefaultSkillsIfAtGitRoot(params) {
13546
- const { packmindCliHexa, cwd, log } = params;
13547
- const gitRoot = await packmindCliHexa.tryGetGitRepositoryRoot(cwd);
13548
- if (!gitRoot || cwd !== gitRoot) {
13549
- return;
13550
- }
13551
- try {
13552
- log("\nInstalling default skills...");
13553
- const skillsResult = await packmindCliHexa.installDefaultSkills({
13554
- cliVersion: CLI_VERSION
13555
- });
13556
- if (skillsResult.errors.length > 0) {
13557
- skillsResult.errors.forEach((err) => {
13558
- log(` Warning: ${err}`);
13559
- });
13560
- }
13561
- const totalSkillFiles = skillsResult.filesCreated + skillsResult.filesUpdated;
13562
- if (totalSkillFiles > 0) {
13563
- log(
13564
- `Default skills: added ${skillsResult.filesCreated} files, changed ${skillsResult.filesUpdated} files`
13565
- );
13566
- } else if (skillsResult.errors.length === 0) {
13567
- log("Default skills are already up to date");
13568
- }
13569
- } catch {
13570
- }
13571
- }
13572
14140
  function formatOverviewRow(configPath, packages, pathColumnWidth) {
13573
14141
  const paddedPath = configPath.padEnd(pathColumnWidth);
13574
14142
  if (packages.length === 0) {
@@ -13641,1150 +14209,310 @@ ${uniqueCount} unique ${packageWord} currently installed.`);
13641
14209
  };
13642
14210
  }
13643
14211
  }
13644
- async function executeInstallForDirectory(directory, deps) {
13645
- const { packmindCliHexa, log } = deps;
13646
- let configPackages;
13647
- let configAgents;
14212
+
14213
+ // apps/cli/src/infra/commands/InstallCommand.ts
14214
+ function findSubDirectoriesWithPackmindJson(dirPath, recursive) {
14215
+ const result = [];
14216
+ let entries;
13648
14217
  try {
13649
- const fullConfig = await packmindCliHexa.readFullConfig(directory);
13650
- if (fullConfig) {
13651
- configPackages = Object.keys(fullConfig.packages);
13652
- configAgents = fullConfig.agents;
13653
- } else {
13654
- configPackages = [];
13655
- }
13656
- } catch (err) {
13657
- const errorMessage = err instanceof Error ? err.message : String(err);
13658
- return {
13659
- success: false,
13660
- filesCreated: 0,
13661
- filesUpdated: 0,
13662
- filesDeleted: 0,
13663
- notificationSent: false,
13664
- errorMessage: `Failed to parse packmind.json: ${errorMessage}`
13665
- };
13666
- }
13667
- if (configPackages.length === 0) {
13668
- return {
13669
- success: true,
13670
- filesCreated: 0,
13671
- filesUpdated: 0,
13672
- filesDeleted: 0,
13673
- notificationSent: false
13674
- };
13675
- }
13676
- const normalizedConfigPackages = await packmindCliHexa.normalizePackageSlugs(configPackages);
13677
- let gitRemoteUrl;
13678
- let gitBranch;
13679
- let relativePath;
13680
- const gitRoot = await packmindCliHexa.tryGetGitRepositoryRoot(directory);
13681
- if (gitRoot) {
13682
- try {
13683
- gitRemoteUrl = packmindCliHexa.getGitRemoteUrlFromPath(gitRoot);
13684
- gitBranch = packmindCliHexa.getCurrentBranch(gitRoot);
13685
- relativePath = directory.startsWith(gitRoot) ? directory.slice(gitRoot.length) : "/";
13686
- if (!relativePath.startsWith("/")) {
13687
- relativePath = "/" + relativePath;
13688
- }
13689
- if (!relativePath.endsWith("/")) {
13690
- relativePath = relativePath + "/";
13691
- }
13692
- } catch {
13693
- }
14218
+ entries = fs18.readdirSync(dirPath, { withFileTypes: true });
14219
+ } catch {
14220
+ return result;
13694
14221
  }
13695
- try {
13696
- const packageCount = normalizedConfigPackages.length;
13697
- const packageWord = packageCount === 1 ? "package" : "packages";
13698
- log(
13699
- ` Fetching ${packageCount} ${packageWord}: ${normalizedConfigPackages.join(", ")}...`
13700
- );
13701
- const result = await packmindCliHexa.installPackages({
13702
- baseDirectory: directory,
13703
- packagesSlugs: normalizedConfigPackages,
13704
- previousPackagesSlugs: normalizedConfigPackages,
13705
- // Pass for consistency
13706
- gitRemoteUrl,
13707
- gitBranch,
13708
- relativePath,
13709
- agents: configAgents
13710
- // Pass agents from config if present
13711
- });
13712
- const parts = [];
13713
- if (result.recipesCount > 0) parts.push(`${result.recipesCount} commands`);
13714
- if (result.standardsCount > 0)
13715
- parts.push(`${result.standardsCount} standards`);
13716
- if (result.skillsCount > 0) parts.push(`${result.skillsCount} skills`);
13717
- log(` Installing ${parts.join(", ") || "artifacts"}...`);
13718
- log(
13719
- ` added ${result.filesCreated} files, changed ${result.filesUpdated} files, removed ${result.filesDeleted} files`
13720
- );
13721
- if (result.errors.length > 0) {
13722
- return {
13723
- success: false,
13724
- filesCreated: result.filesCreated,
13725
- filesUpdated: result.filesUpdated,
13726
- filesDeleted: result.filesDeleted,
13727
- notificationSent: false,
13728
- errorMessage: result.errors.join(", ")
13729
- };
13730
- }
13731
- const configSlugsWereNormalized = configPackages.some(
13732
- (slug3, i) => slug3 !== normalizedConfigPackages[i]
13733
- );
13734
- if (configSlugsWereNormalized) {
13735
- await packmindCliHexa.writeConfig(directory, normalizedConfigPackages);
14222
+ for (const entry of entries) {
14223
+ if (!entry.isDirectory()) continue;
14224
+ const subDir = path20.join(dirPath, entry.name);
14225
+ if (fs18.existsSync(path20.join(subDir, "packmind.json"))) {
14226
+ result.push(subDir);
13736
14227
  }
13737
- const skillDirsDeleted = result.skillDirectoriesDeleted || 0;
13738
- let notificationSent = false;
13739
- if (result.filesCreated > 0 || result.filesUpdated > 0 || result.filesDeleted > 0 || skillDirsDeleted > 0) {
13740
- notificationSent = await notifyDistributionIfInGitRepo({
13741
- packmindCliHexa,
13742
- cwd: directory,
13743
- packages: normalizedConfigPackages,
13744
- agents: configAgents,
13745
- log: () => {
13746
- },
13747
- gitRoot: gitRoot ?? void 0
13748
- });
14228
+ if (recursive) {
14229
+ result.push(...findSubDirectoriesWithPackmindJson(subDir, true));
13749
14230
  }
13750
- return {
13751
- success: true,
13752
- filesCreated: result.filesCreated,
13753
- filesUpdated: result.filesUpdated,
13754
- filesDeleted: result.filesDeleted + skillDirsDeleted,
13755
- notificationSent
13756
- };
13757
- } catch (err) {
13758
- const errorMessage = err instanceof Error ? err.message : String(err);
13759
- return {
13760
- success: false,
13761
- filesCreated: 0,
13762
- filesUpdated: 0,
13763
- filesDeleted: 0,
13764
- notificationSent: false,
13765
- errorMessage
13766
- };
13767
14231
  }
14232
+ return result;
13768
14233
  }
13769
- async function installPackagesHandler(args2, deps) {
13770
- const { packmindCliHexa, exit, getCwd, log, error } = deps;
13771
- const { packagesSlugs } = args2;
13772
- const rawCwd = getCwd();
13773
- let cwd = rawCwd;
13774
- if (args2.path) {
13775
- const resolvedPath = path19.resolve(rawCwd, args2.path);
13776
- try {
13777
- const stat9 = await fs17.stat(resolvedPath);
13778
- if (!stat9.isDirectory()) {
13779
- logErrorConsole(`Path is not a directory: ${resolvedPath}`);
13780
- exit(1);
13781
- return {
13782
- filesCreated: 0,
13783
- filesUpdated: 0,
13784
- filesDeleted: 0,
13785
- notificationSent: false
13786
- };
13787
- }
13788
- cwd = resolvedPath;
13789
- } catch {
13790
- logErrorConsole(`Path does not exist: ${resolvedPath}`);
13791
- exit(1);
13792
- return {
13793
- filesCreated: 0,
13794
- filesUpdated: 0,
13795
- filesDeleted: 0,
13796
- notificationSent: false
13797
- };
13798
- }
13799
- const relativeToCwd = path19.relative(rawCwd, resolvedPath);
13800
- const displayPath = relativeToCwd ? `./${relativeToCwd}/packmind.json` : `./packmind.json`;
13801
- log(`Installing in ${displayPath}...`);
13802
- }
13803
- let configPackages;
13804
- let configAgents;
13805
- let configFileExists = false;
13806
- try {
13807
- configFileExists = await packmindCliHexa.configExists(cwd);
13808
- const fullConfig = await packmindCliHexa.readFullConfig(cwd);
13809
- if (fullConfig) {
13810
- const hasNonWildcardVersions = Object.values(fullConfig.packages).some(
13811
- (version2) => version2 !== "*"
13812
- );
13813
- if (hasNonWildcardVersions) {
13814
- logWarningConsole(
13815
- "Package versions are not supported yet, getting the latest version"
13816
- );
13817
- }
13818
- configPackages = Object.keys(fullConfig.packages);
13819
- configAgents = fullConfig.agents;
13820
- } else {
13821
- configPackages = [];
13822
- }
13823
- } catch (err) {
13824
- error("ERROR Failed to parse packmind.json");
13825
- if (err instanceof Error) {
13826
- error(`ERROR ${err.message}`);
13827
- } else {
13828
- error(`ERROR ${String(err)}`);
13829
- }
13830
- error("\n\u{1F4A1} Please fix the packmind.json file or delete it to continue.");
13831
- exit(1);
13832
- return {
13833
- filesCreated: 0,
13834
- filesUpdated: 0,
13835
- filesDeleted: 0,
13836
- notificationSent: false
13837
- };
13838
- }
13839
- let normalizedNewSlugs;
13840
- let normalizedConfigSlugs;
14234
+ function mergeInstallResults(results) {
14235
+ const merged = {
14236
+ filesCreated: 0,
14237
+ filesUpdated: 0,
14238
+ filesDeleted: 0,
14239
+ contentFilesChanged: 0,
14240
+ errors: [],
14241
+ recipesCount: 0,
14242
+ standardsCount: 0,
14243
+ commandsCount: 0,
14244
+ skillsCount: 0,
14245
+ recipesRemoved: 0,
14246
+ standardsRemoved: 0,
14247
+ commandsRemoved: 0,
14248
+ skillsRemoved: 0,
14249
+ skillDirectoriesDeleted: 0,
14250
+ missingAccess: [],
14251
+ joinSpaceUrl: void 0
14252
+ };
14253
+ for (const r of results) {
14254
+ merged.filesCreated += r.filesCreated;
14255
+ merged.filesUpdated += r.filesUpdated;
14256
+ merged.filesDeleted += r.filesDeleted;
14257
+ merged.contentFilesChanged += r.contentFilesChanged;
14258
+ merged.errors.push(...r.errors);
14259
+ merged.recipesCount += r.recipesCount;
14260
+ merged.standardsCount += r.standardsCount;
14261
+ merged.commandsCount += r.commandsCount;
14262
+ merged.skillsCount += r.skillsCount;
14263
+ merged.recipesRemoved += r.recipesRemoved;
14264
+ merged.standardsRemoved += r.standardsRemoved;
14265
+ merged.commandsRemoved += r.commandsRemoved;
14266
+ merged.skillsRemoved += r.skillsRemoved;
14267
+ merged.skillDirectoriesDeleted += r.skillDirectoriesDeleted;
14268
+ merged.missingAccess.push(...r.missingAccess);
14269
+ }
14270
+ merged.missingAccess = [...new Set(merged.missingAccess)];
14271
+ const urlsFromResultsWithMissingAccess = results.filter((r) => r.missingAccess.length > 0).map((r) => r.joinSpaceUrl);
14272
+ const uniqueUrls = new Set(urlsFromResultsWithMissingAccess.filter(Boolean));
14273
+ if (uniqueUrls.size === 1 && !urlsFromResultsWithMissingAccess.some((u) => u === void 0)) {
14274
+ merged.joinSpaceUrl = [...uniqueUrls][0];
14275
+ }
14276
+ return merged;
14277
+ }
14278
+ function buildInstallSummary(result) {
14279
+ const contentParts = [
14280
+ result.standardsCount > 0 ? `${result.standardsCount} ${result.standardsCount === 1 ? "standard" : "standards"}` : null,
14281
+ result.commandsCount > 0 ? `${result.commandsCount} ${result.commandsCount === 1 ? "command" : "commands"}` : null,
14282
+ result.skillsCount > 0 ? `${result.skillsCount} ${result.skillsCount === 1 ? "skill" : "skills"}` : null,
14283
+ result.recipesCount > 0 ? `${result.recipesCount} ${result.recipesCount === 1 ? "recipe" : "recipes"}` : null
14284
+ ].filter(Boolean);
14285
+ const contentChanged = result.contentFilesChanged > 0;
14286
+ if (!contentChanged && contentParts.length === 0) {
14287
+ return "\u2705 Nothing to install";
14288
+ }
14289
+ if (!contentChanged) {
14290
+ return `\u2705 Already up to date \u2014 ${contentParts.join(", ")}`;
14291
+ }
14292
+ if (contentParts.length === 0) {
14293
+ return "\u2705 Packages removed";
14294
+ }
14295
+ return `\u2705 Synced ${contentParts.join(", ")}`;
14296
+ }
14297
+ async function notifyArtefactsDistributionIfInGitRepo(params) {
14298
+ const { packmindCliHexa, dir } = params;
13841
14299
  try {
13842
- normalizedNewSlugs = await packmindCliHexa.normalizePackageSlugs(packagesSlugs);
13843
- normalizedConfigSlugs = await packmindCliHexa.normalizePackageSlugs(configPackages);
13844
- } catch (err) {
13845
- error(`ERROR ${err instanceof Error ? err.message : String(err)}`);
13846
- exit(1);
13847
- return {
13848
- filesCreated: 0,
13849
- filesUpdated: 0,
13850
- filesDeleted: 0,
13851
- notificationSent: false
13852
- };
13853
- }
13854
- const allPackages = [
13855
- .../* @__PURE__ */ new Set([...normalizedConfigSlugs, ...normalizedNewSlugs])
13856
- ];
13857
- if (allPackages.length === 0) {
13858
- if (configFileExists) {
13859
- logWarningConsole(
13860
- "config packmind.json is empty, no packages to install"
13861
- );
13862
- } else {
13863
- logWarningConsole("config packmind.json not found");
14300
+ const gitRoot = await packmindCliHexa.tryGetGitRepositoryRoot(dir);
14301
+ if (!gitRoot) return;
14302
+ const lockFilePath = path20.join(dir, "packmind-lock.json");
14303
+ const content = fs18.readFileSync(lockFilePath, "utf-8");
14304
+ const packmindLockFile = JSON.parse(content);
14305
+ const gitRemoteUrl = packmindCliHexa.getGitRemoteUrlFromPath(gitRoot);
14306
+ const gitBranch = packmindCliHexa.getCurrentBranch(gitRoot);
14307
+ let relativePath = dir.startsWith(gitRoot) ? dir.slice(gitRoot.length) : "/";
14308
+ if (!relativePath.startsWith("/")) {
14309
+ relativePath = "/" + relativePath;
13864
14310
  }
13865
- log("Usage: packmind-cli install <package-slug> [package-slug...]");
13866
- log(" packmind-cli install --list");
13867
- log("");
13868
- log("Examples:");
13869
- log(" packmind-cli install backend");
13870
- log(" packmind-cli install backend frontend");
13871
- log(" packmind-cli install --list # Show available packages");
13872
- log("");
13873
- log("Install commands and standards from the specified packages.");
13874
- exit(0);
13875
- return {
13876
- filesCreated: 0,
13877
- filesUpdated: 0,
13878
- filesDeleted: 0,
13879
- notificationSent: false
13880
- };
13881
- }
13882
- if (!configFileExists && packagesSlugs.length > 0) {
13883
- log("INFO initializing packmind.json");
13884
- }
13885
- try {
13886
- const packageCount = allPackages.length;
13887
- const packageWord = packageCount === 1 ? "package" : "packages";
13888
- log(
13889
- `Fetching ${packageCount} ${packageWord}: ${allPackages.join(", ")}...`
13890
- );
13891
- let gitRemoteUrl;
13892
- let gitBranch;
13893
- let relativePath;
13894
- const gitRoot = await packmindCliHexa.tryGetGitRepositoryRoot(cwd);
13895
- if (gitRoot) {
13896
- try {
13897
- gitRemoteUrl = packmindCliHexa.getGitRemoteUrlFromPath(gitRoot);
13898
- gitBranch = packmindCliHexa.getCurrentBranch(gitRoot);
13899
- relativePath = cwd.startsWith(gitRoot) ? cwd.slice(gitRoot.length) : "/";
13900
- if (!relativePath.startsWith("/")) {
13901
- relativePath = "/" + relativePath;
13902
- }
13903
- if (!relativePath.endsWith("/")) {
13904
- relativePath = relativePath + "/";
13905
- }
13906
- } catch {
13907
- }
14311
+ if (!relativePath.endsWith("/")) {
14312
+ relativePath = relativePath + "/";
13908
14313
  }
13909
- const result = await packmindCliHexa.installPackages({
13910
- baseDirectory: cwd,
13911
- packagesSlugs: allPackages,
13912
- previousPackagesSlugs: normalizedConfigSlugs,
13913
- // Pass previous config for change detection
14314
+ await packmindCliHexa.notifyArtefactsDistribution({
13914
14315
  gitRemoteUrl,
13915
14316
  gitBranch,
13916
14317
  relativePath,
13917
- agents: configAgents
13918
- // Pass agents from config if present (overrides org-level)
13919
- });
13920
- const parts = [];
13921
- if (result.recipesCount > 0) parts.push(`${result.recipesCount} commands`);
13922
- if (result.standardsCount > 0)
13923
- parts.push(`${result.standardsCount} standards`);
13924
- if (result.skillsCount > 0) parts.push(`${result.skillsCount} skills`);
13925
- log(`Installing ${parts.join(", ") || "artifacts"}...`);
13926
- const skillDirsDeleted = result.skillDirectoriesDeleted || 0;
13927
- const totalDeleted = result.filesDeleted + skillDirsDeleted;
13928
- log(
13929
- `
13930
- added ${result.filesCreated} files, changed ${result.filesUpdated} files, removed ${totalDeleted} files`
13931
- );
13932
- if (result.errors.length > 0) {
13933
- log("\n\u26A0\uFE0F Errors encountered:");
13934
- result.errors.forEach((err) => {
13935
- log(` - ${err}`);
13936
- });
13937
- exit(1);
13938
- return {
13939
- filesCreated: result.filesCreated,
13940
- filesUpdated: result.filesUpdated,
13941
- filesDeleted: totalDeleted,
13942
- notificationSent: false
13943
- };
13944
- }
13945
- const configSlugsWereNormalized = configPackages.some(
13946
- (slug3, i) => slug3 !== normalizedConfigSlugs[i]
13947
- );
13948
- const newPackages = normalizedNewSlugs.filter(
13949
- (slug3) => !normalizedConfigSlugs.includes(slug3)
13950
- );
13951
- if (configSlugsWereNormalized) {
13952
- await packmindCliHexa.writeConfig(cwd, allPackages);
13953
- } else if (newPackages.length > 0) {
13954
- await packmindCliHexa.addPackagesToConfig(cwd, newPackages);
13955
- }
13956
- let notificationSent = false;
13957
- if (result.filesCreated > 0 || result.filesUpdated > 0 || result.filesDeleted > 0 || skillDirsDeleted > 0) {
13958
- notificationSent = await notifyDistributionIfInGitRepo({
13959
- packmindCliHexa,
13960
- cwd,
13961
- packages: allPackages,
13962
- agents: configAgents,
13963
- log
13964
- });
13965
- }
13966
- await installDefaultSkillsIfAtGitRoot({
13967
- packmindCliHexa,
13968
- cwd,
13969
- log
14318
+ packmindLockFile
13970
14319
  });
13971
- if (deps.playbookLocalRepository) {
13972
- deps.playbookLocalRepository.clearAll();
13973
- }
13974
- return {
13975
- filesCreated: result.filesCreated,
13976
- filesUpdated: result.filesUpdated,
13977
- filesDeleted: totalDeleted,
13978
- notificationSent
13979
- };
13980
- } catch (err) {
13981
- error("\n\u274C Failed to install content:");
13982
- if (err instanceof Error) {
13983
- const errorObj = err;
13984
- if (errorObj.statusCode === 400) {
13985
- error(` ${errorObj.message}`);
13986
- error("\n\u{1F4A1} This is a validation error. Please check:");
13987
- error(" - The command syntax is correct");
13988
- error(" - You have provided at least one package slug");
13989
- error(" - Your packmind.json file contains valid package slugs");
13990
- } else if (errorObj.statusCode === 404) {
13991
- error(` ${errorObj.message}`);
13992
- if (configFileExists && configPackages.length > 0) {
13993
- const missingPackages = allPackages.filter(
13994
- (pkg) => configPackages.includes(pkg)
13995
- );
13996
- if (missingPackages.length > 0) {
13997
- error(
13998
- "\n\u{1F4A1} Either remove the following package(s) from packmind.json:"
13999
- );
14000
- missingPackages.forEach((pkg) => {
14001
- error(` "${pkg}"`);
14002
- });
14003
- error(" Or ensure that:");
14004
- error(" - The package slug exists and is correctly spelled");
14005
- error(" - The package exists in your organization");
14006
- error(" - You have the correct API key configured");
14007
- } else {
14008
- error("\n\u{1F4A1} Troubleshooting tips:");
14009
- error(
14010
- " - Check if the package slug exists and is correctly spelled"
14011
- );
14012
- error(" - Check that the package exists in your organization");
14013
- error(" - Ensure you have the correct API key configured");
14014
- }
14015
- } else {
14016
- error("\n\u{1F4A1} Troubleshooting tips:");
14017
- error(
14018
- " - Check if the package slug exists and is correctly spelled"
14019
- );
14020
- error(" - Check that the package exists in your organization");
14021
- error(" - Ensure you have the correct API key configured");
14022
- }
14023
- } else {
14024
- error(` ${errorObj.message}`);
14025
- const apiErrorObj = err;
14026
- if (apiErrorObj.response?.data?.message) {
14027
- error(`
14028
- Details: ${apiErrorObj.response.data.message}`);
14029
- }
14030
- error("\n\u{1F4A1} Troubleshooting tips:");
14031
- error(" - Verify that the package slugs are correct");
14032
- error(" - Check that the packages exist in your organization");
14033
- error(" - Ensure you have the correct API key configured");
14034
- }
14035
- } else {
14036
- error(` ${String(err)}`);
14037
- }
14038
- exit(1);
14039
- return {
14040
- filesCreated: 0,
14041
- filesUpdated: 0,
14042
- filesDeleted: 0,
14043
- notificationSent: false
14044
- };
14320
+ } catch {
14045
14321
  }
14046
14322
  }
14047
- async function uninstallPackagesHandler(args2, deps) {
14048
- const { packmindCliHexa, exit, getCwd, log, error } = deps;
14049
- const { packagesSlugs } = args2;
14050
- const cwd = getCwd();
14051
- if (!packagesSlugs || packagesSlugs.length === 0) {
14052
- error("\u274C No packages specified.");
14053
- log("");
14054
- log("Usage: packmind-cli uninstall <package-slug> [package-slug...]");
14055
- log(" packmind-cli remove <package-slug> [package-slug...]");
14056
- log("");
14057
- log("Examples:");
14058
- log(" packmind-cli uninstall backend");
14059
- log(" packmind-cli remove backend frontend");
14060
- exit(1);
14061
- return {
14062
- filesDeleted: 0,
14063
- packagesUninstalled: []
14064
- };
14065
- }
14066
- let configPackages;
14067
- let configAgents;
14068
- let configFileExists = false;
14069
- try {
14070
- configFileExists = await packmindCliHexa.configExists(cwd);
14071
- const fullConfig = await packmindCliHexa.readFullConfig(cwd);
14072
- if (fullConfig) {
14073
- configPackages = fullConfig.packages;
14074
- configAgents = fullConfig.agents;
14075
- } else {
14076
- configPackages = {};
14077
- }
14078
- } catch (err) {
14079
- error("\u274C Failed to read packmind.json");
14080
- if (err instanceof Error) {
14081
- error(` ${err.message}`);
14082
- } else {
14083
- error(` ${String(err)}`);
14084
- }
14085
- error("\n\u{1F4A1} Please fix the packmind.json file or delete it to continue.");
14086
- exit(1);
14087
- return {
14088
- filesDeleted: 0,
14089
- packagesUninstalled: []
14090
- };
14091
- }
14092
- if (Object.keys(configPackages).length === 0) {
14093
- if (configFileExists) {
14094
- error("\u274C packmind.json is empty.");
14095
- } else {
14096
- error("\u274C No packmind.json found in current directory.");
14097
- }
14098
- log("");
14099
- log("\u{1F4A1} There are no packages to uninstall.");
14100
- log(" To install packages, run: packmind-cli install <package-slug>");
14101
- exit(1);
14102
- return {
14103
- filesDeleted: 0,
14104
- packagesUninstalled: []
14105
- };
14106
- }
14107
- let normalizedRequestedSlugs;
14108
- let normalizedConfigSlugs;
14109
- try {
14110
- normalizedRequestedSlugs = await packmindCliHexa.normalizePackageSlugs(packagesSlugs);
14111
- normalizedConfigSlugs = await packmindCliHexa.normalizePackageSlugs(
14112
- Object.keys(configPackages)
14113
- );
14114
- } catch (err) {
14115
- error(`\u274C ${err instanceof Error ? err.message : String(err)}`);
14116
- exit(1);
14117
- return {
14118
- filesDeleted: 0,
14119
- packagesUninstalled: []
14120
- };
14121
- }
14122
- const normalizedToOriginalConfigKey = /* @__PURE__ */ new Map();
14123
- Object.keys(configPackages).forEach((originalKey, index) => {
14124
- normalizedToOriginalConfigKey.set(
14125
- normalizedConfigSlugs[index],
14126
- originalKey
14127
- );
14128
- });
14129
- const packagesToUninstall = normalizedRequestedSlugs.filter((slug3) => normalizedToOriginalConfigKey.has(slug3)).map((slug3) => normalizedToOriginalConfigKey.get(slug3));
14130
- const notInstalledPackages = packagesSlugs.filter(
14131
- (_, i) => !normalizedToOriginalConfigKey.has(normalizedRequestedSlugs[i])
14132
- );
14133
- if (notInstalledPackages.length > 0) {
14134
- const packageWord = notInstalledPackages.length === 1 ? "package" : "packages";
14135
- log(
14136
- `\u26A0\uFE0F Warning: The following ${packageWord} ${notInstalledPackages.length === 1 ? "is" : "are"} not installed:`
14137
- );
14138
- notInstalledPackages.forEach((pkg) => {
14139
- log(` - ${pkg}`);
14140
- });
14141
- log("");
14142
- }
14143
- if (packagesToUninstall.length === 0) {
14144
- error("\u274C No packages to uninstall.");
14145
- exit(1);
14146
- return {
14147
- filesDeleted: 0,
14148
- packagesUninstalled: []
14149
- };
14150
- }
14151
- try {
14152
- const packageCount = packagesToUninstall.length;
14153
- const packageWord = packageCount === 1 ? "package" : "packages";
14154
- log(
14155
- `Uninstalling ${packageCount} ${packageWord}: ${packagesToUninstall.join(", ")}...`
14156
- );
14157
- const remainingPackages = Object.keys(configPackages).filter(
14158
- (pkg) => !packagesToUninstall.includes(pkg)
14159
- );
14160
- let filesDeleted = 0;
14161
- if (remainingPackages.length === 0) {
14162
- log("Removing all packages and cleaning up...");
14163
- const result = await packmindCliHexa.installPackages({
14164
- baseDirectory: cwd,
14165
- packagesSlugs: [],
14166
- previousPackagesSlugs: Object.keys(configPackages),
14167
- agents: configAgents
14168
- });
14169
- log(`
14170
- removed ${result.filesDeleted} files`);
14171
- if (result.errors.length > 0) {
14172
- log("\n\u26A0\uFE0F Errors encountered:");
14173
- result.errors.forEach((err) => {
14174
- log(` - ${err}`);
14175
- });
14176
- exit(1);
14177
- return {
14178
- filesDeleted: result.filesDeleted,
14179
- packagesUninstalled: packagesToUninstall
14180
- };
14181
- }
14182
- filesDeleted = result.filesDeleted;
14183
- } else {
14184
- const result = await packmindCliHexa.installPackages({
14185
- baseDirectory: cwd,
14186
- packagesSlugs: remainingPackages,
14187
- previousPackagesSlugs: Object.keys(configPackages),
14188
- agents: configAgents
14189
- });
14190
- if (result.recipesCount > 0 || result.standardsCount > 0) {
14191
- log(
14192
- `Removing ${result.recipesCount} commands and ${result.standardsCount} standards...`
14193
- );
14194
- }
14195
- log(`
14196
- removed ${result.filesDeleted} files`);
14197
- if (result.errors.length > 0) {
14198
- log("\n\u26A0\uFE0F Errors encountered:");
14199
- result.errors.forEach((err) => {
14200
- log(` - ${err}`);
14201
- });
14202
- exit(1);
14203
- return {
14204
- filesDeleted: result.filesDeleted,
14205
- packagesUninstalled: packagesToUninstall
14206
- };
14207
- }
14208
- filesDeleted = result.filesDeleted;
14209
- }
14210
- await packmindCliHexa.writeConfig(cwd, remainingPackages);
14211
- await notifyDistributionIfInGitRepo({
14323
+ async function installHandler({
14324
+ installPath,
14325
+ packages,
14326
+ list,
14327
+ show,
14328
+ status
14329
+ }) {
14330
+ const packmindLogger = new PackmindLogger("PackmindCLI", "info" /* INFO */);
14331
+ const packmindCliHexa = new PackmindCliHexa(packmindLogger);
14332
+ if (status) {
14333
+ const deps = {
14212
14334
  packmindCliHexa,
14213
- cwd,
14214
- packages: remainingPackages,
14215
- log
14216
- });
14217
- log("");
14218
- if (packagesToUninstall.length === 1) {
14219
- log(`\u2713 Package '${packagesToUninstall[0]}' has been uninstalled.`);
14220
- } else {
14221
- log(`\u2713 ${packagesToUninstall.length} packages have been uninstalled.`);
14222
- }
14223
- if (remainingPackages.length === 0) {
14224
- log("");
14225
- log("\u{1F4A1} All packages have been uninstalled.");
14226
- log(" Your packmind.json still exists but contains no packages.");
14227
- }
14228
- return {
14229
- filesDeleted,
14230
- packagesUninstalled: packagesToUninstall
14231
- };
14232
- } catch (err) {
14233
- error("\n\u274C Failed to uninstall packages:");
14234
- if (err instanceof Error) {
14235
- error(` ${err.message}`);
14236
- } else {
14237
- error(` ${String(err)}`);
14238
- }
14239
- exit(1);
14240
- return {
14241
- filesDeleted: 0,
14242
- packagesUninstalled: []
14243
- };
14244
- }
14245
- }
14246
- async function recursiveInstallHandler(args2, deps) {
14247
- const { packmindCliHexa, exit, getCwd, log, error } = deps;
14248
- const cwd = getCwd();
14249
- const result = {
14250
- directoriesProcessed: 0,
14251
- totalFilesCreated: 0,
14252
- totalFilesUpdated: 0,
14253
- totalFilesDeleted: 0,
14254
- totalNotifications: 0,
14255
- errors: []
14256
- };
14257
- let startDirectory = cwd;
14258
- if (args2.path) {
14259
- const resolvedPath = path19.resolve(cwd, args2.path);
14260
- try {
14261
- const stat9 = await fs17.stat(resolvedPath);
14262
- if (!stat9.isDirectory()) {
14263
- logErrorConsole(`Path is not a directory: ${resolvedPath}`);
14264
- exit(1);
14265
- return result;
14266
- }
14267
- startDirectory = resolvedPath;
14268
- } catch {
14269
- logErrorConsole(`Path does not exist: ${resolvedPath}`);
14270
- exit(1);
14271
- return result;
14272
- }
14273
- }
14274
- try {
14275
- const gitRoot = await packmindCliHexa.tryGetGitRepositoryRoot(cwd);
14276
- const basePath = args2.path ? startDirectory : gitRoot ?? cwd;
14277
- const allConfigs = await packmindCliHexa.findAllConfigsInTree(
14278
- startDirectory,
14279
- basePath
14280
- );
14281
- if (!allConfigs.hasConfigs) {
14282
- log("No packmind.json files found in this repository.");
14283
- log("");
14284
- log("Usage: packmind-cli install");
14285
- log("");
14286
- log(
14287
- "This command requires at least one packmind.json file in the repository."
14288
- );
14289
- log("Create a packmind.json file first:");
14290
- log("");
14291
- log(" packmind-cli install <package-slug>");
14292
- exit(0);
14293
- return result;
14294
- }
14295
- const sortedConfigs = [...allConfigs.configs].sort(
14296
- (a, b) => a.targetPath.localeCompare(b.targetPath)
14297
- );
14298
- log(`Found ${sortedConfigs.length} packmind.json file(s) to process
14299
- `);
14300
- for (const config of sortedConfigs) {
14301
- const displayPath = args2.path ? computeDisplayPath(
14302
- config.absoluteTargetPath === cwd ? "/" : config.absoluteTargetPath.startsWith(cwd + "/") ? config.absoluteTargetPath.slice(cwd.length) : config.targetPath
14303
- ) : computeDisplayPath(config.targetPath);
14304
- log(`Installing in ${displayPath}...`);
14305
- const installResult = await executeInstallForDirectory(
14306
- config.absoluteTargetPath,
14307
- { packmindCliHexa, getCwd, log, error }
14308
- );
14309
- result.directoriesProcessed++;
14310
- result.totalFilesCreated += installResult.filesCreated;
14311
- result.totalFilesUpdated += installResult.filesUpdated;
14312
- result.totalFilesDeleted += installResult.filesDeleted;
14313
- if (installResult.notificationSent) {
14314
- result.totalNotifications++;
14315
- }
14316
- if (!installResult.success && installResult.errorMessage) {
14317
- result.errors.push({
14318
- directory: displayPath,
14319
- message: installResult.errorMessage
14320
- });
14321
- error(` Error: ${installResult.errorMessage}`);
14322
- }
14323
- log("");
14324
- }
14325
- const dirWord = result.directoriesProcessed === 1 ? "directory" : "directories";
14326
- log(
14327
- `Summary: ${result.directoriesProcessed} ${dirWord} processed, ${result.totalFilesCreated} files added, ${result.totalFilesUpdated} changed, ${result.totalFilesDeleted} removed`
14328
- );
14329
- if (result.totalNotifications > 0) {
14330
- const distWord = result.totalNotifications === 1 ? "distribution" : "distributions";
14331
- log(`Notified Packmind of ${result.totalNotifications} ${distWord}`);
14332
- }
14333
- if (result.errors.length > 0) {
14334
- log("");
14335
- log(`\u26A0\uFE0F ${result.errors.length} error(s) encountered:`);
14336
- result.errors.forEach((err) => {
14337
- log(` - ${err.directory}: ${err.message}`);
14338
- });
14339
- exit(1);
14340
- return result;
14341
- }
14342
- if (deps.playbookLocalRepository) {
14343
- deps.playbookLocalRepository.clearAll();
14344
- }
14345
- exit(0);
14346
- return result;
14347
- } catch (err) {
14348
- error("\n\u274C Failed to run recursive install:");
14349
- if (err instanceof Error) {
14350
- error(` ${err.message}`);
14351
- } else {
14352
- error(` ${String(err)}`);
14353
- }
14354
- exit(1);
14355
- return result;
14356
- }
14357
- }
14358
-
14359
- // apps/cli/src/infra/utils/spaceFilterUtils.ts
14360
- function resolveSpaceFromArgs(spaceArg, spaces) {
14361
- if (!spaceArg) return null;
14362
- const slug3 = spaceArg.startsWith("@") ? spaceArg.slice(1) : spaceArg;
14363
- return spaces.find((s) => s.slug === slug3) ?? null;
14364
- }
14365
-
14366
- // apps/cli/src/infra/utils/urlBuilderUtils.ts
14367
- function resolveUrlBuilder(buildArtifactPath) {
14368
- const apiKey = loadApiKey();
14369
- if (!apiKey) return () => null;
14370
- const decoded = decodeApiKey(apiKey);
14371
- const orgSlug = decoded?.jwt?.organization?.slug;
14372
- if (!decoded?.host || !orgSlug) return () => null;
14373
- return (spaceSlug, artifactId) => `${decoded.host}/org/${orgSlug}/space/${spaceSlug}/${buildArtifactPath(artifactId)}`;
14374
- }
14375
-
14376
- // apps/cli/src/infra/commands/packages/listPackagesHandler.ts
14377
- function logPackageEntry(pkg, fullSlug, spaceSlug, buildUrl) {
14378
- logConsole(`- ${formatSlug(fullSlug)}`);
14379
- logConsole(` ${formatLabel("Name:")} ${pkg.name}`);
14380
- const url = buildUrl(spaceSlug, pkg.id);
14381
- if (url) {
14382
- logConsole(` ${formatLabel("Link:")} ${url}`);
14383
- }
14384
- if (pkg.description) {
14385
- const lines = pkg.description.trim().split("\n").map((l) => l.trim()).filter((l) => l.length > 0);
14386
- const [first, ...rest] = lines;
14387
- logConsole(` ${formatLabel("Description:")} ${first}`);
14388
- rest.forEach((l) => logConsole(` ${l}`));
14389
- }
14390
- }
14391
- function groupPackagesBySpace(packages, spaces) {
14392
- const spaceMap = new Map(
14393
- spaces.map((s) => [s.id, s])
14394
- );
14395
- const groupsMap = /* @__PURE__ */ new Map();
14396
- for (const pkg of packages) {
14397
- const space = spaceMap.get(pkg.spaceId);
14398
- if (!space) {
14399
- continue;
14400
- }
14401
- let group = groupsMap.get(space.id);
14402
- if (!group) {
14403
- group = { space, pkgs: [] };
14404
- groupsMap.set(space.id, group);
14405
- }
14406
- group.pkgs.push(pkg);
14407
- }
14408
- return [...groupsMap.values()].sort(
14409
- (a, b) => a.space.name.localeCompare(b.space.name)
14410
- );
14411
- }
14412
- function displayGroupedPackages(packages, spaces, buildUrl) {
14413
- const groups = groupPackagesBySpace(packages, spaces);
14414
- let firstSlug = null;
14415
- for (const { space, pkgs } of groups) {
14416
- logConsole(`Space "${space.name}":
14417
- `);
14418
- for (const pkg of [...pkgs].sort((a, b) => a.slug.localeCompare(b.slug))) {
14419
- const fullSlug = `@${space.slug}/${pkg.slug}`;
14420
- firstSlug ??= fullSlug;
14421
- logPackageEntry(pkg, fullSlug, space.slug, buildUrl);
14422
- logConsole("");
14423
- }
14424
- }
14425
- return firstSlug ?? formatSlug(packages[0].slug);
14426
- }
14427
- async function listPackagesHandler(args2, deps) {
14428
- const { packmindCliHexa, exit } = deps;
14429
- try {
14430
- logInfoConsole("Fetching available packages...");
14431
- const allSpaces = await packmindCliHexa.getSpaces();
14432
- if (!allSpaces || allSpaces.length === 0) {
14433
- throw new Error("Unable to list organization spaces.");
14434
- }
14435
- const matchedSpace = resolveSpaceFromArgs(args2.space, allSpaces);
14436
- if (args2.space && !matchedSpace) {
14437
- logErrorConsole(`Space "@${args2.space}" not found.`);
14438
- logInfoConsole(
14439
- `Available spaces: ${allSpaces.map((s) => `@${s.slug}`).join(", ")}`
14440
- );
14441
- exit(1);
14442
- return;
14443
- }
14444
- const packages = await packmindCliHexa.listPackages(
14445
- matchedSpace ? { spaceId: matchedSpace.id } : {}
14446
- );
14447
- const spaces = matchedSpace ? [matchedSpace] : allSpaces;
14448
- if (packages.length === 0) {
14449
- logConsole(
14450
- matchedSpace ? `No packages found in space "@${matchedSpace.slug}".` : "No packages found."
14451
- );
14452
- exit(0);
14453
- return;
14454
- }
14455
- const buildUrl = resolveUrlBuilder((id) => `packages/${id}`);
14456
- logConsole("\nAvailable packages:\n");
14457
- const exampleSlug = displayGroupedPackages(packages, spaces, buildUrl);
14458
- logConsole("How to install a package:\n");
14459
- logConsole(` ${formatCommand(`packmind-cli install ${exampleSlug}`)}`);
14460
- exit(0);
14461
- } catch (err) {
14462
- logErrorConsole("Failed to list packages:");
14463
- if (err instanceof Error) {
14464
- logErrorConsole(err.message);
14465
- } else {
14466
- logErrorConsole(String(err));
14467
- }
14468
- exit(1);
14469
- }
14470
- }
14471
-
14472
- // apps/cli/src/infra/utils/packageSlugUtils.ts
14473
- function parsePackageSlug(slug3) {
14474
- if (!slug3.startsWith("@")) return null;
14475
- const slash = slug3.indexOf("/", 1);
14476
- if (slash === -1) return null;
14477
- return { spaceSlug: slug3.slice(1, slash), pkgSlug: slug3.slice(slash + 1) };
14478
- }
14479
-
14480
- // apps/cli/src/infra/commands/packages/showPackageHandler.ts
14481
- function isNotFoundError(err) {
14482
- return err instanceof Error && err.message.includes("does not exist");
14483
- }
14484
- async function resolvePackage(slug3, packmindCliHexa) {
14485
- const allSpaces = await packmindCliHexa.getSpaces();
14486
- const parsed = parsePackageSlug(slug3);
14487
- if (parsed) {
14488
- const { spaceSlug, pkgSlug } = parsed;
14489
- const matchedSpace = allSpaces.find((s) => s.slug === spaceSlug);
14490
- if (!matchedSpace) {
14491
- throw new Error(`Space '@${spaceSlug}' not found.`);
14492
- }
14493
- let pkg;
14494
- try {
14495
- pkg = await packmindCliHexa.getPackageBySlug({
14496
- slug: pkgSlug,
14497
- spaceId: matchedSpace.id
14498
- });
14499
- } catch (err) {
14500
- if (isNotFoundError(err)) {
14501
- throw new Error(
14502
- `Package '${pkgSlug}' not found in space '@${spaceSlug}'.`
14503
- );
14504
- }
14505
- throw err;
14506
- }
14507
- return { pkg, fullSlug: `@${spaceSlug}/${pkgSlug}` };
14508
- }
14509
- const results = await Promise.allSettled(
14510
- allSpaces.map(async (space) => ({
14511
- pkg: await packmindCliHexa.getPackageBySlug({
14512
- slug: slug3,
14513
- spaceId: space.id
14514
- }),
14515
- spaceSlug: space.slug
14516
- }))
14517
- );
14518
- const matches = results.filter(
14519
- (r) => r.status === "fulfilled"
14520
- ).map((r) => r.value);
14521
- if (matches.length === 0) {
14522
- const realError = results.filter((r) => r.status === "rejected").find((r) => !isNotFoundError(r.reason));
14523
- if (realError) {
14524
- throw realError.reason;
14525
- }
14526
- throw new Error(`Package '${slug3}' not found in any space.`);
14527
- }
14528
- if (matches.length > 1) {
14529
- const example = `@${matches[0].spaceSlug}/${slug3}`;
14530
- throw new Error(
14531
- `Package '${slug3}' exists in multiple spaces (${matches.map((m) => `@${m.spaceSlug}`).join(", ")}). Please specify the space using the @space/package format (e.g. ${example}).`
14532
- );
14533
- }
14534
- return {
14535
- pkg: matches[0].pkg,
14536
- fullSlug: `@${matches[0].spaceSlug}/${slug3}`
14537
- };
14538
- }
14539
- async function showPackageHandler(args2, deps) {
14540
- const { packmindCliHexa, exit } = deps;
14541
- try {
14542
- logInfoConsole(`Fetching package details for '${args2.slug}'...`);
14543
- const { pkg, fullSlug } = await resolvePackage(args2.slug, packmindCliHexa);
14544
- logConsole(`
14545
- ${pkg.name} (${fullSlug}):
14546
- `);
14547
- if (pkg.description) {
14548
- logConsole(`${pkg.description}
14549
- `);
14550
- }
14551
- if (pkg.standards && pkg.standards.length > 0) {
14552
- logConsole("Standards:");
14553
- pkg.standards.forEach((standard) => {
14554
- if (standard.summary) {
14555
- logConsole(` - ${standard.name}: ${standard.summary}`);
14556
- } else {
14557
- logConsole(` - ${standard.name}`);
14558
- }
14559
- });
14560
- logConsole("");
14561
- }
14562
- if (pkg.recipes && pkg.recipes.length > 0) {
14563
- logConsole("Commands:");
14564
- pkg.recipes.forEach((recipe) => {
14565
- if (recipe.summary) {
14566
- logConsole(` - ${recipe.name}: ${recipe.summary}`);
14567
- } else {
14568
- logConsole(` - ${recipe.name}`);
14569
- }
14570
- });
14571
- logConsole("");
14572
- }
14573
- if (pkg.skills && pkg.skills.length > 0) {
14574
- logConsole("Skills:");
14575
- pkg.skills.forEach((skill) => {
14576
- if (skill.summary) {
14577
- logConsole(` - ${skill.name}: ${skill.summary}`);
14578
- } else {
14579
- logConsole(` - ${skill.name}`);
14580
- }
14581
- });
14582
- logConsole("");
14583
- }
14584
- exit(0);
14585
- } catch (err) {
14586
- logErrorConsole("Failed to fetch package details:");
14587
- if (err instanceof Error) {
14588
- logErrorConsole(err.message);
14589
- } else {
14590
- logErrorConsole(String(err));
14591
- }
14592
- exit(1);
14593
- }
14594
- }
14595
-
14596
- // apps/cli/src/infra/repositories/PlaybookLocalRepository.ts
14597
- var crypto = __toESM(require("crypto"));
14598
- var fs18 = __toESM(require("fs"));
14599
- var os4 = __toESM(require("os"));
14600
- var path20 = __toESM(require("path"));
14601
- var yaml = __toESM(require("yaml"));
14602
- var PlaybookLocalRepository = class {
14603
- constructor(repoRoot) {
14604
- const normalized = this.normalizeRepoRoot(repoRoot);
14605
- const hash = crypto.createHash("md5").update(normalized).digest("hex");
14606
- this.storagePath = path20.join(
14607
- os4.homedir(),
14608
- ".packmind",
14609
- hash,
14610
- "playbook.yaml"
14611
- );
14612
- }
14613
- addChange(entry) {
14614
- const data = this.readYaml();
14615
- const existingIndex = data.changes.findIndex(
14616
- (c) => c.filePath === entry.filePath && c.spaceId === entry.spaceId
14617
- );
14618
- if (existingIndex >= 0) {
14619
- data.changes[existingIndex] = entry;
14620
- } else {
14621
- data.changes.push(entry);
14622
- }
14623
- this.writeYaml(data);
14624
- }
14625
- removeChange(filePath, spaceId) {
14626
- const data = this.readYaml();
14627
- const initialLength = data.changes.length;
14628
- data.changes = data.changes.filter(
14629
- (c) => !(c.filePath === filePath && c.spaceId === spaceId)
14630
- );
14631
- if (data.changes.length === initialLength) {
14632
- return false;
14633
- }
14634
- this.writeYaml(data);
14635
- return true;
14636
- }
14637
- getChanges() {
14638
- return this.readYaml().changes;
14335
+ exit: process.exit,
14336
+ getCwd: () => process.cwd(),
14337
+ log: console.log,
14338
+ error: console.error
14339
+ };
14340
+ await statusHandler({}, deps);
14341
+ return;
14639
14342
  }
14640
- getChange(filePath, spaceId) {
14641
- return this.readYaml().changes.find(
14642
- (c) => c.filePath === filePath && c.spaceId === spaceId
14643
- ) ?? null;
14343
+ if (list) {
14344
+ logErrorConsole('Command "packmind-cli install --list" has been removed.');
14345
+ logConsole(`Use ${formatCommand("packmind-cli packages list")} instead.`);
14346
+ process.exit(1);
14644
14347
  }
14645
- clearAll() {
14646
- this.writeYaml({ version: 1, changes: [] });
14348
+ if (show) {
14349
+ const showCommand = `packmind-cli packages show ${show}`;
14350
+ logErrorConsole('Command "packmind-cli install --show" has been removed.');
14351
+ logConsole(`Use ${formatCommand(showCommand)} instead.`);
14352
+ process.exit(1);
14647
14353
  }
14648
- normalizeRepoRoot(repoRoot) {
14649
- let normalized = repoRoot.replace(/\\/g, "/");
14650
- normalized = normalized.replace(/\/$/, "");
14651
- return normalized;
14354
+ const cwd = installPath ? path20.resolve(process.cwd(), installPath) : process.cwd();
14355
+ if (installPath) {
14356
+ if (!fs18.existsSync(cwd)) {
14357
+ logErrorConsole(`Path does not exist: ${cwd}`);
14358
+ process.exit(1);
14359
+ return;
14360
+ }
14361
+ if (!fs18.statSync(cwd).isDirectory()) {
14362
+ logErrorConsole(`Path is not a directory: ${cwd}`);
14363
+ process.exit(1);
14364
+ return;
14365
+ }
14652
14366
  }
14653
- readYaml() {
14654
- if (!fs18.existsSync(this.storagePath)) {
14655
- return { version: 1, changes: [] };
14367
+ let targetDirs;
14368
+ if (installPath) {
14369
+ targetDirs = findSubDirectoriesWithPackmindJson(cwd, false);
14370
+ } else if (packages.length > 0) {
14371
+ targetDirs = [cwd];
14372
+ } else {
14373
+ targetDirs = [];
14374
+ if (fs18.existsSync(path20.join(cwd, "packmind.json"))) {
14375
+ targetDirs.push(cwd);
14656
14376
  }
14377
+ targetDirs.push(...findSubDirectoriesWithPackmindJson(cwd, true));
14378
+ }
14379
+ if (targetDirs.length === 0) {
14380
+ targetDirs = [cwd];
14381
+ }
14382
+ const results = [];
14383
+ const thrownErrors = [];
14384
+ const multiDir = targetDirs.length > 1;
14385
+ for (const dir of targetDirs) {
14657
14386
  try {
14658
- const content = fs18.readFileSync(this.storagePath, "utf-8");
14659
- const parsed = yaml.parse(content);
14660
- if (!parsed || !Array.isArray(parsed.changes)) {
14661
- return { version: 1, changes: [] };
14662
- }
14663
- return { version: 1, changes: parsed.changes };
14664
- } catch {
14665
- logWarningConsole(
14666
- `Corrupted playbook file: ${this.storagePath}. Treating as empty.`
14387
+ const result = await packmindCliHexa.install({
14388
+ baseDirectory: dir,
14389
+ packages: packages.length > 0 ? packages : void 0
14390
+ });
14391
+ results.push(result);
14392
+ await notifyArtefactsDistributionIfInGitRepo({
14393
+ packmindCliHexa,
14394
+ dir
14395
+ });
14396
+ } catch (error) {
14397
+ const errorMessage = error instanceof Error ? error.message : String(error);
14398
+ thrownErrors.push(
14399
+ multiDir ? `[${dir}] install failed: ${errorMessage}` : `install failed: ${errorMessage}`
14667
14400
  );
14668
- return { version: 1, changes: [] };
14669
14401
  }
14670
14402
  }
14671
- writeYaml(data) {
14672
- const dir = path20.dirname(this.storagePath);
14673
- fs18.mkdirSync(dir, { recursive: true });
14674
- fs18.writeFileSync(this.storagePath, yaml.stringify(data), "utf-8");
14675
- }
14676
- };
14403
+ const combined = mergeInstallResults(results);
14404
+ if (combined.missingAccess.length > 0) {
14405
+ let warning = `\u26A0\uFE0F You don't have access to the following packages (their artifacts were preserved from the lock file):
14406
+ ` + combined.missingAccess.map((s) => ` - ${s}`).join("\n");
14407
+ if (combined.joinSpaceUrl) {
14408
+ warning += `
14677
14409
 
14678
- // apps/cli/src/infra/commands/InstallCommand.ts
14410
+ \u{1F449} Join the space to get access: ${combined.joinSpaceUrl}`;
14411
+ }
14412
+ logWarningConsole(warning);
14413
+ }
14414
+ logConsole(buildInstallSummary(combined));
14415
+ const allErrors = [...combined.errors, ...thrownErrors];
14416
+ if (allErrors.length > 0) {
14417
+ logWarningConsole(`Encountered ${allErrors.length} error(s):`);
14418
+ allErrors.forEach((err) => logErrorConsole(` - ${err}`));
14419
+ }
14420
+ if (thrownErrors.length > 0) {
14421
+ process.exit(1);
14422
+ }
14423
+ }
14679
14424
  var installCommand = (0, import_cmd_ts2.command)({
14680
14425
  name: "install",
14681
- description: "Install packages and save their artifacts locally",
14682
14426
  aliases: ["pull"],
14427
+ description: "Install packages and save their artifacts locally",
14683
14428
  args: {
14684
- list: (0, import_cmd_ts2.flag)({
14685
- long: "list",
14686
- description: "List available packages"
14429
+ installPath: (0, import_cmd_ts2.option)({
14430
+ type: import_cmd_ts2.string,
14431
+ short: "p",
14432
+ long: "path",
14433
+ defaultValue: () => "",
14434
+ description: "Run install in the specified directory instead of the current directory"
14435
+ }),
14436
+ packages: (0, import_cmd_ts2.restPositionals)({
14437
+ type: import_cmd_ts2.string,
14438
+ displayName: "packages",
14439
+ description: "Package slugs to install (e.g. @my-space/my-package)"
14687
14440
  }),
14688
14441
  status: (0, import_cmd_ts2.flag)({
14689
14442
  long: "status",
14690
14443
  description: "Show status of all packmind.json files and their packages in the workspace"
14691
14444
  }),
14692
- recursive: (0, import_cmd_ts2.flag)({
14693
- short: "r",
14694
- long: "recursive",
14695
- description: "[Deprecated] Install is now recursive by default. This flag will be removed in a future version."
14696
- }),
14697
- path: (0, import_cmd_ts2.option)({
14698
- type: import_cmd_ts2.string,
14699
- short: "p",
14700
- long: "path",
14701
- defaultValue: () => "",
14702
- description: "Run install in the specified directory (recursive within that path)"
14445
+ list: (0, import_cmd_ts2.flag)({
14446
+ long: "list",
14447
+ description: "[Deprecated] List available packages"
14703
14448
  }),
14704
14449
  show: (0, import_cmd_ts2.option)({
14705
14450
  type: import_cmd_ts2.string,
14706
14451
  long: "show",
14707
- description: "Show details of a specific package",
14452
+ description: "[Deprecated] Show details of a specific package",
14708
14453
  defaultValue: () => ""
14709
- }),
14710
- packagesSlugs: (0, import_cmd_ts2.restPositionals)({
14711
- type: import_cmd_ts2.string,
14712
- displayName: "packages",
14713
- description: "Package slugs to install (e.g., backend frontend)"
14714
14454
  })
14715
14455
  },
14716
- handler: async ({ list, status, recursive, path: path36, show, packagesSlugs }) => {
14717
- const packmindLogger = new PackmindLogger("PackmindCLI", "info" /* INFO */);
14718
- const packmindCliHexa = new PackmindCliHexa(packmindLogger);
14719
- const repoRoot = await packmindCliHexa.tryGetGitRepositoryRoot(
14720
- process.cwd()
14721
- );
14722
- const playbookLocalRepository = repoRoot ? new PlaybookLocalRepository(repoRoot) : void 0;
14723
- const deps = {
14724
- packmindCliHexa,
14725
- exit: process.exit,
14726
- getCwd: () => process.cwd(),
14727
- log: console.log,
14728
- error: console.error,
14729
- playbookLocalRepository
14730
- };
14731
- if (list) {
14732
- await listPackagesHandler({}, deps);
14733
- return;
14734
- }
14735
- if (status) {
14736
- await statusHandler({}, deps);
14737
- return;
14738
- }
14739
- if (show) {
14740
- await showPackageHandler(
14741
- { slug: show },
14742
- { packmindCliHexa, exit: process.exit }
14743
- );
14744
- return;
14745
- }
14746
- if (recursive) {
14747
- logWarningConsole(
14748
- "\u26A0\uFE0F The --recursive flag is deprecated. Install is now recursive by default."
14749
- );
14750
- await recursiveInstallHandler({ path: path36 || void 0 }, deps);
14751
- return;
14752
- }
14753
- if (packagesSlugs.length > 0) {
14754
- await installPackagesHandler(
14755
- { packagesSlugs, path: path36 || void 0 },
14756
- deps
14757
- );
14758
- return;
14759
- }
14760
- await recursiveInstallHandler({ path: path36 || void 0 }, deps);
14761
- }
14456
+ handler: installHandler
14762
14457
  });
14763
14458
 
14764
14459
  // apps/cli/src/infra/commands/UninstallCommand.ts
14765
14460
  var import_cmd_ts3 = __toESM(require_cjs());
14461
+ function buildUninstallSummary(result) {
14462
+ const removedParts = [
14463
+ result.standardsRemoved > 0 ? `${result.standardsRemoved} ${result.standardsRemoved === 1 ? "standard" : "standards"}` : null,
14464
+ result.commandsRemoved > 0 ? `${result.commandsRemoved} ${result.commandsRemoved === 1 ? "command" : "commands"}` : null,
14465
+ result.skillsRemoved > 0 ? `${result.skillsRemoved} ${result.skillsRemoved === 1 ? "skill" : "skills"}` : null,
14466
+ result.recipesRemoved > 0 ? `${result.recipesRemoved} ${result.recipesRemoved === 1 ? "recipe" : "recipes"}` : null
14467
+ ].filter(Boolean);
14468
+ if (removedParts.length === 0) {
14469
+ return "\u2705 Package removed";
14470
+ }
14471
+ return `\u2705 Removed ${removedParts.join(", ")}`;
14472
+ }
14766
14473
  var uninstallCommand = (0, import_cmd_ts3.command)({
14767
14474
  name: "uninstall",
14768
- description: "Uninstall packages and remove their commands and standards from the current directory",
14475
+ description: "Uninstall packages and sync artifacts. Specify package slugs (e.g. @my-space/my-package) to uninstall.",
14769
14476
  aliases: ["remove"],
14770
14477
  args: {
14771
- packagesSlugs: (0, import_cmd_ts3.restPositionals)({
14478
+ packages: (0, import_cmd_ts3.restPositionals)({
14772
14479
  type: import_cmd_ts3.string,
14773
14480
  displayName: "packages",
14774
- description: "Package slugs to uninstall (e.g., backend frontend)"
14481
+ description: "Package slugs to uninstall (e.g. @my-space/my-package)"
14775
14482
  })
14776
14483
  },
14777
- handler: async ({ packagesSlugs }) => {
14484
+ handler: async ({ packages }) => {
14485
+ if (packages.length === 0) {
14486
+ logErrorConsole("Please specify at least one package to uninstall.");
14487
+ process.exit(1);
14488
+ }
14778
14489
  const packmindLogger = new PackmindLogger("PackmindCLI", "info" /* INFO */);
14779
14490
  const packmindCliHexa = new PackmindCliHexa(packmindLogger);
14780
- const deps = {
14781
- packmindCliHexa,
14782
- exit: process.exit,
14783
- getCwd: () => process.cwd(),
14784
- log: console.log,
14785
- error: console.error
14786
- };
14787
- await uninstallPackagesHandler({ packagesSlugs }, deps);
14491
+ try {
14492
+ const result = await packmindCliHexa.uninstall({
14493
+ baseDirectory: process.cwd(),
14494
+ packages
14495
+ });
14496
+ if (result.missingAccess.length > 0) {
14497
+ let warning = `\u26A0\uFE0F You don't have access to the following packages (their artifacts were preserved from the lock file):
14498
+ ` + result.missingAccess.map((s) => ` - ${s}`).join("\n");
14499
+ if (result.joinSpaceUrl) {
14500
+ warning += `
14501
+
14502
+ \u{1F449} Join the space to get access: ${result.joinSpaceUrl}`;
14503
+ }
14504
+ logWarningConsole(warning);
14505
+ }
14506
+ logConsole(buildUninstallSummary(result));
14507
+ if (result.errors.length > 0) {
14508
+ logWarningConsole(`Encountered ${result.errors.length} error(s):`);
14509
+ result.errors.forEach((err) => logErrorConsole(` - ${err}`));
14510
+ }
14511
+ } catch (error) {
14512
+ const errorMessage = error instanceof Error ? error.message : String(error);
14513
+ logErrorConsole(`uninstall failed: ${errorMessage}`);
14514
+ process.exit(1);
14515
+ }
14788
14516
  }
14789
14517
  });
14790
14518
 
@@ -14899,7 +14627,7 @@ function displayVersionNotice(result) {
14899
14627
  }
14900
14628
 
14901
14629
  // apps/cli/src/infra/commands/WhoamiCommand.ts
14902
- var { version: CLI_VERSION2 } = require_package();
14630
+ var { version: CLI_VERSION } = require_package();
14903
14631
  function formatExpiresAt(expiresAt) {
14904
14632
  const now = /* @__PURE__ */ new Date();
14905
14633
  if (expiresAt < now) {
@@ -14943,7 +14671,7 @@ var whoamiCommand = (0, import_cmd_ts6.command)({
14943
14671
  const packmindLogger = new PackmindLogger("PackmindCLI", "info" /* INFO */);
14944
14672
  const packmindCliHexa = new PackmindCliHexa(packmindLogger);
14945
14673
  const versionCheckPromise = packmindCliHexa.checkCliVersion({
14946
- currentVersion: CLI_VERSION2
14674
+ currentVersion: CLI_VERSION
14947
14675
  });
14948
14676
  const result = await packmindCliHexa.whoami({});
14949
14677
  if (!result.isAuthenticated) {
@@ -14980,7 +14708,7 @@ var inquirer = __toESM(require("inquirer"));
14980
14708
  // apps/cli/src/application/services/AgentDetectionService.ts
14981
14709
  var fs19 = __toESM(require("fs"));
14982
14710
  var path21 = __toESM(require("path"));
14983
- var os5 = __toESM(require("os"));
14711
+ var os4 = __toESM(require("os"));
14984
14712
  var import_child_process4 = require("child_process");
14985
14713
  var AgentDetectionService = class {
14986
14714
  constructor(projectDir = process.cwd()) {
@@ -15006,7 +14734,7 @@ var AgentDetectionService = class {
15006
14734
  return this.isCommandAvailable("claude");
15007
14735
  }
15008
14736
  isCursorAvailable() {
15009
- const cursorConfigDir = path21.join(os5.homedir(), ".cursor");
14737
+ const cursorConfigDir = path21.join(os4.homedir(), ".cursor");
15010
14738
  return fs19.existsSync(cursorConfigDir);
15011
14739
  }
15012
14740
  isVSCodeAvailable() {
@@ -15073,7 +14801,7 @@ async function promptAgentsWithReadline(choices) {
15073
14801
  output.write("\n");
15074
14802
  const preselected = choices.map((c, i) => c.checked ? i + 1 : null).filter((i) => i !== null);
15075
14803
  const defaultValue = preselected.length > 0 ? preselected.join(",") : "1,2,3";
15076
- return new Promise((resolve14) => {
14804
+ return new Promise((resolve15) => {
15077
14805
  rl.question(
15078
14806
  `Enter numbers separated by commas (default: ${defaultValue}): `,
15079
14807
  (answer) => {
@@ -15084,7 +14812,7 @@ async function promptAgentsWithReadline(choices) {
15084
14812
  const numbersStr = trimmed === "" ? defaultValue : trimmed;
15085
14813
  const numbers = numbersStr.split(",").map((s) => parseInt(s.trim(), 10)).filter((n) => !isNaN(n) && n >= 1 && n <= choices.length);
15086
14814
  const selectedAgents = numbers.map((n) => choices[n - 1].value);
15087
- resolve14(selectedAgents);
14815
+ resolve15(selectedAgents);
15088
14816
  }
15089
14817
  );
15090
14818
  });
@@ -15314,7 +15042,7 @@ async function handleIncompatibleInstalledSkills(skills, baseDirectory, confirm)
15314
15042
  }
15315
15043
 
15316
15044
  // apps/cli/src/infra/commands/skills/InstallDefaultSkillsCommand.ts
15317
- var { version: CLI_VERSION3 } = require_package();
15045
+ var { version: CLI_VERSION2 } = require_package();
15318
15046
  var installDefaultSkillsCommand = (0, import_cmd_ts10.command)({
15319
15047
  name: "install-default",
15320
15048
  description: "Install default Packmind skills for configured coding agents",
@@ -15332,7 +15060,7 @@ var installDefaultSkillsCommand = (0, import_cmd_ts10.command)({
15332
15060
  const baseDirectory = process.cwd();
15333
15061
  const result = await packmindCliHexa.installDefaultSkills({
15334
15062
  includeBeta,
15335
- cliVersion: includeBeta ? void 0 : CLI_VERSION3,
15063
+ cliVersion: includeBeta ? void 0 : CLI_VERSION2,
15336
15064
  baseDirectory
15337
15065
  });
15338
15066
  if (result.skippedSkillsCount > 0) {
@@ -15393,10 +15121,10 @@ async function promptConfirmation(question) {
15393
15121
  input: process.stdin,
15394
15122
  output: process.stdout
15395
15123
  });
15396
- return new Promise((resolve14) => {
15124
+ return new Promise((resolve15) => {
15397
15125
  rl.question(question, (answer) => {
15398
15126
  rl.close();
15399
- resolve14(answer.trim().toLowerCase() === "y");
15127
+ resolve15(answer.trim().toLowerCase() === "y");
15400
15128
  });
15401
15129
  });
15402
15130
  }
@@ -15404,6 +15132,23 @@ async function promptConfirmation(question) {
15404
15132
  // apps/cli/src/infra/commands/ListSkillsCommand.ts
15405
15133
  var import_cmd_ts11 = __toESM(require_cjs());
15406
15134
 
15135
+ // apps/cli/src/infra/utils/spaceFilterUtils.ts
15136
+ function resolveSpaceFromArgs(spaceArg, spaces) {
15137
+ if (!spaceArg) return null;
15138
+ const slug3 = spaceArg.startsWith("@") ? spaceArg.slice(1) : spaceArg;
15139
+ return spaces.find((s) => s.slug === slug3) ?? null;
15140
+ }
15141
+
15142
+ // apps/cli/src/infra/utils/urlBuilderUtils.ts
15143
+ function resolveUrlBuilder(buildArtifactPath) {
15144
+ const apiKey = loadApiKey();
15145
+ if (!apiKey) return () => null;
15146
+ const decoded = decodeApiKey(apiKey);
15147
+ const orgSlug = decoded?.jwt?.organization?.slug;
15148
+ if (!decoded?.host || !orgSlug) return () => null;
15149
+ return (spaceSlug, artifactId) => `${decoded.host}/org/${orgSlug}/space/${spaceSlug}/${buildArtifactPath(artifactId)}`;
15150
+ }
15151
+
15407
15152
  // apps/cli/src/infra/commands/skills/listSkillsHandler.ts
15408
15153
  function groupSkillsBySpace(skills, spaces) {
15409
15154
  const spaceMap = new Map(
@@ -16011,6 +15756,21 @@ async function findTargetDirectories(searchPath, packmindCliHexa) {
16011
15756
  targets.push(dir);
16012
15757
  }
16013
15758
  }
15759
+ if (targets.length === 0) {
15760
+ let currentDir = nodePath.dirname(searchPath);
15761
+ while (true) {
15762
+ const ancestorExists = await packmindCliHexa.configExists(currentDir);
15763
+ if (ancestorExists) {
15764
+ targets.push(currentDir);
15765
+ break;
15766
+ }
15767
+ const parentDir = nodePath.dirname(currentDir);
15768
+ if (parentDir === currentDir) {
15769
+ break;
15770
+ }
15771
+ currentDir = parentDir;
15772
+ }
15773
+ }
16014
15774
  return targets;
16015
15775
  }
16016
15776
  function computeRelativePath(targetAbsDir, gitRoot) {
@@ -16193,7 +15953,11 @@ async function diffArtefactsHandler(deps) {
16193
15953
  relativePath,
16194
15954
  agents: config.agents
16195
15955
  });
16196
- targetResults.push({ targetRelativePath, diffs });
15956
+ const filterPrefix = nodePath.relative(targetDir, searchPath);
15957
+ const filteredDiffs = filterPrefix !== "" && !filterPrefix.startsWith("..") ? diffs.filter(
15958
+ (d) => d.filePath === filterPrefix || d.filePath.startsWith(filterPrefix + "/")
15959
+ ) : diffs;
15960
+ targetResults.push({ targetRelativePath, diffs: filteredDiffs });
16197
15961
  }
16198
15962
  if (targetResults.length === 0) {
16199
15963
  log("No packages configured in any target.");
@@ -16285,7 +16049,7 @@ var diffCommand = (0, import_cmd_ts19.command)({
16285
16049
  description: "Subcommand and arguments (e.g., add <path>, remove <path>)"
16286
16050
  })
16287
16051
  },
16288
- handler: async ({ submit, includeSubmitted, message, path: path36, positionals }) => {
16052
+ handler: async ({ submit, includeSubmitted, message, path: path37, positionals }) => {
16289
16053
  const packmindLogger = new PackmindLogger("PackmindCLI", "info" /* INFO */);
16290
16054
  const packmindCliHexa = new PackmindCliHexa(packmindLogger);
16291
16055
  if (submit) {
@@ -16301,7 +16065,7 @@ var diffCommand = (0, import_cmd_ts19.command)({
16301
16065
  process.exit(1);
16302
16066
  }
16303
16067
  if (positionals[0] === "add") {
16304
- const addFilePath = path36 && positionals[1] ? `${path36}/${positionals[1]}`.replace(/\/+/g, "/") : positionals[1];
16068
+ const addFilePath = path37 && positionals[1] ? `${path37}/${positionals[1]}`.replace(/\/+/g, "/") : positionals[1];
16305
16069
  const addCommand = `packmind-cli playbook add ${addFilePath}`;
16306
16070
  logErrorConsole("Deprecated: `packmind-cli diff add` has been removed");
16307
16071
  logInfoConsole("Use the following command instead:");
@@ -16309,7 +16073,7 @@ var diffCommand = (0, import_cmd_ts19.command)({
16309
16073
  process.exit(1);
16310
16074
  }
16311
16075
  if (positionals[0] === "remove" || positionals[0] === "rm") {
16312
- const removeFilePath = path36 && positionals[1] ? `${path36}/${positionals[1]}`.replace(/\/+/g, "/") : positionals[1];
16076
+ const removeFilePath = path37 && positionals[1] ? `${path37}/${positionals[1]}`.replace(/\/+/g, "/") : positionals[1];
16313
16077
  const removeCommand = `packmind-cli playbook remove ${removeFilePath}`;
16314
16078
  logErrorConsole(
16315
16079
  "Deprecated: `packmind-cli diff remove` has been removed"
@@ -16318,7 +16082,7 @@ var diffCommand = (0, import_cmd_ts19.command)({
16318
16082
  logInfoConsole(` ${formatCommand(removeCommand)}`);
16319
16083
  process.exit(1);
16320
16084
  }
16321
- const diffCommand3 = `packmind-cli playbook diff${includeSubmitted ? " --include-submitted" : ""}${path36 ? ` --path ${path36}` : ""}`;
16085
+ const diffCommand3 = `packmind-cli playbook diff${includeSubmitted ? " --include-submitted" : ""}${path37 ? ` --path ${path37}` : ""}`;
16322
16086
  logErrorConsole("Deprecated: `packmind-cli diff` will be removed");
16323
16087
  logInfoConsole("Use the following command instead:");
16324
16088
  logInfoConsole(` ${formatCommand(diffCommand3)}`);
@@ -16328,7 +16092,7 @@ var diffCommand = (0, import_cmd_ts19.command)({
16328
16092
  getCwd: () => process.cwd(),
16329
16093
  log: console.log,
16330
16094
  includeSubmitted,
16331
- path: path36
16095
+ path: path37
16332
16096
  });
16333
16097
  }
16334
16098
  });
@@ -16608,6 +16372,14 @@ var AddToPackageUseCase = class {
16608
16372
  }
16609
16373
  };
16610
16374
 
16375
+ // apps/cli/src/infra/utils/packageSlugUtils.ts
16376
+ function parsePackageSlug(slug3) {
16377
+ if (!slug3.startsWith("@")) return null;
16378
+ const slash = slug3.indexOf("/", 1);
16379
+ if (slash === -1) return null;
16380
+ return { spaceSlug: slug3.slice(1, slash), pkgSlug: slug3.slice(slash + 1) };
16381
+ }
16382
+
16611
16383
  // apps/cli/src/infra/commands/packages/addToPackageHandler.ts
16612
16384
  function pluralize(singular, count) {
16613
16385
  return count === 1 ? singular : `${singular}s`;
@@ -16755,18 +16527,116 @@ var addToPackageCommand = (0, import_cmd_ts21.command)({
16755
16527
  );
16756
16528
  process.exit(1);
16757
16529
  }
16758
- const { type: itemType, slugs: itemSlugs } = itemTypes[0];
16759
- const packmindLogger = new PackmindLogger("PackmindCLI", "info" /* INFO */);
16760
- const hexa = new PackmindCliHexa(packmindLogger);
16761
- await addToPackageHandler(
16762
- { to, itemType, itemSlugs, originSkill },
16763
- { hexa, exit: process.exit }
16764
- );
16530
+ const { type: itemType, slugs: itemSlugs } = itemTypes[0];
16531
+ const packmindLogger = new PackmindLogger("PackmindCLI", "info" /* INFO */);
16532
+ const hexa = new PackmindCliHexa(packmindLogger);
16533
+ await addToPackageHandler(
16534
+ { to, itemType, itemSlugs, originSkill },
16535
+ { hexa, exit: process.exit }
16536
+ );
16537
+ }
16538
+ });
16539
+
16540
+ // apps/cli/src/infra/commands/listPackagesCommand.ts
16541
+ var import_cmd_ts22 = __toESM(require_cjs());
16542
+
16543
+ // apps/cli/src/infra/commands/packages/listPackagesHandler.ts
16544
+ function logPackageEntry(pkg, fullSlug, spaceSlug, buildUrl) {
16545
+ logConsole(`- ${formatSlug(fullSlug)}`);
16546
+ logConsole(` ${formatLabel("Name:")} ${pkg.name}`);
16547
+ const url = buildUrl(spaceSlug, pkg.id);
16548
+ if (url) {
16549
+ logConsole(` ${formatLabel("Link:")} ${url}`);
16550
+ }
16551
+ if (pkg.description) {
16552
+ const lines = pkg.description.trim().split("\n").map((l) => l.trim()).filter((l) => l.length > 0);
16553
+ const [first, ...rest] = lines;
16554
+ logConsole(` ${formatLabel("Description:")} ${first}`);
16555
+ rest.forEach((l) => logConsole(` ${l}`));
16556
+ }
16557
+ }
16558
+ function groupPackagesBySpace(packages, spaces) {
16559
+ const spaceMap = new Map(
16560
+ spaces.map((s) => [s.id, s])
16561
+ );
16562
+ const groupsMap = /* @__PURE__ */ new Map();
16563
+ for (const pkg of packages) {
16564
+ const space = spaceMap.get(pkg.spaceId);
16565
+ if (!space) {
16566
+ continue;
16567
+ }
16568
+ let group = groupsMap.get(space.id);
16569
+ if (!group) {
16570
+ group = { space, pkgs: [] };
16571
+ groupsMap.set(space.id, group);
16572
+ }
16573
+ group.pkgs.push(pkg);
16574
+ }
16575
+ return [...groupsMap.values()].sort(
16576
+ (a, b) => a.space.name.localeCompare(b.space.name)
16577
+ );
16578
+ }
16579
+ function displayGroupedPackages(packages, spaces, buildUrl) {
16580
+ const groups = groupPackagesBySpace(packages, spaces);
16581
+ let firstSlug = null;
16582
+ for (const { space, pkgs } of groups) {
16583
+ logConsole(`Space "${space.name}":
16584
+ `);
16585
+ for (const pkg of [...pkgs].sort((a, b) => a.slug.localeCompare(b.slug))) {
16586
+ const fullSlug = `@${space.slug}/${pkg.slug}`;
16587
+ firstSlug ??= fullSlug;
16588
+ logPackageEntry(pkg, fullSlug, space.slug, buildUrl);
16589
+ logConsole("");
16590
+ }
16591
+ }
16592
+ return firstSlug ?? formatSlug(packages[0].slug);
16593
+ }
16594
+ async function listPackagesHandler(args2, deps) {
16595
+ const { packmindCliHexa, exit } = deps;
16596
+ try {
16597
+ logInfoConsole("Fetching available packages...");
16598
+ const allSpaces = await packmindCliHexa.getSpaces();
16599
+ if (!allSpaces || allSpaces.length === 0) {
16600
+ throw new Error("Unable to list organization spaces.");
16601
+ }
16602
+ const matchedSpace = resolveSpaceFromArgs(args2.space, allSpaces);
16603
+ if (args2.space && !matchedSpace) {
16604
+ logErrorConsole(`Space "@${args2.space}" not found.`);
16605
+ logInfoConsole(
16606
+ `Available spaces: ${allSpaces.map((s) => `@${s.slug}`).join(", ")}`
16607
+ );
16608
+ exit(1);
16609
+ return;
16610
+ }
16611
+ const packages = await packmindCliHexa.listPackages(
16612
+ matchedSpace ? { spaceId: matchedSpace.id } : {}
16613
+ );
16614
+ const spaces = matchedSpace ? [matchedSpace] : allSpaces;
16615
+ if (packages.length === 0) {
16616
+ logConsole(
16617
+ matchedSpace ? `No packages found in space "@${matchedSpace.slug}".` : "No packages found."
16618
+ );
16619
+ exit(0);
16620
+ return;
16621
+ }
16622
+ const buildUrl = resolveUrlBuilder((id) => `packages/${id}`);
16623
+ logConsole("\nAvailable packages:\n");
16624
+ const exampleSlug = displayGroupedPackages(packages, spaces, buildUrl);
16625
+ logConsole("How to install a package:\n");
16626
+ logConsole(` ${formatCommand(`packmind-cli install ${exampleSlug}`)}`);
16627
+ exit(0);
16628
+ } catch (err) {
16629
+ logErrorConsole("Failed to list packages:");
16630
+ if (err instanceof Error) {
16631
+ logErrorConsole(err.message);
16632
+ } else {
16633
+ logErrorConsole(String(err));
16634
+ }
16635
+ exit(1);
16765
16636
  }
16766
- });
16637
+ }
16767
16638
 
16768
16639
  // apps/cli/src/infra/commands/listPackagesCommand.ts
16769
- var import_cmd_ts22 = __toESM(require_cjs());
16770
16640
  var listPackagesCommand = (0, import_cmd_ts22.command)({
16771
16641
  name: "list",
16772
16642
  description: "List available packages",
@@ -16790,6 +16660,124 @@ var listPackagesCommand = (0, import_cmd_ts22.command)({
16790
16660
 
16791
16661
  // apps/cli/src/infra/commands/packages/showPackageCommand.ts
16792
16662
  var import_cmd_ts23 = __toESM(require_cjs());
16663
+
16664
+ // apps/cli/src/infra/commands/packages/showPackageHandler.ts
16665
+ function isNotFoundError(err) {
16666
+ return err instanceof Error && err.message.includes("does not exist");
16667
+ }
16668
+ async function resolvePackage(slug3, packmindCliHexa) {
16669
+ const allSpaces = await packmindCliHexa.getSpaces();
16670
+ const parsed = parsePackageSlug(slug3);
16671
+ if (parsed) {
16672
+ const { spaceSlug, pkgSlug } = parsed;
16673
+ const matchedSpace = allSpaces.find((s) => s.slug === spaceSlug);
16674
+ if (!matchedSpace) {
16675
+ throw new Error(`Space '@${spaceSlug}' not found.`);
16676
+ }
16677
+ let pkg;
16678
+ try {
16679
+ pkg = await packmindCliHexa.getPackageBySlug({
16680
+ slug: pkgSlug,
16681
+ spaceId: matchedSpace.id
16682
+ });
16683
+ } catch (err) {
16684
+ if (isNotFoundError(err)) {
16685
+ throw new Error(
16686
+ `Package '${pkgSlug}' not found in space '@${spaceSlug}'.`
16687
+ );
16688
+ }
16689
+ throw err;
16690
+ }
16691
+ return { pkg, fullSlug: `@${spaceSlug}/${pkgSlug}` };
16692
+ }
16693
+ const results = await Promise.allSettled(
16694
+ allSpaces.map(async (space) => ({
16695
+ pkg: await packmindCliHexa.getPackageBySlug({
16696
+ slug: slug3,
16697
+ spaceId: space.id
16698
+ }),
16699
+ spaceSlug: space.slug
16700
+ }))
16701
+ );
16702
+ const matches = results.filter(
16703
+ (r) => r.status === "fulfilled"
16704
+ ).map((r) => r.value);
16705
+ if (matches.length === 0) {
16706
+ const realError = results.filter((r) => r.status === "rejected").find((r) => !isNotFoundError(r.reason));
16707
+ if (realError) {
16708
+ throw realError.reason;
16709
+ }
16710
+ throw new Error(`Package '${slug3}' not found in any space.`);
16711
+ }
16712
+ if (matches.length > 1) {
16713
+ const example = `@${matches[0].spaceSlug}/${slug3}`;
16714
+ throw new Error(
16715
+ `Package '${slug3}' exists in multiple spaces (${matches.map((m) => `@${m.spaceSlug}`).join(", ")}). Please specify the space using the @space/package format (e.g. ${example}).`
16716
+ );
16717
+ }
16718
+ return {
16719
+ pkg: matches[0].pkg,
16720
+ fullSlug: `@${matches[0].spaceSlug}/${slug3}`
16721
+ };
16722
+ }
16723
+ async function showPackageHandler(args2, deps) {
16724
+ const { packmindCliHexa, exit } = deps;
16725
+ try {
16726
+ logInfoConsole(`Fetching package details for '${args2.slug}'...`);
16727
+ const { pkg, fullSlug } = await resolvePackage(args2.slug, packmindCliHexa);
16728
+ logConsole(`
16729
+ ${pkg.name} (${fullSlug}):
16730
+ `);
16731
+ if (pkg.description) {
16732
+ logConsole(`${pkg.description}
16733
+ `);
16734
+ }
16735
+ if (pkg.standards && pkg.standards.length > 0) {
16736
+ logConsole("Standards:");
16737
+ pkg.standards.forEach((standard) => {
16738
+ if (standard.summary) {
16739
+ logConsole(` - ${standard.name}: ${standard.summary}`);
16740
+ } else {
16741
+ logConsole(` - ${standard.name}`);
16742
+ }
16743
+ });
16744
+ logConsole("");
16745
+ }
16746
+ if (pkg.recipes && pkg.recipes.length > 0) {
16747
+ logConsole("Commands:");
16748
+ pkg.recipes.forEach((recipe) => {
16749
+ if (recipe.summary) {
16750
+ logConsole(` - ${recipe.name}: ${recipe.summary}`);
16751
+ } else {
16752
+ logConsole(` - ${recipe.name}`);
16753
+ }
16754
+ });
16755
+ logConsole("");
16756
+ }
16757
+ if (pkg.skills && pkg.skills.length > 0) {
16758
+ logConsole("Skills:");
16759
+ pkg.skills.forEach((skill) => {
16760
+ if (skill.summary) {
16761
+ logConsole(` - ${skill.name}: ${skill.summary}`);
16762
+ } else {
16763
+ logConsole(` - ${skill.name}`);
16764
+ }
16765
+ });
16766
+ logConsole("");
16767
+ }
16768
+ exit(0);
16769
+ } catch (err) {
16770
+ logErrorConsole("Failed to fetch package details:");
16771
+ if (err instanceof Error) {
16772
+ logErrorConsole(err.message);
16773
+ } else {
16774
+ logErrorConsole(String(err));
16775
+ }
16776
+ exit(1);
16777
+ }
16778
+ }
16779
+
16780
+ // apps/cli/src/infra/commands/packages/showPackageCommand.ts
16793
16781
  var showPackageCommand = (0, import_cmd_ts23.command)({
16794
16782
  name: "show",
16795
16783
  description: "Show details of a specific package",
@@ -16826,14 +16814,96 @@ var import_cmd_ts31 = __toESM(require_cjs());
16826
16814
  var import_fs21 = require("fs");
16827
16815
  var import_cmd_ts25 = __toESM(require_cjs());
16828
16816
 
16829
- // apps/cli/src/infra/commands/playbook/addHandler.ts
16817
+ // apps/cli/src/infra/repositories/PlaybookLocalRepository.ts
16818
+ var crypto = __toESM(require("crypto"));
16830
16819
  var fs23 = __toESM(require("fs"));
16831
- var path26 = __toESM(require("path"));
16820
+ var os5 = __toESM(require("os"));
16821
+ var path23 = __toESM(require("path"));
16822
+ var yaml = __toESM(require("yaml"));
16823
+ var PlaybookLocalRepository = class {
16824
+ constructor(repoRoot) {
16825
+ const normalized = this.normalizeRepoRoot(repoRoot);
16826
+ const hash = crypto.createHash("md5").update(normalized).digest("hex");
16827
+ this.storagePath = path23.join(
16828
+ os5.homedir(),
16829
+ ".packmind",
16830
+ hash,
16831
+ "playbook.yaml"
16832
+ );
16833
+ }
16834
+ addChange(entry) {
16835
+ const data = this.readYaml();
16836
+ const existingIndex = data.changes.findIndex(
16837
+ (c) => c.filePath === entry.filePath && c.spaceId === entry.spaceId
16838
+ );
16839
+ if (existingIndex >= 0) {
16840
+ data.changes[existingIndex] = entry;
16841
+ } else {
16842
+ data.changes.push(entry);
16843
+ }
16844
+ this.writeYaml(data);
16845
+ }
16846
+ removeChange(filePath, spaceId) {
16847
+ const data = this.readYaml();
16848
+ const initialLength = data.changes.length;
16849
+ data.changes = data.changes.filter(
16850
+ (c) => !(c.filePath === filePath && c.spaceId === spaceId)
16851
+ );
16852
+ if (data.changes.length === initialLength) {
16853
+ return false;
16854
+ }
16855
+ this.writeYaml(data);
16856
+ return true;
16857
+ }
16858
+ getChanges() {
16859
+ return this.readYaml().changes;
16860
+ }
16861
+ getChange(filePath, spaceId) {
16862
+ return this.readYaml().changes.find(
16863
+ (c) => c.filePath === filePath && c.spaceId === spaceId
16864
+ ) ?? null;
16865
+ }
16866
+ clearAll() {
16867
+ this.writeYaml({ version: 1, changes: [] });
16868
+ }
16869
+ normalizeRepoRoot(repoRoot) {
16870
+ let normalized = repoRoot.replace(/\\/g, "/");
16871
+ normalized = normalized.replace(/\/$/, "");
16872
+ return normalized;
16873
+ }
16874
+ readYaml() {
16875
+ if (!fs23.existsSync(this.storagePath)) {
16876
+ return { version: 1, changes: [] };
16877
+ }
16878
+ try {
16879
+ const content = fs23.readFileSync(this.storagePath, "utf-8");
16880
+ const parsed = yaml.parse(content);
16881
+ if (!parsed || !Array.isArray(parsed.changes)) {
16882
+ return { version: 1, changes: [] };
16883
+ }
16884
+ return { version: 1, changes: parsed.changes };
16885
+ } catch {
16886
+ logWarningConsole(
16887
+ `Corrupted playbook file: ${this.storagePath}. Treating as empty.`
16888
+ );
16889
+ return { version: 1, changes: [] };
16890
+ }
16891
+ }
16892
+ writeYaml(data) {
16893
+ const dir = path23.dirname(this.storagePath);
16894
+ fs23.mkdirSync(dir, { recursive: true });
16895
+ fs23.writeFileSync(this.storagePath, yaml.stringify(data), "utf-8");
16896
+ }
16897
+ };
16898
+
16899
+ // apps/cli/src/infra/commands/playbook/addHandler.ts
16900
+ var fs24 = __toESM(require("fs"));
16901
+ var path27 = __toESM(require("path"));
16832
16902
  var yaml2 = __toESM(require("yaml"));
16833
16903
  var import_slug = __toESM(require("slug"));
16834
16904
 
16835
16905
  // apps/cli/src/application/utils/parseCommandFile.ts
16836
- var path23 = __toESM(require("path"));
16906
+ var path24 = __toESM(require("path"));
16837
16907
  var FRONTMATTER_DELIMITER3 = "---";
16838
16908
  function parseCommandFile(content, filePath) {
16839
16909
  content = normalizeLineEndings(content);
@@ -16889,7 +16959,7 @@ function stripYamlQuotes2(value) {
16889
16959
  return value;
16890
16960
  }
16891
16961
  function extractFilenameSlug(filePath) {
16892
- let basename4 = path23.basename(filePath);
16962
+ let basename4 = path24.basename(filePath);
16893
16963
  if (basename4.endsWith(".prompt.md")) {
16894
16964
  basename4 = basename4.slice(0, -".prompt.md".length);
16895
16965
  } else if (basename4.endsWith(".md")) {
@@ -17056,7 +17126,7 @@ function parseSkillDirectory(files) {
17056
17126
  }
17057
17127
 
17058
17128
  // apps/cli/src/application/utils/findNearestConfigDir.ts
17059
- var path24 = __toESM(require("path"));
17129
+ var path25 = __toESM(require("path"));
17060
17130
  async function findNearestConfigDir(startDir, packmindCliHexa) {
17061
17131
  let current = startDir;
17062
17132
  while (true) {
@@ -17064,7 +17134,7 @@ async function findNearestConfigDir(startDir, packmindCliHexa) {
17064
17134
  if (exists) {
17065
17135
  return current;
17066
17136
  }
17067
- const parent = path24.dirname(current);
17137
+ const parent = path25.dirname(current);
17068
17138
  if (parent === current) {
17069
17139
  return null;
17070
17140
  }
@@ -17073,7 +17143,7 @@ async function findNearestConfigDir(startDir, packmindCliHexa) {
17073
17143
  }
17074
17144
 
17075
17145
  // apps/cli/src/application/utils/resolveDeployedContext.ts
17076
- var path25 = __toESM(require("path"));
17146
+ var path26 = __toESM(require("path"));
17077
17147
  async function resolveDeployedContext(packmindCliHexa, targetDir) {
17078
17148
  try {
17079
17149
  const space = await packmindCliHexa.getDefaultSpace();
@@ -17085,7 +17155,7 @@ async function resolveDeployedContext(packmindCliHexa, targetDir) {
17085
17155
  }
17086
17156
  const gitRemoteUrl = packmindCliHexa.getGitRemoteUrlFromPath(gitRoot);
17087
17157
  const gitBranch = packmindCliHexa.getCurrentBranch(gitRoot);
17088
- const rel = path25.relative(gitRoot, targetDir);
17158
+ const rel = path26.relative(gitRoot, targetDir);
17089
17159
  const relativePath = rel.startsWith("..") ? "/" : rel ? `/${rel}/` : "/";
17090
17160
  const deployedContent = await packmindCliHexa.getPackmindGateway().deployment.getDeployed({
17091
17161
  packagesSlugs: configPackages,
@@ -17150,19 +17220,19 @@ async function fetchDeployedFiles(gateway, lockFile) {
17150
17220
 
17151
17221
  // apps/cli/src/infra/commands/playbook/addHandler.ts
17152
17222
  async function tryStageRemovedFromLockFile(resolvedPath, deps) {
17153
- const fileDir = path26.dirname(resolvedPath);
17223
+ const fileDir = path27.dirname(resolvedPath);
17154
17224
  const targetDir = await findNearestConfigDir(fileDir, deps.packmindCliHexa);
17155
17225
  if (!targetDir) return false;
17156
17226
  const lockFile = await deps.lockFileRepository.read(targetDir);
17157
17227
  if (!lockFile) return false;
17158
- const normalizedPath = normalizePath2(path26.relative(targetDir, resolvedPath));
17228
+ const normalizedPath = normalizePath2(path27.relative(targetDir, resolvedPath));
17159
17229
  const lockEntry = findLockFileEntryForPath(
17160
17230
  normalizedPath,
17161
17231
  lockFile.artifacts
17162
17232
  );
17163
17233
  if (!lockEntry) return false;
17164
17234
  const gitRoot = await deps.packmindCliHexa.tryGetGitRepositoryRoot(targetDir);
17165
- const configDir = gitRoot ? normalizePath2(path26.relative(gitRoot, targetDir)) : "";
17235
+ const configDir = gitRoot ? normalizePath2(path27.relative(gitRoot, targetDir)) : "";
17166
17236
  const deployedContext = await resolveDeployedContext(
17167
17237
  deps.packmindCliHexa,
17168
17238
  targetDir
@@ -17194,22 +17264,22 @@ async function tryStageRemovedFromLockFile(resolvedPath, deps) {
17194
17264
  }
17195
17265
  function resolveSkillDirectoryRoot(absolutePath) {
17196
17266
  if (absolutePath.endsWith("SKILL.md")) {
17197
- return path26.dirname(absolutePath);
17267
+ return path27.dirname(absolutePath);
17198
17268
  }
17199
17269
  try {
17200
- if (fs23.statSync(absolutePath).isDirectory()) {
17270
+ if (fs24.statSync(absolutePath).isDirectory()) {
17201
17271
  return absolutePath;
17202
17272
  }
17203
17273
  } catch {
17204
17274
  return absolutePath;
17205
17275
  }
17206
- let current = path26.dirname(absolutePath);
17207
- const root = path26.parse(current).root;
17276
+ let current = path27.dirname(absolutePath);
17277
+ const root = path27.parse(current).root;
17208
17278
  while (current !== root) {
17209
- if (fs23.existsSync(path26.join(current, "SKILL.md"))) {
17279
+ if (fs24.existsSync(path27.join(current, "SKILL.md"))) {
17210
17280
  return current;
17211
17281
  }
17212
- current = path26.dirname(current);
17282
+ current = path27.dirname(current);
17213
17283
  }
17214
17284
  return absolutePath;
17215
17285
  }
@@ -17220,7 +17290,7 @@ async function playbookAddHandler(deps) {
17220
17290
  spaceSlug,
17221
17291
  exit,
17222
17292
  cwd,
17223
- readFile: readFile10,
17293
+ readFile: readFile11,
17224
17294
  readSkillDirectory: readSkillDirectory2,
17225
17295
  playbookLocalRepository,
17226
17296
  lockFileRepository
@@ -17232,17 +17302,17 @@ async function playbookAddHandler(deps) {
17232
17302
  exit(1);
17233
17303
  return;
17234
17304
  }
17235
- const absolutePath = path26.resolve(cwd, filePath);
17305
+ const absolutePath = path27.resolve(cwd, filePath);
17236
17306
  let artifactType;
17237
17307
  let codingAgent;
17238
17308
  const earlyTargetDir = await findNearestConfigDir(
17239
- path26.dirname(absolutePath),
17309
+ path27.dirname(absolutePath),
17240
17310
  packmindCliHexa
17241
17311
  );
17242
17312
  const earlyLockFile = earlyTargetDir ? await lockFileRepository.read(earlyTargetDir) : null;
17243
17313
  if (earlyLockFile && earlyTargetDir) {
17244
17314
  const normalizedForLookup = normalizePath2(
17245
- path26.relative(earlyTargetDir, absolutePath)
17315
+ path27.relative(earlyTargetDir, absolutePath)
17246
17316
  );
17247
17317
  const lockResult = findLockFileEntryAndFileForPath(
17248
17318
  normalizedForLookup,
@@ -17322,7 +17392,7 @@ async function playbookAddHandler(deps) {
17322
17392
  localContent = skillMdFile?.content ?? serializedContent;
17323
17393
  } else {
17324
17394
  try {
17325
- localContent = readFile10(absolutePath);
17395
+ localContent = readFile11(absolutePath);
17326
17396
  } catch (err) {
17327
17397
  const staged = await tryStageRemovedFromLockFile(absolutePath, {
17328
17398
  packmindCliHexa,
@@ -17376,7 +17446,7 @@ Content goes here...`
17376
17446
  return;
17377
17447
  }
17378
17448
  const gitRoot = await packmindCliHexa.tryGetGitRepositoryRoot(targetDir);
17379
- const configDir = gitRoot ? normalizePath2(path26.relative(gitRoot, targetDir)) : "";
17449
+ const configDir = gitRoot ? normalizePath2(path27.relative(gitRoot, targetDir)) : "";
17380
17450
  const deployedContext = await resolveDeployedContext(
17381
17451
  packmindCliHexa,
17382
17452
  targetDir
@@ -17384,7 +17454,7 @@ Content goes here...`
17384
17454
  const targetId = deployedContext?.targetId ?? earlyLockFile?.targetId;
17385
17455
  const normalizedFilePath = (() => {
17386
17456
  const refPath = artifactType === "skill" && skillDirPath ? skillDirPath : absolutePath;
17387
- return normalizePath2(path26.relative(targetDir, refPath));
17457
+ return normalizePath2(path27.relative(targetDir, refPath));
17388
17458
  })();
17389
17459
  let spaceId;
17390
17460
  let spaceName;
@@ -17499,7 +17569,7 @@ Run ${formatLabel("packmind-cli install")} to update before making changes.`
17499
17569
  );
17500
17570
  const allMatch = skillDeployedFiles.length > 0 && skillDeployedFiles.length === skillFiles.length && skillDeployedFiles.every((deployed) => {
17501
17571
  const localFile = skillFiles.find(
17502
- (f) => normalizePath2(path26.join(normalizedFilePath, f.relativePath)) === normalizePath2(deployed.path)
17572
+ (f) => normalizePath2(path27.join(normalizedFilePath, f.relativePath)) === normalizePath2(deployed.path)
17503
17573
  );
17504
17574
  return localFile && deployed.content?.trim() === localFile.content.trim() && (!deployed.skillFilePermissions || deployed.skillFilePermissions === localFile.permissions);
17505
17575
  });
@@ -17611,8 +17681,8 @@ var addPlaybookCommand = (0, import_cmd_ts25.command)({
17611
17681
  var import_cmd_ts26 = __toESM(require_cjs());
17612
17682
 
17613
17683
  // apps/cli/src/infra/commands/playbook/rmHandler.ts
17614
- var fs24 = __toESM(require("fs"));
17615
- var path27 = __toESM(require("path"));
17684
+ var fs25 = __toESM(require("fs"));
17685
+ var path28 = __toESM(require("path"));
17616
17686
  function isSkillSupportFile(absolutePath) {
17617
17687
  const normalized = absolutePath.replace(/\\/g, "/");
17618
17688
  const skillDirMatch = normalized.match(/\/skills\/[^/]+\//);
@@ -17639,14 +17709,14 @@ async function playbookRmHandler(deps) {
17639
17709
  exit(1);
17640
17710
  return;
17641
17711
  }
17642
- const absolutePath = path27.resolve(getCwd(), filePath);
17643
- if (!fs24.existsSync(absolutePath)) {
17712
+ const absolutePath = path28.resolve(getCwd(), filePath);
17713
+ if (!fs25.existsSync(absolutePath)) {
17644
17714
  logErrorConsole(`File not found: "${filePath}"`);
17645
17715
  exit(1);
17646
17716
  return;
17647
17717
  }
17648
17718
  const targetDir = await findNearestConfigDir(
17649
- path27.dirname(absolutePath),
17719
+ path28.dirname(absolutePath),
17650
17720
  packmindCliHexa
17651
17721
  );
17652
17722
  if (!targetDir) {
@@ -17663,7 +17733,7 @@ async function playbookRmHandler(deps) {
17663
17733
  return;
17664
17734
  }
17665
17735
  const normalizedForLookup = normalizePath2(
17666
- path27.relative(targetDir, absolutePath)
17736
+ path28.relative(targetDir, absolutePath)
17667
17737
  );
17668
17738
  const lockResult = findLockFileEntryAndFileForPath(
17669
17739
  normalizedForLookup,
@@ -17685,7 +17755,7 @@ async function playbookRmHandler(deps) {
17685
17755
  }
17686
17756
  const resolvedAbsolutePath = artifactType === "skill" ? resolveSkillDirPath(absolutePath) : absolutePath;
17687
17757
  const normalizedFilePath = normalizePath2(
17688
- path27.relative(targetDir, resolvedAbsolutePath)
17758
+ path28.relative(targetDir, resolvedAbsolutePath)
17689
17759
  );
17690
17760
  const lockEntry = findLockFileEntryAndFileForPath(normalizedFilePath, lockFile.artifacts)?.entry ?? lockResult.entry;
17691
17761
  if (!lockEntry) {
@@ -17713,7 +17783,7 @@ async function playbookRmHandler(deps) {
17713
17783
  }
17714
17784
  const spaceName = matchingSpace.name;
17715
17785
  const gitRoot = await packmindCliHexa.tryGetGitRepositoryRoot(targetDir);
17716
- const configDir = gitRoot ? normalizePath2(path27.relative(gitRoot, targetDir)) : "";
17786
+ const configDir = gitRoot ? normalizePath2(path28.relative(gitRoot, targetDir)) : "";
17717
17787
  const deployedContext = await resolveDeployedContext(
17718
17788
  packmindCliHexa,
17719
17789
  targetDir
@@ -17774,7 +17844,7 @@ var rmPlaybookCommand = (0, import_cmd_ts26.command)({
17774
17844
  var import_cmd_ts27 = __toESM(require_cjs());
17775
17845
 
17776
17846
  // apps/cli/src/infra/commands/playbook/unstageHandler.ts
17777
- var path28 = __toESM(require("path"));
17847
+ var path29 = __toESM(require("path"));
17778
17848
  async function playbookUnstageHandler(deps) {
17779
17849
  const {
17780
17850
  packmindCliHexa,
@@ -17792,10 +17862,10 @@ async function playbookUnstageHandler(deps) {
17792
17862
  return;
17793
17863
  }
17794
17864
  const cwd = getCwd();
17795
- const absolutePath = path28.resolve(cwd, filePath);
17865
+ const absolutePath = path29.resolve(cwd, filePath);
17796
17866
  const resolvedPath = resolveSkillDirPath(absolutePath);
17797
17867
  const configDir = await findNearestConfigDir(
17798
- path28.dirname(resolvedPath),
17868
+ path29.dirname(resolvedPath),
17799
17869
  packmindCliHexa
17800
17870
  );
17801
17871
  if (!configDir) {
@@ -17808,10 +17878,10 @@ async function playbookUnstageHandler(deps) {
17808
17878
  const gitRoot = await packmindCliHexa.tryGetGitRepositoryRoot(cwd);
17809
17879
  const baseDir = gitRoot ?? configDir;
17810
17880
  const normalizedFilePath = normalizePath2(
17811
- path28.relative(baseDir, resolvedPath)
17881
+ path29.relative(baseDir, resolvedPath)
17812
17882
  );
17813
17883
  const matchingEntries = playbookLocalRepository.getChanges().filter((c) => {
17814
- const fullEntryPath = c.configDir ? normalizePath2(path28.join(c.configDir, c.filePath)) : c.filePath;
17884
+ const fullEntryPath = c.configDir ? normalizePath2(path29.join(c.configDir, c.filePath)) : c.filePath;
17815
17885
  return fullEntryPath === normalizedFilePath;
17816
17886
  });
17817
17887
  if (matchingEntries.length === 0) {
@@ -17895,15 +17965,15 @@ var import_cmd_ts28 = __toESM(require_cjs());
17895
17965
 
17896
17966
  // apps/cli/src/infra/utils/listDirectoryFiles.ts
17897
17967
  var import_fs22 = require("fs");
17898
- var path29 = __toESM(require("path"));
17968
+ var path30 = __toESM(require("path"));
17899
17969
  function listDirectoryFiles(dirPath) {
17900
17970
  const results = [];
17901
17971
  const entries = (0, import_fs22.readdirSync)(dirPath, { withFileTypes: true });
17902
17972
  for (const entry of entries) {
17903
- const fullPath = path29.join(dirPath, entry.name);
17973
+ const fullPath = path30.join(dirPath, entry.name);
17904
17974
  if (entry.isDirectory()) {
17905
17975
  for (const nested of listDirectoryFiles(fullPath)) {
17906
- results.push(path29.join(entry.name, nested));
17976
+ results.push(path30.join(entry.name, nested));
17907
17977
  }
17908
17978
  } else if (entry.isFile()) {
17909
17979
  results.push(entry.name);
@@ -17913,7 +17983,7 @@ function listDirectoryFiles(dirPath) {
17913
17983
  }
17914
17984
 
17915
17985
  // apps/cli/src/infra/commands/playbook/statusHandler.ts
17916
- var path30 = __toESM(require("path"));
17986
+ var path31 = __toESM(require("path"));
17917
17987
 
17918
17988
  // apps/cli/src/infra/utils/stringUtils.ts
17919
17989
  function capitalize(s) {
@@ -17948,7 +18018,7 @@ function groupStagedChanges(changes, cwd, gitRoot) {
17948
18018
  const changeType = change.changeType ?? "updated";
17949
18019
  const key = `${change.artifactType}:${change.artifactName}:${changeType}`;
17950
18020
  const rootRelativePath = change.configDir ? `${change.configDir}/${change.filePath}` : change.filePath;
17951
- const displayPath = gitRoot ? normalizePath2(path30.relative(cwd, path30.join(gitRoot, rootRelativePath))) : rootRelativePath;
18021
+ const displayPath = gitRoot ? normalizePath2(path31.relative(cwd, path31.join(gitRoot, rootRelativePath))) : rootRelativePath;
17952
18022
  const existing = groups.get(key);
17953
18023
  if (existing) {
17954
18024
  existing.filePaths.push(displayPath);
@@ -17989,7 +18059,7 @@ async function playbookStatusHandler(deps) {
17989
18059
  lockFileRepository,
17990
18060
  cwd,
17991
18061
  exit,
17992
- readFile: readFile10,
18062
+ readFile: readFile11,
17993
18063
  listDirectoryFiles: listDirectoryFiles2,
17994
18064
  getFileMode
17995
18065
  } = deps;
@@ -18006,12 +18076,12 @@ async function playbookStatusHandler(deps) {
18006
18076
  const fallbackConfigDir = await findNearestConfigDir(cwd, packmindCliHexa);
18007
18077
  const configDirs = /* @__PURE__ */ new Set([...stagedByConfigDir.keys()]);
18008
18078
  if (fallbackConfigDir && !configDirs.has("__cwd__")) {
18009
- const rel = gitRoot ? normalizePath2(path30.relative(gitRoot, fallbackConfigDir)) : "";
18079
+ const rel = gitRoot ? normalizePath2(path31.relative(gitRoot, fallbackConfigDir)) : "";
18010
18080
  if (!configDirs.has(rel)) configDirs.add(rel);
18011
18081
  }
18012
18082
  const descendantDirs = await packmindCliHexa.findDescendantConfigs(cwd);
18013
18083
  for (const descendantDir of descendantDirs) {
18014
- const rel = gitRoot ? normalizePath2(path30.relative(gitRoot, descendantDir)) : normalizePath2(path30.relative(cwd, descendantDir));
18084
+ const rel = gitRoot ? normalizePath2(path31.relative(gitRoot, descendantDir)) : normalizePath2(path31.relative(cwd, descendantDir));
18015
18085
  if (!configDirs.has(rel)) configDirs.add(rel);
18016
18086
  }
18017
18087
  for (const configDirKey of configDirs) {
@@ -18019,7 +18089,7 @@ async function playbookStatusHandler(deps) {
18019
18089
  if (configDirKey === "__cwd__") {
18020
18090
  projectDir = fallbackConfigDir;
18021
18091
  } else if (gitRoot) {
18022
- projectDir = path30.join(gitRoot, configDirKey);
18092
+ projectDir = path31.join(gitRoot, configDirKey);
18023
18093
  } else {
18024
18094
  continue;
18025
18095
  }
@@ -18044,11 +18114,11 @@ async function playbookStatusHandler(deps) {
18044
18114
  continue;
18045
18115
  }
18046
18116
  const displayPath = normalizePath2(
18047
- path30.relative(cwd, path30.join(projectDir, deployedFile.path))
18117
+ path31.relative(cwd, path31.join(projectDir, deployedFile.path))
18048
18118
  );
18049
18119
  let localContent;
18050
18120
  try {
18051
- localContent = readFile10(path30.join(projectDir, deployedFile.path));
18121
+ localContent = readFile11(path31.join(projectDir, deployedFile.path));
18052
18122
  } catch {
18053
18123
  const artifact = findArtifactForFile(
18054
18124
  deployedFile.path,
@@ -18077,7 +18147,7 @@ async function playbookStatusHandler(deps) {
18077
18147
  });
18078
18148
  }
18079
18149
  } else if (deployedFile.skillFilePermissions && getFileMode) {
18080
- const localMode = getFileMode(path30.join(projectDir, deployedFile.path));
18150
+ const localMode = getFileMode(path31.join(projectDir, deployedFile.path));
18081
18151
  if (localMode !== null) {
18082
18152
  const localPermissions = modeToPermissionStringOrDefault(localMode);
18083
18153
  if (localPermissions !== deployedFile.skillFilePermissions) {
@@ -18106,13 +18176,13 @@ async function playbookStatusHandler(deps) {
18106
18176
  (f) => normalizePath2(f.path).endsWith("/SKILL.md")
18107
18177
  );
18108
18178
  if (!skillMdFile) continue;
18109
- const skillDir = normalizePath2(path30.dirname(skillMdFile.path));
18179
+ const skillDir = normalizePath2(path31.dirname(skillMdFile.path));
18110
18180
  if (targetStagedPaths.has(skillDir) || targetSkillDirPaths.some(
18111
18181
  (staged) => skillDir === staged || skillDir.startsWith(staged + "/")
18112
18182
  )) {
18113
18183
  continue;
18114
18184
  }
18115
- const absoluteSkillDir = path30.join(projectDir, skillDir);
18185
+ const absoluteSkillDir = path31.join(projectDir, skillDir);
18116
18186
  let localFiles;
18117
18187
  try {
18118
18188
  localFiles = listDirectoryFiles2(absoluteSkillDir);
@@ -18121,11 +18191,11 @@ async function playbookStatusHandler(deps) {
18121
18191
  }
18122
18192
  for (const localRelPath of localFiles) {
18123
18193
  const normalizedLocalPath = normalizePath2(
18124
- path30.join(skillDir, localRelPath)
18194
+ path31.join(skillDir, localRelPath)
18125
18195
  );
18126
18196
  if (!deployedPathSet.has(normalizedLocalPath)) {
18127
18197
  const displayPath = normalizePath2(
18128
- path30.relative(cwd, path30.join(projectDir, normalizedLocalPath))
18198
+ path31.relative(cwd, path31.join(projectDir, normalizedLocalPath))
18129
18199
  );
18130
18200
  untrackedChanges.push({
18131
18201
  artifactName: entry.name,
@@ -18213,7 +18283,7 @@ var import_path5 = require("path");
18213
18283
  var import_cmd_ts29 = __toESM(require_cjs());
18214
18284
 
18215
18285
  // apps/cli/src/infra/commands/playbook/submitHandler.ts
18216
- var path32 = __toESM(require("path"));
18286
+ var path33 = __toESM(require("path"));
18217
18287
 
18218
18288
  // apps/cli/src/infra/commands/playbook/submit/duplicateNameChecker.ts
18219
18289
  var import_slug2 = __toESM(require("slug"));
@@ -18275,7 +18345,7 @@ async function checkForDuplicateNames(createdEntries, packmindGateway) {
18275
18345
  }
18276
18346
 
18277
18347
  // apps/cli/src/infra/commands/playbook/submit/targetContextResolver.ts
18278
- var path31 = __toESM(require("path"));
18348
+ var path32 = __toESM(require("path"));
18279
18349
  async function createTargetContextResolver(deps) {
18280
18350
  const { lockFileRepository, cwd, packmindCliHexa } = deps;
18281
18351
  const gitRoot = await packmindCliHexa.tryGetGitRepositoryRoot(cwd);
@@ -18286,7 +18356,7 @@ async function createTargetContextResolver(deps) {
18286
18356
  if (cache.has(key)) return cache.get(key);
18287
18357
  let projectDir;
18288
18358
  if (entry.configDir !== void 0 && gitRoot) {
18289
- projectDir = path31.join(gitRoot, entry.configDir);
18359
+ projectDir = path32.join(gitRoot, entry.configDir);
18290
18360
  } else {
18291
18361
  projectDir = await findNearestConfigDir(cwd, packmindCliHexa);
18292
18362
  }
@@ -19234,7 +19304,7 @@ Only one agent version can be submitted at a time. Use "playbook unstage" to rem
19234
19304
  const entryCtx = resolver.getCachedContext(entry.configDir);
19235
19305
  if (!entryCtx?.projectDir) continue;
19236
19306
  try {
19237
- const fullPath = path32.join(entryCtx.projectDir, entry.filePath);
19307
+ const fullPath = path33.join(entryCtx.projectDir, entry.filePath);
19238
19308
  if (entry.artifactType === "skill") {
19239
19309
  deps.rmSync(fullPath, { recursive: true });
19240
19310
  } else {
@@ -19262,7 +19332,7 @@ Only one agent version can be submitted at a time. Use "playbook unstage" to rem
19262
19332
  const entryCtx = resolver.getCachedContext(entry.configDir);
19263
19333
  if (!entryCtx?.projectDir) continue;
19264
19334
  try {
19265
- const fullPath = path32.join(entryCtx.projectDir, entry.filePath);
19335
+ const fullPath = path33.join(entryCtx.projectDir, entry.filePath);
19266
19336
  if (entry.artifactType === "skill") {
19267
19337
  deps.rmSync(fullPath, { recursive: true });
19268
19338
  } else {
@@ -19384,7 +19454,7 @@ var diffCommand2 = (0, import_cmd_ts30.command)({
19384
19454
  type: (0, import_cmd_ts30.optional)(import_cmd_ts30.string)
19385
19455
  })
19386
19456
  },
19387
- handler: async ({ includeSubmitted, path: path36 }) => {
19457
+ handler: async ({ includeSubmitted, path: path37 }) => {
19388
19458
  const packmindLogger = new PackmindLogger("PackmindCLI", "info" /* INFO */);
19389
19459
  const packmindCliHexa = new PackmindCliHexa(packmindLogger);
19390
19460
  await diffArtefactsHandler({
@@ -19393,7 +19463,7 @@ var diffCommand2 = (0, import_cmd_ts30.command)({
19393
19463
  getCwd: () => process.cwd(),
19394
19464
  log: console.log,
19395
19465
  includeSubmitted,
19396
- path: path36
19466
+ path: path37
19397
19467
  });
19398
19468
  }
19399
19469
  });
@@ -19482,8 +19552,8 @@ var import_cmd_ts39 = __toESM(require_cjs());
19482
19552
  var import_cmd_ts38 = __toESM(require_cjs());
19483
19553
 
19484
19554
  // apps/cli/src/application/services/AgentArtifactDetectionService.ts
19485
- var fs25 = __toESM(require("fs/promises"));
19486
- var path33 = __toESM(require("path"));
19555
+ var fs26 = __toESM(require("fs/promises"));
19556
+ var path34 = __toESM(require("path"));
19487
19557
  var AGENT_ARTIFACT_CHECKS = [
19488
19558
  { agent: "claude", paths: [".claude"] },
19489
19559
  { agent: "cursor", paths: [".cursor"] },
@@ -19512,7 +19582,7 @@ var AgentArtifactDetectionService = class {
19512
19582
  }
19513
19583
  } else {
19514
19584
  for (const relativePath of check.paths) {
19515
- const fullPath = path33.join(baseDirectory, relativePath);
19585
+ const fullPath = path34.join(baseDirectory, relativePath);
19516
19586
  const exists = await this.pathExists(fullPath);
19517
19587
  if (exists) {
19518
19588
  detected.push({
@@ -19528,7 +19598,7 @@ var AgentArtifactDetectionService = class {
19528
19598
  }
19529
19599
  async pathExists(filePath) {
19530
19600
  try {
19531
- await fs25.access(filePath);
19601
+ await fs26.access(filePath);
19532
19602
  return true;
19533
19603
  } catch {
19534
19604
  return false;
@@ -19539,16 +19609,16 @@ var AgentArtifactDetectionService = class {
19539
19609
  while (queue.length > 0) {
19540
19610
  const currentDir = queue.shift();
19541
19611
  for (const targetPath of targetPaths) {
19542
- const fullPath = path33.join(currentDir, targetPath);
19612
+ const fullPath = path34.join(currentDir, targetPath);
19543
19613
  if (await this.pathExists(fullPath)) {
19544
19614
  return fullPath;
19545
19615
  }
19546
19616
  }
19547
19617
  try {
19548
- const entries = await fs25.readdir(currentDir, { withFileTypes: true });
19618
+ const entries = await fs26.readdir(currentDir, { withFileTypes: true });
19549
19619
  for (const entry of entries) {
19550
19620
  if (entry.isDirectory() && !entry.name.startsWith(".") && entry.name !== "node_modules") {
19551
- queue.push(path33.join(currentDir, entry.name));
19621
+ queue.push(path34.join(currentDir, entry.name));
19552
19622
  }
19553
19623
  }
19554
19624
  } catch {
@@ -19563,18 +19633,18 @@ var readline4 = __toESM(require("readline"));
19563
19633
  var inquirer2 = __toESM(require("inquirer"));
19564
19634
 
19565
19635
  // apps/cli/src/infra/commands/config/agents/agentsHandlerUtils.ts
19566
- var path34 = __toESM(require("path"));
19567
- var fs26 = __toESM(require("fs/promises"));
19636
+ var path35 = __toESM(require("path"));
19637
+ var fs27 = __toESM(require("fs/promises"));
19568
19638
  function getRelativePath(dir, startDirectory) {
19569
19639
  if (dir === startDirectory) return "./packmind.json";
19570
- return "./" + path34.relative(startDirectory, dir) + "/packmind.json";
19640
+ return "./" + path35.relative(startDirectory, dir) + "/packmind.json";
19571
19641
  }
19572
19642
  async function resolveStartDirectory(args2, getCwd, exit) {
19573
19643
  let startDirectory = getCwd();
19574
19644
  if (args2.path) {
19575
- const resolvedPath = path34.resolve(getCwd(), args2.path);
19645
+ const resolvedPath = path35.resolve(getCwd(), args2.path);
19576
19646
  try {
19577
- const stat9 = await fs26.stat(resolvedPath);
19647
+ const stat9 = await fs27.stat(resolvedPath);
19578
19648
  if (!stat9.isDirectory()) {
19579
19649
  logErrorConsole(`Path is not a directory: ${resolvedPath}`);
19580
19650
  exit(1);
@@ -19685,7 +19755,7 @@ async function promptAgentsWithReadline2(choices) {
19685
19755
  output.write("\n");
19686
19756
  const preselected = choices.map((c, i) => c.checked ? i + 1 : null).filter((i) => i !== null);
19687
19757
  const defaultValue = preselected.length > 0 ? preselected.join(",") : "1,2,3";
19688
- return new Promise((resolve14) => {
19758
+ return new Promise((resolve15) => {
19689
19759
  rl.question(
19690
19760
  `Enter numbers separated by commas (default: ${defaultValue}): `,
19691
19761
  (answer) => {
@@ -19694,7 +19764,7 @@ async function promptAgentsWithReadline2(choices) {
19694
19764
  const numbersStr = trimmed === "" ? defaultValue : trimmed;
19695
19765
  const numbers = numbersStr.split(",").map((s) => parseInt(s.trim(), 10)).filter((n) => !isNaN(n) && n >= 1 && n <= choices.length);
19696
19766
  const selectedAgents = numbers.map((n) => choices[n - 1].value);
19697
- resolve14(selectedAgents);
19767
+ resolve15(selectedAgents);
19698
19768
  }
19699
19769
  );
19700
19770
  });
@@ -19841,14 +19911,14 @@ To restore organization settings later, remove all local agents with: packmind-c
19841
19911
 
19842
19912
  // apps/cli/src/infra/commands/config/ConfigAgentsAddCommand.ts
19843
19913
  function createPromptConfirm() {
19844
- return (message) => new Promise((resolve14) => {
19914
+ return (message) => new Promise((resolve15) => {
19845
19915
  const rl = readline5.createInterface({
19846
19916
  input: process.stdin,
19847
19917
  output: process.stdout
19848
19918
  });
19849
19919
  rl.question(`${message} (y/N) `, (answer) => {
19850
19920
  rl.close();
19851
- resolve14(answer.toLowerCase() === "y");
19921
+ resolve15(answer.toLowerCase() === "y");
19852
19922
  });
19853
19923
  });
19854
19924
  }
@@ -20203,7 +20273,7 @@ async function initHandler(deps) {
20203
20273
  }
20204
20274
 
20205
20275
  // apps/cli/src/infra/commands/InitCommand.ts
20206
- var { version: CLI_VERSION4 } = require_package();
20276
+ var { version: CLI_VERSION3 } = require_package();
20207
20277
  var initCommand = (0, import_cmd_ts40.command)({
20208
20278
  name: "init",
20209
20279
  description: "Initialize Packmind in the current project",
@@ -20220,7 +20290,7 @@ var initCommand = (0, import_cmd_ts40.command)({
20220
20290
  packmindGateway: packmindCliHexa.getPackmindGateway(),
20221
20291
  baseDirectory,
20222
20292
  installDefaultSkills: packmindCliHexa.installDefaultSkills.bind(packmindCliHexa),
20223
- cliVersion: CLI_VERSION4
20293
+ cliVersion: CLI_VERSION3
20224
20294
  });
20225
20295
  if (!result.success) {
20226
20296
  for (const error of result.errors) {
@@ -20233,7 +20303,7 @@ var initCommand = (0, import_cmd_ts40.command)({
20233
20303
 
20234
20304
  // apps/cli/src/infra/commands/UpdateCommand.ts
20235
20305
  var import_cmd_ts41 = __toESM(require_cjs());
20236
- var { version: CLI_VERSION5 } = require_package();
20306
+ var { version: CLI_VERSION4 } = require_package();
20237
20307
  var updateCommand = (0, import_cmd_ts41.command)({
20238
20308
  name: "update",
20239
20309
  description: "Update packmind-cli to the latest version",
@@ -20245,7 +20315,7 @@ var updateCommand = (0, import_cmd_ts41.command)({
20245
20315
  },
20246
20316
  handler: async ({ check }) => {
20247
20317
  await updateHandler({
20248
- currentVersion: CLI_VERSION5,
20318
+ currentVersion: CLI_VERSION4,
20249
20319
  isExecutableMode: hasEmbeddedWasmFiles(),
20250
20320
  executablePath: process.execPath,
20251
20321
  scriptPath: require.main?.filename,
@@ -20258,25 +20328,25 @@ var updateCommand = (0, import_cmd_ts41.command)({
20258
20328
  });
20259
20329
 
20260
20330
  // apps/cli/src/main.ts
20261
- var { version: CLI_VERSION6 } = require_package();
20331
+ var { version: CLI_VERSION5 } = require_package();
20262
20332
  function findEnvFile() {
20263
20333
  const currentDir = process.cwd();
20264
20334
  const gitService = new GitService();
20265
20335
  const gitRoot = gitService.getGitRepositoryRootSync(currentDir);
20266
- const filesystemRoot = path35.parse(currentDir).root;
20336
+ const filesystemRoot = path36.parse(currentDir).root;
20267
20337
  const stopDir = gitRoot ?? filesystemRoot;
20268
20338
  let searchDir = currentDir;
20269
- let parentDir = path35.dirname(searchDir);
20339
+ let parentDir = path36.dirname(searchDir);
20270
20340
  while (searchDir !== parentDir) {
20271
- const envPath2 = path35.join(searchDir, ".env");
20272
- if (fs27.existsSync(envPath2)) {
20341
+ const envPath2 = path36.join(searchDir, ".env");
20342
+ if (fs28.existsSync(envPath2)) {
20273
20343
  return envPath2;
20274
20344
  }
20275
20345
  if (searchDir === stopDir) {
20276
20346
  return null;
20277
20347
  }
20278
20348
  searchDir = parentDir;
20279
- parentDir = path35.dirname(searchDir);
20349
+ parentDir = path36.dirname(searchDir);
20280
20350
  }
20281
20351
  return null;
20282
20352
  }
@@ -20293,7 +20363,7 @@ if (hasEmbeddedWasmFiles()) {
20293
20363
  }
20294
20364
  var args = process.argv.slice(2);
20295
20365
  if (args.includes("--version") || args.includes("-v")) {
20296
- logConsole(`packmind-cli version ${CLI_VERSION6}`);
20366
+ logConsole(`packmind-cli version ${CLI_VERSION5}`);
20297
20367
  process.exit(0);
20298
20368
  }
20299
20369
  var app = (0, import_cmd_ts42.subcommands)({