@packmind/cli 0.15.0 → 0.16.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 +1162 -679
  2. package/package.json +14 -1
package/main.cjs CHANGED
@@ -371,32 +371,32 @@ var init_supports_color = __esm({
371
371
  });
372
372
 
373
373
  // node_modules/chalk/source/utilities.js
374
- function stringReplaceAll(string9, substring, replacer) {
375
- let index = string9.indexOf(substring);
374
+ function stringReplaceAll(string10, substring, replacer) {
375
+ let index = string10.indexOf(substring);
376
376
  if (index === -1) {
377
- return string9;
377
+ return string10;
378
378
  }
379
379
  const substringLength = substring.length;
380
380
  let endIndex = 0;
381
381
  let returnValue = "";
382
382
  do {
383
- returnValue += string9.slice(endIndex, index) + substring + replacer;
383
+ returnValue += string10.slice(endIndex, index) + substring + replacer;
384
384
  endIndex = index + substringLength;
385
- index = string9.indexOf(substring, endIndex);
385
+ index = string10.indexOf(substring, endIndex);
386
386
  } while (index !== -1);
387
- returnValue += string9.slice(endIndex);
387
+ returnValue += string10.slice(endIndex);
388
388
  return returnValue;
389
389
  }
390
- function stringEncaseCRLFWithFirstIndex(string9, prefix, postfix, index) {
390
+ function stringEncaseCRLFWithFirstIndex(string10, prefix, postfix, index) {
391
391
  let endIndex = 0;
392
392
  let returnValue = "";
393
393
  do {
394
- const gotCR = string9[index - 1] === "\r";
395
- returnValue += string9.slice(endIndex, gotCR ? index - 1 : index) + prefix + (gotCR ? "\r\n" : "\n") + postfix;
394
+ const gotCR = string10[index - 1] === "\r";
395
+ returnValue += string10.slice(endIndex, gotCR ? index - 1 : index) + prefix + (gotCR ? "\r\n" : "\n") + postfix;
396
396
  endIndex = index + 1;
397
- index = string9.indexOf("\n", endIndex);
397
+ index = string10.indexOf("\n", endIndex);
398
398
  } while (index !== -1);
399
- returnValue += string9.slice(endIndex);
399
+ returnValue += string10.slice(endIndex);
400
400
  return returnValue;
401
401
  }
402
402
  var init_utilities = __esm({
@@ -555,26 +555,26 @@ var init_source = __esm({
555
555
  builder[IS_EMPTY] = _isEmpty;
556
556
  return builder;
557
557
  };
558
- applyStyle = (self, string9) => {
559
- if (self.level <= 0 || !string9) {
560
- return self[IS_EMPTY] ? "" : string9;
558
+ applyStyle = (self, string10) => {
559
+ if (self.level <= 0 || !string10) {
560
+ return self[IS_EMPTY] ? "" : string10;
561
561
  }
562
562
  let styler = self[STYLER];
563
563
  if (styler === void 0) {
564
- return string9;
564
+ return string10;
565
565
  }
566
566
  const { openAll, closeAll } = styler;
567
- if (string9.includes("\x1B")) {
567
+ if (string10.includes("\x1B")) {
568
568
  while (styler !== void 0) {
569
- string9 = stringReplaceAll(string9, styler.close, styler.open);
569
+ string10 = stringReplaceAll(string10, styler.close, styler.open);
570
570
  styler = styler.parent;
571
571
  }
572
572
  }
573
- const lfIndex = string9.indexOf("\n");
573
+ const lfIndex = string10.indexOf("\n");
574
574
  if (lfIndex !== -1) {
575
- string9 = stringEncaseCRLFWithFirstIndex(string9, closeAll, openAll, lfIndex);
575
+ string10 = stringEncaseCRLFWithFirstIndex(string10, closeAll, openAll, lfIndex);
576
576
  }
577
- return openAll + string9 + closeAll;
577
+ return openAll + string10 + closeAll;
578
578
  };
579
579
  Object.defineProperties(createChalk.prototype, styles2);
580
580
  chalk = createChalk();
@@ -767,9 +767,9 @@ var require_findOption = __commonJS({
767
767
  continue;
768
768
  }
769
769
  if (node.type === "shortOptions" && opts.shortNames.length) {
770
- for (const option5 of node.options) {
771
- if (opts.shortNames.includes(option5.key)) {
772
- result.push(option5);
770
+ for (const option6 of node.options) {
771
+ if (opts.shortNames.includes(option6.key)) {
772
+ result.push(option6);
773
773
  }
774
774
  }
775
775
  }
@@ -843,7 +843,7 @@ var require_types = __commonJS({
843
843
  Object.defineProperty(exports2, "__esModule", { value: true });
844
844
  exports2.boolean = exports2.string = exports2.number = void 0;
845
845
  exports2.optional = optional4;
846
- exports2.array = array2;
846
+ exports2.array = array3;
847
847
  var type_1 = require_type();
848
848
  exports2.number = {
849
849
  async from(str) {
@@ -877,7 +877,7 @@ var require_types = __commonJS({
877
877
  }
878
878
  };
879
879
  }
880
- function array2(t) {
880
+ function array3(t) {
881
881
  return {
882
882
  ...t,
883
883
  async from(inputs) {
@@ -1379,13 +1379,13 @@ var require_subcommands = __commonJS({
1379
1379
  return mod && mod.__esModule ? mod : { "default": mod };
1380
1380
  };
1381
1381
  Object.defineProperty(exports2, "__esModule", { value: true });
1382
- exports2.subcommands = subcommands6;
1382
+ exports2.subcommands = subcommands7;
1383
1383
  var chalk_1 = __importDefault((init_source(), __toCommonJS(source_exports)));
1384
1384
  var didyoumean_1 = __importDefault(require_didYouMean_1_2_1());
1385
1385
  var Result = __importStar(require_Result());
1386
1386
  var circuitbreaker_1 = require_circuitbreaker();
1387
1387
  var positional_1 = require_positional();
1388
- function subcommands6(config) {
1388
+ function subcommands7(config) {
1389
1389
  const circuitbreaker = (0, circuitbreaker_1.createCircuitBreaker)(!!config.version);
1390
1390
  const type = {
1391
1391
  async from(str) {
@@ -1403,9 +1403,9 @@ var require_subcommands = __commonJS({
1403
1403
  let errorMessage = "Not a valid subcommand name";
1404
1404
  const closeOptions = (0, didyoumean_1.default)(str, flatMap(commands, (x) => x.names));
1405
1405
  if (closeOptions) {
1406
- const option5 = Array.isArray(closeOptions) ? closeOptions[0] : closeOptions;
1406
+ const option6 = Array.isArray(closeOptions) ? closeOptions[0] : closeOptions;
1407
1407
  errorMessage += `
1408
- Did you mean ${chalk_1.default.italic(option5)}?`;
1408
+ Did you mean ${chalk_1.default.italic(option6)}?`;
1409
1409
  }
1410
1410
  throw new Error(errorMessage);
1411
1411
  }
@@ -1526,9 +1526,9 @@ Did you mean ${chalk_1.default.italic(option5)}?`;
1526
1526
  }
1527
1527
  };
1528
1528
  }
1529
- function flatMap(array2, f) {
1529
+ function flatMap(array3, f) {
1530
1530
  const rs = [];
1531
- for (const item of array2) {
1531
+ for (const item of array3) {
1532
1532
  rs.push(...f(item));
1533
1533
  }
1534
1534
  return rs;
@@ -1578,11 +1578,11 @@ var strip_ansi_exports = {};
1578
1578
  __export(strip_ansi_exports, {
1579
1579
  default: () => stripAnsi
1580
1580
  });
1581
- function stripAnsi(string9) {
1582
- if (typeof string9 !== "string") {
1583
- throw new TypeError(`Expected a \`string\`, got \`${typeof string9}\``);
1581
+ function stripAnsi(string10) {
1582
+ if (typeof string10 !== "string") {
1583
+ throw new TypeError(`Expected a \`string\`, got \`${typeof string10}\``);
1584
1584
  }
1585
- return string9.replace(regex, "");
1585
+ return string10.replace(regex, "");
1586
1586
  }
1587
1587
  var regex;
1588
1588
  var init_strip_ansi = __esm({
@@ -1698,12 +1698,12 @@ var require_command = __commonJS({
1698
1698
  return mod && mod.__esModule ? mod : { "default": mod };
1699
1699
  };
1700
1700
  Object.defineProperty(exports2, "__esModule", { value: true });
1701
- exports2.command = command16;
1701
+ exports2.command = command20;
1702
1702
  var chalk_1 = __importDefault((init_source(), __toCommonJS(source_exports)));
1703
1703
  var Result = __importStar(require_Result());
1704
1704
  var circuitbreaker_1 = require_circuitbreaker();
1705
1705
  var utils_1 = require_utils();
1706
- function command16(config) {
1706
+ function command20(config) {
1707
1707
  const argEntries = (0, utils_1.entries)(config.args);
1708
1708
  const circuitbreaker = (0, circuitbreaker_1.createCircuitBreaker)(!!config.version);
1709
1709
  return {
@@ -1781,11 +1781,11 @@ var require_command = __commonJS({
1781
1781
  }
1782
1782
  if (node.type === "forcePositional") {
1783
1783
  } else if (node.type === "shortOptions") {
1784
- for (const option5 of node.options) {
1785
- if (context.visitedNodes.has(option5)) {
1784
+ for (const option6 of node.options) {
1785
+ if (context.visitedNodes.has(option6)) {
1786
1786
  continue;
1787
1787
  }
1788
- unknownArguments.push(option5);
1788
+ unknownArguments.push(option6);
1789
1789
  }
1790
1790
  } else {
1791
1791
  unknownArguments.push(node);
@@ -1864,7 +1864,7 @@ var require_option = __commonJS({
1864
1864
  return mod && mod.__esModule ? mod : { "default": mod };
1865
1865
  };
1866
1866
  Object.defineProperty(exports2, "__esModule", { value: true });
1867
- exports2.option = option5;
1867
+ exports2.option = option6;
1868
1868
  var chalk_1 = __importDefault((init_source(), __toCommonJS(source_exports)));
1869
1869
  var Result = __importStar(require_Result());
1870
1870
  var findOption_1 = require_findOption();
@@ -1940,11 +1940,11 @@ var require_option = __commonJS({
1940
1940
  const valueFromEnv = config.env ? process.env[config.env] : void 0;
1941
1941
  const defaultValueFn = config.defaultValue || config.type.defaultValue;
1942
1942
  const onMissingFn = config.onMissing || config.type.onMissing;
1943
- const option6 = options[0];
1943
+ const option7 = options[0];
1944
1944
  let rawValue;
1945
1945
  let envPrefix = "";
1946
- if (option6 === null || option6 === void 0 ? void 0 : option6.value) {
1947
- rawValue = option6.value.node.raw;
1946
+ if (option7 === null || option7 === void 0 ? void 0 : option7.value) {
1947
+ rawValue = option7.value.node.raw;
1948
1948
  } else if (valueFromEnv !== void 0) {
1949
1949
  rawValue = valueFromEnv;
1950
1950
  envPrefix = `env[${chalk_1.default.italic(config.env)}]: `;
@@ -1979,7 +1979,7 @@ var require_option = __commonJS({
1979
1979
  });
1980
1980
  }
1981
1981
  } else {
1982
- const raw = (option6 === null || option6 === void 0 ? void 0 : option6.type) === "shortOption" ? `-${option6 === null || option6 === void 0 ? void 0 : option6.key}` : `--${config.long}`;
1982
+ const raw = (option7 === null || option7 === void 0 ? void 0 : option7.type) === "shortOption" ? `-${option7 === null || option7 === void 0 ? void 0 : option7.key}` : `--${config.long}`;
1983
1983
  return Result.err({
1984
1984
  errors: [
1985
1985
  {
@@ -2001,7 +2001,7 @@ var require_option = __commonJS({
2001
2001
  }
2002
2002
  };
2003
2003
  }
2004
- function option5(config) {
2004
+ function option6(config) {
2005
2005
  return fullOption({
2006
2006
  type: types_1.string,
2007
2007
  ...config
@@ -2040,12 +2040,12 @@ var require_errorBox = __commonJS({
2040
2040
  if (node.type === "shortOptions") {
2041
2041
  let failed = false;
2042
2042
  let s = "";
2043
- for (const option5 of node.options) {
2044
- if (error.nodes.includes(option5)) {
2045
- s += chalk_1.default.red(option5.raw);
2043
+ for (const option6 of node.options) {
2044
+ if (error.nodes.includes(option6)) {
2045
+ s += chalk_1.default.red(option6.raw);
2046
2046
  failed = true;
2047
2047
  } else {
2048
- s += chalk_1.default.dim(option5.raw);
2048
+ s += chalk_1.default.dim(option6.raw);
2049
2049
  }
2050
2050
  }
2051
2051
  const prefix = failed ? chalk_1.default.red("-") : chalk_1.default.dim("-");
@@ -3084,8 +3084,8 @@ var require_tokenizer = __commonJS({
3084
3084
  tokens.push(token);
3085
3085
  overallIndex += token.raw.length;
3086
3086
  };
3087
- for (const [stringIndex, string9] of (0, utils_1.enumerate)(strings)) {
3088
- const chars = [...string9];
3087
+ for (const [stringIndex, string10] of (0, utils_1.enumerate)(strings)) {
3088
+ const chars = [...string10];
3089
3089
  for (let i = 0; i < chars.length; i++) {
3090
3090
  if (chars[i] === "-" && chars[i + 1] === "-") {
3091
3091
  push({ type: "longPrefix", raw: "--", index: overallIndex });
@@ -3346,15 +3346,15 @@ var require_multiflag = __commonJS({
3346
3346
  longNames: [config.long],
3347
3347
  shortNames: config.short ? [config.short] : []
3348
3348
  }).filter((x) => !visitedNodes.has(x));
3349
- for (const option5 of options) {
3350
- visitedNodes.add(option5);
3349
+ for (const option6 of options) {
3350
+ visitedNodes.add(option6);
3351
3351
  }
3352
3352
  const optionValues = [];
3353
3353
  const errors = [];
3354
- for (const option5 of options) {
3355
- const decoded = await Result.safeAsync(flag_1.boolean.from((_b = (_a = option5.value) === null || _a === void 0 ? void 0 : _a.node.raw) !== null && _b !== void 0 ? _b : "true"));
3354
+ for (const option6 of options) {
3355
+ const decoded = await Result.safeAsync(flag_1.boolean.from((_b = (_a = option6.value) === null || _a === void 0 ? void 0 : _a.node.raw) !== null && _b !== void 0 ? _b : "true"));
3356
3356
  if (Result.isErr(decoded)) {
3357
- errors.push({ nodes: [option5], message: decoded.error.message });
3357
+ errors.push({ nodes: [option6], message: decoded.error.message });
3358
3358
  } else {
3359
3359
  optionValues.push(decoded.value);
3360
3360
  }
@@ -3427,11 +3427,11 @@ var require_multioption = __commonJS({
3427
3427
  return mod && mod.__esModule ? mod : { "default": mod };
3428
3428
  };
3429
3429
  Object.defineProperty(exports2, "__esModule", { value: true });
3430
- exports2.multioption = multioption2;
3430
+ exports2.multioption = multioption3;
3431
3431
  var chalk_1 = __importDefault((init_source(), __toCommonJS(source_exports)));
3432
3432
  var Result = __importStar(require_Result());
3433
3433
  var findOption_1 = require_findOption();
3434
- function multioption2(config) {
3434
+ function multioption3(config) {
3435
3435
  return {
3436
3436
  helpTopics() {
3437
3437
  var _a, _b;
@@ -3518,16 +3518,16 @@ var require_multioption = __commonJS({
3518
3518
  });
3519
3519
  }
3520
3520
  }
3521
- for (const option5 of options) {
3522
- visitedNodes.add(option5);
3521
+ for (const option6 of options) {
3522
+ visitedNodes.add(option6);
3523
3523
  }
3524
3524
  const optionValues = [];
3525
3525
  const errors = [];
3526
3526
  const flagNodes = [];
3527
- for (const option5 of options) {
3528
- const providedValue = (_a = option5.value) === null || _a === void 0 ? void 0 : _a.node.raw;
3527
+ for (const option6 of options) {
3528
+ const providedValue = (_a = option6.value) === null || _a === void 0 ? void 0 : _a.node.raw;
3529
3529
  if (providedValue === void 0) {
3530
- flagNodes.push(option5);
3530
+ flagNodes.push(option6);
3531
3531
  continue;
3532
3532
  }
3533
3533
  optionValues.push(providedValue);
@@ -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.15.0",
3855
+ version: "0.16.0",
3856
3856
  description: "A command-line interface for Packmind linting and code quality checks",
3857
3857
  private: false,
3858
3858
  bin: {
@@ -3895,7 +3895,7 @@ var require_package = __commonJS({
3895
3895
  });
3896
3896
 
3897
3897
  // apps/cli/src/main.ts
3898
- var import_cmd_ts20 = __toESM(require_cjs());
3898
+ var import_cmd_ts25 = __toESM(require_cjs());
3899
3899
 
3900
3900
  // apps/cli/src/infra/commands/LinterCommand.ts
3901
3901
  var import_cmd_ts = __toESM(require_cjs());
@@ -4003,6 +4003,9 @@ var createOrganizationId = brandedIdFactory();
4003
4003
  // packages/types/src/accounts/User.ts
4004
4004
  var createUserId = brandedIdFactory();
4005
4005
 
4006
+ // packages/types/src/accounts/UserMetadata.ts
4007
+ var createUserMetadataId = brandedIdFactory();
4008
+
4006
4009
  // packages/types/src/events/PackmindEvent.ts
4007
4010
  var PackmindEvent = class {
4008
4011
  constructor(payload) {
@@ -4060,6 +4063,41 @@ var OrganizationCreatedEvent = class extends UserEvent {
4060
4063
  var createTrialActivationTokenId = brandedIdFactory();
4061
4064
  var createTrialActivationToken = brandedIdFactory();
4062
4065
 
4066
+ // packages/types/src/coding-agent/validation.ts
4067
+ var VALID_CODING_AGENTS = [
4068
+ "packmind",
4069
+ "junie",
4070
+ "claude",
4071
+ "cursor",
4072
+ "copilot",
4073
+ "agents_md",
4074
+ "gitlab_duo",
4075
+ "continue"
4076
+ ];
4077
+ function isValidCodingAgent(value) {
4078
+ return VALID_CODING_AGENTS.includes(value);
4079
+ }
4080
+ function validateAgentsWithWarnings(agents) {
4081
+ if (agents === void 0 || agents === null) {
4082
+ return { validAgents: null, invalidAgents: [] };
4083
+ }
4084
+ if (!Array.isArray(agents)) {
4085
+ return { validAgents: null, invalidAgents: [] };
4086
+ }
4087
+ const validAgents = [];
4088
+ const invalidAgents = [];
4089
+ for (const agent of agents) {
4090
+ if (typeof agent === "string") {
4091
+ if (isValidCodingAgent(agent)) {
4092
+ validAgents.push(agent);
4093
+ } else {
4094
+ invalidAgents.push(agent);
4095
+ }
4096
+ }
4097
+ }
4098
+ return { validAgents, invalidAgents };
4099
+ }
4100
+
4063
4101
  // packages/types/src/recipes/RecipeId.ts
4064
4102
  var createRecipeId = brandedIdFactory();
4065
4103
 
@@ -4908,8 +4946,8 @@ var ExecuteSingleFileAstUseCase = class _ExecuteSingleFileAstUseCase {
4908
4946
  static {
4909
4947
  this.fallbackRuleContent = "adhoc-rule";
4910
4948
  }
4911
- async execute(command16) {
4912
- const { program, fileContent, language } = command16;
4949
+ async execute(command20) {
4950
+ const { program, fileContent, language } = command20;
4913
4951
  const result = await this.linterExecutionUseCase.execute({
4914
4952
  filePath: "cli-single-file",
4915
4953
  fileContent,
@@ -4959,30 +4997,30 @@ var GitService = class {
4959
4997
  this.gitRunner = gitRunner;
4960
4998
  this.logger = logger2;
4961
4999
  }
4962
- getGitRepositoryRoot(path13) {
5000
+ getGitRepositoryRoot(path14) {
4963
5001
  try {
4964
5002
  const { stdout } = this.gitRunner("rev-parse --show-toplevel", {
4965
- cwd: path13
5003
+ cwd: path14
4966
5004
  });
4967
5005
  const gitRoot = stdout.trim();
4968
5006
  this.logger.debug("Resolved git repository root", {
4969
- inputPath: path13,
5007
+ inputPath: path14,
4970
5008
  gitRoot
4971
5009
  });
4972
5010
  return gitRoot;
4973
5011
  } catch (error) {
4974
5012
  if (error instanceof Error) {
4975
5013
  throw new Error(
4976
- `Failed to get Git repository root. The path '${path13}' does not appear to be inside a Git repository.
5014
+ `Failed to get Git repository root. The path '${path14}' does not appear to be inside a Git repository.
4977
5015
  ${error.message}`
4978
5016
  );
4979
5017
  }
4980
5018
  throw new Error("Failed to get Git repository root: Unknown error");
4981
5019
  }
4982
5020
  }
4983
- tryGetGitRepositoryRoot(path13) {
5021
+ tryGetGitRepositoryRoot(path14) {
4984
5022
  try {
4985
- return this.getGitRepositoryRoot(path13);
5023
+ return this.getGitRepositoryRoot(path14);
4986
5024
  } catch {
4987
5025
  return null;
4988
5026
  }
@@ -5289,8 +5327,8 @@ var GetGitRemoteUrlUseCase = class {
5289
5327
  constructor(gitRemoteUrlService = new GitService()) {
5290
5328
  this.gitRemoteUrlService = gitRemoteUrlService;
5291
5329
  }
5292
- async execute(command16) {
5293
- const { path: repoPath, origin: origin9 } = command16;
5330
+ async execute(command20) {
5331
+ const { path: repoPath, origin: origin9 } = command20;
5294
5332
  return this.gitRemoteUrlService.getGitRemoteUrl(repoPath, origin9);
5295
5333
  }
5296
5334
  };
@@ -5432,8 +5470,8 @@ var ListFilesInDirectoryUseCase = class {
5432
5470
  constructor(listFiles = new ListFiles()) {
5433
5471
  this.listFiles = listFiles;
5434
5472
  }
5435
- async execute(command16) {
5436
- const { path: directoryPath, extensions, excludes = [] } = command16;
5473
+ async execute(command20) {
5474
+ const { path: directoryPath, extensions, excludes = [] } = command20;
5437
5475
  const files = await this.listFiles.listFilesInDirectory(
5438
5476
  directoryPath,
5439
5477
  extensions,
@@ -5527,7 +5565,7 @@ var LintFilesAgainstRuleUseCase = class {
5527
5565
  }
5528
5566
  return pattern;
5529
5567
  }
5530
- async execute(command16) {
5568
+ async execute(command20) {
5531
5569
  const {
5532
5570
  path: userPath,
5533
5571
  draftMode,
@@ -5535,7 +5573,7 @@ var LintFilesAgainstRuleUseCase = class {
5535
5573
  ruleId,
5536
5574
  language,
5537
5575
  diffMode
5538
- } = command16;
5576
+ } = command20;
5539
5577
  this.logger.debug(
5540
5578
  `Starting linting: path="${userPath}", draftMode=${!!draftMode}, standardSlug="${standardSlug || "N/A"}", ruleId="${ruleId || "N/A"}", language="${language || "N/A"}", diffMode="${diffMode ?? "none"}"`
5541
5579
  );
@@ -5707,6 +5745,11 @@ var LintFilesAgainstRuleUseCase = class {
5707
5745
  this.logger.debug(
5708
5746
  `Retrieved detection programs: targetsCount=${detectionPrograms.targets.length}`
5709
5747
  );
5748
+ this.repositories.packmindGateway.linter.trackLinterExecution({
5749
+ targetCount: 1,
5750
+ standardCount: 1
5751
+ }).catch(() => {
5752
+ });
5710
5753
  const violations = [];
5711
5754
  for (const file of files) {
5712
5755
  const fileViolations = [];
@@ -5848,8 +5891,8 @@ var LintFilesAgainstRuleUseCase = class {
5848
5891
  return null;
5849
5892
  }
5850
5893
  }
5851
- async executeProgramsForFile(command16) {
5852
- const result = await this.services.linterExecutionUseCase.execute(command16);
5894
+ async executeProgramsForFile(command20) {
5895
+ const result = await this.services.linterExecutionUseCase.execute(command20);
5853
5896
  return result.violations;
5854
5897
  }
5855
5898
  extractExtensionFromFile(filePath) {
@@ -5906,8 +5949,8 @@ var LintFilesFromConfigUseCase = class {
5906
5949
  }
5907
5950
  return pattern;
5908
5951
  }
5909
- async execute(command16) {
5910
- const { path: userPath, diffMode } = command16;
5952
+ async execute(command20) {
5953
+ const { path: userPath, diffMode } = command20;
5911
5954
  this.logger.debug(
5912
5955
  `Starting local linting: path="${userPath}", diffMode="${diffMode ?? "none"}"`
5913
5956
  );
@@ -6084,6 +6127,11 @@ var LintFilesFromConfigUseCase = class {
6084
6127
  });
6085
6128
  }
6086
6129
  }
6130
+ this.repositories.packmindGateway.linter.trackLinterExecution({
6131
+ targetCount: allConfigs.configs.length,
6132
+ standardCount: allStandardsChecked.size
6133
+ }).catch(() => {
6134
+ });
6087
6135
  let filteredViolations = violations;
6088
6136
  if (diffMode === "lines" /* LINES */ && modifiedLines) {
6089
6137
  filteredViolations = this.services.diffViolationFilterService.filterByLines(
@@ -6151,8 +6199,8 @@ var LintFilesFromConfigUseCase = class {
6151
6199
  return null;
6152
6200
  }
6153
6201
  }
6154
- async executeProgramsForFile(command16) {
6155
- const result = await this.services.linterExecutionUseCase.execute(command16);
6202
+ async executeProgramsForFile(command20) {
6203
+ const result = await this.services.linterExecutionUseCase.execute(command20);
6156
6204
  return result.violations;
6157
6205
  }
6158
6206
  extractExtensionFromFile(filePath) {
@@ -6218,10 +6266,10 @@ var PackmindHttpClient = class {
6218
6266
  return null;
6219
6267
  }
6220
6268
  }
6221
- async request(path13, options = {}) {
6269
+ async request(path14, options = {}) {
6222
6270
  const { host } = this.getAuthContext();
6223
6271
  const { method = "GET", body } = options;
6224
- const url = `${host}${path13}`;
6272
+ const url = `${host}${path14}`;
6225
6273
  try {
6226
6274
  const response = await fetch(url, {
6227
6275
  method,
@@ -6278,13 +6326,13 @@ var CommunityEditionError = class extends Error {
6278
6326
  var LinterGateway = class {
6279
6327
  constructor(httpClient) {
6280
6328
  this.httpClient = httpClient;
6281
- this.getDraftDetectionProgramsForRule = async (command16) => {
6329
+ this.getDraftDetectionProgramsForRule = async (command20) => {
6282
6330
  const payload = {
6283
- standardSlug: command16.standardSlug,
6284
- ruleId: command16.ruleId
6331
+ standardSlug: command20.standardSlug,
6332
+ ruleId: command20.ruleId
6285
6333
  };
6286
- if (command16.language) {
6287
- payload.language = command16.language;
6334
+ if (command20.language) {
6335
+ payload.language = command20.language;
6288
6336
  }
6289
6337
  return this.httpClient.request("/api/v0/list-draft-detection-program", {
6290
6338
  method: "POST",
@@ -6296,13 +6344,13 @@ var LinterGateway = class {
6296
6344
  }
6297
6345
  });
6298
6346
  };
6299
- this.getActiveDetectionProgramsForRule = async (command16) => {
6347
+ this.getActiveDetectionProgramsForRule = async (command20) => {
6300
6348
  const payload = {
6301
- standardSlug: command16.standardSlug,
6302
- ruleId: command16.ruleId
6349
+ standardSlug: command20.standardSlug,
6350
+ ruleId: command20.ruleId
6303
6351
  };
6304
- if (command16.language) {
6305
- payload.language = command16.language;
6352
+ if (command20.language) {
6353
+ payload.language = command20.language;
6306
6354
  }
6307
6355
  return this.httpClient.request("/api/v0/list-active-detection-program", {
6308
6356
  method: "POST",
@@ -6314,13 +6362,13 @@ var LinterGateway = class {
6314
6362
  }
6315
6363
  });
6316
6364
  };
6317
- this.getDetectionProgramsForPackages = async (command16) => {
6365
+ this.getDetectionProgramsForPackages = async (command20) => {
6318
6366
  const response = await this.httpClient.request(
6319
6367
  "/api/v0/detection-programs-for-packages",
6320
6368
  {
6321
6369
  method: "POST",
6322
6370
  body: {
6323
- packagesSlugs: command16.packagesSlugs
6371
+ packagesSlugs: command20.packagesSlugs
6324
6372
  },
6325
6373
  onError: (response2) => {
6326
6374
  if (response2.status === 404) {
@@ -6331,6 +6379,12 @@ var LinterGateway = class {
6331
6379
  );
6332
6380
  return handleScopeInTargetsResponse(response);
6333
6381
  };
6382
+ this.trackLinterExecution = async (command20) => {
6383
+ return this.httpClient.request(`/api/v0/track-execution`, {
6384
+ method: "POST",
6385
+ body: command20
6386
+ });
6387
+ };
6334
6388
  }
6335
6389
  };
6336
6390
  function handleScopeInTargetsResponse(response) {
@@ -6386,33 +6440,39 @@ var SpacesGateway = class {
6386
6440
  var SkillsGateway = class {
6387
6441
  constructor(httpClient) {
6388
6442
  this.httpClient = httpClient;
6389
- this.upload = async (command16) => {
6443
+ this.upload = async (command20) => {
6390
6444
  const { organizationId } = this.httpClient.getAuthContext();
6391
6445
  return this.httpClient.request(
6392
- `/api/v0/organizations/${organizationId}/spaces/${command16.spaceId}/skills/upload`,
6446
+ `/api/v0/organizations/${organizationId}/spaces/${command20.spaceId}/skills/upload`,
6393
6447
  {
6394
6448
  method: "POST",
6395
- body: command16
6449
+ body: command20
6396
6450
  }
6397
6451
  );
6398
6452
  };
6399
- this.getDefaults = async (command16) => {
6453
+ this.getDefaults = async (command20) => {
6400
6454
  const { organizationId } = this.httpClient.getAuthContext();
6401
6455
  const queryParams = new URLSearchParams();
6402
- if (command16.includeBeta) {
6456
+ if (command20.includeBeta) {
6403
6457
  queryParams.set("includeBeta", "true");
6404
- } else if (command16.cliVersion) {
6405
- queryParams.set("cliVersion", command16.cliVersion);
6458
+ } else if (command20.cliVersion) {
6459
+ queryParams.set("cliVersion", command20.cliVersion);
6460
+ }
6461
+ if (command20.agents !== void 0) {
6462
+ queryParams.append("agentsConfigOverride", "true");
6463
+ command20.agents.forEach((agent) => {
6464
+ queryParams.append("agent", agent);
6465
+ });
6406
6466
  }
6407
6467
  const queryString = queryParams.toString();
6408
6468
  return this.httpClient.request(
6409
6469
  `/api/v0/organizations/${organizationId}/skills/default${queryString ? `?${queryString}` : ""}`
6410
6470
  );
6411
6471
  };
6412
- this.list = async (command16) => {
6472
+ this.list = async (command20) => {
6413
6473
  const { organizationId } = this.httpClient.getAuthContext();
6414
6474
  return this.httpClient.request(
6415
- `/api/v0/organizations/${organizationId}/spaces/${command16.spaceId}/skills`
6475
+ `/api/v0/organizations/${organizationId}/spaces/${command20.spaceId}/skills`
6416
6476
  );
6417
6477
  };
6418
6478
  }
@@ -6420,25 +6480,24 @@ var SkillsGateway = class {
6420
6480
 
6421
6481
  // apps/cli/src/infra/repositories/CommandsGateway.ts
6422
6482
  var CommandsGateway = class {
6423
- constructor(httpClient, spaces) {
6483
+ constructor(httpClient) {
6424
6484
  this.httpClient = httpClient;
6425
- this.spaces = spaces;
6426
- this.create = async (spaceId, data) => {
6485
+ this.create = async (command20) => {
6427
6486
  const { organizationId } = this.httpClient.getAuthContext();
6428
6487
  return this.httpClient.request(
6429
- `/api/v0/organizations/${organizationId}/spaces/${spaceId}/recipes`,
6430
- { method: "POST", body: data }
6488
+ `/api/v0/organizations/${organizationId}/spaces/${command20.spaceId}/recipes`,
6489
+ { method: "POST", body: command20 }
6431
6490
  );
6432
6491
  };
6433
- this.list = async () => {
6434
- const space = await this.spaces.getGlobal();
6492
+ this.list = async (command20) => {
6435
6493
  const { organizationId } = this.httpClient.getAuthContext();
6436
- const recipes = await this.httpClient.request(`/api/v0/organizations/${organizationId}/spaces/${space.id}/recipes`);
6437
- return recipes.map((r) => ({
6438
- id: r.id,
6439
- slug: r.slug,
6440
- name: r.name
6441
- }));
6494
+ const listRecipesResponse = await this.httpClient.request(
6495
+ `/api/v0/organizations/${organizationId}/spaces/${command20.spaceId}/recipes`
6496
+ );
6497
+ if (listRecipesResponse instanceof Array) {
6498
+ return { recipes: listRecipesResponse };
6499
+ }
6500
+ return listRecipesResponse;
6442
6501
  };
6443
6502
  }
6444
6503
  };
@@ -6475,374 +6534,101 @@ var StandardsGateway = class {
6475
6534
  }
6476
6535
  );
6477
6536
  };
6478
- this.list = async () => {
6479
- const space = await this.spaces.getGlobal();
6537
+ this.list = async (command20) => {
6480
6538
  const { organizationId } = this.httpClient.getAuthContext();
6481
- const response = await this.httpClient.request(`/api/v0/organizations/${organizationId}/spaces/${space.id}/standards`);
6482
- return response.standards.map((s) => ({
6483
- id: s.id,
6484
- slug: s.slug,
6485
- name: s.name,
6486
- description: s.description
6487
- }));
6539
+ return this.httpClient.request(
6540
+ `/api/v0/organizations/${organizationId}/spaces/${command20.spaceId}/standards`
6541
+ );
6488
6542
  };
6489
6543
  }
6490
6544
  };
6491
6545
 
6492
6546
  // apps/cli/src/infra/repositories/PackagesGateway.ts
6493
- function decodeJwt(jwt) {
6494
- try {
6495
- const parts = jwt.split(".");
6496
- if (parts.length !== 3) {
6497
- return null;
6498
- }
6499
- const payload = JSON.parse(
6500
- Buffer.from(parts[1], "base64").toString("utf-8")
6501
- );
6502
- return payload;
6503
- } catch {
6504
- return null;
6505
- }
6506
- }
6507
- function decodeApiKey(apiKey) {
6508
- if (!apiKey) {
6509
- return {
6510
- payload: { host: "", jwt: "" },
6511
- isValid: false,
6512
- error: "NOT_LOGGED_IN"
6513
- };
6514
- }
6515
- try {
6516
- const trimmedKey = apiKey.trim();
6517
- const jsonString = Buffer.from(trimmedKey, "base64").toString("utf-8");
6518
- const payload = JSON.parse(jsonString);
6519
- if (!payload.host || typeof payload.host !== "string") {
6520
- return {
6521
- payload,
6522
- isValid: false,
6523
- error: "Invalid API key: missing or invalid host field"
6524
- };
6525
- }
6526
- if (!payload.jwt || typeof payload.jwt !== "string") {
6527
- return {
6528
- payload,
6529
- isValid: false,
6530
- error: "Invalid API key: missing or invalid jwt field"
6531
- };
6532
- }
6533
- return {
6534
- payload,
6535
- isValid: true
6536
- };
6537
- } catch (error) {
6538
- return {
6539
- payload: { host: "", jwt: "" },
6540
- isValid: false,
6541
- error: `Failed to decode API key: ${error}`
6542
- };
6543
- }
6544
- }
6545
6547
  var PackagesGateway = class {
6546
6548
  constructor(apiKey, httpClient) {
6547
6549
  this.apiKey = apiKey;
6548
6550
  this.httpClient = httpClient;
6549
6551
  this.list = async () => {
6550
- const decodedApiKey = decodeApiKey(this.apiKey);
6551
- if (!decodedApiKey.isValid) {
6552
- if (decodedApiKey.error === "NOT_LOGGED_IN") {
6553
- throw new NotLoggedInError();
6554
- }
6555
- throw new Error(`Invalid API key: ${decodedApiKey.error}`);
6556
- }
6557
- const { host, jwt } = decodedApiKey.payload;
6558
- const jwtPayload = decodeJwt(jwt);
6559
- if (!jwtPayload?.organization?.id) {
6560
- throw new Error("Invalid API key: missing organizationId in JWT");
6561
- }
6562
- const organizationId = jwtPayload.organization.id;
6563
- const url = `${host}/api/v0/organizations/${organizationId}/packages`;
6564
- try {
6565
- const response = await fetch(url, {
6566
- method: "GET",
6567
- headers: {
6568
- "Content-Type": "application/json",
6569
- Authorization: `Bearer ${this.apiKey}`
6570
- }
6571
- });
6572
- if (!response.ok) {
6573
- let errorMsg = `API request failed: ${response.status} ${response.statusText}`;
6574
- try {
6575
- const errorBody = await response.json();
6576
- if (errorBody && errorBody.message) {
6577
- errorMsg = `${errorBody.message}`;
6578
- }
6579
- } catch {
6580
- }
6581
- const error = new Error(errorMsg);
6582
- error.statusCode = response.status;
6583
- throw error;
6584
- }
6585
- const result = await response.json();
6586
- return result.packages;
6587
- } catch (error) {
6588
- const err = error;
6589
- const code = err?.code || err?.cause?.code;
6590
- if (code === "ECONNREFUSED" || code === "ENOTFOUND" || err?.name === "FetchError" || typeof err?.message === "string" && (err.message.includes("Failed to fetch") || err.message.includes("network") || err.message.includes("NetworkError"))) {
6591
- throw new Error(
6592
- `Packmind server is not accessible at ${host}. Please check your network connection or the server URL.`
6593
- );
6594
- }
6595
- throw new Error(
6596
- `Failed to list packages: Error: ${err?.message || JSON.stringify(error)}`
6597
- );
6598
- }
6552
+ const { organizationId } = this.httpClient.getAuthContext();
6553
+ return this.httpClient.request(
6554
+ `/api/v0/organizations/${organizationId}/packages`
6555
+ );
6599
6556
  };
6600
- this.getSummary = async ({
6601
- slug
6602
- }) => {
6603
- const decodedApiKey = decodeApiKey(this.apiKey);
6604
- if (!decodedApiKey.isValid) {
6605
- if (decodedApiKey.error === "NOT_LOGGED_IN") {
6606
- throw new NotLoggedInError();
6607
- }
6608
- throw new Error(`Invalid API key: ${decodedApiKey.error}`);
6609
- }
6610
- const { host, jwt } = decodedApiKey.payload;
6611
- const jwtPayload = decodeJwt(jwt);
6612
- if (!jwtPayload?.organization?.id) {
6613
- throw new Error("Invalid API key: missing organizationId in JWT");
6614
- }
6615
- const organizationId = jwtPayload.organization.id;
6616
- const url = `${host}/api/v0/organizations/${organizationId}/packages/${encodeURIComponent(slug)}`;
6617
- try {
6618
- const response = await fetch(url, {
6619
- method: "GET",
6620
- headers: {
6621
- "Content-Type": "application/json",
6622
- Authorization: `Bearer ${this.apiKey}`
6623
- }
6624
- });
6625
- if (!response.ok) {
6626
- let errorMsg = `API request failed: ${response.status} ${response.statusText}`;
6627
- try {
6628
- const errorBody = await response.json();
6629
- if (errorBody && errorBody.message) {
6630
- errorMsg = `${errorBody.message}`;
6631
- }
6632
- } catch {
6633
- }
6634
- const error = new Error(errorMsg);
6635
- error.statusCode = response.status;
6636
- throw error;
6637
- }
6638
- const result = await response.json();
6639
- return result;
6640
- } catch (error) {
6641
- const err = error;
6642
- const code = err?.code || err?.cause?.code;
6643
- if (code === "ECONNREFUSED" || code === "ENOTFOUND" || err?.name === "FetchError" || typeof err?.message === "string" && (err.message.includes("Failed to fetch") || err.message.includes("network") || err.message.includes("NetworkError"))) {
6644
- throw new Error(
6645
- `Packmind server is not accessible at ${host}. Please check your network connection or the server URL.`
6646
- );
6557
+ this.getSummary = async ({ slug }) => {
6558
+ const { organizationId } = this.httpClient.getAuthContext();
6559
+ return this.httpClient.request(
6560
+ `/api/v0/organizations/${organizationId}/packages/${encodeURIComponent(slug)}`
6561
+ );
6562
+ };
6563
+ this.create = async (command20) => {
6564
+ const { organizationId } = this.httpClient.getAuthContext();
6565
+ return this.httpClient.request(
6566
+ `/api/v0/organizations/${organizationId}/spaces/${command20.spaceId}/packages`,
6567
+ {
6568
+ method: "POST",
6569
+ body: command20
6647
6570
  }
6648
- throw new Error(
6649
- `Failed to get package '${slug}': Error: ${err?.message || JSON.stringify(error)}`
6650
- );
6651
- }
6571
+ );
6652
6572
  };
6653
- this.create = async (spaceId, data) => {
6573
+ this.addArtefacts = async (command20) => {
6654
6574
  const { organizationId } = this.httpClient.getAuthContext();
6655
- const response = await this.httpClient.request(`/api/v0/organizations/${organizationId}/spaces/${spaceId}/packages`, {
6656
- method: "POST",
6657
- body: data
6658
- });
6659
- return response.package;
6575
+ const { packageId, spaceId } = command20;
6576
+ return this.httpClient.request(
6577
+ `/api/v0/organizations/${organizationId}/spaces/${spaceId}/packages/${packageId}/add-artifacts`,
6578
+ {
6579
+ method: "POST",
6580
+ body: command20
6581
+ }
6582
+ );
6660
6583
  };
6661
6584
  }
6662
6585
  };
6663
6586
 
6664
6587
  // apps/cli/src/infra/repositories/DeploymentGateway.ts
6665
- function decodeJwt2(jwt) {
6666
- try {
6667
- const parts = jwt.split(".");
6668
- if (parts.length !== 3) {
6669
- return null;
6670
- }
6671
- const payload = JSON.parse(
6672
- Buffer.from(parts[1], "base64").toString("utf-8")
6673
- );
6674
- return payload;
6675
- } catch {
6676
- return null;
6677
- }
6678
- }
6679
- function decodeApiKey2(apiKey) {
6680
- if (!apiKey) {
6681
- return {
6682
- payload: { host: "", jwt: "" },
6683
- isValid: false,
6684
- error: "NOT_LOGGED_IN"
6685
- };
6686
- }
6687
- try {
6688
- const trimmedKey = apiKey.trim();
6689
- const jsonString = Buffer.from(trimmedKey, "base64").toString("utf-8");
6690
- const payload = JSON.parse(jsonString);
6691
- if (!payload.host || typeof payload.host !== "string") {
6692
- return {
6693
- payload,
6694
- isValid: false,
6695
- error: "Invalid API key: missing or invalid host field"
6696
- };
6697
- }
6698
- if (!payload.jwt || typeof payload.jwt !== "string") {
6699
- return {
6700
- payload,
6701
- isValid: false,
6702
- error: "Invalid API key: missing or invalid jwt field"
6703
- };
6704
- }
6705
- return {
6706
- payload,
6707
- isValid: true
6708
- };
6709
- } catch (error) {
6710
- return {
6711
- payload: { host: "", jwt: "" },
6712
- isValid: false,
6713
- error: `Failed to decode API key: ${error}`
6714
- };
6715
- }
6716
- }
6717
6588
  var DeploymentGateway = class {
6718
- constructor(apiKey) {
6719
- this.apiKey = apiKey;
6720
- this.pull = async (command16) => {
6721
- const decodedApiKey = decodeApiKey2(this.apiKey);
6722
- if (!decodedApiKey.isValid) {
6723
- if (decodedApiKey.error === "NOT_LOGGED_IN") {
6724
- throw new NotLoggedInError();
6725
- }
6726
- throw new Error(`Invalid API key: ${decodedApiKey.error}`);
6727
- }
6728
- const { host, jwt } = decodedApiKey.payload;
6729
- const jwtPayload = decodeJwt2(jwt);
6730
- if (!jwtPayload?.organization?.id) {
6731
- throw new Error("Invalid API key: missing organizationId in JWT");
6732
- }
6733
- const organizationId = jwtPayload.organization.id;
6589
+ constructor(httpClient) {
6590
+ this.httpClient = httpClient;
6591
+ this.pull = async (command20) => {
6592
+ const { organizationId } = this.httpClient.getAuthContext();
6734
6593
  const queryParams = new URLSearchParams();
6735
- if (command16.packagesSlugs && command16.packagesSlugs.length > 0) {
6736
- command16.packagesSlugs.forEach((slug) => {
6594
+ if (command20.packagesSlugs && command20.packagesSlugs.length > 0) {
6595
+ command20.packagesSlugs.forEach((slug) => {
6737
6596
  queryParams.append("packageSlug", slug);
6738
6597
  });
6739
6598
  }
6740
- if (command16.previousPackagesSlugs && command16.previousPackagesSlugs.length > 0) {
6741
- command16.previousPackagesSlugs.forEach((slug) => {
6599
+ if (command20.previousPackagesSlugs && command20.previousPackagesSlugs.length > 0) {
6600
+ command20.previousPackagesSlugs.forEach((slug) => {
6742
6601
  queryParams.append("previousPackageSlug", slug);
6743
6602
  });
6744
6603
  }
6745
- if (command16.gitRemoteUrl) {
6746
- queryParams.append("gitRemoteUrl", command16.gitRemoteUrl);
6604
+ if (command20.gitRemoteUrl) {
6605
+ queryParams.append("gitRemoteUrl", command20.gitRemoteUrl);
6747
6606
  }
6748
- if (command16.gitBranch) {
6749
- queryParams.append("gitBranch", command16.gitBranch);
6607
+ if (command20.gitBranch) {
6608
+ queryParams.append("gitBranch", command20.gitBranch);
6750
6609
  }
6751
- if (command16.relativePath) {
6752
- queryParams.append("relativePath", command16.relativePath);
6610
+ if (command20.relativePath) {
6611
+ queryParams.append("relativePath", command20.relativePath);
6753
6612
  }
6754
- const url = `${host}/api/v0/organizations/${organizationId}/pull?${queryParams.toString()}`;
6755
- try {
6756
- const response = await fetch(url, {
6757
- method: "GET",
6758
- headers: {
6759
- "Content-Type": "application/json",
6760
- Authorization: `Bearer ${this.apiKey}`
6761
- }
6613
+ if (command20.agents !== void 0) {
6614
+ queryParams.append("agentsConfigOverride", "true");
6615
+ command20.agents.forEach((agent) => {
6616
+ queryParams.append("agent", agent);
6762
6617
  });
6763
- if (!response.ok) {
6764
- let errorMsg = `API request failed: ${response.status} ${response.statusText}`;
6765
- try {
6766
- const errorBody = await response.json();
6767
- if (errorBody && errorBody.message) {
6768
- errorMsg = `${errorBody.message}`;
6769
- }
6770
- } catch {
6771
- }
6772
- const error = new Error(errorMsg);
6773
- error.statusCode = response.status;
6774
- throw error;
6775
- }
6776
- const result = await response.json();
6777
- return result;
6778
- } catch (error) {
6779
- const err = error;
6780
- const code = err?.code || err?.cause?.code;
6781
- if (code === "ECONNREFUSED" || code === "ENOTFOUND" || err?.name === "FetchError" || typeof err?.message === "string" && (err.message.includes("Failed to fetch") || err.message.includes("network") || err.message.includes("NetworkError"))) {
6782
- throw new Error(
6783
- `Packmind server is not accessible at ${host}. Please check your network connection or the server URL.`
6784
- );
6785
- }
6786
- throw new Error(
6787
- `Failed to fetch content: Error: ${err?.message || JSON.stringify(error)}`
6788
- );
6789
6618
  }
6619
+ return this.httpClient.request(
6620
+ `/api/v0/organizations/${organizationId}/pull?${queryParams.toString()}`
6621
+ );
6790
6622
  };
6791
- this.notifyDistribution = async (params) => {
6792
- const decodedApiKey = decodeApiKey2(this.apiKey);
6793
- if (!decodedApiKey.isValid) {
6794
- if (decodedApiKey.error === "NOT_LOGGED_IN") {
6795
- throw new NotLoggedInError();
6796
- }
6797
- throw new Error(`Invalid API key: ${decodedApiKey.error}`);
6798
- }
6799
- const { host, jwt } = decodedApiKey.payload;
6800
- const jwtPayload = decodeJwt2(jwt);
6801
- if (!jwtPayload?.organization?.id) {
6802
- throw new Error("Invalid API key: missing organizationId in JWT");
6803
- }
6804
- const organizationId = jwtPayload.organization.id;
6805
- const url = `${host}/api/v0/organizations/${organizationId}/deployments`;
6806
- const payload = {
6807
- distributedPackages: params.distributedPackages,
6808
- gitRemoteUrl: params.gitRemoteUrl,
6809
- gitBranch: params.gitBranch,
6810
- relativePath: params.relativePath
6811
- };
6812
- try {
6813
- const response = await fetch(url, {
6623
+ this.notifyDistribution = async (command20) => {
6624
+ const { organizationId } = this.httpClient.getAuthContext();
6625
+ return this.httpClient.request(
6626
+ `/api/v0/organizations/${organizationId}/deployments`,
6627
+ {
6814
6628
  method: "POST",
6815
- headers: {
6816
- "Content-Type": "application/json",
6817
- Authorization: `Bearer ${this.apiKey}`
6818
- },
6819
- body: JSON.stringify(payload)
6820
- });
6821
- if (!response.ok) {
6822
- let errorMsg = `API request failed: ${response.status} ${response.statusText}`;
6823
- try {
6824
- const errorBody = await response.json();
6825
- if (errorBody && errorBody.message) {
6826
- errorMsg = `${errorBody.message}`;
6827
- }
6828
- } catch {
6829
- }
6830
- throw new Error(errorMsg);
6831
- }
6832
- const result = await response.json();
6833
- return result;
6834
- } catch (error) {
6835
- const err = error;
6836
- const code = err?.code || err?.cause?.code;
6837
- if (code === "ECONNREFUSED" || code === "ENOTFOUND" || err?.name === "FetchError" || typeof err?.message === "string" && (err.message.includes("Failed to fetch") || err.message.includes("network") || err.message.includes("NetworkError"))) {
6838
- throw new Error(
6839
- `Packmind server is not accessible at ${host}. Please check your network connection or the server URL.`
6840
- );
6629
+ body: command20
6841
6630
  }
6842
- throw new Error(
6843
- `Failed to notify distribution: Error: ${err?.message || JSON.stringify(error)}`
6844
- );
6845
- }
6631
+ );
6846
6632
  };
6847
6633
  }
6848
6634
  };
@@ -6856,10 +6642,10 @@ var PackmindGateway = class {
6856
6642
  this.mcp = new McpGateway(this.httpClient);
6857
6643
  this.spaces = new SpacesGateway(this.httpClient);
6858
6644
  this.skills = new SkillsGateway(this.httpClient);
6859
- this.commands = new CommandsGateway(this.httpClient, this.spaces);
6645
+ this.commands = new CommandsGateway(this.httpClient);
6860
6646
  this.standards = new StandardsGateway(this.httpClient, this.spaces);
6861
6647
  this.packages = new PackagesGateway(apiKey, this.httpClient);
6862
- this.deployment = new DeploymentGateway(apiKey);
6648
+ this.deployment = new DeploymentGateway(this.httpClient);
6863
6649
  }
6864
6650
  };
6865
6651
 
@@ -8603,8 +8389,8 @@ var ExecuteLinterProgramsUseCase = class {
8603
8389
  this.linterAstAdapter = linterAstAdapter;
8604
8390
  this.logger = logger2;
8605
8391
  }
8606
- async execute(command16) {
8607
- const { filePath, fileContent, language, programs } = command16;
8392
+ async execute(command20) {
8393
+ const { filePath, fileContent, language, programs } = command20;
8608
8394
  if (programs.length === 0) {
8609
8395
  return {
8610
8396
  file: filePath,
@@ -9281,8 +9067,8 @@ var InstallPackagesUseCase = class {
9281
9067
  constructor(packmindGateway) {
9282
9068
  this.packmindGateway = packmindGateway;
9283
9069
  }
9284
- async execute(command16) {
9285
- const baseDirectory = command16.baseDirectory || process.cwd();
9070
+ async execute(command20) {
9071
+ const baseDirectory = command20.baseDirectory || process.cwd();
9286
9072
  const result = {
9287
9073
  filesCreated: 0,
9288
9074
  filesUpdated: 0,
@@ -9294,14 +9080,18 @@ var InstallPackagesUseCase = class {
9294
9080
  skillDirectoriesDeleted: 0
9295
9081
  };
9296
9082
  const response = await this.packmindGateway.deployment.pull({
9297
- packagesSlugs: command16.packagesSlugs,
9298
- previousPackagesSlugs: command16.previousPackagesSlugs,
9299
- gitRemoteUrl: command16.gitRemoteUrl,
9300
- gitBranch: command16.gitBranch,
9301
- relativePath: command16.relativePath
9083
+ packagesSlugs: command20.packagesSlugs,
9084
+ previousPackagesSlugs: command20.previousPackagesSlugs,
9085
+ gitRemoteUrl: command20.gitRemoteUrl,
9086
+ gitBranch: command20.gitBranch,
9087
+ relativePath: command20.relativePath,
9088
+ agents: command20.agents
9302
9089
  });
9090
+ const filteredCreateOrUpdate = response.fileUpdates.createOrUpdate.filter(
9091
+ (file) => file.path !== "packmind.json"
9092
+ );
9303
9093
  const uniqueFilesMap = /* @__PURE__ */ new Map();
9304
- for (const file of response.fileUpdates.createOrUpdate) {
9094
+ for (const file of filteredCreateOrUpdate) {
9305
9095
  uniqueFilesMap.set(file.path, file);
9306
9096
  }
9307
9097
  const uniqueFiles = Array.from(uniqueFilesMap.values());
@@ -9361,7 +9151,8 @@ var InstallPackagesUseCase = class {
9361
9151
  fullPath,
9362
9152
  file.sections,
9363
9153
  fileExists,
9364
- result
9154
+ result,
9155
+ baseDirectory
9365
9156
  );
9366
9157
  }
9367
9158
  }
@@ -9398,7 +9189,7 @@ var InstallPackagesUseCase = class {
9398
9189
  result.filesCreated++;
9399
9190
  }
9400
9191
  }
9401
- async handleSectionsUpdate(fullPath, sections, fileExists, result) {
9192
+ async handleSectionsUpdate(fullPath, sections, fileExists, result, baseDirectory) {
9402
9193
  let currentContent = "";
9403
9194
  if (fileExists) {
9404
9195
  currentContent = await fs4.readFile(fullPath, "utf-8");
@@ -9411,6 +9202,7 @@ var InstallPackagesUseCase = class {
9411
9202
  if (this.isEffectivelyEmpty(mergedContent) && fileExists) {
9412
9203
  await fs4.unlink(fullPath);
9413
9204
  result.filesDeleted++;
9205
+ await this.removeEmptyParentDirectories(fullPath, baseDirectory);
9414
9206
  } else {
9415
9207
  await fs4.writeFile(fullPath, mergedContent, "utf-8");
9416
9208
  if (fileExists) {
@@ -9427,9 +9219,11 @@ var InstallPackagesUseCase = class {
9427
9219
  if (stat4?.isDirectory()) {
9428
9220
  await fs4.rm(fullPath, { recursive: true, force: true });
9429
9221
  result.filesDeleted++;
9222
+ await this.removeEmptyParentDirectories(fullPath, baseDirectory);
9430
9223
  } else if (stat4?.isFile()) {
9431
9224
  await fs4.unlink(fullPath);
9432
9225
  result.filesDeleted++;
9226
+ await this.removeEmptyParentDirectories(fullPath, baseDirectory);
9433
9227
  }
9434
9228
  }
9435
9229
  async fileExists(filePath) {
@@ -9509,6 +9303,7 @@ ${endMarker}`;
9509
9303
  const fileCount = await this.countFilesInDirectory(fullPath);
9510
9304
  await fs4.rm(fullPath, { recursive: true, force: true });
9511
9305
  deletedFilesCount += fileCount;
9306
+ await this.removeEmptyParentDirectories(fullPath, baseDirectory);
9512
9307
  } catch {
9513
9308
  }
9514
9309
  }
@@ -9530,26 +9325,60 @@ ${endMarker}`;
9530
9325
  }
9531
9326
  return count;
9532
9327
  }
9328
+ /**
9329
+ * Checks if a directory is empty (has no entries).
9330
+ */
9331
+ async isDirectoryEmpty(dirPath) {
9332
+ try {
9333
+ const entries = await fs4.readdir(dirPath);
9334
+ return entries.length === 0;
9335
+ } catch {
9336
+ return false;
9337
+ }
9338
+ }
9339
+ /**
9340
+ * Removes empty parent directories from fullPath up to (but not including) baseDirectory.
9341
+ * Stops when encountering a non-empty directory or reaching baseDirectory.
9342
+ */
9343
+ async removeEmptyParentDirectories(fullPath, baseDirectory) {
9344
+ const normalizedBase = path5.resolve(baseDirectory);
9345
+ let currentDir = path5.dirname(path5.resolve(fullPath));
9346
+ while (currentDir.startsWith(normalizedBase + path5.sep) && currentDir !== normalizedBase) {
9347
+ const isEmpty = await this.isDirectoryEmpty(currentDir);
9348
+ if (!isEmpty) break;
9349
+ try {
9350
+ await fs4.rmdir(currentDir);
9351
+ } catch {
9352
+ break;
9353
+ }
9354
+ currentDir = path5.dirname(currentDir);
9355
+ }
9356
+ }
9533
9357
  };
9534
9358
 
9535
9359
  // apps/cli/src/application/useCases/InstallDefaultSkillsUseCase.ts
9536
9360
  var fs5 = __toESM(require("fs/promises"));
9537
9361
  var path6 = __toESM(require("path"));
9538
9362
  var InstallDefaultSkillsUseCase = class {
9539
- constructor(packmindGateway) {
9540
- this.packmindGateway = packmindGateway;
9363
+ constructor(repositories) {
9364
+ this.repositories = repositories;
9541
9365
  }
9542
- async execute(command16) {
9543
- const baseDirectory = command16.baseDirectory || process.cwd();
9366
+ async execute(command20) {
9367
+ const baseDirectory = command20.baseDirectory || process.cwd();
9544
9368
  const result = {
9545
9369
  filesCreated: 0,
9546
9370
  filesUpdated: 0,
9547
9371
  errors: []
9548
9372
  };
9549
- const response = await this.packmindGateway.skills.getDefaults({
9550
- cliVersion: command16.cliVersion,
9551
- includeBeta: command16.includeBeta
9552
- });
9373
+ const config = await this.repositories.configFileRepository.readConfig(baseDirectory);
9374
+ const agents = config?.agents;
9375
+ const response = await this.repositories.packmindGateway.skills.getDefaults(
9376
+ {
9377
+ cliVersion: command20.cliVersion,
9378
+ includeBeta: command20.includeBeta,
9379
+ agents
9380
+ }
9381
+ );
9553
9382
  try {
9554
9383
  for (const file of response.fileUpdates.createOrUpdate) {
9555
9384
  try {
@@ -9601,7 +9430,8 @@ var ListPackagesUseCase = class {
9601
9430
  this.packmindGateway = packmindGateway;
9602
9431
  }
9603
9432
  async execute() {
9604
- return this.packmindGateway.packages.list({});
9433
+ const listPackagesResponse = await this.packmindGateway.packages.list({});
9434
+ return listPackagesResponse.packages;
9605
9435
  }
9606
9436
  };
9607
9437
 
@@ -9610,8 +9440,8 @@ var GetPackageSummaryUseCase = class {
9610
9440
  constructor(gateway) {
9611
9441
  this.gateway = gateway;
9612
9442
  }
9613
- async execute(command16) {
9614
- return this.gateway.packages.getSummary(command16);
9443
+ async execute(command20) {
9444
+ return this.gateway.packages.getSummary(command20);
9615
9445
  }
9616
9446
  };
9617
9447
 
@@ -9621,7 +9451,7 @@ var import_open = __toESM(require("open"));
9621
9451
  var readline = __toESM(require("readline"));
9622
9452
 
9623
9453
  // apps/cli/src/infra/utils/credentials/decodeApiKey.ts
9624
- function decodeApiKey3(apiKey) {
9454
+ function decodeApiKey(apiKey) {
9625
9455
  try {
9626
9456
  const jsonString = Buffer.from(apiKey.trim(), "base64").toString("utf-8");
9627
9457
  const apiKeyPayload = JSON.parse(jsonString);
@@ -9655,7 +9485,7 @@ var EnvCredentialsProvider = class {
9655
9485
  if (!apiKey) {
9656
9486
  return null;
9657
9487
  }
9658
- const decoded = decodeApiKey3(apiKey);
9488
+ const decoded = decodeApiKey(apiKey);
9659
9489
  if (!decoded) {
9660
9490
  return null;
9661
9491
  }
@@ -9707,7 +9537,7 @@ var FileCredentialsProvider = class {
9707
9537
  if (!credentials.apiKey) {
9708
9538
  return null;
9709
9539
  }
9710
- const decoded = decodeApiKey3(credentials.apiKey);
9540
+ const decoded = decodeApiKey(credentials.apiKey);
9711
9541
  if (!decoded) {
9712
9542
  return null;
9713
9543
  }
@@ -9802,10 +9632,10 @@ async function defaultPromptForCode() {
9802
9632
  input: process.stdin,
9803
9633
  output: process.stdout
9804
9634
  });
9805
- return new Promise((resolve6) => {
9635
+ return new Promise((resolve7) => {
9806
9636
  rl.question("Enter the login code from the browser: ", (answer) => {
9807
9637
  rl.close();
9808
- resolve6(answer.trim());
9638
+ resolve7(answer.trim());
9809
9639
  });
9810
9640
  });
9811
9641
  }
@@ -9839,7 +9669,7 @@ async function defaultExchangeCodeForApiKey(code, host) {
9839
9669
  return await response.json();
9840
9670
  }
9841
9671
  function defaultStartCallbackServer() {
9842
- return new Promise((resolve6, reject) => {
9672
+ return new Promise((resolve7, reject) => {
9843
9673
  let timeoutId = null;
9844
9674
  const server = http.createServer((req, res) => {
9845
9675
  res.setHeader("Access-Control-Allow-Origin", "*");
@@ -9852,7 +9682,7 @@ function defaultStartCallbackServer() {
9852
9682
  if (timeoutId) {
9853
9683
  clearTimeout(timeoutId);
9854
9684
  }
9855
- resolve6(code);
9685
+ resolve7(code);
9856
9686
  setImmediate(() => {
9857
9687
  server.close();
9858
9688
  });
@@ -9890,8 +9720,8 @@ var LoginUseCase = class {
9890
9720
  startCallbackServer: deps?.startCallbackServer ?? defaultStartCallbackServer
9891
9721
  };
9892
9722
  }
9893
- async execute(command16) {
9894
- const { host, code: providedCode } = command16;
9723
+ async execute(command20) {
9724
+ const { host, code: providedCode } = command20;
9895
9725
  let code;
9896
9726
  if (providedCode) {
9897
9727
  code = providedCode;
@@ -9929,8 +9759,8 @@ var LogoutUseCase = class {
9929
9759
  constructor(deps) {
9930
9760
  this.deps = {
9931
9761
  getCredentialsPath: deps?.getCredentialsPath ?? getCredentialsPath,
9932
- fileExists: deps?.fileExists ?? ((path13) => fs7.existsSync(path13)),
9933
- deleteFile: deps?.deleteFile ?? ((path13) => fs7.unlinkSync(path13)),
9762
+ fileExists: deps?.fileExists ?? ((path14) => fs7.existsSync(path14)),
9763
+ deleteFile: deps?.deleteFile ?? ((path14) => fs7.unlinkSync(path14)),
9934
9764
  hasEnvVar: deps?.hasEnvVar ?? (() => !!process.env[ENV_VAR_NAME2])
9935
9765
  };
9936
9766
  }
@@ -9990,8 +9820,8 @@ var SetupMcpUseCase = class {
9990
9820
  constructor(deps) {
9991
9821
  this.deps = deps;
9992
9822
  }
9993
- async execute(command16) {
9994
- const { agentTypes } = command16;
9823
+ async execute(command20) {
9824
+ const { agentTypes } = command20;
9995
9825
  const [tokenResult, urlResult] = await Promise.all([
9996
9826
  this.deps.gateway.mcp.getToken({}),
9997
9827
  this.deps.gateway.mcp.getUrl({})
@@ -10062,9 +9892,9 @@ var McpConfigService = class {
10062
9892
  return JSON.stringify(mcpConfig, null, 2);
10063
9893
  }
10064
9894
  installClaudeMcp(config) {
10065
- const command16 = `claude mcp add --transport http packmind ${config.url} --header "Authorization: Bearer ${config.accessToken}"`;
9895
+ const command20 = `claude mcp add --transport http packmind ${config.url} --header "Authorization: Bearer ${config.accessToken}"`;
10066
9896
  try {
10067
- (0, import_child_process2.execSync)(command16, { stdio: "pipe" });
9897
+ (0, import_child_process2.execSync)(command20, { stdio: "pipe" });
10068
9898
  return { success: true };
10069
9899
  } catch (error) {
10070
9900
  const execError = error;
@@ -10209,12 +10039,11 @@ var ConfigFileRepository = class {
10209
10039
  ];
10210
10040
  }
10211
10041
  async writeConfig(baseDirectory, config) {
10212
- const configPath = path9.join(baseDirectory, this.CONFIG_FILENAME);
10213
- const configContent = JSON.stringify(config, null, 2) + "\n";
10214
- await fs9.writeFile(configPath, configContent, "utf-8");
10042
+ const configPath = this.getConfigPath(baseDirectory);
10043
+ await this.writeConfigToPath(configPath, config);
10215
10044
  }
10216
10045
  async configExists(baseDirectory) {
10217
- const configPath = path9.join(baseDirectory, this.CONFIG_FILENAME);
10046
+ const configPath = this.getConfigPath(baseDirectory);
10218
10047
  try {
10219
10048
  await fs9.access(configPath);
10220
10049
  return true;
@@ -10223,15 +10052,29 @@ var ConfigFileRepository = class {
10223
10052
  }
10224
10053
  }
10225
10054
  async readConfig(baseDirectory) {
10226
- const configPath = path9.join(baseDirectory, this.CONFIG_FILENAME);
10055
+ const configPath = this.getConfigPath(baseDirectory);
10227
10056
  try {
10228
10057
  const configContent = await fs9.readFile(configPath, "utf-8");
10229
- const config = JSON.parse(configContent);
10230
- if (!config.packages || typeof config.packages !== "object") {
10058
+ const rawConfig = JSON.parse(configContent);
10059
+ if (!rawConfig.packages || typeof rawConfig.packages !== "object") {
10231
10060
  throw new Error(
10232
10061
  "Invalid packmind.json structure. Expected { packages: { ... } }"
10233
10062
  );
10234
10063
  }
10064
+ const { validAgents, invalidAgents } = validateAgentsWithWarnings(
10065
+ rawConfig.agents
10066
+ );
10067
+ if (invalidAgents.length > 0) {
10068
+ logWarningConsole(
10069
+ `Invalid agent(s) in ${configPath}: ${invalidAgents.join(", ")}. Valid agents are: packmind, junie, claude, cursor, copilot, agents_md, gitlab_duo, continue`
10070
+ );
10071
+ }
10072
+ const config = {
10073
+ packages: rawConfig.packages
10074
+ };
10075
+ if (validAgents !== null) {
10076
+ config.agents = validAgents;
10077
+ }
10235
10078
  return config;
10236
10079
  } catch (error) {
10237
10080
  if (error.code === "ENOENT") {
@@ -10244,46 +10087,56 @@ var ConfigFileRepository = class {
10244
10087
  return null;
10245
10088
  }
10246
10089
  }
10090
+ getConfigPath(directory) {
10091
+ return path9.join(directory, this.CONFIG_FILENAME);
10092
+ }
10093
+ async writeConfigToPath(configPath, config) {
10094
+ const configContent = JSON.stringify(config, null, 2) + "\n";
10095
+ await fs9.writeFile(configPath, configContent, "utf-8");
10096
+ }
10247
10097
  /**
10248
10098
  * Recursively finds all directories containing packmind.json in descendant folders.
10249
10099
  * Excludes common build/dependency directories (node_modules, .git, dist, etc.)
10250
- *
10251
- * @param directory - The root directory to search from
10252
- * @returns Array of directory paths that contain a packmind.json file
10253
10100
  */
10254
10101
  async findDescendantConfigs(directory) {
10255
10102
  const normalizedDir = normalizePath(path9.resolve(directory));
10103
+ return this.searchDescendantsRecursively(normalizedDir);
10104
+ }
10105
+ async searchDescendantsRecursively(currentDir) {
10106
+ const entries = await this.tryReadDirectory(currentDir);
10107
+ if (!entries) {
10108
+ return [];
10109
+ }
10256
10110
  const results = [];
10257
- const searchRecursively = async (currentDir) => {
10258
- let entries;
10259
- try {
10260
- entries = await fs9.readdir(currentDir, { withFileTypes: true });
10261
- } catch {
10262
- return;
10111
+ for (const entry of entries) {
10112
+ if (!entry.isDirectory() || this.isExcludedDirectory(entry.name)) {
10113
+ continue;
10263
10114
  }
10264
- for (const entry of entries) {
10265
- if (!entry.isDirectory()) {
10266
- continue;
10267
- }
10268
- if (this.EXCLUDED_DIRECTORIES.includes(entry.name)) {
10269
- continue;
10270
- }
10271
- const entryPath = normalizePath(path9.join(currentDir, entry.name));
10272
- const config = await this.readConfig(entryPath);
10273
- if (config) {
10274
- results.push(entryPath);
10275
- }
10276
- await searchRecursively(entryPath);
10115
+ const entryPath = normalizePath(path9.join(currentDir, entry.name));
10116
+ const config = await this.readConfig(entryPath);
10117
+ if (config) {
10118
+ results.push(entryPath);
10277
10119
  }
10278
- };
10279
- await searchRecursively(normalizedDir);
10120
+ const nestedResults = await this.searchDescendantsRecursively(entryPath);
10121
+ results.push(...nestedResults);
10122
+ }
10280
10123
  return results;
10281
10124
  }
10282
- /**
10283
- * Reads all packmind.json files from startDirectory up to stopDirectory (inclusive)
10284
- * and merges their package configurations.
10285
- *
10286
- * @param startDirectory - Directory to start searching from (typically the lint target)
10125
+ async tryReadDirectory(directory) {
10126
+ try {
10127
+ return await fs9.readdir(directory, { withFileTypes: true });
10128
+ } catch {
10129
+ return null;
10130
+ }
10131
+ }
10132
+ isExcludedDirectory(name) {
10133
+ return this.EXCLUDED_DIRECTORIES.includes(name);
10134
+ }
10135
+ /**
10136
+ * Reads all packmind.json files from startDirectory up to stopDirectory (inclusive)
10137
+ * and merges their package configurations.
10138
+ *
10139
+ * @param startDirectory - Directory to start searching from (typically the lint target)
10287
10140
  * @param stopDirectory - Directory to stop searching at (typically git repo root), or null to walk to filesystem root
10288
10141
  * @returns Merged configuration from all found packmind.json files
10289
10142
  */
@@ -10327,28 +10180,33 @@ var ConfigFileRepository = class {
10327
10180
  /**
10328
10181
  * Finds all packmind.json files in the tree (both ancestors and descendants)
10329
10182
  * and returns each config with its target path.
10330
- *
10331
- * @param startDirectory - Directory to start searching from (typically the lint target)
10332
- * @param stopDirectory - Directory to stop ancestor search at (typically git repo root), also used as base for descendants search
10333
- * @returns All configs found with their target paths
10334
10183
  */
10335
10184
  async findAllConfigsInTree(startDirectory, stopDirectory) {
10336
10185
  const normalizedStart = normalizePath(path9.resolve(startDirectory));
10337
10186
  const normalizedStop = stopDirectory ? normalizePath(path9.resolve(stopDirectory)) : null;
10338
10187
  const basePath = normalizedStop ?? normalizedStart;
10188
+ const searchRoot = normalizedStop ?? normalizedStart;
10339
10189
  const configsMap = /* @__PURE__ */ new Map();
10340
- let currentDir = normalizedStart;
10190
+ await this.collectAncestorConfigs(
10191
+ normalizedStart,
10192
+ normalizedStop,
10193
+ basePath,
10194
+ configsMap
10195
+ );
10196
+ await this.collectDescendantConfigs(searchRoot, basePath, configsMap);
10197
+ await this.collectRootConfigIfMissing(searchRoot, basePath, configsMap);
10198
+ const configs = Array.from(configsMap.values());
10199
+ return {
10200
+ configs,
10201
+ hasConfigs: configs.length > 0,
10202
+ basePath
10203
+ };
10204
+ }
10205
+ async collectAncestorConfigs(startDir, stopDir, basePath, configsMap) {
10206
+ let currentDir = startDir;
10341
10207
  while (true) {
10342
- const config = await this.readConfig(currentDir);
10343
- if (config) {
10344
- const targetPath = this.computeRelativeTargetPath(currentDir, basePath);
10345
- configsMap.set(currentDir, {
10346
- targetPath,
10347
- absoluteTargetPath: currentDir,
10348
- packages: config.packages
10349
- });
10350
- }
10351
- if (normalizedStop !== null && currentDir === normalizedStop) {
10208
+ await this.addConfigToMap(currentDir, basePath, configsMap);
10209
+ if (stopDir !== null && currentDir === stopDir) {
10352
10210
  break;
10353
10211
  }
10354
10212
  const parentDir = normalizePath(path9.dirname(currentDir));
@@ -10357,42 +10215,34 @@ var ConfigFileRepository = class {
10357
10215
  }
10358
10216
  currentDir = parentDir;
10359
10217
  }
10360
- const searchRoot = normalizedStop ?? normalizedStart;
10218
+ }
10219
+ async collectDescendantConfigs(searchRoot, basePath, configsMap) {
10361
10220
  const descendantDirs = await this.findDescendantConfigs(searchRoot);
10362
10221
  for (const descendantDir of descendantDirs) {
10363
10222
  const normalizedDescendantDir = normalizePath(descendantDir);
10364
10223
  if (configsMap.has(normalizedDescendantDir)) {
10365
10224
  continue;
10366
10225
  }
10367
- const config = await this.readConfig(normalizedDescendantDir);
10368
- if (config) {
10369
- const targetPath = this.computeRelativeTargetPath(
10370
- normalizedDescendantDir,
10371
- basePath
10372
- );
10373
- configsMap.set(normalizedDescendantDir, {
10374
- targetPath,
10375
- absoluteTargetPath: normalizedDescendantDir,
10376
- packages: config.packages
10377
- });
10378
- }
10226
+ await this.addConfigToMap(normalizedDescendantDir, basePath, configsMap);
10379
10227
  }
10228
+ }
10229
+ async collectRootConfigIfMissing(searchRoot, basePath, configsMap) {
10380
10230
  if (!configsMap.has(searchRoot)) {
10381
- const rootConfig = await this.readConfig(searchRoot);
10382
- if (rootConfig) {
10383
- configsMap.set(searchRoot, {
10384
- targetPath: "/",
10385
- absoluteTargetPath: searchRoot,
10386
- packages: rootConfig.packages
10387
- });
10388
- }
10231
+ await this.addConfigToMap(searchRoot, basePath, configsMap);
10389
10232
  }
10390
- const configs = Array.from(configsMap.values());
10391
- return {
10392
- configs,
10393
- hasConfigs: configs.length > 0,
10394
- basePath
10395
- };
10233
+ }
10234
+ async addConfigToMap(directory, basePath, configsMap) {
10235
+ const config = await this.readConfig(directory);
10236
+ if (!config) {
10237
+ return;
10238
+ }
10239
+ const targetPath = this.computeRelativeTargetPath(directory, basePath);
10240
+ configsMap.set(directory, {
10241
+ targetPath,
10242
+ absoluteTargetPath: directory,
10243
+ packages: config.packages,
10244
+ agents: config.agents
10245
+ });
10396
10246
  }
10397
10247
  computeRelativeTargetPath(absolutePath, basePath) {
10398
10248
  const normalizedAbsolute = normalizePath(absolutePath);
@@ -10403,6 +10253,91 @@ var ConfigFileRepository = class {
10403
10253
  const relativePath = normalizedAbsolute.substring(normalizedBase.length);
10404
10254
  return relativePath.startsWith("/") ? relativePath : "/" + relativePath;
10405
10255
  }
10256
+ /**
10257
+ * Adds new packages to an existing packmind.json while preserving property order.
10258
+ * If the file doesn't exist, creates a new one with default order (packages first).
10259
+ *
10260
+ * Uses JavaScript's built-in property order preservation: JSON.parse() preserves
10261
+ * insertion order for string keys, and mutating the existing object maintains
10262
+ * that order when JSON.stringify() outputs it.
10263
+ */
10264
+ async addPackagesToConfig(baseDirectory, newPackageSlugs) {
10265
+ const configPath = this.getConfigPath(baseDirectory);
10266
+ const rawContent = await this.tryReadFile(configPath);
10267
+ if (!rawContent) {
10268
+ const newConfig = this.createConfigWithPackages(newPackageSlugs);
10269
+ await this.writeConfigToPath(configPath, newConfig);
10270
+ return;
10271
+ }
10272
+ let parsed;
10273
+ try {
10274
+ parsed = JSON.parse(rawContent);
10275
+ } catch {
10276
+ const newConfig = this.createConfigWithPackages(newPackageSlugs);
10277
+ await this.writeConfigToPath(configPath, newConfig);
10278
+ return;
10279
+ }
10280
+ if (!parsed.packages || typeof parsed.packages !== "object") {
10281
+ parsed.packages = {};
10282
+ }
10283
+ const packages = parsed.packages;
10284
+ for (const slug of newPackageSlugs) {
10285
+ if (!(slug in packages)) {
10286
+ packages[slug] = "*";
10287
+ }
10288
+ }
10289
+ await this.writeConfigToPath(configPath, parsed);
10290
+ }
10291
+ /**
10292
+ * Updates a specific field in packmind.json while preserving property order.
10293
+ * If the file doesn't exist, creates a new one with default packages and the field.
10294
+ */
10295
+ async updateConfig(baseDirectory, field, value) {
10296
+ const configPath = this.getConfigPath(baseDirectory);
10297
+ const rawContent = await this.tryReadFile(configPath);
10298
+ if (!rawContent) {
10299
+ const newConfig = { packages: {}, [field]: value };
10300
+ await this.writeConfigToPath(configPath, newConfig);
10301
+ return;
10302
+ }
10303
+ let parsed;
10304
+ try {
10305
+ parsed = JSON.parse(rawContent);
10306
+ } catch {
10307
+ const newConfig = { packages: {}, [field]: value };
10308
+ await this.writeConfigToPath(configPath, newConfig);
10309
+ return;
10310
+ }
10311
+ if (!parsed.packages || typeof parsed.packages !== "object") {
10312
+ parsed.packages = {};
10313
+ }
10314
+ parsed[field] = value;
10315
+ await this.writeConfigToPath(configPath, parsed);
10316
+ }
10317
+ /**
10318
+ * Updates the agents configuration in packmind.json.
10319
+ * Convenience wrapper around updateConfig for the agents field.
10320
+ */
10321
+ async updateAgentsConfig(baseDirectory, agents) {
10322
+ return this.updateConfig(baseDirectory, "agents", agents);
10323
+ }
10324
+ async tryReadFile(filePath) {
10325
+ try {
10326
+ return await fs9.readFile(filePath, "utf-8");
10327
+ } catch (error) {
10328
+ if (error.code === "ENOENT") {
10329
+ return null;
10330
+ }
10331
+ throw error;
10332
+ }
10333
+ }
10334
+ createConfigWithPackages(slugs) {
10335
+ const packages = {};
10336
+ for (const slug of slugs) {
10337
+ packages[slug] = "*";
10338
+ }
10339
+ return { packages };
10340
+ }
10406
10341
  };
10407
10342
 
10408
10343
  // apps/cli/src/application/useCases/ListStandardsUseCase.ts
@@ -10411,7 +10346,11 @@ var ListStandardsUseCase = class {
10411
10346
  this.packmindGateway = packmindGateway;
10412
10347
  }
10413
10348
  async execute() {
10414
- return this.packmindGateway.standards.list();
10349
+ const globalSpace = await this.packmindGateway.spaces.getGlobal();
10350
+ const listStandardsResponse = await this.packmindGateway.standards.list({
10351
+ spaceId: globalSpace.id
10352
+ });
10353
+ return listStandardsResponse.standards;
10415
10354
  }
10416
10355
  };
10417
10356
 
@@ -10421,7 +10360,11 @@ var ListCommandsUseCase = class {
10421
10360
  this.packmindGateway = packmindGateway;
10422
10361
  }
10423
10362
  async execute() {
10424
- return this.packmindGateway.commands.list();
10363
+ const space = await this.packmindGateway.spaces.getGlobal();
10364
+ const listCommandsResponse = await this.packmindGateway.commands.list({
10365
+ spaceId: space.id
10366
+ });
10367
+ return listCommandsResponse.recipes;
10425
10368
  }
10426
10369
  };
10427
10370
 
@@ -10582,8 +10525,8 @@ var UploadSkillUseCase = class {
10582
10525
  constructor(deps) {
10583
10526
  this.deps = deps;
10584
10527
  }
10585
- async execute(command16) {
10586
- const files = await readSkillDirectory(command16.skillPath);
10528
+ async execute(command20) {
10529
+ const files = await readSkillDirectory(command20.skillPath);
10587
10530
  if (!files.find((f) => f.relativePath === "SKILL.md")) {
10588
10531
  throw new Error("SKILL.md not found in skill directory");
10589
10532
  }
@@ -10652,9 +10595,7 @@ var PackmindCliHexaFactory = class {
10652
10595
  installPackages: new InstallPackagesUseCase(
10653
10596
  this.repositories.packmindGateway
10654
10597
  ),
10655
- installDefaultSkills: new InstallDefaultSkillsUseCase(
10656
- this.repositories.packmindGateway
10657
- ),
10598
+ installDefaultSkills: new InstallDefaultSkillsUseCase(this.repositories),
10658
10599
  listPackages: new ListPackagesUseCase(this.repositories.packmindGateway),
10659
10600
  getPackageBySlug: new GetPackageSummaryUseCase(
10660
10601
  this.repositories.packmindGateway
@@ -10682,6 +10623,11 @@ var PackmindCliHexaFactory = class {
10682
10623
  var origin8 = "PackmindCliHexa";
10683
10624
  var PackmindCliHexa = class {
10684
10625
  constructor(logger2 = new PackmindLogger(origin8)) {
10626
+ this.notifyDistribution = async (command20) => {
10627
+ return this.hexa.repositories.packmindGateway.deployment.notifyDistribution(
10628
+ command20
10629
+ );
10630
+ };
10685
10631
  this.logger = logger2;
10686
10632
  try {
10687
10633
  this.hexa = new PackmindCliHexaFactory();
@@ -10699,38 +10645,38 @@ var PackmindCliHexa = class {
10699
10645
  this.logger.info("Destroying PackmindCliHexa");
10700
10646
  this.logger.info("PackmindCliHexa destroyed");
10701
10647
  }
10702
- async getGitRemoteUrl(command16) {
10703
- return this.hexa.useCases.getGitRemoteUrl.execute(command16);
10648
+ async getGitRemoteUrl(command20) {
10649
+ return this.hexa.useCases.getGitRemoteUrl.execute(command20);
10704
10650
  }
10705
- async executeSingleFileAst(command16) {
10706
- return this.hexa.useCases.executeSingleFileAst.execute(command16);
10651
+ async executeSingleFileAst(command20) {
10652
+ return this.hexa.useCases.executeSingleFileAst.execute(command20);
10707
10653
  }
10708
- async listFilesInDirectory(command16) {
10709
- return this.hexa.useCases.listFilesInDirectoryUseCase.execute(command16);
10654
+ async listFilesInDirectory(command20) {
10655
+ return this.hexa.useCases.listFilesInDirectoryUseCase.execute(command20);
10710
10656
  }
10711
- async lintFilesAgainstRule(command16) {
10712
- return this.hexa.useCases.lintFilesAgainstRule.execute(command16);
10657
+ async lintFilesAgainstRule(command20) {
10658
+ return this.hexa.useCases.lintFilesAgainstRule.execute(command20);
10713
10659
  }
10714
- async lintFilesFromConfig(command16) {
10715
- return this.hexa.useCases.lintFilesFromConfig.execute(command16);
10660
+ async lintFilesFromConfig(command20) {
10661
+ return this.hexa.useCases.lintFilesFromConfig.execute(command20);
10716
10662
  }
10717
- async installPackages(command16) {
10718
- return this.hexa.useCases.installPackages.execute(command16);
10663
+ async installPackages(command20) {
10664
+ return this.hexa.useCases.installPackages.execute(command20);
10719
10665
  }
10720
- async listPackages(command16) {
10721
- return this.hexa.useCases.listPackages.execute(command16);
10666
+ async listPackages(command20) {
10667
+ return this.hexa.useCases.listPackages.execute(command20);
10722
10668
  }
10723
- async getPackageBySlug(command16) {
10724
- return this.hexa.useCases.getPackageBySlug.execute(command16);
10669
+ async getPackageBySlug(command20) {
10670
+ return this.hexa.useCases.getPackageBySlug.execute(command20);
10725
10671
  }
10726
- async listStandards(command16) {
10727
- return this.hexa.useCases.listStandards.execute(command16);
10672
+ async listStandards(command20) {
10673
+ return this.hexa.useCases.listStandards.execute(command20);
10728
10674
  }
10729
- async listCommands(command16) {
10730
- return this.hexa.useCases.listCommands.execute(command16);
10675
+ async listCommands(command20) {
10676
+ return this.hexa.useCases.listCommands.execute(command20);
10731
10677
  }
10732
- async listSkills(command16) {
10733
- return this.hexa.useCases.listSkills.execute(command16);
10678
+ async listSkills(command20) {
10679
+ return this.hexa.useCases.listSkills.execute(command20);
10734
10680
  }
10735
10681
  async configExists(baseDirectory) {
10736
10682
  return await this.hexa.repositories.configFileRepository.configExists(
@@ -10741,7 +10687,7 @@ var PackmindCliHexa = class {
10741
10687
  const config = await this.hexa.repositories.configFileRepository.readConfig(
10742
10688
  baseDirectory
10743
10689
  );
10744
- if (!config) return [];
10690
+ if (!config) return { packages: {} };
10745
10691
  const hasNonWildcardVersions = Object.values(config.packages).some(
10746
10692
  (version) => version !== "*"
10747
10693
  );
@@ -10750,16 +10696,44 @@ var PackmindCliHexa = class {
10750
10696
  "Package versions are not supported yet, getting the latest version"
10751
10697
  );
10752
10698
  }
10753
- return Object.keys(config.packages);
10699
+ return config;
10700
+ }
10701
+ /**
10702
+ * Reads the full packmind.json configuration including agents.
10703
+ * Returns null if no config file exists.
10704
+ */
10705
+ async readFullConfig(baseDirectory) {
10706
+ return this.hexa.repositories.configFileRepository.readConfig(
10707
+ baseDirectory
10708
+ );
10754
10709
  }
10755
10710
  async writeConfig(baseDirectory, packagesSlugs) {
10756
10711
  const packages = {};
10757
10712
  packagesSlugs.forEach((slug) => {
10758
10713
  packages[slug] = "*";
10759
10714
  });
10715
+ const existingConfig = await this.hexa.repositories.configFileRepository.readConfig(
10716
+ baseDirectory
10717
+ );
10760
10718
  await this.hexa.repositories.configFileRepository.writeConfig(
10761
10719
  baseDirectory,
10762
- { packages }
10720
+ {
10721
+ ...existingConfig,
10722
+ packages
10723
+ }
10724
+ );
10725
+ }
10726
+ /**
10727
+ * Adds new packages to an existing packmind.json while preserving property order.
10728
+ * If the file doesn't exist, creates a new one with default order (packages first).
10729
+ *
10730
+ * @param baseDirectory - The directory containing packmind.json
10731
+ * @param newPackageSlugs - Array of package slugs to add
10732
+ */
10733
+ async addPackagesToConfig(baseDirectory, newPackageSlugs) {
10734
+ return this.hexa.repositories.configFileRepository.addPackagesToConfig(
10735
+ baseDirectory,
10736
+ newPackageSlugs
10763
10737
  );
10764
10738
  }
10765
10739
  async readHierarchicalConfig(startDirectory, stopDirectory) {
@@ -10789,17 +10763,17 @@ var PackmindCliHexa = class {
10789
10763
  directory
10790
10764
  );
10791
10765
  }
10792
- async login(command16) {
10793
- return this.hexa.useCases.login.execute(command16);
10766
+ async login(command20) {
10767
+ return this.hexa.useCases.login.execute(command20);
10794
10768
  }
10795
- async logout(command16) {
10796
- return this.hexa.useCases.logout.execute(command16);
10769
+ async logout(command20) {
10770
+ return this.hexa.useCases.logout.execute(command20);
10797
10771
  }
10798
- async whoami(command16) {
10799
- return this.hexa.useCases.whoami.execute(command16);
10772
+ async whoami(command20) {
10773
+ return this.hexa.useCases.whoami.execute(command20);
10800
10774
  }
10801
- async setupMcp(command16) {
10802
- return this.hexa.useCases.setupMcp.execute(command16);
10775
+ async setupMcp(command20) {
10776
+ return this.hexa.useCases.setupMcp.execute(command20);
10803
10777
  }
10804
10778
  getCurrentBranch(repoPath) {
10805
10779
  return this.hexa.services.gitRemoteUrlService.getCurrentBranch(repoPath).branch;
@@ -10807,16 +10781,11 @@ var PackmindCliHexa = class {
10807
10781
  getGitRemoteUrlFromPath(repoPath) {
10808
10782
  return this.hexa.services.gitRemoteUrlService.getGitRemoteUrl(repoPath).gitRemoteUrl;
10809
10783
  }
10810
- async notifyDistribution(command16) {
10811
- return this.hexa.repositories.packmindGateway.deployment.notifyDistribution(
10812
- command16
10813
- );
10814
- }
10815
- async uploadSkill(command16) {
10816
- return this.hexa.useCases.uploadSkill.execute(command16);
10784
+ async uploadSkill(command20) {
10785
+ return this.hexa.useCases.uploadSkill.execute(command20);
10817
10786
  }
10818
- async installDefaultSkills(command16) {
10819
- return this.hexa.useCases.installDefaultSkills.execute(command16);
10787
+ async installDefaultSkills(command20) {
10788
+ return this.hexa.useCases.installDefaultSkills.execute(command20);
10820
10789
  }
10821
10790
  getPackmindGateway() {
10822
10791
  return this.hexa.repositories.packmindGateway;
@@ -10893,7 +10862,7 @@ function isNotLoggedInError(error) {
10893
10862
  }
10894
10863
  async function lintHandler(args2, deps) {
10895
10864
  const {
10896
- path: path13,
10865
+ path: path14,
10897
10866
  draft,
10898
10867
  rule,
10899
10868
  language,
@@ -10913,7 +10882,7 @@ async function lintHandler(args2, deps) {
10913
10882
  throw new Error("option --rule is required to use --draft mode");
10914
10883
  }
10915
10884
  const startedAt = Date.now();
10916
- const targetPath = path13 ?? ".";
10885
+ const targetPath = path14 ?? ".";
10917
10886
  const absolutePath = resolvePath(targetPath);
10918
10887
  if (diff) {
10919
10888
  const gitRoot = await packmindCliHexa.tryGetGitRepositoryRoot(absolutePath);
@@ -11164,8 +11133,8 @@ function extractWasmFiles() {
11164
11133
 
11165
11134
  // apps/cli/src/main.ts
11166
11135
  var import_dotenv = require("dotenv");
11167
- var fs15 = __toESM(require("fs"));
11168
- var path12 = __toESM(require("path"));
11136
+ var fs16 = __toESM(require("fs"));
11137
+ var path13 = __toESM(require("path"));
11169
11138
 
11170
11139
  // apps/cli/src/infra/commands/InstallCommand.ts
11171
11140
  var import_cmd_ts2 = __toESM(require_cjs());
@@ -11176,7 +11145,7 @@ function buildPackageUrl(host, orgSlug, packageId) {
11176
11145
  }
11177
11146
  var { version: CLI_VERSION } = require_package();
11178
11147
  async function notifyDistributionIfInGitRepo(params) {
11179
- const { packmindCliHexa, cwd, packages, log } = params;
11148
+ const { packmindCliHexa, cwd, packages, log, agents } = params;
11180
11149
  const gitRoot = await packmindCliHexa.tryGetGitRepositoryRoot(cwd);
11181
11150
  if (!gitRoot) {
11182
11151
  return false;
@@ -11195,7 +11164,8 @@ async function notifyDistributionIfInGitRepo(params) {
11195
11164
  distributedPackages: packages,
11196
11165
  gitRemoteUrl,
11197
11166
  gitBranch,
11198
- relativePath
11167
+ relativePath,
11168
+ agents
11199
11169
  });
11200
11170
  log("Successfully notified Packmind of the new distribution");
11201
11171
  return true;
@@ -11246,7 +11216,7 @@ async function listPackagesHandler(_args, deps) {
11246
11216
  let urlBuilder = null;
11247
11217
  const apiKey = loadApiKey();
11248
11218
  if (apiKey) {
11249
- const decoded = decodeApiKey3(apiKey);
11219
+ const decoded = decodeApiKey(apiKey);
11250
11220
  const orgSlug = decoded?.jwt?.organization?.slug;
11251
11221
  if (decoded?.host && orgSlug) {
11252
11222
  urlBuilder = (id) => buildPackageUrl(decoded.host, orgSlug, id);
@@ -11407,8 +11377,15 @@ ${uniqueCount} unique ${packageWord} currently installed.`);
11407
11377
  async function executeInstallForDirectory(directory, deps) {
11408
11378
  const { packmindCliHexa, log } = deps;
11409
11379
  let configPackages;
11380
+ let configAgents;
11410
11381
  try {
11411
- configPackages = await packmindCliHexa.readConfig(directory);
11382
+ const fullConfig = await packmindCliHexa.readFullConfig(directory);
11383
+ if (fullConfig) {
11384
+ configPackages = Object.keys(fullConfig.packages);
11385
+ configAgents = fullConfig.agents;
11386
+ } else {
11387
+ configPackages = [];
11388
+ }
11412
11389
  } catch (err) {
11413
11390
  const errorMessage = err instanceof Error ? err.message : String(err);
11414
11391
  return {
@@ -11438,8 +11415,10 @@ async function executeInstallForDirectory(directory, deps) {
11438
11415
  const result = await packmindCliHexa.installPackages({
11439
11416
  baseDirectory: directory,
11440
11417
  packagesSlugs: configPackages,
11441
- previousPackagesSlugs: configPackages
11418
+ previousPackagesSlugs: configPackages,
11442
11419
  // Pass for consistency
11420
+ agents: configAgents
11421
+ // Pass agents from config if present
11443
11422
  });
11444
11423
  const parts = [];
11445
11424
  if (result.recipesCount > 0) parts.push(`${result.recipesCount} commands`);
@@ -11467,6 +11446,7 @@ async function executeInstallForDirectory(directory, deps) {
11467
11446
  packmindCliHexa,
11468
11447
  cwd: directory,
11469
11448
  packages: configPackages,
11449
+ agents: configAgents,
11470
11450
  log: () => {
11471
11451
  }
11472
11452
  });
@@ -11495,10 +11475,25 @@ async function installPackagesHandler(args2, deps) {
11495
11475
  const { packagesSlugs } = args2;
11496
11476
  const cwd = getCwd();
11497
11477
  let configPackages;
11478
+ let configAgents;
11498
11479
  let configFileExists = false;
11499
11480
  try {
11500
11481
  configFileExists = await packmindCliHexa.configExists(cwd);
11501
- configPackages = await packmindCliHexa.readConfig(cwd);
11482
+ const fullConfig = await packmindCliHexa.readFullConfig(cwd);
11483
+ if (fullConfig) {
11484
+ const hasNonWildcardVersions = Object.values(fullConfig.packages).some(
11485
+ (version) => version !== "*"
11486
+ );
11487
+ if (hasNonWildcardVersions) {
11488
+ logWarningConsole(
11489
+ "Package versions are not supported yet, getting the latest version"
11490
+ );
11491
+ }
11492
+ configPackages = Object.keys(fullConfig.packages);
11493
+ configAgents = fullConfig.agents;
11494
+ } else {
11495
+ configPackages = [];
11496
+ }
11502
11497
  } catch (err) {
11503
11498
  error("ERROR Failed to parse packmind.json");
11504
11499
  if (err instanceof Error) {
@@ -11575,7 +11570,9 @@ async function installPackagesHandler(args2, deps) {
11575
11570
  // Pass previous config for change detection
11576
11571
  gitRemoteUrl,
11577
11572
  gitBranch,
11578
- relativePath
11573
+ relativePath,
11574
+ agents: configAgents
11575
+ // Pass agents from config if present (overrides org-level)
11579
11576
  });
11580
11577
  const parts = [];
11581
11578
  if (result.recipesCount > 0) parts.push(`${result.recipesCount} commands`);
@@ -11602,16 +11599,27 @@ added ${result.filesCreated} files, changed ${result.filesUpdated} files, remove
11602
11599
  notificationSent: false
11603
11600
  };
11604
11601
  }
11602
+ const newPackages = packagesSlugs.filter(
11603
+ (slug) => !configPackages.includes(slug)
11604
+ );
11605
+ if (newPackages.length > 0) {
11606
+ await packmindCliHexa.addPackagesToConfig(cwd, newPackages);
11607
+ }
11605
11608
  let notificationSent = false;
11606
11609
  if (result.filesCreated > 0 || result.filesUpdated > 0 || result.filesDeleted > 0 || skillDirsDeleted > 0) {
11607
11610
  notificationSent = await notifyDistributionIfInGitRepo({
11608
11611
  packmindCliHexa,
11609
11612
  cwd,
11610
11613
  packages: allPackages,
11614
+ agents: configAgents,
11611
11615
  log
11612
11616
  });
11613
11617
  }
11614
- await installDefaultSkillsIfAtGitRoot({ packmindCliHexa, cwd, log });
11618
+ await installDefaultSkillsIfAtGitRoot({
11619
+ packmindCliHexa,
11620
+ cwd,
11621
+ log
11622
+ });
11615
11623
  return {
11616
11624
  filesCreated: result.filesCreated,
11617
11625
  filesUpdated: result.filesUpdated,
@@ -11708,7 +11716,8 @@ async function uninstallPackagesHandler(args2, deps) {
11708
11716
  let configFileExists = false;
11709
11717
  try {
11710
11718
  configFileExists = await packmindCliHexa.configExists(cwd);
11711
- configPackages = await packmindCliHexa.readConfig(cwd);
11719
+ const config = await packmindCliHexa.readConfig(cwd);
11720
+ configPackages = config.packages;
11712
11721
  } catch (err) {
11713
11722
  error("\u274C Failed to read packmind.json");
11714
11723
  if (err instanceof Error) {
@@ -11723,7 +11732,7 @@ async function uninstallPackagesHandler(args2, deps) {
11723
11732
  packagesUninstalled: []
11724
11733
  };
11725
11734
  }
11726
- if (configPackages.length === 0) {
11735
+ if (Object.keys(configPackages).length === 0) {
11727
11736
  if (configFileExists) {
11728
11737
  error("\u274C packmind.json is empty.");
11729
11738
  } else {
@@ -11739,10 +11748,10 @@ async function uninstallPackagesHandler(args2, deps) {
11739
11748
  };
11740
11749
  }
11741
11750
  const packagesToUninstall = packagesSlugs.filter(
11742
- (slug) => configPackages.includes(slug)
11751
+ (slug) => slug in configPackages
11743
11752
  );
11744
11753
  const notInstalledPackages = packagesSlugs.filter(
11745
- (slug) => !configPackages.includes(slug)
11754
+ (slug) => !(slug in configPackages)
11746
11755
  );
11747
11756
  if (notInstalledPackages.length > 0) {
11748
11757
  const packageWord = notInstalledPackages.length === 1 ? "package" : "packages";
@@ -11768,7 +11777,7 @@ async function uninstallPackagesHandler(args2, deps) {
11768
11777
  log(
11769
11778
  `Uninstalling ${packageCount} ${packageWord}: ${packagesToUninstall.join(", ")}...`
11770
11779
  );
11771
- const remainingPackages = configPackages.filter(
11780
+ const remainingPackages = Object.keys(configPackages).filter(
11772
11781
  (pkg) => !packagesToUninstall.includes(pkg)
11773
11782
  );
11774
11783
  let filesDeleted = 0;
@@ -11777,7 +11786,7 @@ async function uninstallPackagesHandler(args2, deps) {
11777
11786
  const result = await packmindCliHexa.installPackages({
11778
11787
  baseDirectory: cwd,
11779
11788
  packagesSlugs: [],
11780
- previousPackagesSlugs: configPackages
11789
+ previousPackagesSlugs: Object.keys(configPackages)
11781
11790
  });
11782
11791
  log(`
11783
11792
  removed ${result.filesDeleted} files`);
@@ -11797,7 +11806,7 @@ removed ${result.filesDeleted} files`);
11797
11806
  const result = await packmindCliHexa.installPackages({
11798
11807
  baseDirectory: cwd,
11799
11808
  packagesSlugs: remainingPackages,
11800
- previousPackagesSlugs: configPackages
11809
+ previousPackagesSlugs: Object.keys(configPackages)
11801
11810
  });
11802
11811
  if (result.recipesCount > 0 || result.standardsCount > 0) {
11803
11812
  log(
@@ -12244,10 +12253,10 @@ var AgentDetectionService = class {
12244
12253
  const continueDir = path11.join(this.projectDir, ".continue");
12245
12254
  return fs11.existsSync(continueDir);
12246
12255
  }
12247
- isCommandAvailable(command16) {
12256
+ isCommandAvailable(command20) {
12248
12257
  try {
12249
12258
  const whichCommand = process.platform === "win32" ? "where" : "which";
12250
- (0, import_child_process3.execSync)(`${whichCommand} ${command16}`, { stdio: "pipe" });
12259
+ (0, import_child_process3.execSync)(`${whichCommand} ${command20}`, { stdio: "pipe" });
12251
12260
  return true;
12252
12261
  } catch {
12253
12262
  return false;
@@ -12296,7 +12305,7 @@ async function promptAgentsWithReadline(choices) {
12296
12305
  output.write("\n");
12297
12306
  const preselected = choices.map((c, i) => c.checked ? i + 1 : null).filter((i) => i !== null);
12298
12307
  const defaultValue = preselected.length > 0 ? preselected.join(",") : "1,2,3";
12299
- return new Promise((resolve6) => {
12308
+ return new Promise((resolve7) => {
12300
12309
  rl.question(
12301
12310
  `Enter numbers separated by commas (default: ${defaultValue}): `,
12302
12311
  (answer) => {
@@ -12307,7 +12316,7 @@ async function promptAgentsWithReadline(choices) {
12307
12316
  const numbersStr = trimmed === "" ? defaultValue : trimmed;
12308
12317
  const numbers = numbersStr.split(",").map((s) => parseInt(s.trim(), 10)).filter((n) => !isNaN(n) && n >= 1 && n <= choices.length);
12309
12318
  const selectedAgents = numbers.map((n) => choices[n - 1].value);
12310
- resolve6(selectedAgents);
12319
+ resolve7(selectedAgents);
12311
12320
  }
12312
12321
  );
12313
12322
  });
@@ -12564,7 +12573,7 @@ async function listSkillsHandler(deps) {
12564
12573
  let urlBuilder = null;
12565
12574
  const apiKey = loadApiKey();
12566
12575
  if (apiKey) {
12567
- const decoded = decodeApiKey3(apiKey);
12576
+ const decoded = decodeApiKey(apiKey);
12568
12577
  const orgSlug = decoded?.jwt?.organization?.slug;
12569
12578
  if (decoded?.host && orgSlug) {
12570
12579
  urlBuilder = (slug) => buildSkillUrl(decoded.host, orgSlug, slug);
@@ -12815,7 +12824,7 @@ async function listStandardsHandler(deps) {
12815
12824
  let urlBuilder = null;
12816
12825
  const apiKey = loadApiKey();
12817
12826
  if (apiKey) {
12818
- const decoded = decodeApiKey3(apiKey);
12827
+ const decoded = decodeApiKey(apiKey);
12819
12828
  const orgSlug = decoded?.jwt?.organization?.slug;
12820
12829
  if (decoded?.host && orgSlug) {
12821
12830
  urlBuilder = (id) => buildStandardUrl(decoded.host, orgSlug, id);
@@ -12972,7 +12981,7 @@ async function createCommandHandler(filePath, useCase) {
12972
12981
  let webappUrl;
12973
12982
  const apiKey = loadApiKey();
12974
12983
  if (apiKey) {
12975
- const decoded = decodeApiKey3(apiKey);
12984
+ const decoded = decodeApiKey(apiKey);
12976
12985
  if (decoded?.host && decoded?.jwt?.organization?.slug) {
12977
12986
  webappUrl = buildWebappUrl(
12978
12987
  decoded.host,
@@ -13002,7 +13011,8 @@ var CreateCommandFromPlaybookUseCase = class {
13002
13011
  }
13003
13012
  async execute(playbook) {
13004
13013
  const space = await this.gateway.spaces.getGlobal();
13005
- const command16 = await this.gateway.commands.create(space.id, {
13014
+ const command20 = await this.gateway.commands.create({
13015
+ spaceId: space.id,
13006
13016
  name: playbook.name,
13007
13017
  summary: playbook.summary,
13008
13018
  whenToUse: playbook.whenToUse,
@@ -13014,9 +13024,9 @@ var CreateCommandFromPlaybookUseCase = class {
13014
13024
  }))
13015
13025
  });
13016
13026
  return {
13017
- commandId: command16.id,
13018
- name: command16.name,
13019
- slug: command16.slug
13027
+ commandId: command20.id,
13028
+ name: command20.name,
13029
+ slug: command20.slug
13020
13030
  };
13021
13031
  }
13022
13032
  };
@@ -13084,7 +13094,7 @@ async function listCommandsHandler(deps) {
13084
13094
  let urlBuilder = null;
13085
13095
  const apiKey = loadApiKey();
13086
13096
  if (apiKey) {
13087
- const decoded = decodeApiKey3(apiKey);
13097
+ const decoded = decodeApiKey(apiKey);
13088
13098
  const orgSlug = decoded?.jwt?.organization?.slug;
13089
13099
  if (decoded?.host && orgSlug) {
13090
13100
  urlBuilder = (id) => buildCommandUrl(decoded.host, orgSlug, id);
@@ -13143,7 +13153,7 @@ var commandsCommand = (0, import_cmd_ts17.subcommands)({
13143
13153
  });
13144
13154
 
13145
13155
  // apps/cli/src/infra/commands/PackagesCommand.ts
13146
- var import_cmd_ts19 = __toESM(require_cjs());
13156
+ var import_cmd_ts21 = __toESM(require_cjs());
13147
13157
 
13148
13158
  // apps/cli/src/infra/commands/CreatePackageCommand.ts
13149
13159
  var import_cmd_ts18 = __toESM(require_cjs());
@@ -13165,7 +13175,7 @@ async function createPackageHandler(name, description, useCase) {
13165
13175
  let webappUrl;
13166
13176
  const apiKey = loadApiKey();
13167
13177
  if (apiKey) {
13168
- const decoded = decodeApiKey3(apiKey);
13178
+ const decoded = decodeApiKey(apiKey);
13169
13179
  if (decoded?.host && decoded?.jwt?.organization?.slug) {
13170
13180
  webappUrl = buildWebappUrl2(
13171
13181
  decoded.host,
@@ -13194,16 +13204,19 @@ var CreatePackageUseCase = class {
13194
13204
  constructor(gateway) {
13195
13205
  this.gateway = gateway;
13196
13206
  }
13197
- async execute(command16) {
13207
+ async execute(command20) {
13198
13208
  const space = await this.gateway.spaces.getGlobal();
13199
- const result = await this.gateway.packages.create(space.id, {
13200
- name: command16.name,
13201
- description: command16.description
13209
+ const result = await this.gateway.packages.create({
13210
+ spaceId: space.id,
13211
+ name: command20.name,
13212
+ description: command20.description ?? "",
13213
+ recipeIds: [],
13214
+ standardIds: []
13202
13215
  });
13203
13216
  return {
13204
- packageId: result.id,
13205
- name: result.name,
13206
- slug: result.slug
13217
+ packageId: result.package.id,
13218
+ name: result.package.name,
13219
+ slug: result.package.slug
13207
13220
  };
13208
13221
  }
13209
13222
  };
@@ -13264,35 +13277,503 @@ var createPackageCommand = (0, import_cmd_ts18.command)({
13264
13277
  }
13265
13278
  });
13266
13279
 
13280
+ // apps/cli/src/infra/commands/AddToPackageCommand.ts
13281
+ var import_cmd_ts19 = __toESM(require_cjs());
13282
+
13283
+ // apps/cli/src/domain/errors/ItemNotFoundError.ts
13284
+ var ItemNotFoundError = class extends Error {
13285
+ constructor(itemType, slug) {
13286
+ super(`${itemType} '${slug}' not found`);
13287
+ this.itemType = itemType;
13288
+ this.slug = slug;
13289
+ this.name = "ItemNotFoundError";
13290
+ }
13291
+ };
13292
+
13293
+ // apps/cli/src/application/useCases/AddToPackageUseCase.ts
13294
+ var AddToPackageUseCase = class {
13295
+ constructor(gateway) {
13296
+ this.gateway = gateway;
13297
+ }
13298
+ async execute(command20) {
13299
+ const { packageSlug, itemType, itemSlugs } = command20;
13300
+ const space = await this.gateway.spaces.getGlobal();
13301
+ const packages = await this.gateway.packages.list({});
13302
+ const pkg = packages.packages.find((pkg2) => pkg2.slug === packageSlug);
13303
+ if (!pkg) {
13304
+ throw new ItemNotFoundError("package", packageSlug);
13305
+ }
13306
+ const { ids, idToSlugMap } = await this.resolveSlugsToIds(
13307
+ itemType,
13308
+ itemSlugs
13309
+ );
13310
+ const addCommand = {
13311
+ packageId: pkg.id,
13312
+ spaceId: space.id,
13313
+ standardIds: [],
13314
+ recipeIds: [],
13315
+ skillIds: []
13316
+ };
13317
+ if (itemType === "standard") {
13318
+ addCommand.standardIds = ids.map(createStandardId);
13319
+ } else if (itemType === "command") {
13320
+ addCommand.recipeIds = ids.map(createRecipeId);
13321
+ } else if (itemType === "skill") {
13322
+ addCommand.skillIds = ids.map(createSkillId);
13323
+ }
13324
+ const result = await this.gateway.packages.addArtefacts(addCommand);
13325
+ const typeKey = itemType === "command" ? "commands" : `${itemType}s`;
13326
+ const addedIds = result.added[typeKey];
13327
+ const skippedIds = result.skipped[typeKey];
13328
+ return {
13329
+ added: addedIds.map((id) => idToSlugMap.get(id) ?? id),
13330
+ skipped: skippedIds.map((id) => idToSlugMap.get(id) ?? id)
13331
+ };
13332
+ }
13333
+ async resolveSlugsToIds(itemType, slugs) {
13334
+ const ids = [];
13335
+ const idToSlugMap = /* @__PURE__ */ new Map();
13336
+ const globalSpace = await this.gateway.spaces.getGlobal();
13337
+ for (const slug of slugs) {
13338
+ let item = null;
13339
+ if (itemType === "standard") {
13340
+ item = await this.findStandardBySlug(slug, globalSpace.id);
13341
+ } else if (itemType === "command") {
13342
+ item = await this.findCommandBySlug(slug, globalSpace.id);
13343
+ } else if (itemType === "skill") {
13344
+ item = await this.findSkillBySlug(slug, globalSpace.id);
13345
+ }
13346
+ if (!item) {
13347
+ throw new ItemNotFoundError(itemType, slug);
13348
+ }
13349
+ ids.push(item.id);
13350
+ idToSlugMap.set(item.id, slug);
13351
+ }
13352
+ return { ids, idToSlugMap };
13353
+ }
13354
+ async findStandardBySlug(slug, spaceId) {
13355
+ const standards = await this.gateway.standards.list({ spaceId });
13356
+ return standards.standards.find((skill) => skill.slug === slug) ?? null;
13357
+ }
13358
+ async findCommandBySlug(slug, spaceId) {
13359
+ const commands = await this.gateway.commands.list({ spaceId });
13360
+ return commands.recipes.find((command20) => command20.slug === slug) ?? null;
13361
+ }
13362
+ async findSkillBySlug(slug, spaceId) {
13363
+ const skills = await this.gateway.skills.list({ spaceId });
13364
+ return skills.find((skill) => skill.slug === slug) ?? null;
13365
+ }
13366
+ };
13367
+
13368
+ // apps/cli/src/infra/commands/addToPackageHandler.ts
13369
+ function pluralize(singular, count) {
13370
+ return count === 1 ? singular : `${singular}s`;
13371
+ }
13372
+ function formatItemType(itemType, count) {
13373
+ return pluralize(itemType.charAt(0).toUpperCase() + itemType.slice(1), count);
13374
+ }
13375
+ function formatItemList(items) {
13376
+ return items.map((item) => `"${item}"`).join(", ");
13377
+ }
13378
+ async function addToPackageHandler(packageSlug, itemType, itemSlugs, useCase) {
13379
+ if (itemSlugs.length === 0) {
13380
+ return { success: false, error: "No items provided to add" };
13381
+ }
13382
+ try {
13383
+ const result = await useCase.execute({ packageSlug, itemType, itemSlugs });
13384
+ if (result.added.length) {
13385
+ logSuccessConsole(
13386
+ `${formatItemType(itemType, result.added.length)} ${formatItemList(result.added)} added to "${packageSlug}"`
13387
+ );
13388
+ logSuccessConsole(
13389
+ `Run \`packmind-cli install ${packageSlug}\` to install the ${pluralize(itemType, result.added.length)}`
13390
+ );
13391
+ }
13392
+ if (result.skipped.length) {
13393
+ logWarningConsole(
13394
+ `${formatItemType(itemType, result.skipped.length)} ${formatItemList(result.skipped)} already in "${packageSlug}" (skipped)`
13395
+ );
13396
+ }
13397
+ return { success: true, added: result.added, skipped: result.skipped };
13398
+ } catch (error) {
13399
+ const message = error instanceof Error ? error.message : String(error);
13400
+ logErrorConsole(message);
13401
+ if (error instanceof ItemNotFoundError) {
13402
+ logInfoConsole(
13403
+ `Run \`packmind-cli ${error.itemType}s list\` to display available ${error.itemType}s`
13404
+ );
13405
+ }
13406
+ return { success: false, error: message };
13407
+ }
13408
+ }
13409
+
13410
+ // apps/cli/src/infra/commands/AddToPackageCommand.ts
13411
+ var addToPackageCommand = (0, import_cmd_ts19.command)({
13412
+ name: "add",
13413
+ description: "Add standards, commands, or skills to a package",
13414
+ args: {
13415
+ to: (0, import_cmd_ts19.option)({
13416
+ long: "to",
13417
+ description: "Target package slug",
13418
+ type: import_cmd_ts19.string
13419
+ }),
13420
+ standards: (0, import_cmd_ts19.multioption)({
13421
+ long: "standard",
13422
+ description: "Standard slug(s) to add",
13423
+ type: (0, import_cmd_ts19.array)(import_cmd_ts19.string)
13424
+ }),
13425
+ commands: (0, import_cmd_ts19.multioption)({
13426
+ long: "command",
13427
+ description: "Command slug(s) to add",
13428
+ type: (0, import_cmd_ts19.array)(import_cmd_ts19.string)
13429
+ }),
13430
+ skills: (0, import_cmd_ts19.multioption)({
13431
+ long: "skill",
13432
+ description: "Skill slug(s) to add",
13433
+ type: (0, import_cmd_ts19.array)(import_cmd_ts19.string)
13434
+ })
13435
+ },
13436
+ handler: async ({ to, standards, commands, skills }) => {
13437
+ const standardSlugs = standards ?? [];
13438
+ const commandSlugs = commands ?? [];
13439
+ const skillSlugs = skills ?? [];
13440
+ const itemTypes = [
13441
+ { type: "standard", slugs: standardSlugs },
13442
+ { type: "command", slugs: commandSlugs },
13443
+ { type: "skill", slugs: skillSlugs }
13444
+ ].filter((t) => t.slugs.length > 0);
13445
+ if (itemTypes.length === 0) {
13446
+ logErrorConsole(
13447
+ "Error: At least one --standard, --command, or --skill is required"
13448
+ );
13449
+ process.exit(1);
13450
+ }
13451
+ if (itemTypes.length > 1) {
13452
+ logErrorConsole(
13453
+ "Cannot add standards, commands, and skills simultaneously. Use dedicated commands for each artefact."
13454
+ );
13455
+ process.exit(1);
13456
+ }
13457
+ const { type: itemType, slugs: itemSlugs } = itemTypes[0];
13458
+ const packmindLogger = new PackmindLogger("PackmindCLI", "info" /* INFO */);
13459
+ const hexa = new PackmindCliHexa(packmindLogger);
13460
+ const gateway = hexa.getPackmindGateway();
13461
+ const useCase = new AddToPackageUseCase(gateway);
13462
+ const result = await addToPackageHandler(to, itemType, itemSlugs, useCase);
13463
+ if (!result.success) {
13464
+ process.exit(1);
13465
+ }
13466
+ }
13467
+ });
13468
+
13469
+ // apps/cli/src/infra/commands/listPackagesCommand.ts
13470
+ var import_cmd_ts20 = __toESM(require_cjs());
13471
+ var listPackagesCommand = (0, import_cmd_ts20.command)({
13472
+ name: "list",
13473
+ description: "List available packages",
13474
+ args: {},
13475
+ handler: async () => {
13476
+ const packmindLogger = new PackmindLogger("PackmindCLI", "info" /* INFO */);
13477
+ const packmindCliHexa = new PackmindCliHexa(packmindLogger);
13478
+ const deps = {
13479
+ packmindCliHexa,
13480
+ exit: process.exit,
13481
+ getCwd: () => process.cwd(),
13482
+ log: console.log,
13483
+ error: console.error
13484
+ };
13485
+ await listPackagesHandler({}, deps);
13486
+ }
13487
+ });
13488
+
13267
13489
  // apps/cli/src/infra/commands/PackagesCommand.ts
13268
- var packagesCommand = (0, import_cmd_ts19.subcommands)({
13490
+ var packagesCommand = (0, import_cmd_ts21.subcommands)({
13269
13491
  name: "packages",
13270
13492
  description: "Manage packages",
13271
13493
  cmds: {
13272
- create: createPackageCommand
13494
+ create: createPackageCommand,
13495
+ add: addToPackageCommand,
13496
+ list: listPackagesCommand
13273
13497
  }
13274
13498
  });
13275
13499
 
13276
- // apps/cli/src/main.ts
13500
+ // apps/cli/src/infra/commands/config/ConfigCommand.ts
13501
+ var import_cmd_ts23 = __toESM(require_cjs());
13502
+
13503
+ // apps/cli/src/infra/commands/config/ConfigAgentsCommand.ts
13504
+ var import_cmd_ts22 = __toESM(require_cjs());
13505
+
13506
+ // apps/cli/src/application/services/AgentArtifactDetectionService.ts
13507
+ var fs15 = __toESM(require("fs/promises"));
13508
+ var path12 = __toESM(require("path"));
13509
+ var AGENT_ARTIFACT_CHECKS = [
13510
+ { agent: "claude", paths: [".claude"] },
13511
+ { agent: "cursor", paths: [".cursor"] },
13512
+ {
13513
+ agent: "copilot",
13514
+ paths: [".github/copilot-instructions.md", ".github/instructions"]
13515
+ },
13516
+ { agent: "continue", paths: [".continue"] },
13517
+ { agent: "junie", paths: [".junie", ".junie.md"] },
13518
+ { agent: "agents_md", paths: ["AGENTS.md"] },
13519
+ { agent: "gitlab_duo", paths: [".gitlab"] }
13520
+ ];
13521
+ var AgentArtifactDetectionService = class {
13522
+ async detectAgentArtifacts(baseDirectory) {
13523
+ const detected = [];
13524
+ for (const check of AGENT_ARTIFACT_CHECKS) {
13525
+ for (const relativePath of check.paths) {
13526
+ const fullPath = path12.join(baseDirectory, relativePath);
13527
+ const exists = await this.pathExists(fullPath);
13528
+ if (exists) {
13529
+ detected.push({
13530
+ agent: check.agent,
13531
+ artifactPath: fullPath
13532
+ });
13533
+ break;
13534
+ }
13535
+ }
13536
+ }
13537
+ return detected;
13538
+ }
13539
+ async pathExists(filePath) {
13540
+ try {
13541
+ await fs15.access(filePath);
13542
+ return true;
13543
+ } catch {
13544
+ return false;
13545
+ }
13546
+ }
13547
+ };
13548
+
13549
+ // apps/cli/src/infra/commands/config/configAgentsHandler.ts
13550
+ var readline3 = __toESM(require("readline"));
13551
+ var inquirer2 = __toESM(require("inquirer"));
13552
+ var SELECTABLE_AGENTS = [
13553
+ "claude",
13554
+ "cursor",
13555
+ "copilot",
13556
+ "agents_md",
13557
+ "continue",
13558
+ "junie",
13559
+ "gitlab_duo"
13560
+ ];
13561
+ var AGENT_DISPLAY_NAMES = {
13562
+ packmind: "Packmind",
13563
+ claude: "Claude Code",
13564
+ cursor: "Cursor",
13565
+ copilot: "GitHub Copilot",
13566
+ continue: "Continue.dev",
13567
+ junie: "Junie",
13568
+ agents_md: "AGENTS.md",
13569
+ gitlab_duo: "GitLab Duo"
13570
+ };
13571
+ async function promptAgentsWithReadline2(choices) {
13572
+ const input = process.stdin;
13573
+ const output = process.stdout;
13574
+ const rl = readline3.createInterface({
13575
+ input,
13576
+ output
13577
+ });
13578
+ output.write("\nSelect coding agents to generate artifacts for:\n");
13579
+ choices.forEach((choice, index) => {
13580
+ const marker = choice.checked ? "*" : " ";
13581
+ output.write(` ${index + 1}. [${marker}] ${choice.name}
13582
+ `);
13583
+ });
13584
+ output.write("\n");
13585
+ const preselected = choices.map((c, i) => c.checked ? i + 1 : null).filter((i) => i !== null);
13586
+ const defaultValue = preselected.length > 0 ? preselected.join(",") : "1,2,3";
13587
+ return new Promise((resolve7) => {
13588
+ rl.question(
13589
+ `Enter numbers separated by commas (default: ${defaultValue}): `,
13590
+ (answer) => {
13591
+ rl.close();
13592
+ const trimmed = answer.trim();
13593
+ const numbersStr = trimmed === "" ? defaultValue : trimmed;
13594
+ const numbers = numbersStr.split(",").map((s) => parseInt(s.trim(), 10)).filter((n) => !isNaN(n) && n >= 1 && n <= choices.length);
13595
+ const selectedAgents = numbers.map((n) => choices[n - 1].value);
13596
+ resolve7(selectedAgents);
13597
+ }
13598
+ );
13599
+ });
13600
+ }
13601
+ async function configAgentsHandler(deps) {
13602
+ const { configRepository, agentDetectionService, baseDirectory } = deps;
13603
+ const isTTY = deps.isTTY ?? process.stdin.isTTY;
13604
+ const useSimplePrompt = process.env.PACKMIND_SIMPLE_PROMPT === "1" || !isTTY;
13605
+ const existingConfig = await configRepository.readConfig(baseDirectory);
13606
+ let preselectedAgents;
13607
+ if (existingConfig?.agents && existingConfig.agents.length > 0) {
13608
+ preselectedAgents = new Set(
13609
+ existingConfig.agents.filter(
13610
+ (agent) => SELECTABLE_AGENTS.includes(agent)
13611
+ )
13612
+ );
13613
+ } else {
13614
+ const detectedArtifacts = await agentDetectionService.detectAgentArtifacts(baseDirectory);
13615
+ preselectedAgents = new Set(detectedArtifacts.map((a) => a.agent));
13616
+ }
13617
+ const choices = SELECTABLE_AGENTS.map((agent) => ({
13618
+ name: AGENT_DISPLAY_NAMES[agent],
13619
+ value: agent,
13620
+ checked: preselectedAgents.has(agent)
13621
+ }));
13622
+ let selectedAgents;
13623
+ if (useSimplePrompt) {
13624
+ selectedAgents = await promptAgentsWithReadline2(choices);
13625
+ } else {
13626
+ const result = await inquirer2.default.prompt([
13627
+ {
13628
+ type: "checkbox",
13629
+ name: "selectedAgents",
13630
+ message: "Select coding agents to generate artifacts for:",
13631
+ choices
13632
+ }
13633
+ ]);
13634
+ selectedAgents = result.selectedAgents;
13635
+ }
13636
+ await configRepository.updateAgentsConfig(baseDirectory, selectedAgents);
13637
+ const agentNames = selectedAgents.map((a) => AGENT_DISPLAY_NAMES[a]);
13638
+ if (selectedAgents.length === 0) {
13639
+ logInfoConsole(
13640
+ "No agents selected. Only packmind artifacts will be generated."
13641
+ );
13642
+ } else {
13643
+ logSuccessConsole(
13644
+ `Configuration saved. Artifacts will be generated for: ${agentNames.join(", ")}`
13645
+ );
13646
+ }
13647
+ }
13648
+
13649
+ // apps/cli/src/infra/commands/config/ConfigAgentsCommand.ts
13650
+ var configAgentsCommand = (0, import_cmd_ts22.command)({
13651
+ name: "agents",
13652
+ description: "Configure which coding agents to generate artifacts for",
13653
+ args: {},
13654
+ handler: async () => {
13655
+ const configRepository = new ConfigFileRepository();
13656
+ const agentDetectionService = new AgentArtifactDetectionService();
13657
+ const baseDirectory = process.cwd();
13658
+ await configAgentsHandler({
13659
+ configRepository,
13660
+ agentDetectionService,
13661
+ baseDirectory
13662
+ });
13663
+ }
13664
+ });
13665
+
13666
+ // apps/cli/src/infra/commands/config/ConfigCommand.ts
13667
+ var configCommand = (0, import_cmd_ts23.subcommands)({
13668
+ name: "config",
13669
+ description: "Manage Packmind configuration",
13670
+ cmds: {
13671
+ agents: configAgentsCommand
13672
+ }
13673
+ });
13674
+
13675
+ // apps/cli/src/infra/commands/InitCommand.ts
13676
+ var import_cmd_ts24 = __toESM(require_cjs());
13677
+
13678
+ // apps/cli/src/infra/commands/initHandler.ts
13679
+ async function initHandler(deps) {
13680
+ const {
13681
+ configRepository,
13682
+ agentDetectionService,
13683
+ baseDirectory,
13684
+ installDefaultSkills,
13685
+ cliVersion,
13686
+ isTTY
13687
+ } = deps;
13688
+ const configAgentsDeps = {
13689
+ configRepository,
13690
+ agentDetectionService,
13691
+ baseDirectory,
13692
+ isTTY
13693
+ };
13694
+ await configAgentsHandler(configAgentsDeps);
13695
+ logInfoConsole("Installing default skills...");
13696
+ const result = await installDefaultSkills({
13697
+ includeBeta: false,
13698
+ cliVersion
13699
+ });
13700
+ if (result.errors.length > 0) {
13701
+ return {
13702
+ success: false,
13703
+ errors: result.errors
13704
+ };
13705
+ }
13706
+ const totalFiles = result.filesCreated + result.filesUpdated;
13707
+ if (totalFiles === 0) {
13708
+ logInfoConsole("Default skills are already up to date.");
13709
+ } else {
13710
+ logSuccessConsole("Default skills installed successfully!");
13711
+ if (result.filesCreated > 0) {
13712
+ logInfoConsole(` Files created: ${result.filesCreated}`);
13713
+ }
13714
+ if (result.filesUpdated > 0) {
13715
+ logInfoConsole(` Files updated: ${result.filesUpdated}`);
13716
+ }
13717
+ }
13718
+ logConsole("");
13719
+ logSuccessConsole("Packmind initialized successfully!");
13720
+ logInfoConsole(
13721
+ `Next step: Run ${formatCommand("/packmind-onboard")} in your AI agent to onboard the project`
13722
+ );
13723
+ return {
13724
+ success: true,
13725
+ errors: []
13726
+ };
13727
+ }
13728
+
13729
+ // apps/cli/src/infra/commands/InitCommand.ts
13277
13730
  var { version: CLI_VERSION3 } = require_package();
13731
+ var initCommand = (0, import_cmd_ts24.command)({
13732
+ name: "init",
13733
+ description: "Initialize Packmind in the current project",
13734
+ args: {},
13735
+ handler: async () => {
13736
+ const packmindLogger = new PackmindLogger("PackmindCLI", "info" /* INFO */);
13737
+ const packmindCliHexa = new PackmindCliHexa(packmindLogger);
13738
+ const configRepository = new ConfigFileRepository();
13739
+ const agentDetectionService = new AgentArtifactDetectionService();
13740
+ const baseDirectory = process.cwd();
13741
+ const result = await initHandler({
13742
+ configRepository,
13743
+ agentDetectionService,
13744
+ baseDirectory,
13745
+ installDefaultSkills: packmindCliHexa.installDefaultSkills.bind(packmindCliHexa),
13746
+ cliVersion: CLI_VERSION3
13747
+ });
13748
+ if (!result.success) {
13749
+ for (const error of result.errors) {
13750
+ logErrorConsole(`Error: ${error}`);
13751
+ }
13752
+ process.exit(1);
13753
+ }
13754
+ }
13755
+ });
13756
+
13757
+ // apps/cli/src/main.ts
13758
+ var { version: CLI_VERSION4 } = require_package();
13278
13759
  function findEnvFile() {
13279
13760
  const currentDir = process.cwd();
13280
13761
  const gitService = new GitService();
13281
13762
  const gitRoot = gitService.getGitRepositoryRootSync(currentDir);
13282
- const filesystemRoot = path12.parse(currentDir).root;
13763
+ const filesystemRoot = path13.parse(currentDir).root;
13283
13764
  const stopDir = gitRoot ?? filesystemRoot;
13284
13765
  let searchDir = currentDir;
13285
- let parentDir = path12.dirname(searchDir);
13766
+ let parentDir = path13.dirname(searchDir);
13286
13767
  while (searchDir !== parentDir) {
13287
- const envPath2 = path12.join(searchDir, ".env");
13288
- if (fs15.existsSync(envPath2)) {
13768
+ const envPath2 = path13.join(searchDir, ".env");
13769
+ if (fs16.existsSync(envPath2)) {
13289
13770
  return envPath2;
13290
13771
  }
13291
13772
  if (searchDir === stopDir) {
13292
13773
  return null;
13293
13774
  }
13294
13775
  searchDir = parentDir;
13295
- parentDir = path12.dirname(searchDir);
13776
+ parentDir = path13.dirname(searchDir);
13296
13777
  }
13297
13778
  return null;
13298
13779
  }
@@ -13309,29 +13790,31 @@ if (hasEmbeddedWasmFiles()) {
13309
13790
  }
13310
13791
  var args = process.argv.slice(2);
13311
13792
  if (args.includes("--version") || args.includes("-v")) {
13312
- logConsole(`packmind-cli version ${CLI_VERSION3}`);
13793
+ logConsole(`packmind-cli version ${CLI_VERSION4}`);
13313
13794
  process.exit(0);
13314
13795
  }
13315
- var app = (0, import_cmd_ts20.subcommands)({
13796
+ var app = (0, import_cmd_ts25.subcommands)({
13316
13797
  name: "packmind-cli",
13317
13798
  description: "Packmind CLI tool",
13318
13799
  cmds: {
13319
- lint: lintCommand,
13800
+ commands: commandsCommand,
13801
+ config: configCommand,
13802
+ init: initCommand,
13320
13803
  install: installCommand,
13321
- uninstall: uninstallCommand,
13322
- remove: uninstallCommand,
13323
- // Alias for uninstall
13804
+ lint: lintCommand,
13324
13805
  login: loginCommand,
13325
13806
  logout: logoutCommand,
13326
- whoami: whoamiCommand,
13807
+ packages: packagesCommand,
13808
+ remove: uninstallCommand,
13809
+ // Alias for uninstall
13327
13810
  "setup-mcp": setupMcpCommand,
13328
13811
  skills: skillsCommand,
13329
13812
  standards: standardsCommand,
13330
- commands: commandsCommand,
13331
- packages: packagesCommand
13813
+ uninstall: uninstallCommand,
13814
+ whoami: whoamiCommand
13332
13815
  }
13333
13816
  });
13334
- (0, import_cmd_ts20.run)(app, args).catch((error) => {
13817
+ (0, import_cmd_ts25.run)(app, args).catch((error) => {
13335
13818
  logErrorConsole(error.message);
13336
13819
  process.exit(1);
13337
13820
  });