@packmind/cli 0.13.1 → 0.14.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 +1125 -288
  2. package/package.json +3 -2
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(string6, substring, replacer) {
375
- let index = string6.indexOf(substring);
374
+ function stringReplaceAll(string8, substring, replacer) {
375
+ let index = string8.indexOf(substring);
376
376
  if (index === -1) {
377
- return string6;
377
+ return string8;
378
378
  }
379
379
  const substringLength = substring.length;
380
380
  let endIndex = 0;
381
381
  let returnValue = "";
382
382
  do {
383
- returnValue += string6.slice(endIndex, index) + substring + replacer;
383
+ returnValue += string8.slice(endIndex, index) + substring + replacer;
384
384
  endIndex = index + substringLength;
385
- index = string6.indexOf(substring, endIndex);
385
+ index = string8.indexOf(substring, endIndex);
386
386
  } while (index !== -1);
387
- returnValue += string6.slice(endIndex);
387
+ returnValue += string8.slice(endIndex);
388
388
  return returnValue;
389
389
  }
390
- function stringEncaseCRLFWithFirstIndex(string6, prefix, postfix, index) {
390
+ function stringEncaseCRLFWithFirstIndex(string8, prefix, postfix, index) {
391
391
  let endIndex = 0;
392
392
  let returnValue = "";
393
393
  do {
394
- const gotCR = string6[index - 1] === "\r";
395
- returnValue += string6.slice(endIndex, gotCR ? index - 1 : index) + prefix + (gotCR ? "\r\n" : "\n") + postfix;
394
+ const gotCR = string8[index - 1] === "\r";
395
+ returnValue += string8.slice(endIndex, gotCR ? index - 1 : index) + prefix + (gotCR ? "\r\n" : "\n") + postfix;
396
396
  endIndex = index + 1;
397
- index = string6.indexOf("\n", endIndex);
397
+ index = string8.indexOf("\n", endIndex);
398
398
  } while (index !== -1);
399
- returnValue += string6.slice(endIndex);
399
+ returnValue += string8.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, string6) => {
559
- if (self.level <= 0 || !string6) {
560
- return self[IS_EMPTY] ? "" : string6;
558
+ applyStyle = (self, string8) => {
559
+ if (self.level <= 0 || !string8) {
560
+ return self[IS_EMPTY] ? "" : string8;
561
561
  }
562
562
  let styler = self[STYLER];
563
563
  if (styler === void 0) {
564
- return string6;
564
+ return string8;
565
565
  }
566
566
  const { openAll, closeAll } = styler;
567
- if (string6.includes("\x1B")) {
567
+ if (string8.includes("\x1B")) {
568
568
  while (styler !== void 0) {
569
- string6 = stringReplaceAll(string6, styler.close, styler.open);
569
+ string8 = stringReplaceAll(string8, styler.close, styler.open);
570
570
  styler = styler.parent;
571
571
  }
572
572
  }
573
- const lfIndex = string6.indexOf("\n");
573
+ const lfIndex = string8.indexOf("\n");
574
574
  if (lfIndex !== -1) {
575
- string6 = stringEncaseCRLFWithFirstIndex(string6, closeAll, openAll, lfIndex);
575
+ string8 = stringEncaseCRLFWithFirstIndex(string8, closeAll, openAll, lfIndex);
576
576
  }
577
- return openAll + string6 + closeAll;
577
+ return openAll + string8 + closeAll;
578
578
  };
579
579
  Object.defineProperties(createChalk.prototype, styles2);
580
580
  chalk = createChalk();
@@ -1255,7 +1255,7 @@ var require_positional = __commonJS({
1255
1255
  return mod && mod.__esModule ? mod : { "default": mod };
1256
1256
  };
1257
1257
  Object.defineProperty(exports2, "__esModule", { value: true });
1258
- exports2.positional = positional3;
1258
+ exports2.positional = positional5;
1259
1259
  var chalk_1 = __importDefault((init_source(), __toCommonJS(source_exports)));
1260
1260
  var Result = __importStar(require_Result());
1261
1261
  var types_1 = require_types();
@@ -1295,8 +1295,8 @@ var require_positional = __commonJS({
1295
1295
  var _a2;
1296
1296
  const positionals = nodes.filter((node) => node.type === "positionalArgument" && !visitedNodes.has(node));
1297
1297
  const defaultValueFn = (_a2 = config.defaultValue) !== null && _a2 !== void 0 ? _a2 : config.type.defaultValue;
1298
- const positional4 = positionals[0];
1299
- if (!positional4) {
1298
+ const positional6 = positionals[0];
1299
+ if (!positional6) {
1300
1300
  if (defaultValueFn) {
1301
1301
  return Result.ok(defaultValueFn());
1302
1302
  }
@@ -1309,13 +1309,13 @@ var require_positional = __commonJS({
1309
1309
  ]
1310
1310
  });
1311
1311
  }
1312
- visitedNodes.add(positional4);
1313
- const decoded = await Result.safeAsync(config.type.from(positional4.raw));
1312
+ visitedNodes.add(positional6);
1313
+ const decoded = await Result.safeAsync(config.type.from(positional6.raw));
1314
1314
  if (Result.isErr(decoded)) {
1315
1315
  return Result.err({
1316
1316
  errors: [
1317
1317
  {
1318
- nodes: [positional4],
1318
+ nodes: [positional6],
1319
1319
  message: decoded.error.message
1320
1320
  }
1321
1321
  ]
@@ -1325,7 +1325,7 @@ var require_positional = __commonJS({
1325
1325
  }
1326
1326
  };
1327
1327
  }
1328
- function positional3(config) {
1328
+ function positional5(config) {
1329
1329
  return fullPositional({
1330
1330
  type: types_1.string,
1331
1331
  ...config
@@ -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 = subcommands3;
1382
+ exports2.subcommands = subcommands5;
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 subcommands3(config) {
1388
+ function subcommands5(config) {
1389
1389
  const circuitbreaker = (0, circuitbreaker_1.createCircuitBreaker)(!!config.version);
1390
1390
  const type = {
1391
1391
  async from(str) {
@@ -1578,11 +1578,11 @@ var strip_ansi_exports = {};
1578
1578
  __export(strip_ansi_exports, {
1579
1579
  default: () => stripAnsi
1580
1580
  });
1581
- function stripAnsi(string6) {
1582
- if (typeof string6 !== "string") {
1583
- throw new TypeError(`Expected a \`string\`, got \`${typeof string6}\``);
1581
+ function stripAnsi(string8) {
1582
+ if (typeof string8 !== "string") {
1583
+ throw new TypeError(`Expected a \`string\`, got \`${typeof string8}\``);
1584
1584
  }
1585
- return string6.replace(regex, "");
1585
+ return string8.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 = command9;
1701
+ exports2.command = command12;
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 command9(config) {
1706
+ function command12(config) {
1707
1707
  const argEntries = (0, utils_1.entries)(config.args);
1708
1708
  const circuitbreaker = (0, circuitbreaker_1.createCircuitBreaker)(!!config.version);
1709
1709
  return {
@@ -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, string6] of (0, utils_1.enumerate)(strings)) {
3088
- const chars = [...string6];
3087
+ for (const [stringIndex, string8] of (0, utils_1.enumerate)(strings)) {
3088
+ const chars = [...string8];
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 });
@@ -3241,14 +3241,14 @@ var require_restPositionals = __commonJS({
3241
3241
  const positionals = nodes.filter((node) => node.type === "positionalArgument" && !visitedNodes.has(node));
3242
3242
  const results = [];
3243
3243
  const errors = [];
3244
- for (const positional3 of positionals) {
3245
- visitedNodes.add(positional3);
3246
- const decoded = await Result.safeAsync(config.type.from(positional3.raw));
3244
+ for (const positional5 of positionals) {
3245
+ visitedNodes.add(positional5);
3246
+ const decoded = await Result.safeAsync(config.type.from(positional5.raw));
3247
3247
  if (Result.isOk(decoded)) {
3248
3248
  results.push(decoded.value);
3249
3249
  } else {
3250
3250
  errors.push({
3251
- nodes: [positional3],
3251
+ nodes: [positional5],
3252
3252
  message: decoded.error.message
3253
3253
  });
3254
3254
  }
@@ -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.13.1",
3855
+ version: "0.14.0",
3856
3856
  description: "A command-line interface for Packmind linting and code quality checks",
3857
3857
  private: false,
3858
3858
  bin: {
@@ -3887,14 +3887,15 @@ var require_package = __commonJS({
3887
3887
  },
3888
3888
  dependencies: {
3889
3889
  "@types/inquirer": "^9.0.9",
3890
- inquirer: "^13.0.2"
3890
+ inquirer: "^13.0.2",
3891
+ zod: "^4.3.5"
3891
3892
  }
3892
3893
  };
3893
3894
  }
3894
3895
  });
3895
3896
 
3896
3897
  // apps/cli/src/main.ts
3897
- var import_cmd_ts10 = __toESM(require_cjs());
3898
+ var import_cmd_ts15 = __toESM(require_cjs());
3898
3899
 
3899
3900
  // apps/cli/src/infra/commands/LinterCommand.ts
3900
3901
  var import_cmd_ts = __toESM(require_cjs());
@@ -4048,6 +4049,13 @@ var AnonymousTrialAccountActivatedEvent = class extends UserEvent {
4048
4049
  }
4049
4050
  };
4050
4051
 
4052
+ // packages/types/src/accounts/events/OrganizationCreatedEvent.ts
4053
+ var OrganizationCreatedEvent = class extends UserEvent {
4054
+ static {
4055
+ this.eventName = "accounts.organization.created";
4056
+ }
4057
+ };
4058
+
4051
4059
  // packages/types/src/accounts/TrialActivationToken.ts
4052
4060
  var createTrialActivationTokenId = brandedIdFactory();
4053
4061
  var createTrialActivationToken = brandedIdFactory();
@@ -4735,6 +4743,17 @@ function createUserContextChangeEvent(userId, organizationId, changeType, role)
4735
4743
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
4736
4744
  };
4737
4745
  }
4746
+ function createDistributionStatusChangeEvent(distributionId, status, organizationId) {
4747
+ return {
4748
+ type: "DISTRIBUTION_STATUS_CHANGE",
4749
+ data: {
4750
+ distributionId,
4751
+ status,
4752
+ organizationId
4753
+ },
4754
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
4755
+ };
4756
+ }
4738
4757
 
4739
4758
  // apps/cli/src/application/useCases/ExecuteSingleFileAstUseCase.ts
4740
4759
  var ExecuteSingleFileAstUseCase = class _ExecuteSingleFileAstUseCase {
@@ -4747,8 +4766,8 @@ var ExecuteSingleFileAstUseCase = class _ExecuteSingleFileAstUseCase {
4747
4766
  static {
4748
4767
  this.fallbackRuleContent = "adhoc-rule";
4749
4768
  }
4750
- async execute(command9) {
4751
- const { program, fileContent, language } = command9;
4769
+ async execute(command12) {
4770
+ const { program, fileContent, language } = command12;
4752
4771
  const result = await this.linterExecutionUseCase.execute({
4753
4772
  filePath: "cli-single-file",
4754
4773
  fileContent,
@@ -4798,30 +4817,30 @@ var GitService = class {
4798
4817
  this.gitRunner = gitRunner;
4799
4818
  this.logger = logger2;
4800
4819
  }
4801
- getGitRepositoryRoot(path12) {
4820
+ getGitRepositoryRoot(path13) {
4802
4821
  try {
4803
4822
  const { stdout } = this.gitRunner("rev-parse --show-toplevel", {
4804
- cwd: path12
4823
+ cwd: path13
4805
4824
  });
4806
4825
  const gitRoot = stdout.trim();
4807
4826
  this.logger.debug("Resolved git repository root", {
4808
- inputPath: path12,
4827
+ inputPath: path13,
4809
4828
  gitRoot
4810
4829
  });
4811
4830
  return gitRoot;
4812
4831
  } catch (error) {
4813
4832
  if (error instanceof Error) {
4814
4833
  throw new Error(
4815
- `Failed to get Git repository root. The path '${path12}' does not appear to be inside a Git repository.
4834
+ `Failed to get Git repository root. The path '${path13}' does not appear to be inside a Git repository.
4816
4835
  ${error.message}`
4817
4836
  );
4818
4837
  }
4819
4838
  throw new Error("Failed to get Git repository root: Unknown error");
4820
4839
  }
4821
4840
  }
4822
- tryGetGitRepositoryRoot(path12) {
4841
+ tryGetGitRepositoryRoot(path13) {
4823
4842
  try {
4824
- return this.getGitRepositoryRoot(path12);
4843
+ return this.getGitRepositoryRoot(path13);
4825
4844
  } catch {
4826
4845
  return null;
4827
4846
  }
@@ -5128,8 +5147,8 @@ var GetGitRemoteUrlUseCase = class {
5128
5147
  constructor(gitRemoteUrlService = new GitService()) {
5129
5148
  this.gitRemoteUrlService = gitRemoteUrlService;
5130
5149
  }
5131
- async execute(command9) {
5132
- const { path: repoPath, origin: origin11 } = command9;
5150
+ async execute(command12) {
5151
+ const { path: repoPath, origin: origin11 } = command12;
5133
5152
  return this.gitRemoteUrlService.getGitRemoteUrl(repoPath, origin11);
5134
5153
  }
5135
5154
  };
@@ -5137,6 +5156,42 @@ var GetGitRemoteUrlUseCase = class {
5137
5156
  // apps/cli/src/application/services/ListFiles.ts
5138
5157
  var fs = __toESM(require("fs/promises"));
5139
5158
  var path2 = __toESM(require("path"));
5159
+
5160
+ // apps/cli/src/infra/utils/consoleLogger.ts
5161
+ init_source();
5162
+ var CLI_PREFIX = "packmind-cli";
5163
+ function logConsole(message, logger2 = console) {
5164
+ logger2.log(message);
5165
+ }
5166
+ function logWarningConsole(message, logger2 = console) {
5167
+ logger2.warn(source_default.bgYellow.bold(CLI_PREFIX), source_default.yellow(message));
5168
+ }
5169
+ function logInfoConsole(message, logger2 = console) {
5170
+ logger2.log(source_default.bgBlue.bold(CLI_PREFIX), source_default.blue(message));
5171
+ }
5172
+ function logErrorConsole(message, logger2 = console) {
5173
+ logger2.error(source_default.bgRed.bold(CLI_PREFIX), source_default.red(message));
5174
+ }
5175
+ function logSuccessConsole(message, logger2 = console) {
5176
+ logger2.log(source_default.bgGreen.bold(CLI_PREFIX), source_default.green.bold(message));
5177
+ }
5178
+ function formatSlug(text) {
5179
+ return source_default.blue.bold(text);
5180
+ }
5181
+ function formatLabel(text) {
5182
+ return source_default.dim(text);
5183
+ }
5184
+ function formatError(text) {
5185
+ return source_default.red(text);
5186
+ }
5187
+ function formatBold(text) {
5188
+ return source_default.bold(text);
5189
+ }
5190
+ function formatFilePath(text) {
5191
+ return source_default.underline.gray(text);
5192
+ }
5193
+
5194
+ // apps/cli/src/application/services/ListFiles.ts
5140
5195
  var ListFiles = class {
5141
5196
  async listFilesInDirectory(directoryPath, extensions, excludes = [], skipHidden = true) {
5142
5197
  const results = [];
@@ -5184,7 +5239,7 @@ var ListFiles = class {
5184
5239
  }
5185
5240
  }
5186
5241
  } catch (error) {
5187
- console.error(`Error reading directory ${directoryPath}:`, error);
5242
+ logErrorConsole(`Error reading directory ${directoryPath}: ${error}`);
5188
5243
  }
5189
5244
  }
5190
5245
  shouldExcludePath(filePath, excludes) {
@@ -5218,7 +5273,7 @@ var ListFiles = class {
5218
5273
  try {
5219
5274
  return await fs.readFile(filePath, "utf-8");
5220
5275
  } catch (error) {
5221
- console.error(`Error reading file ${filePath}:`, error);
5276
+ logErrorConsole(`Error reading file ${filePath}: ${error}`);
5222
5277
  throw error;
5223
5278
  }
5224
5279
  }
@@ -5229,8 +5284,8 @@ var ListFilesInDirectoryUseCase = class {
5229
5284
  constructor(listFiles = new ListFiles()) {
5230
5285
  this.listFiles = listFiles;
5231
5286
  }
5232
- async execute(command9) {
5233
- const { path: directoryPath, extensions, excludes = [] } = command9;
5287
+ async execute(command12) {
5288
+ const { path: directoryPath, extensions, excludes = [] } = command12;
5234
5289
  const files = await this.listFiles.listFilesInDirectory(
5235
5290
  directoryPath,
5236
5291
  extensions,
@@ -5245,7 +5300,7 @@ var ListFilesInDirectoryUseCase = class {
5245
5300
  content
5246
5301
  });
5247
5302
  } catch (error) {
5248
- console.error(`Error reading file ${file.path}:`, error);
5303
+ logErrorConsole(`Error reading file ${file.path}: ${error}`);
5249
5304
  }
5250
5305
  }
5251
5306
  return filesWithContent;
@@ -5315,7 +5370,7 @@ var LintFilesInDirectoryUseCase = class {
5315
5370
  }
5316
5371
  return pattern;
5317
5372
  }
5318
- async execute(command9) {
5373
+ async execute(command12) {
5319
5374
  const {
5320
5375
  path: userPath,
5321
5376
  draftMode,
@@ -5323,7 +5378,7 @@ var LintFilesInDirectoryUseCase = class {
5323
5378
  ruleId,
5324
5379
  language,
5325
5380
  diffMode
5326
- } = command9;
5381
+ } = command12;
5327
5382
  this.logger.debug(
5328
5383
  `Starting linting: path="${userPath}", draftMode=${!!draftMode}, standardSlug="${standardSlug || "N/A"}", ruleId="${ruleId || "N/A"}", language="${language || "N/A"}", diffMode="${diffMode ?? "none"}"`
5329
5384
  );
@@ -5544,7 +5599,7 @@ var LintFilesInDirectoryUseCase = class {
5544
5599
  activeProgram.language
5545
5600
  );
5546
5601
  if (!programLanguage) {
5547
- console.error(
5602
+ logErrorConsole(
5548
5603
  `Unsupported language "${activeProgram.language}" for file ${file.path}`
5549
5604
  );
5550
5605
  continue;
@@ -5562,7 +5617,7 @@ var LintFilesInDirectoryUseCase = class {
5562
5617
  });
5563
5618
  programsByLanguage.set(programLanguage, programsForLanguage);
5564
5619
  } catch (error) {
5565
- console.error(
5620
+ logErrorConsole(
5566
5621
  `Error preparing program for file ${file.path}: ${error}`
5567
5622
  );
5568
5623
  }
@@ -5585,13 +5640,13 @@ var LintFilesInDirectoryUseCase = class {
5585
5640
  });
5586
5641
  fileViolations.push(...result);
5587
5642
  } catch (error) {
5588
- console.error(
5643
+ logErrorConsole(
5589
5644
  `Error executing programs for file ${file.path} (${language2}): ${error}`
5590
5645
  );
5591
5646
  }
5592
5647
  }
5593
5648
  } catch (error) {
5594
- console.error(
5649
+ logErrorConsole(
5595
5650
  `Error reading file content for ${file.path}: ${error}`
5596
5651
  );
5597
5652
  }
@@ -5642,8 +5697,8 @@ var LintFilesInDirectoryUseCase = class {
5642
5697
  return null;
5643
5698
  }
5644
5699
  }
5645
- async executeProgramsForFile(command9) {
5646
- const result = await this.services.linterExecutionUseCase.execute(command9);
5700
+ async executeProgramsForFile(command12) {
5701
+ const result = await this.services.linterExecutionUseCase.execute(command12);
5647
5702
  return result.violations;
5648
5703
  }
5649
5704
  extractExtensionFromFile(filePath) {
@@ -5700,8 +5755,8 @@ var LintFilesLocallyUseCase = class {
5700
5755
  }
5701
5756
  return pattern;
5702
5757
  }
5703
- async execute(command9) {
5704
- const { path: userPath, diffMode } = command9;
5758
+ async execute(command12) {
5759
+ const { path: userPath, diffMode } = command12;
5705
5760
  this.logger.debug(
5706
5761
  `Starting local linting: path="${userPath}", diffMode="${diffMode ?? "none"}"`
5707
5762
  );
@@ -5836,7 +5891,7 @@ var LintFilesLocallyUseCase = class {
5836
5891
  });
5837
5892
  programsByLanguage.set(programLanguage, programsForLanguage);
5838
5893
  } catch (error) {
5839
- console.error(
5894
+ logErrorConsole(
5840
5895
  `Error preparing program for file ${file.path}: ${error}`
5841
5896
  );
5842
5897
  }
@@ -5860,13 +5915,13 @@ var LintFilesLocallyUseCase = class {
5860
5915
  });
5861
5916
  fileViolations.push(...result);
5862
5917
  } catch (error) {
5863
- console.error(
5918
+ logErrorConsole(
5864
5919
  `Error executing programs for file ${file.path} (${language}): ${error}`
5865
5920
  );
5866
5921
  }
5867
5922
  }
5868
5923
  } catch (error) {
5869
- console.error(
5924
+ logErrorConsole(
5870
5925
  `Error reading file content for ${file.path}: ${error}`
5871
5926
  );
5872
5927
  }
@@ -5943,8 +5998,8 @@ var LintFilesLocallyUseCase = class {
5943
5998
  return null;
5944
5999
  }
5945
6000
  }
5946
- async executeProgramsForFile(command9) {
5947
- const result = await this.services.linterExecutionUseCase.execute(command9);
6001
+ async executeProgramsForFile(command12) {
6002
+ const result = await this.services.linterExecutionUseCase.execute(command12);
5948
6003
  return result.violations;
5949
6004
  }
5950
6005
  extractExtensionFromFile(filePath) {
@@ -6110,6 +6165,93 @@ var NotLoggedInError = class extends Error {
6110
6165
  }
6111
6166
  };
6112
6167
 
6168
+ // apps/cli/src/infra/http/PackmindHttpClient.ts
6169
+ var PackmindHttpClient = class {
6170
+ constructor(apiKey) {
6171
+ this.apiKey = apiKey;
6172
+ }
6173
+ getAuthContext() {
6174
+ if (!this.apiKey) {
6175
+ throw new NotLoggedInError();
6176
+ }
6177
+ let decoded;
6178
+ try {
6179
+ const decodedString = Buffer.from(this.apiKey, "base64").toString(
6180
+ "utf-8"
6181
+ );
6182
+ decoded = JSON.parse(decodedString);
6183
+ } catch {
6184
+ throw new Error("Invalid API key");
6185
+ }
6186
+ const jwtPayload = this.decodeJwt(decoded.jwt);
6187
+ const organizationId = jwtPayload?.organization?.id;
6188
+ if (!organizationId) {
6189
+ throw new Error("Invalid API key: missing organizationId");
6190
+ }
6191
+ return {
6192
+ host: decoded.host,
6193
+ jwt: decoded.jwt,
6194
+ organizationId
6195
+ };
6196
+ }
6197
+ decodeJwt(jwt) {
6198
+ try {
6199
+ const parts = jwt.split(".");
6200
+ if (parts.length !== 3) {
6201
+ return null;
6202
+ }
6203
+ const payloadBase64 = parts[1];
6204
+ const payloadString = Buffer.from(payloadBase64, "base64").toString(
6205
+ "utf-8"
6206
+ );
6207
+ return JSON.parse(payloadString);
6208
+ } catch {
6209
+ return null;
6210
+ }
6211
+ }
6212
+ async request(path13, options = {}) {
6213
+ const { host } = this.getAuthContext();
6214
+ const { method = "GET", body } = options;
6215
+ const url = `${host}${path13}`;
6216
+ try {
6217
+ const response = await fetch(url, {
6218
+ method,
6219
+ headers: {
6220
+ "Content-Type": "application/json",
6221
+ Authorization: `Bearer ${this.apiKey}`
6222
+ },
6223
+ ...body ? { body: JSON.stringify(body) } : {}
6224
+ });
6225
+ if (!response.ok) {
6226
+ let errorMsg = `API request failed: ${response.status} ${response.statusText}`;
6227
+ try {
6228
+ const errorBody = await response.json();
6229
+ if (errorBody?.message) {
6230
+ errorMsg = errorBody.message;
6231
+ }
6232
+ } catch {
6233
+ }
6234
+ const error = new Error(errorMsg);
6235
+ error.statusCode = response.status;
6236
+ throw error;
6237
+ }
6238
+ return response.json();
6239
+ } catch (error) {
6240
+ const err = error;
6241
+ if (err.statusCode) throw error;
6242
+ const code = err?.code || err?.cause?.code;
6243
+ 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"))) {
6244
+ throw new Error(
6245
+ `Packmind server is not accessible at ${host}. Please check your network connection or the server URL.`
6246
+ );
6247
+ }
6248
+ throw new Error(
6249
+ `Request failed: ${err?.message || JSON.stringify(error)}`
6250
+ );
6251
+ }
6252
+ }
6253
+ };
6254
+
6113
6255
  // apps/cli/src/infra/repositories/PackmindGateway.ts
6114
6256
  function decodeJwt(jwt) {
6115
6257
  try {
@@ -6166,7 +6308,7 @@ function decodeApiKey(apiKey) {
6166
6308
  var PackmindGateway = class {
6167
6309
  constructor(apiKey) {
6168
6310
  this.apiKey = apiKey;
6169
- this.getPullData = async (command9) => {
6311
+ this.getPullData = async (command12) => {
6170
6312
  const decodedApiKey = decodeApiKey(this.apiKey);
6171
6313
  if (!decodedApiKey.isValid) {
6172
6314
  if (decodedApiKey.error === "NOT_LOGGED_IN") {
@@ -6181,16 +6323,25 @@ var PackmindGateway = class {
6181
6323
  }
6182
6324
  const organizationId = jwtPayload.organization.id;
6183
6325
  const queryParams = new URLSearchParams();
6184
- if (command9.packagesSlugs && command9.packagesSlugs.length > 0) {
6185
- command9.packagesSlugs.forEach((slug) => {
6326
+ if (command12.packagesSlugs && command12.packagesSlugs.length > 0) {
6327
+ command12.packagesSlugs.forEach((slug) => {
6186
6328
  queryParams.append("packageSlug", slug);
6187
6329
  });
6188
6330
  }
6189
- if (command9.previousPackagesSlugs && command9.previousPackagesSlugs.length > 0) {
6190
- command9.previousPackagesSlugs.forEach((slug) => {
6331
+ if (command12.previousPackagesSlugs && command12.previousPackagesSlugs.length > 0) {
6332
+ command12.previousPackagesSlugs.forEach((slug) => {
6191
6333
  queryParams.append("previousPackageSlug", slug);
6192
6334
  });
6193
6335
  }
6336
+ if (command12.gitRemoteUrl) {
6337
+ queryParams.append("gitRemoteUrl", command12.gitRemoteUrl);
6338
+ }
6339
+ if (command12.gitBranch) {
6340
+ queryParams.append("gitBranch", command12.gitBranch);
6341
+ }
6342
+ if (command12.relativePath) {
6343
+ queryParams.append("relativePath", command12.relativePath);
6344
+ }
6194
6345
  const url = `${host}/api/v0/organizations/${organizationId}/pull?${queryParams.toString()}`;
6195
6346
  try {
6196
6347
  const response = await fetch(url, {
@@ -6727,7 +6878,7 @@ var PackmindGateway = class {
6727
6878
  );
6728
6879
  }
6729
6880
  };
6730
- this.uploadSkill = async (command9) => {
6881
+ this.uploadSkill = async (command12) => {
6731
6882
  const decodedApiKey = decodeApiKey(this.apiKey);
6732
6883
  if (!decodedApiKey.isValid) {
6733
6884
  if (decodedApiKey.error === "NOT_LOGGED_IN") {
@@ -6755,7 +6906,7 @@ var PackmindGateway = class {
6755
6906
  }
6756
6907
  const space = await spaceResponse.json();
6757
6908
  const spaceId = space.id;
6758
- const files = await readSkillDirectory(command9.skillPath);
6909
+ const files = await readSkillDirectory(command12.skillPath);
6759
6910
  if (!files.find((f) => f.relativePath === "SKILL.md")) {
6760
6911
  throw new Error("SKILL.md not found in skill directory");
6761
6912
  }
@@ -6825,6 +6976,96 @@ var PackmindGateway = class {
6825
6976
  );
6826
6977
  }
6827
6978
  };
6979
+ this.getDefaultSkills = async () => {
6980
+ const decodedApiKey = decodeApiKey(this.apiKey);
6981
+ if (!decodedApiKey.isValid) {
6982
+ if (decodedApiKey.error === "NOT_LOGGED_IN") {
6983
+ throw new NotLoggedInError();
6984
+ }
6985
+ throw new Error(`Invalid API key: ${decodedApiKey.error}`);
6986
+ }
6987
+ const { host, jwt } = decodedApiKey.payload;
6988
+ const jwtPayload = decodeJwt(jwt);
6989
+ if (!jwtPayload?.organization?.id) {
6990
+ throw new Error("Invalid API key: missing organizationId in JWT");
6991
+ }
6992
+ const organizationId = jwtPayload.organization.id;
6993
+ const url = `${host}/api/v0/organizations/${organizationId}/skills/default`;
6994
+ try {
6995
+ const response = await fetch(url, {
6996
+ method: "GET",
6997
+ headers: {
6998
+ "Content-Type": "application/json",
6999
+ Authorization: `Bearer ${this.apiKey}`
7000
+ }
7001
+ });
7002
+ if (!response.ok) {
7003
+ let errorMsg = `API request failed: ${response.status} ${response.statusText}`;
7004
+ try {
7005
+ const errorBody = await response.json();
7006
+ if (errorBody?.message) {
7007
+ errorMsg = errorBody.message;
7008
+ }
7009
+ } catch {
7010
+ }
7011
+ throw new Error(errorMsg);
7012
+ }
7013
+ const result = await response.json();
7014
+ return result;
7015
+ } catch (error) {
7016
+ const err = error;
7017
+ const code = err?.code || err?.cause?.code;
7018
+ 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"))) {
7019
+ throw new Error(
7020
+ `Packmind server is not accessible at ${host}. Please check your network connection or the server URL.`
7021
+ );
7022
+ }
7023
+ throw new Error(
7024
+ `Failed to get default skills: Error: ${err?.message || JSON.stringify(error)}`
7025
+ );
7026
+ }
7027
+ };
7028
+ this.getGlobalSpace = async () => {
7029
+ const { organizationId } = this.httpClient.getAuthContext();
7030
+ return this.httpClient.request(
7031
+ `/api/v0/organizations/${organizationId}/spaces/global`
7032
+ );
7033
+ };
7034
+ this.createStandardInSpace = async (spaceId, data) => {
7035
+ const { organizationId } = this.httpClient.getAuthContext();
7036
+ return this.httpClient.request(
7037
+ `/api/v0/organizations/${organizationId}/spaces/${spaceId}/standards`,
7038
+ { method: "POST", body: data }
7039
+ );
7040
+ };
7041
+ this.getRulesForStandard = async (spaceId, standardId) => {
7042
+ const { organizationId } = this.httpClient.getAuthContext();
7043
+ return this.httpClient.request(
7044
+ `/api/v0/organizations/${organizationId}/spaces/${spaceId}/standards/${standardId}/rules`
7045
+ );
7046
+ };
7047
+ this.addExampleToRule = async (spaceId, standardId, ruleId, example) => {
7048
+ const { organizationId } = this.httpClient.getAuthContext();
7049
+ await this.httpClient.request(
7050
+ `/api/v0/organizations/${organizationId}/spaces/${spaceId}/standards/${standardId}/rules/${ruleId}/examples`,
7051
+ {
7052
+ method: "POST",
7053
+ body: {
7054
+ lang: example.language,
7055
+ positive: example.positive,
7056
+ negative: example.negative
7057
+ }
7058
+ }
7059
+ );
7060
+ };
7061
+ this.createCommand = async (spaceId, data) => {
7062
+ const { organizationId } = this.httpClient.getAuthContext();
7063
+ return this.httpClient.request(
7064
+ `/api/v0/organizations/${organizationId}/spaces/${spaceId}/recipes`,
7065
+ { method: "POST", body: data }
7066
+ );
7067
+ };
7068
+ this.httpClient = new PackmindHttpClient(apiKey);
6828
7069
  }
6829
7070
  };
6830
7071
 
@@ -8568,8 +8809,8 @@ var ExecuteLinterProgramsUseCase = class {
8568
8809
  this.linterAstAdapter = linterAstAdapter;
8569
8810
  this.logger = logger2;
8570
8811
  }
8571
- async execute(command9) {
8572
- const { filePath, fileContent, language, programs } = command9;
8812
+ async execute(command12) {
8813
+ const { filePath, fileContent, language, programs } = command12;
8573
8814
  if (programs.length === 0) {
8574
8815
  return {
8575
8816
  file: filePath,
@@ -9573,6 +9814,51 @@ var SSEEventPublisher = class _SSEEventPublisher {
9573
9814
  throw error;
9574
9815
  }
9575
9816
  }
9817
+ /**
9818
+ * Publish a distribution status change event for cache invalidation
9819
+ * This triggers React Query to refetch the distribution data when status changes
9820
+ */
9821
+ static async publishDistributionStatusChangeEvent(distributionId, status, organizationId) {
9822
+ _SSEEventPublisher.logger.info(
9823
+ "Publishing distribution status change event",
9824
+ {
9825
+ distributionId,
9826
+ status,
9827
+ organizationId
9828
+ }
9829
+ );
9830
+ try {
9831
+ const event = createDistributionStatusChangeEvent(
9832
+ distributionId,
9833
+ status,
9834
+ organizationId
9835
+ );
9836
+ await _SSEEventPublisher.publishEvent(
9837
+ "DISTRIBUTION_STATUS_CHANGE",
9838
+ [organizationId],
9839
+ event
9840
+ );
9841
+ _SSEEventPublisher.logger.debug(
9842
+ "Successfully published distribution status change event",
9843
+ {
9844
+ distributionId,
9845
+ status,
9846
+ organizationId
9847
+ }
9848
+ );
9849
+ } catch (error) {
9850
+ _SSEEventPublisher.logger.error(
9851
+ "Failed to publish distribution status change event",
9852
+ {
9853
+ distributionId,
9854
+ status,
9855
+ organizationId,
9856
+ error: error instanceof Error ? error.message : String(error)
9857
+ }
9858
+ );
9859
+ throw error;
9860
+ }
9861
+ }
9576
9862
  /**
9577
9863
  * Generic method to publish any SSE event type to Redis pub/sub
9578
9864
  */
@@ -9657,6 +9943,11 @@ ${sectionBlock}
9657
9943
  return result;
9658
9944
  }
9659
9945
 
9946
+ // packages/node-utils/src/text/urlUtils.ts
9947
+ function removeTrailingSlash(url) {
9948
+ return url.endsWith("/") ? url.slice(0, -1) : url;
9949
+ }
9950
+
9660
9951
  // apps/cli/src/application/useCases/InstallPackagesUseCase.ts
9661
9952
  var fs5 = __toESM(require("fs/promises"));
9662
9953
  var path6 = __toESM(require("path"));
@@ -9664,8 +9955,8 @@ var InstallPackagesUseCase = class {
9664
9955
  constructor(packmindGateway) {
9665
9956
  this.packmindGateway = packmindGateway;
9666
9957
  }
9667
- async execute(command9) {
9668
- const baseDirectory = command9.baseDirectory || process.cwd();
9958
+ async execute(command12) {
9959
+ const baseDirectory = command12.baseDirectory || process.cwd();
9669
9960
  const result = {
9670
9961
  filesCreated: 0,
9671
9962
  filesUpdated: 0,
@@ -9673,11 +9964,15 @@ var InstallPackagesUseCase = class {
9673
9964
  errors: [],
9674
9965
  recipesCount: 0,
9675
9966
  standardsCount: 0,
9676
- skillsCount: 0
9967
+ skillsCount: 0,
9968
+ skillDirectoriesDeleted: 0
9677
9969
  };
9678
9970
  const response = await this.packmindGateway.getPullData({
9679
- packagesSlugs: command9.packagesSlugs,
9680
- previousPackagesSlugs: command9.previousPackagesSlugs
9971
+ packagesSlugs: command12.packagesSlugs,
9972
+ previousPackagesSlugs: command12.previousPackagesSlugs,
9973
+ gitRemoteUrl: command12.gitRemoteUrl,
9974
+ gitBranch: command12.gitBranch,
9975
+ relativePath: command12.relativePath
9681
9976
  });
9682
9977
  const uniqueFilesMap = /* @__PURE__ */ new Map();
9683
9978
  for (const file of response.fileUpdates.createOrUpdate) {
@@ -9694,6 +9989,10 @@ var InstallPackagesUseCase = class {
9694
9989
  }
9695
9990
  }
9696
9991
  try {
9992
+ result.skillDirectoriesDeleted = await this.deleteSkillFolders(
9993
+ baseDirectory,
9994
+ response.skillFolders
9995
+ );
9697
9996
  for (const file of uniqueFiles) {
9698
9997
  try {
9699
9998
  await this.createOrUpdateFile(baseDirectory, file, result);
@@ -9871,6 +10170,99 @@ ${endMarker}`;
9871
10170
  escapeRegex(str) {
9872
10171
  return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
9873
10172
  }
10173
+ /**
10174
+ * Deletes all skill folders before recreating them with fresh content.
10175
+ * Returns the count of files that were actually deleted.
10176
+ */
10177
+ async deleteSkillFolders(baseDirectory, folders) {
10178
+ let deletedFilesCount = 0;
10179
+ for (const folder of folders) {
10180
+ const fullPath = path6.join(baseDirectory, folder);
10181
+ try {
10182
+ await fs5.access(fullPath);
10183
+ const fileCount = await this.countFilesInDirectory(fullPath);
10184
+ await fs5.rm(fullPath, { recursive: true, force: true });
10185
+ deletedFilesCount += fileCount;
10186
+ } catch {
10187
+ }
10188
+ }
10189
+ return deletedFilesCount;
10190
+ }
10191
+ /**
10192
+ * Recursively counts all files in a directory.
10193
+ */
10194
+ async countFilesInDirectory(dirPath) {
10195
+ let count = 0;
10196
+ const entries = await fs5.readdir(dirPath, { withFileTypes: true });
10197
+ for (const entry of entries) {
10198
+ const entryPath = path6.join(dirPath, entry.name);
10199
+ if (entry.isDirectory()) {
10200
+ count += await this.countFilesInDirectory(entryPath);
10201
+ } else {
10202
+ count++;
10203
+ }
10204
+ }
10205
+ return count;
10206
+ }
10207
+ };
10208
+
10209
+ // apps/cli/src/application/useCases/InstallDefaultSkillsUseCase.ts
10210
+ var fs6 = __toESM(require("fs/promises"));
10211
+ var path7 = __toESM(require("path"));
10212
+ var InstallDefaultSkillsUseCase = class {
10213
+ constructor(packmindGateway) {
10214
+ this.packmindGateway = packmindGateway;
10215
+ }
10216
+ async execute(command12) {
10217
+ const baseDirectory = command12.baseDirectory || process.cwd();
10218
+ const result = {
10219
+ filesCreated: 0,
10220
+ filesUpdated: 0,
10221
+ errors: []
10222
+ };
10223
+ const response = await this.packmindGateway.getDefaultSkills({});
10224
+ console.log(JSON.stringify(response, null, 2));
10225
+ try {
10226
+ for (const file of response.fileUpdates.createOrUpdate) {
10227
+ try {
10228
+ await this.createOrUpdateFile(baseDirectory, file, result);
10229
+ } catch (error) {
10230
+ const errorMsg = error instanceof Error ? error.message : String(error);
10231
+ result.errors.push(
10232
+ `Failed to create/update ${file.path}: ${errorMsg}`
10233
+ );
10234
+ }
10235
+ }
10236
+ } catch (error) {
10237
+ const errorMsg = error instanceof Error ? error.message : String(error);
10238
+ result.errors.push(`Failed to install default skills: ${errorMsg}`);
10239
+ }
10240
+ return result;
10241
+ }
10242
+ async createOrUpdateFile(baseDirectory, file, result) {
10243
+ const fullPath = path7.join(baseDirectory, file.path);
10244
+ const directory = path7.dirname(fullPath);
10245
+ await fs6.mkdir(directory, { recursive: true });
10246
+ const fileExists = await this.fileExists(fullPath);
10247
+ if (fileExists) {
10248
+ const existingContent = await fs6.readFile(fullPath, "utf-8");
10249
+ if (existingContent !== file.content) {
10250
+ await fs6.writeFile(fullPath, file.content, "utf-8");
10251
+ result.filesUpdated++;
10252
+ }
10253
+ } else {
10254
+ await fs6.writeFile(fullPath, file.content, "utf-8");
10255
+ result.filesCreated++;
10256
+ }
10257
+ }
10258
+ async fileExists(filePath) {
10259
+ try {
10260
+ await fs6.access(filePath);
10261
+ return true;
10262
+ } catch {
10263
+ return false;
10264
+ }
10265
+ }
9874
10266
  };
9875
10267
 
9876
10268
  // apps/cli/src/application/useCases/ListPackagesUseCase.ts
@@ -9888,8 +10280,8 @@ var GetPackageSummaryUseCase = class {
9888
10280
  constructor(gateway) {
9889
10281
  this.gateway = gateway;
9890
10282
  }
9891
- async execute(command9) {
9892
- return this.gateway.getPackageSummary(command9);
10283
+ async execute(command12) {
10284
+ return this.gateway.getPackageSummary(command12);
9893
10285
  }
9894
10286
  };
9895
10287
 
@@ -9949,13 +10341,13 @@ var EnvCredentialsProvider = class {
9949
10341
  };
9950
10342
 
9951
10343
  // apps/cli/src/infra/utils/credentials/FileCredentialsProvider.ts
9952
- var fs6 = __toESM(require("fs"));
9953
- var path7 = __toESM(require("path"));
10344
+ var fs7 = __toESM(require("fs"));
10345
+ var path8 = __toESM(require("path"));
9954
10346
  var os2 = __toESM(require("os"));
9955
10347
  var CREDENTIALS_DIR = ".packmind";
9956
10348
  var CREDENTIALS_FILE = "credentials.json";
9957
10349
  function getCredentialsPath() {
9958
- return path7.join(os2.homedir(), CREDENTIALS_DIR, CREDENTIALS_FILE);
10350
+ return path8.join(os2.homedir(), CREDENTIALS_DIR, CREDENTIALS_FILE);
9959
10351
  }
9960
10352
  var FileCredentialsProvider = class {
9961
10353
  getSourceName() {
@@ -9963,11 +10355,11 @@ var FileCredentialsProvider = class {
9963
10355
  }
9964
10356
  hasCredentials() {
9965
10357
  const credentialsPath = getCredentialsPath();
9966
- if (!fs6.existsSync(credentialsPath)) {
10358
+ if (!fs7.existsSync(credentialsPath)) {
9967
10359
  return false;
9968
10360
  }
9969
10361
  try {
9970
- const content = fs6.readFileSync(credentialsPath, "utf-8");
10362
+ const content = fs7.readFileSync(credentialsPath, "utf-8");
9971
10363
  const credentials = JSON.parse(content);
9972
10364
  return !!credentials.apiKey;
9973
10365
  } catch {
@@ -9976,11 +10368,11 @@ var FileCredentialsProvider = class {
9976
10368
  }
9977
10369
  loadCredentials() {
9978
10370
  const credentialsPath = getCredentialsPath();
9979
- if (!fs6.existsSync(credentialsPath)) {
10371
+ if (!fs7.existsSync(credentialsPath)) {
9980
10372
  return null;
9981
10373
  }
9982
10374
  try {
9983
- const content = fs6.readFileSync(credentialsPath, "utf-8");
10375
+ const content = fs7.readFileSync(credentialsPath, "utf-8");
9984
10376
  const credentials = JSON.parse(content);
9985
10377
  if (!credentials.apiKey) {
9986
10378
  return null;
@@ -10003,13 +10395,13 @@ var FileCredentialsProvider = class {
10003
10395
  }
10004
10396
  };
10005
10397
  function saveCredentials(apiKey) {
10006
- const credentialsDir = path7.join(os2.homedir(), CREDENTIALS_DIR);
10007
- if (!fs6.existsSync(credentialsDir)) {
10008
- fs6.mkdirSync(credentialsDir, { recursive: true, mode: 448 });
10398
+ const credentialsDir = path8.join(os2.homedir(), CREDENTIALS_DIR);
10399
+ if (!fs7.existsSync(credentialsDir)) {
10400
+ fs7.mkdirSync(credentialsDir, { recursive: true, mode: 448 });
10009
10401
  }
10010
10402
  const credentialsPath = getCredentialsPath();
10011
10403
  const credentials = { apiKey };
10012
- fs6.writeFileSync(credentialsPath, JSON.stringify(credentials, null, 2), {
10404
+ fs7.writeFileSync(credentialsPath, JSON.stringify(credentials, null, 2), {
10013
10405
  mode: 384
10014
10406
  });
10015
10407
  }
@@ -10088,7 +10480,8 @@ async function defaultPromptForCode() {
10088
10480
  });
10089
10481
  }
10090
10482
  async function defaultExchangeCodeForApiKey(code, host) {
10091
- const url = `${host}/api/v0/auth/cli-login-exchange`;
10483
+ const normalizedHost = removeTrailingSlash(host);
10484
+ const url = `${normalizedHost}/api/v0/auth/cli-login-exchange`;
10092
10485
  const response = await fetch(url, {
10093
10486
  method: "POST",
10094
10487
  headers: {
@@ -10167,15 +10560,16 @@ var LoginUseCase = class {
10167
10560
  startCallbackServer: deps?.startCallbackServer ?? defaultStartCallbackServer
10168
10561
  };
10169
10562
  }
10170
- async execute(command9) {
10171
- const { host, code: providedCode } = command9;
10563
+ async execute(command12) {
10564
+ const { host, code: providedCode } = command12;
10172
10565
  let code;
10173
10566
  if (providedCode) {
10174
10567
  code = providedCode;
10175
10568
  } else {
10176
10569
  const callbackPromise = this.deps.startCallbackServer();
10177
10570
  const callbackUrl = `http://127.0.0.1:${CALLBACK_PORT}`;
10178
- const loginUrl = `${host}/cli-login?callback_url=${encodeURIComponent(callbackUrl)}`;
10571
+ const normalizedHost = removeTrailingSlash(host);
10572
+ const loginUrl = `${normalizedHost}/cli-login?callback_url=${encodeURIComponent(callbackUrl)}`;
10179
10573
  try {
10180
10574
  await this.deps.openBrowser(loginUrl);
10181
10575
  } catch {
@@ -10199,14 +10593,14 @@ var LoginUseCase = class {
10199
10593
  };
10200
10594
 
10201
10595
  // apps/cli/src/application/useCases/LogoutUseCase.ts
10202
- var fs7 = __toESM(require("fs"));
10596
+ var fs8 = __toESM(require("fs"));
10203
10597
  var ENV_VAR_NAME2 = "PACKMIND_API_KEY_V3";
10204
10598
  var LogoutUseCase = class {
10205
10599
  constructor(deps) {
10206
10600
  this.deps = {
10207
10601
  getCredentialsPath: deps?.getCredentialsPath ?? getCredentialsPath,
10208
- fileExists: deps?.fileExists ?? ((path12) => fs7.existsSync(path12)),
10209
- deleteFile: deps?.deleteFile ?? ((path12) => fs7.unlinkSync(path12)),
10602
+ fileExists: deps?.fileExists ?? ((path13) => fs8.existsSync(path13)),
10603
+ deleteFile: deps?.deleteFile ?? ((path13) => fs8.unlinkSync(path13)),
10210
10604
  hasEnvVar: deps?.hasEnvVar ?? (() => !!process.env[ENV_VAR_NAME2])
10211
10605
  };
10212
10606
  }
@@ -10266,8 +10660,8 @@ var SetupMcpUseCase = class {
10266
10660
  constructor(deps) {
10267
10661
  this.deps = deps;
10268
10662
  }
10269
- async execute(command9) {
10270
- const { agentTypes } = command9;
10663
+ async execute(command12) {
10664
+ const { agentTypes } = command12;
10271
10665
  const [tokenResult, urlResult] = await Promise.all([
10272
10666
  this.deps.gateway.getMcpToken({}),
10273
10667
  this.deps.gateway.getMcpUrl({})
@@ -10302,8 +10696,8 @@ var SetupMcpUseCase = class {
10302
10696
  };
10303
10697
 
10304
10698
  // apps/cli/src/application/services/McpConfigService.ts
10305
- var fs8 = __toESM(require("fs"));
10306
- var path8 = __toESM(require("path"));
10699
+ var fs9 = __toESM(require("fs"));
10700
+ var path9 = __toESM(require("path"));
10307
10701
  var os3 = __toESM(require("os"));
10308
10702
  var import_child_process2 = require("child_process");
10309
10703
  var McpConfigService = class {
@@ -10338,9 +10732,9 @@ var McpConfigService = class {
10338
10732
  return JSON.stringify(mcpConfig, null, 2);
10339
10733
  }
10340
10734
  installClaudeMcp(config) {
10341
- const command9 = `claude mcp add --transport http packmind ${config.url} --header "Authorization: Bearer ${config.accessToken}"`;
10735
+ const command12 = `claude mcp add --transport http packmind ${config.url} --header "Authorization: Bearer ${config.accessToken}"`;
10342
10736
  try {
10343
- (0, import_child_process2.execSync)(command9, { stdio: "pipe" });
10737
+ (0, import_child_process2.execSync)(command12, { stdio: "pipe" });
10344
10738
  return { success: true };
10345
10739
  } catch (error) {
10346
10740
  const execError = error;
@@ -10350,11 +10744,11 @@ var McpConfigService = class {
10350
10744
  }
10351
10745
  installCursorMcp(config) {
10352
10746
  try {
10353
- const cursorConfigPath = path8.join(os3.homedir(), ".cursor", "mcp.json");
10747
+ const cursorConfigPath = path9.join(os3.homedir(), ".cursor", "mcp.json");
10354
10748
  const cursorConfig = this.buildCursorConfig(config);
10355
10749
  const existingConfig = this.readExistingJsonConfig(cursorConfigPath);
10356
10750
  const mergedConfig = this.mergeConfig(existingConfig, cursorConfig);
10357
- fs8.writeFileSync(cursorConfigPath, JSON.stringify(mergedConfig, null, 2));
10751
+ fs9.writeFileSync(cursorConfigPath, JSON.stringify(mergedConfig, null, 2));
10358
10752
  return { success: true };
10359
10753
  } catch (error) {
10360
10754
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -10363,15 +10757,15 @@ var McpConfigService = class {
10363
10757
  }
10364
10758
  installVSCodeMcp(config) {
10365
10759
  try {
10366
- const vscodeDir = path8.join(this.projectDir, ".vscode");
10367
- if (!fs8.existsSync(vscodeDir)) {
10368
- fs8.mkdirSync(vscodeDir, { recursive: true });
10760
+ const vscodeDir = path9.join(this.projectDir, ".vscode");
10761
+ if (!fs9.existsSync(vscodeDir)) {
10762
+ fs9.mkdirSync(vscodeDir, { recursive: true });
10369
10763
  }
10370
- const vscodeConfigPath = path8.join(vscodeDir, "mcp.json");
10764
+ const vscodeConfigPath = path9.join(vscodeDir, "mcp.json");
10371
10765
  const vscodeConfig = this.buildVSCodeConfig(config);
10372
10766
  const existingConfig = this.readExistingJsonConfig(vscodeConfigPath);
10373
10767
  const mergedConfig = this.mergeVSCodeConfig(existingConfig, vscodeConfig);
10374
- fs8.writeFileSync(vscodeConfigPath, JSON.stringify(mergedConfig, null, 2));
10768
+ fs9.writeFileSync(vscodeConfigPath, JSON.stringify(mergedConfig, null, 2));
10375
10769
  return { success: true };
10376
10770
  } catch (error) {
10377
10771
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -10380,14 +10774,14 @@ var McpConfigService = class {
10380
10774
  }
10381
10775
  installContinueMcp(config) {
10382
10776
  try {
10383
- const continueDir = path8.join(this.projectDir, ".continue");
10384
- const mcpServersDir = path8.join(continueDir, "mcpServers");
10385
- if (!fs8.existsSync(mcpServersDir)) {
10386
- fs8.mkdirSync(mcpServersDir, { recursive: true });
10777
+ const continueDir = path9.join(this.projectDir, ".continue");
10778
+ const mcpServersDir = path9.join(continueDir, "mcpServers");
10779
+ if (!fs9.existsSync(mcpServersDir)) {
10780
+ fs9.mkdirSync(mcpServersDir, { recursive: true });
10387
10781
  }
10388
- const continueConfigPath = path8.join(mcpServersDir, "packmind.yaml");
10782
+ const continueConfigPath = path9.join(mcpServersDir, "packmind.yaml");
10389
10783
  const continueConfig = this.buildContinueYamlConfig(config);
10390
- fs8.writeFileSync(continueConfigPath, continueConfig);
10784
+ fs9.writeFileSync(continueConfigPath, continueConfig);
10391
10785
  return { success: true };
10392
10786
  } catch (error) {
10393
10787
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -10435,8 +10829,8 @@ mcpServers:
10435
10829
  }
10436
10830
  readExistingJsonConfig(filePath) {
10437
10831
  try {
10438
- if (fs8.existsSync(filePath)) {
10439
- const content = fs8.readFileSync(filePath, "utf-8");
10832
+ if (fs9.existsSync(filePath)) {
10833
+ const content = fs9.readFileSync(filePath, "utf-8");
10440
10834
  return JSON.parse(content);
10441
10835
  }
10442
10836
  } catch {
@@ -10469,41 +10863,8 @@ mcpServers:
10469
10863
  };
10470
10864
 
10471
10865
  // apps/cli/src/infra/repositories/ConfigFileRepository.ts
10472
- var fs9 = __toESM(require("fs/promises"));
10473
- var path9 = __toESM(require("path"));
10474
-
10475
- // apps/cli/src/infra/utils/consoleLogger.ts
10476
- init_source();
10477
- var CLI_PREFIX = "packmind-cli";
10478
- function logWarningConsole(message) {
10479
- console.warn(source_default.bgYellow.bold(CLI_PREFIX), source_default.yellow(message));
10480
- }
10481
- function logInfoConsole(message) {
10482
- console.log(source_default.bgBlue.bold(CLI_PREFIX), source_default.blue(message));
10483
- }
10484
- function logErrorConsole(message) {
10485
- console.error(source_default.bgRed.bold(CLI_PREFIX), source_default.red(message));
10486
- }
10487
- function logSuccessConsole(message) {
10488
- console.log(source_default.bgGreen.bold(CLI_PREFIX), source_default.green.bold(message));
10489
- }
10490
- function formatSlug(text) {
10491
- return source_default.blue.bold(text);
10492
- }
10493
- function formatLabel(text) {
10494
- return source_default.dim(text);
10495
- }
10496
- function formatError(text) {
10497
- return source_default.red(text);
10498
- }
10499
- function formatBold(text) {
10500
- return source_default.bold(text);
10501
- }
10502
- function formatFilePath(text) {
10503
- return source_default.underline.gray(text);
10504
- }
10505
-
10506
- // apps/cli/src/infra/repositories/ConfigFileRepository.ts
10866
+ var fs10 = __toESM(require("fs/promises"));
10867
+ var path10 = __toESM(require("path"));
10507
10868
  var ConfigFileRepository = class {
10508
10869
  constructor() {
10509
10870
  this.CONFIG_FILENAME = "packmind.json";
@@ -10518,23 +10879,23 @@ var ConfigFileRepository = class {
10518
10879
  ];
10519
10880
  }
10520
10881
  async writeConfig(baseDirectory, config) {
10521
- const configPath = path9.join(baseDirectory, this.CONFIG_FILENAME);
10882
+ const configPath = path10.join(baseDirectory, this.CONFIG_FILENAME);
10522
10883
  const configContent = JSON.stringify(config, null, 2) + "\n";
10523
- await fs9.writeFile(configPath, configContent, "utf-8");
10884
+ await fs10.writeFile(configPath, configContent, "utf-8");
10524
10885
  }
10525
10886
  async configExists(baseDirectory) {
10526
- const configPath = path9.join(baseDirectory, this.CONFIG_FILENAME);
10887
+ const configPath = path10.join(baseDirectory, this.CONFIG_FILENAME);
10527
10888
  try {
10528
- await fs9.access(configPath);
10889
+ await fs10.access(configPath);
10529
10890
  return true;
10530
10891
  } catch {
10531
10892
  return false;
10532
10893
  }
10533
10894
  }
10534
10895
  async readConfig(baseDirectory) {
10535
- const configPath = path9.join(baseDirectory, this.CONFIG_FILENAME);
10896
+ const configPath = path10.join(baseDirectory, this.CONFIG_FILENAME);
10536
10897
  try {
10537
- const configContent = await fs9.readFile(configPath, "utf-8");
10898
+ const configContent = await fs10.readFile(configPath, "utf-8");
10538
10899
  const config = JSON.parse(configContent);
10539
10900
  if (!config.packages || typeof config.packages !== "object") {
10540
10901
  throw new Error(
@@ -10561,12 +10922,12 @@ var ConfigFileRepository = class {
10561
10922
  * @returns Array of directory paths that contain a packmind.json file
10562
10923
  */
10563
10924
  async findDescendantConfigs(directory) {
10564
- const normalizedDir = normalizePath(path9.resolve(directory));
10925
+ const normalizedDir = normalizePath(path10.resolve(directory));
10565
10926
  const results = [];
10566
10927
  const searchRecursively = async (currentDir) => {
10567
10928
  let entries;
10568
10929
  try {
10569
- entries = await fs9.readdir(currentDir, { withFileTypes: true });
10930
+ entries = await fs10.readdir(currentDir, { withFileTypes: true });
10570
10931
  } catch {
10571
10932
  return;
10572
10933
  }
@@ -10577,7 +10938,7 @@ var ConfigFileRepository = class {
10577
10938
  if (this.EXCLUDED_DIRECTORIES.includes(entry.name)) {
10578
10939
  continue;
10579
10940
  }
10580
- const entryPath = normalizePath(path9.join(currentDir, entry.name));
10941
+ const entryPath = normalizePath(path10.join(currentDir, entry.name));
10581
10942
  const config = await this.readConfig(entryPath);
10582
10943
  if (config) {
10583
10944
  results.push(entryPath);
@@ -10599,21 +10960,21 @@ var ConfigFileRepository = class {
10599
10960
  async readHierarchicalConfig(startDirectory, stopDirectory) {
10600
10961
  const configs = [];
10601
10962
  const configPaths = [];
10602
- const normalizedStart = normalizePath(path9.resolve(startDirectory));
10603
- const normalizedStop = stopDirectory ? normalizePath(path9.resolve(stopDirectory)) : null;
10963
+ const normalizedStart = normalizePath(path10.resolve(startDirectory));
10964
+ const normalizedStop = stopDirectory ? normalizePath(path10.resolve(stopDirectory)) : null;
10604
10965
  let currentDir = normalizedStart;
10605
10966
  while (true) {
10606
10967
  const config = await this.readConfig(currentDir);
10607
10968
  if (config) {
10608
10969
  configs.push(config);
10609
10970
  configPaths.push(
10610
- normalizePath(path9.join(currentDir, this.CONFIG_FILENAME))
10971
+ normalizePath(path10.join(currentDir, this.CONFIG_FILENAME))
10611
10972
  );
10612
10973
  }
10613
10974
  if (normalizedStop !== null && currentDir === normalizedStop) {
10614
10975
  break;
10615
10976
  }
10616
- const parentDir = normalizePath(path9.dirname(currentDir));
10977
+ const parentDir = normalizePath(path10.dirname(currentDir));
10617
10978
  if (parentDir === currentDir) {
10618
10979
  break;
10619
10980
  }
@@ -10642,8 +11003,8 @@ var ConfigFileRepository = class {
10642
11003
  * @returns All configs found with their target paths
10643
11004
  */
10644
11005
  async findAllConfigsInTree(startDirectory, stopDirectory) {
10645
- const normalizedStart = normalizePath(path9.resolve(startDirectory));
10646
- const normalizedStop = stopDirectory ? normalizePath(path9.resolve(stopDirectory)) : null;
11006
+ const normalizedStart = normalizePath(path10.resolve(startDirectory));
11007
+ const normalizedStop = stopDirectory ? normalizePath(path10.resolve(stopDirectory)) : null;
10647
11008
  const basePath = normalizedStop ?? normalizedStart;
10648
11009
  const configsMap = /* @__PURE__ */ new Map();
10649
11010
  let currentDir = normalizedStart;
@@ -10660,7 +11021,7 @@ var ConfigFileRepository = class {
10660
11021
  if (normalizedStop !== null && currentDir === normalizedStop) {
10661
11022
  break;
10662
11023
  }
10663
- const parentDir = normalizePath(path9.dirname(currentDir));
11024
+ const parentDir = normalizePath(path10.dirname(currentDir));
10664
11025
  if (parentDir === currentDir) {
10665
11026
  break;
10666
11027
  }
@@ -10747,6 +11108,9 @@ var PackmindCliHexaFactory = class {
10747
11108
  installPackages: new InstallPackagesUseCase(
10748
11109
  this.repositories.packmindGateway
10749
11110
  ),
11111
+ installDefaultSkills: new InstallDefaultSkillsUseCase(
11112
+ this.repositories.packmindGateway
11113
+ ),
10750
11114
  listPackages: new ListPackagesUseCase(this.repositories.packmindGateway),
10751
11115
  getPackageBySlug: new GetPackageSummaryUseCase(
10752
11116
  this.repositories.packmindGateway
@@ -10783,29 +11147,29 @@ var PackmindCliHexa = class {
10783
11147
  this.logger.info("Destroying PackmindCliHexa");
10784
11148
  this.logger.info("PackmindCliHexa destroyed");
10785
11149
  }
10786
- async getGitRemoteUrl(command9) {
10787
- return this.hexa.useCases.getGitRemoteUrl.execute(command9);
11150
+ async getGitRemoteUrl(command12) {
11151
+ return this.hexa.useCases.getGitRemoteUrl.execute(command12);
10788
11152
  }
10789
- async executeSingleFileAst(command9) {
10790
- return this.hexa.useCases.executeSingleFileAst.execute(command9);
11153
+ async executeSingleFileAst(command12) {
11154
+ return this.hexa.useCases.executeSingleFileAst.execute(command12);
10791
11155
  }
10792
- async listFilesInDirectory(command9) {
10793
- return this.hexa.useCases.listFilesInDirectoryUseCase.execute(command9);
11156
+ async listFilesInDirectory(command12) {
11157
+ return this.hexa.useCases.listFilesInDirectoryUseCase.execute(command12);
10794
11158
  }
10795
- async lintFilesInDirectory(command9) {
10796
- return this.hexa.useCases.lintFilesInDirectory.execute(command9);
11159
+ async lintFilesInDirectory(command12) {
11160
+ return this.hexa.useCases.lintFilesInDirectory.execute(command12);
10797
11161
  }
10798
- async lintFilesLocally(command9) {
10799
- return this.hexa.useCases.lintFilesLocally.execute(command9);
11162
+ async lintFilesLocally(command12) {
11163
+ return this.hexa.useCases.lintFilesLocally.execute(command12);
10800
11164
  }
10801
- async installPackages(command9) {
10802
- return this.hexa.useCases.installPackages.execute(command9);
11165
+ async installPackages(command12) {
11166
+ return this.hexa.useCases.installPackages.execute(command12);
10803
11167
  }
10804
- async listPackages(command9) {
10805
- return this.hexa.useCases.listPackages.execute(command9);
11168
+ async listPackages(command12) {
11169
+ return this.hexa.useCases.listPackages.execute(command12);
10806
11170
  }
10807
- async getPackageBySlug(command9) {
10808
- return this.hexa.useCases.getPackageBySlug.execute(command9);
11171
+ async getPackageBySlug(command12) {
11172
+ return this.hexa.useCases.getPackageBySlug.execute(command12);
10809
11173
  }
10810
11174
  async configExists(baseDirectory) {
10811
11175
  return await this.hexa.repositories.configFileRepository.configExists(
@@ -10864,17 +11228,17 @@ var PackmindCliHexa = class {
10864
11228
  directory
10865
11229
  );
10866
11230
  }
10867
- async login(command9) {
10868
- return this.hexa.useCases.login.execute(command9);
11231
+ async login(command12) {
11232
+ return this.hexa.useCases.login.execute(command12);
10869
11233
  }
10870
- async logout(command9) {
10871
- return this.hexa.useCases.logout.execute(command9);
11234
+ async logout(command12) {
11235
+ return this.hexa.useCases.logout.execute(command12);
10872
11236
  }
10873
- async whoami(command9) {
10874
- return this.hexa.useCases.whoami.execute(command9);
11237
+ async whoami(command12) {
11238
+ return this.hexa.useCases.whoami.execute(command12);
10875
11239
  }
10876
- async setupMcp(command9) {
10877
- return this.hexa.useCases.setupMcp.execute(command9);
11240
+ async setupMcp(command12) {
11241
+ return this.hexa.useCases.setupMcp.execute(command12);
10878
11242
  }
10879
11243
  getCurrentBranch(repoPath) {
10880
11244
  return this.hexa.services.gitRemoteUrlService.getCurrentBranch(repoPath).branch;
@@ -10882,11 +11246,17 @@ var PackmindCliHexa = class {
10882
11246
  getGitRemoteUrlFromPath(repoPath) {
10883
11247
  return this.hexa.services.gitRemoteUrlService.getGitRemoteUrl(repoPath).gitRemoteUrl;
10884
11248
  }
10885
- async notifyDistribution(command9) {
10886
- return this.hexa.repositories.packmindGateway.notifyDistribution(command9);
11249
+ async notifyDistribution(command12) {
11250
+ return this.hexa.repositories.packmindGateway.notifyDistribution(command12);
11251
+ }
11252
+ async uploadSkill(command12) {
11253
+ return this.hexa.repositories.packmindGateway.uploadSkill(command12);
10887
11254
  }
10888
- async uploadSkill(command9) {
10889
- return this.hexa.repositories.packmindGateway.uploadSkill(command9);
11255
+ async installDefaultSkills(command12) {
11256
+ return this.hexa.useCases.installDefaultSkills.execute(command12);
11257
+ }
11258
+ getPackmindGateway() {
11259
+ return this.hexa.repositories.packmindGateway;
10890
11260
  }
10891
11261
  };
10892
11262
 
@@ -10899,7 +11269,7 @@ var IDELintLogger = class {
10899
11269
  }
10900
11270
  logViolation(violation) {
10901
11271
  violation.violations.forEach(({ line, character, standard, rule }) => {
10902
- console.log(
11272
+ logConsole(
10903
11273
  `${violation.file}:${line}:${character}:error:@${standard}/${rule}`
10904
11274
  );
10905
11275
  });
@@ -10925,9 +11295,9 @@ var HumanReadableLogger = class {
10925
11295
  }
10926
11296
  }
10927
11297
  logViolation(violation) {
10928
- console.log(formatFilePath(violation.file));
11298
+ logConsole(formatFilePath(violation.file));
10929
11299
  violation.violations.forEach(({ line, character, standard, rule }) => {
10930
- console.log(
11300
+ logConsole(
10931
11301
  formatError(` ${line}:${character} error @${standard}/${rule}`)
10932
11302
  );
10933
11303
  });
@@ -10943,7 +11313,7 @@ function isNotLoggedInError(error) {
10943
11313
  }
10944
11314
  async function lintHandler(args2, deps) {
10945
11315
  const {
10946
- path: path12,
11316
+ path: path13,
10947
11317
  draft,
10948
11318
  rule,
10949
11319
  language,
@@ -10963,7 +11333,7 @@ async function lintHandler(args2, deps) {
10963
11333
  throw new Error("option --rule is required to use --draft mode");
10964
11334
  }
10965
11335
  const startedAt = Date.now();
10966
- const targetPath = path12 ?? ".";
11336
+ const targetPath = path13 ?? ".";
10967
11337
  const hasArguments = !!(draft || rule || language);
10968
11338
  const absolutePath = resolvePath(targetPath);
10969
11339
  if (diff) {
@@ -11220,8 +11590,8 @@ function extractWasmFiles() {
11220
11590
 
11221
11591
  // apps/cli/src/main.ts
11222
11592
  var import_dotenv = require("dotenv");
11223
- var fs12 = __toESM(require("fs"));
11224
- var path11 = __toESM(require("path"));
11593
+ var fs15 = __toESM(require("fs"));
11594
+ var path12 = __toESM(require("path"));
11225
11595
 
11226
11596
  // apps/cli/src/infra/commands/InstallCommand.ts
11227
11597
  var import_cmd_ts2 = __toESM(require_cjs());
@@ -11255,6 +11625,31 @@ async function notifyDistributionIfInGitRepo(params) {
11255
11625
  return false;
11256
11626
  }
11257
11627
  }
11628
+ async function installDefaultSkillsIfAtGitRoot(params) {
11629
+ const { packmindCliHexa, cwd, log } = params;
11630
+ const gitRoot = await packmindCliHexa.tryGetGitRepositoryRoot(cwd);
11631
+ if (!gitRoot || cwd !== gitRoot) {
11632
+ return;
11633
+ }
11634
+ try {
11635
+ log("\nInstalling default skills...");
11636
+ const skillsResult = await packmindCliHexa.installDefaultSkills({});
11637
+ if (skillsResult.errors.length > 0) {
11638
+ skillsResult.errors.forEach((err) => {
11639
+ log(` Warning: ${err}`);
11640
+ });
11641
+ }
11642
+ const totalSkillFiles = skillsResult.filesCreated + skillsResult.filesUpdated;
11643
+ if (totalSkillFiles > 0) {
11644
+ log(
11645
+ `Default skills: added ${skillsResult.filesCreated} files, changed ${skillsResult.filesUpdated} files`
11646
+ );
11647
+ } else if (skillsResult.errors.length === 0) {
11648
+ log("Default skills are already up to date");
11649
+ }
11650
+ } catch {
11651
+ }
11652
+ }
11258
11653
  async function listPackagesHandler(_args, deps) {
11259
11654
  const { packmindCliHexa, exit, log, error } = deps;
11260
11655
  try {
@@ -11472,8 +11867,9 @@ async function executeInstallForDirectory(directory, deps) {
11472
11867
  errorMessage: result.errors.join(", ")
11473
11868
  };
11474
11869
  }
11870
+ const skillDirsDeleted = result.skillDirectoriesDeleted || 0;
11475
11871
  let notificationSent = false;
11476
- if (result.filesCreated > 0 || result.filesUpdated > 0 || result.filesDeleted > 0) {
11872
+ if (result.filesCreated > 0 || result.filesUpdated > 0 || result.filesDeleted > 0 || skillDirsDeleted > 0) {
11477
11873
  notificationSent = await notifyDistributionIfInGitRepo({
11478
11874
  packmindCliHexa,
11479
11875
  cwd: directory,
@@ -11486,7 +11882,7 @@ async function executeInstallForDirectory(directory, deps) {
11486
11882
  success: true,
11487
11883
  filesCreated: result.filesCreated,
11488
11884
  filesUpdated: result.filesUpdated,
11489
- filesDeleted: result.filesDeleted,
11885
+ filesDeleted: result.filesDeleted + skillDirsDeleted,
11490
11886
  notificationSent
11491
11887
  };
11492
11888
  } catch (err) {
@@ -11561,11 +11957,32 @@ async function installPackagesHandler(args2, deps) {
11561
11957
  log(
11562
11958
  `Fetching ${packageCount} ${packageWord}: ${allPackages.join(", ")}...`
11563
11959
  );
11960
+ let gitRemoteUrl;
11961
+ let gitBranch;
11962
+ let relativePath;
11963
+ const gitRoot = await packmindCliHexa.tryGetGitRepositoryRoot(cwd);
11964
+ if (gitRoot) {
11965
+ try {
11966
+ gitRemoteUrl = packmindCliHexa.getGitRemoteUrlFromPath(gitRoot);
11967
+ gitBranch = packmindCliHexa.getCurrentBranch(gitRoot);
11968
+ relativePath = cwd.startsWith(gitRoot) ? cwd.slice(gitRoot.length) : "/";
11969
+ if (!relativePath.startsWith("/")) {
11970
+ relativePath = "/" + relativePath;
11971
+ }
11972
+ if (!relativePath.endsWith("/")) {
11973
+ relativePath = relativePath + "/";
11974
+ }
11975
+ } catch {
11976
+ }
11977
+ }
11564
11978
  const result = await packmindCliHexa.installPackages({
11565
11979
  baseDirectory: cwd,
11566
11980
  packagesSlugs: allPackages,
11567
- previousPackagesSlugs: configPackages
11981
+ previousPackagesSlugs: configPackages,
11568
11982
  // Pass previous config for change detection
11983
+ gitRemoteUrl,
11984
+ gitBranch,
11985
+ relativePath
11569
11986
  });
11570
11987
  const parts = [];
11571
11988
  if (result.recipesCount > 0) parts.push(`${result.recipesCount} commands`);
@@ -11573,9 +11990,11 @@ async function installPackagesHandler(args2, deps) {
11573
11990
  parts.push(`${result.standardsCount} standards`);
11574
11991
  if (result.skillsCount > 0) parts.push(`${result.skillsCount} skills`);
11575
11992
  log(`Installing ${parts.join(", ") || "artifacts"}...`);
11993
+ const skillDirsDeleted = result.skillDirectoriesDeleted || 0;
11994
+ const totalDeleted = result.filesDeleted + skillDirsDeleted;
11576
11995
  log(
11577
11996
  `
11578
- added ${result.filesCreated} files, changed ${result.filesUpdated} files, removed ${result.filesDeleted} files`
11997
+ added ${result.filesCreated} files, changed ${result.filesUpdated} files, removed ${totalDeleted} files`
11579
11998
  );
11580
11999
  if (result.errors.length > 0) {
11581
12000
  log("\n\u26A0\uFE0F Errors encountered:");
@@ -11586,12 +12005,12 @@ added ${result.filesCreated} files, changed ${result.filesUpdated} files, remove
11586
12005
  return {
11587
12006
  filesCreated: result.filesCreated,
11588
12007
  filesUpdated: result.filesUpdated,
11589
- filesDeleted: result.filesDeleted,
12008
+ filesDeleted: totalDeleted,
11590
12009
  notificationSent: false
11591
12010
  };
11592
12011
  }
11593
12012
  let notificationSent = false;
11594
- if (result.filesCreated > 0 || result.filesUpdated > 0 || result.filesDeleted > 0) {
12013
+ if (result.filesCreated > 0 || result.filesUpdated > 0 || result.filesDeleted > 0 || skillDirsDeleted > 0) {
11595
12014
  notificationSent = await notifyDistributionIfInGitRepo({
11596
12015
  packmindCliHexa,
11597
12016
  cwd,
@@ -11599,10 +12018,11 @@ added ${result.filesCreated} files, changed ${result.filesUpdated} files, remove
11599
12018
  log
11600
12019
  });
11601
12020
  }
12021
+ await installDefaultSkillsIfAtGitRoot({ packmindCliHexa, cwd, log });
11602
12022
  return {
11603
12023
  filesCreated: result.filesCreated,
11604
12024
  filesUpdated: result.filesUpdated,
11605
- filesDeleted: result.filesDeleted,
12025
+ filesDeleted: totalDeleted,
11606
12026
  notificationSent
11607
12027
  };
11608
12028
  } catch (err) {
@@ -12050,10 +12470,11 @@ var loginCommand = (0, import_cmd_ts4.command)({
12050
12470
  const packmindCliHexa = new PackmindCliHexa(packmindLogger);
12051
12471
  try {
12052
12472
  if (!code) {
12053
- console.log("\nOpening browser for authentication...");
12054
- console.log(
12473
+ logConsole("\nOpening browser for authentication...");
12474
+ const normalizedHost = removeTrailingSlash(host);
12475
+ logConsole(
12055
12476
  `
12056
- If the browser doesn't open, visit: ${host}/cli-login?callback_url=${encodeURIComponent("http://127.0.0.1:19284")}
12477
+ If the browser doesn't open, visit: ${normalizedHost}/cli-login?callback_url=${encodeURIComponent("http://127.0.0.1:19284")}
12057
12478
  `
12058
12479
  );
12059
12480
  logInfoConsole("Waiting for browser authentication...");
@@ -12061,9 +12482,9 @@ If the browser doesn't open, visit: ${host}/cli-login?callback_url=${encodeURICo
12061
12482
  logInfoConsole("Exchanging code for API key...");
12062
12483
  const result = await packmindCliHexa.login({ host, code });
12063
12484
  logSuccessConsole("Login successful!");
12064
- console.log(`
12485
+ logConsole(`
12065
12486
  Credentials saved to: ${result.credentialsPath}`);
12066
- console.log(
12487
+ logConsole(
12067
12488
  "\nYou can now use packmind-cli commands with your authenticated account."
12068
12489
  );
12069
12490
  } catch (error) {
@@ -12094,20 +12515,20 @@ var logoutCommand = (0, import_cmd_ts5.command)({
12094
12515
  }
12095
12516
  if (result.hadCredentialsFile) {
12096
12517
  logSuccessConsole("Logged out successfully.");
12097
- console.log(`Removed credentials from: ${result.credentialsPath}`);
12518
+ logConsole(`Removed credentials from: ${result.credentialsPath}`);
12098
12519
  }
12099
12520
  if (result.hasEnvVar) {
12100
12521
  if (!result.hadCredentialsFile) {
12101
12522
  logInfoConsole("No stored credentials file found.");
12102
12523
  }
12103
- console.log(
12524
+ logConsole(
12104
12525
  "\nNote: PACKMIND_API_KEY_V3 environment variable is still set."
12105
12526
  );
12106
- console.log("To fully log out, run: unset PACKMIND_API_KEY_V3");
12527
+ logConsole("To fully log out, run: unset PACKMIND_API_KEY_V3");
12107
12528
  }
12108
12529
  } catch (error) {
12109
12530
  logErrorConsole("Failed to remove credentials file.");
12110
- console.log(
12531
+ logConsole(
12111
12532
  `Error: ${error instanceof Error ? error.message : String(error)}`
12112
12533
  );
12113
12534
  process.exit(1);
@@ -12136,20 +12557,20 @@ function formatExpiresAt(expiresAt) {
12136
12557
  return "Expires soon";
12137
12558
  }
12138
12559
  function displayAuthInfo(result) {
12139
- console.log(`
12560
+ logConsole(`
12140
12561
  Host: ${result.host}`);
12141
12562
  if (result.organizationName) {
12142
- console.log(`Organization: ${result.organizationName}`);
12563
+ logConsole(`Organization: ${result.organizationName}`);
12143
12564
  }
12144
12565
  if (result.userName) {
12145
- console.log(`User: ${result.userName}`);
12566
+ logConsole(`User: ${result.userName}`);
12146
12567
  }
12147
12568
  if (result.expiresAt) {
12148
- console.log(formatExpiresAt(result.expiresAt));
12569
+ logConsole(formatExpiresAt(result.expiresAt));
12149
12570
  }
12150
12571
  logInfoConsole(`Source: ${result.source}`);
12151
12572
  if (result.isExpired) {
12152
- console.log("\nRun `packmind-cli login` to re-authenticate.");
12573
+ logConsole("\nRun `packmind-cli login` to re-authenticate.");
12153
12574
  }
12154
12575
  }
12155
12576
  var whoamiCommand = (0, import_cmd_ts6.command)({
@@ -12162,14 +12583,14 @@ var whoamiCommand = (0, import_cmd_ts6.command)({
12162
12583
  const result = await packmindCliHexa.whoami({});
12163
12584
  if (!result.isAuthenticated) {
12164
12585
  logErrorConsole("Not authenticated");
12165
- console.log(
12586
+ logConsole(
12166
12587
  `
12167
12588
  No credentials found. Run \`packmind-cli login\` to authenticate.`
12168
12589
  );
12169
- console.log(`
12590
+ logConsole(`
12170
12591
  Credentials are loaded from (in order of priority):`);
12171
- console.log(` 1. PACKMIND_API_KEY_V3 environment variable`);
12172
- console.log(` 2. ${result.credentialsPath}`);
12592
+ logConsole(` 1. PACKMIND_API_KEY_V3 environment variable`);
12593
+ logConsole(` 2. ${result.credentialsPath}`);
12173
12594
  process.exit(1);
12174
12595
  }
12175
12596
  if (result.isExpired) {
@@ -12186,13 +12607,13 @@ Credentials are loaded from (in order of priority):`);
12186
12607
 
12187
12608
  // apps/cli/src/infra/commands/SetupMcpCommand.ts
12188
12609
  var import_cmd_ts7 = __toESM(require_cjs());
12189
- var fs11 = __toESM(require("fs"));
12610
+ var fs12 = __toESM(require("fs"));
12190
12611
  var readline2 = __toESM(require("readline"));
12191
12612
  var inquirer = __toESM(require("inquirer"));
12192
12613
 
12193
12614
  // apps/cli/src/application/services/AgentDetectionService.ts
12194
- var fs10 = __toESM(require("fs"));
12195
- var path10 = __toESM(require("path"));
12615
+ var fs11 = __toESM(require("fs"));
12616
+ var path11 = __toESM(require("path"));
12196
12617
  var os4 = __toESM(require("os"));
12197
12618
  var import_child_process3 = require("child_process");
12198
12619
  var AgentDetectionService = class {
@@ -12219,21 +12640,21 @@ var AgentDetectionService = class {
12219
12640
  return this.isCommandAvailable("claude");
12220
12641
  }
12221
12642
  isCursorAvailable() {
12222
- const cursorConfigDir = path10.join(os4.homedir(), ".cursor");
12223
- return fs10.existsSync(cursorConfigDir);
12643
+ const cursorConfigDir = path11.join(os4.homedir(), ".cursor");
12644
+ return fs11.existsSync(cursorConfigDir);
12224
12645
  }
12225
12646
  isVSCodeAvailable() {
12226
- const vscodeDir = path10.join(this.projectDir, ".vscode");
12227
- return fs10.existsSync(vscodeDir);
12647
+ const vscodeDir = path11.join(this.projectDir, ".vscode");
12648
+ return fs11.existsSync(vscodeDir);
12228
12649
  }
12229
12650
  isContinueAvailable() {
12230
- const continueDir = path10.join(this.projectDir, ".continue");
12231
- return fs10.existsSync(continueDir);
12651
+ const continueDir = path11.join(this.projectDir, ".continue");
12652
+ return fs11.existsSync(continueDir);
12232
12653
  }
12233
- isCommandAvailable(command9) {
12654
+ isCommandAvailable(command12) {
12234
12655
  try {
12235
12656
  const whichCommand = process.platform === "win32" ? "where" : "which";
12236
- (0, import_child_process3.execSync)(`${whichCommand} ${command9}`, { stdio: "pipe" });
12657
+ (0, import_child_process3.execSync)(`${whichCommand} ${command12}`, { stdio: "pipe" });
12237
12658
  return true;
12238
12659
  } catch {
12239
12660
  return false;
@@ -12267,8 +12688,8 @@ var ALL_AGENTS2 = [
12267
12688
  { type: "continue", name: "Continue.dev" }
12268
12689
  ];
12269
12690
  async function promptAgentsWithReadline(choices) {
12270
- const input = fs11.createReadStream("/dev/tty");
12271
- const output = fs11.createWriteStream("/dev/tty");
12691
+ const input = fs12.createReadStream("/dev/tty");
12692
+ const output = fs12.createWriteStream("/dev/tty");
12272
12693
  const rl = readline2.createInterface({
12273
12694
  input,
12274
12695
  output
@@ -12313,18 +12734,18 @@ var setupMcpCommand = (0, import_cmd_ts7.command)({
12313
12734
  const credentials = loadCredentials();
12314
12735
  if (!credentials) {
12315
12736
  logErrorConsole("Not authenticated");
12316
- console.log("\nNo credentials found. You can authenticate by either:");
12317
- console.log(" 1. Running `packmind-cli login`");
12318
- console.log(" 2. Setting PACKMIND_API_KEY_V3 environment variable");
12319
- console.log(`
12737
+ logConsole("\nNo credentials found. You can authenticate by either:");
12738
+ logConsole(" 1. Running `packmind-cli login`");
12739
+ logConsole(" 2. Setting PACKMIND_API_KEY_V3 environment variable");
12740
+ logConsole(`
12320
12741
  Credentials are loaded from (in order of priority):`);
12321
- console.log(` 1. PACKMIND_API_KEY_V3 environment variable`);
12322
- console.log(` 2. ${getCredentialsPath()}`);
12742
+ logConsole(` 1. PACKMIND_API_KEY_V3 environment variable`);
12743
+ logConsole(` 2. ${getCredentialsPath()}`);
12323
12744
  process.exit(1);
12324
12745
  }
12325
12746
  if (credentials.isExpired) {
12326
12747
  logErrorConsole("Credentials expired");
12327
- console.log("\nRun `packmind-cli login` to re-authenticate.");
12748
+ logConsole("\nRun `packmind-cli login` to re-authenticate.");
12328
12749
  process.exit(1);
12329
12750
  }
12330
12751
  const agentDetectionService = new AgentDetectionService();
@@ -12332,16 +12753,16 @@ Credentials are loaded from (in order of priority):`);
12332
12753
  if (targets.length > 0) {
12333
12754
  selectedAgents = targets.map((t) => agentArgToType[t]);
12334
12755
  } else {
12335
- console.log("\nDetecting installed AI agents...\n");
12756
+ logConsole("\nDetecting installed AI agents...\n");
12336
12757
  const detectedAgents = agentDetectionService.detectAgents();
12337
12758
  if (detectedAgents.length > 0) {
12338
- console.log("Found agents:");
12759
+ logConsole("Found agents:");
12339
12760
  detectedAgents.forEach((detectedAgent) => {
12340
- console.log(` - ${detectedAgent.name}`);
12761
+ logConsole(` - ${detectedAgent.name}`);
12341
12762
  });
12342
- console.log("");
12763
+ logConsole("");
12343
12764
  } else {
12344
- console.log("No supported agents detected.\n");
12765
+ logConsole("No supported agents detected.\n");
12345
12766
  }
12346
12767
  const detectedTypes = new Set(detectedAgents.map((a) => a.type));
12347
12768
  const choices = ALL_AGENTS2.map((agentInfo) => ({
@@ -12365,12 +12786,12 @@ Credentials are loaded from (in order of priority):`);
12365
12786
  promptedAgents = result2.selectedAgents;
12366
12787
  }
12367
12788
  if (promptedAgents.length === 0) {
12368
- console.log("\nNo agents selected. Exiting.");
12789
+ logConsole("\nNo agents selected. Exiting.");
12369
12790
  process.exit(0);
12370
12791
  }
12371
12792
  selectedAgents = promptedAgents;
12372
12793
  }
12373
- console.log("\nFetching MCP configuration...\n");
12794
+ logConsole("\nFetching MCP configuration...\n");
12374
12795
  const packmindLogger = new PackmindLogger("PackmindCLI", "info" /* INFO */);
12375
12796
  const packmindCliHexa = new PackmindCliHexa(packmindLogger);
12376
12797
  let result;
@@ -12379,14 +12800,14 @@ Credentials are loaded from (in order of priority):`);
12379
12800
  } catch (error) {
12380
12801
  logErrorConsole("Failed to fetch MCP configuration from server.");
12381
12802
  if (error instanceof Error) {
12382
- console.log(` ${error.message}`);
12803
+ logConsole(` ${error.message}`);
12383
12804
  }
12384
12805
  process.exit(1);
12385
12806
  }
12386
12807
  let successCount = 0;
12387
12808
  const failedAgents = [];
12388
12809
  for (const agentResult of result.results) {
12389
- console.log(`Installing MCP for ${agentResult.agentName}...`);
12810
+ logConsole(`Installing MCP for ${agentResult.agentName}...`);
12390
12811
  if (agentResult.success) {
12391
12812
  logSuccessConsole(` ${agentResult.agentName} configured successfully`);
12392
12813
  successCount++;
@@ -12398,27 +12819,27 @@ Credentials are loaded from (in order of priority):`);
12398
12819
  });
12399
12820
  }
12400
12821
  }
12401
- console.log("");
12822
+ logConsole("");
12402
12823
  if (failedAgents.length > 0) {
12403
12824
  for (const failed of failedAgents) {
12404
12825
  logWarningConsole(`Failed to configure ${failed.name}:`);
12405
- console.log(`
12826
+ logConsole(`
12406
12827
  Error: ${failed.error}`);
12407
12828
  if (failed.error.includes("ENOENT") || failed.error.includes("not found") || failed.error.includes("command not found")) {
12408
- console.log(
12829
+ logConsole(
12409
12830
  `
12410
12831
  Hint: Make sure the agent CLI is installed and available in your PATH.`
12411
12832
  );
12412
12833
  }
12413
- console.log(`
12834
+ logConsole(`
12414
12835
  Manual configuration:`);
12415
- console.log(result.manualConfigJson);
12416
- console.log("");
12836
+ logConsole(result.manualConfigJson ?? "undefined");
12837
+ logConsole("");
12417
12838
  }
12418
12839
  }
12419
12840
  if (successCount > 0) {
12420
12841
  const agentWord = successCount === 1 ? "agent" : "agents";
12421
- console.log(
12842
+ logConsole(
12422
12843
  formatBold(`Done! MCP configured for ${successCount} ${agentWord}.`)
12423
12844
  );
12424
12845
  }
@@ -12429,7 +12850,7 @@ Credentials are loaded from (in order of priority):`);
12429
12850
  });
12430
12851
 
12431
12852
  // apps/cli/src/infra/commands/SkillsCommand.ts
12432
- var import_cmd_ts9 = __toESM(require_cjs());
12853
+ var import_cmd_ts10 = __toESM(require_cjs());
12433
12854
 
12434
12855
  // apps/cli/src/infra/commands/skills/AddSkillCommand.ts
12435
12856
  var import_cmd_ts8 = __toESM(require_cjs());
@@ -12479,12 +12900,426 @@ var addSkillCommand = (0, import_cmd_ts8.command)({
12479
12900
  }
12480
12901
  });
12481
12902
 
12903
+ // apps/cli/src/infra/commands/skills/InstallDefaultSkillsCommand.ts
12904
+ var import_cmd_ts9 = __toESM(require_cjs());
12905
+ var installDefaultSkillsCommand = (0, import_cmd_ts9.command)({
12906
+ name: "install-default",
12907
+ description: "Install default Packmind skills for configured coding agents",
12908
+ args: {},
12909
+ handler: async () => {
12910
+ const packmindLogger = new PackmindLogger("PackmindCLI", "info" /* INFO */);
12911
+ const packmindCliHexa = new PackmindCliHexa(packmindLogger);
12912
+ try {
12913
+ logInfoConsole("Installing default skills...");
12914
+ const result = await packmindCliHexa.installDefaultSkills({});
12915
+ console.log(JSON.stringify(result, null, 2));
12916
+ if (result.errors.length > 0) {
12917
+ for (const error of result.errors) {
12918
+ logErrorConsole(`Error: ${error}`);
12919
+ }
12920
+ process.exit(1);
12921
+ }
12922
+ const totalFiles = result.filesCreated + result.filesUpdated;
12923
+ if (totalFiles === 0) {
12924
+ logInfoConsole("Default skills are already up to date.");
12925
+ } else {
12926
+ logSuccessConsole("Default skills installed successfully!");
12927
+ if (result.filesCreated > 0) {
12928
+ logInfoConsole(` Files created: ${result.filesCreated}`);
12929
+ }
12930
+ if (result.filesUpdated > 0) {
12931
+ logInfoConsole(` Files updated: ${result.filesUpdated}`);
12932
+ }
12933
+ }
12934
+ } catch (error) {
12935
+ if (error instanceof Error) {
12936
+ logErrorConsole(`Installation failed: ${error.message}`);
12937
+ } else {
12938
+ logErrorConsole(`Installation failed: ${String(error)}`);
12939
+ }
12940
+ process.exit(1);
12941
+ }
12942
+ }
12943
+ });
12944
+
12482
12945
  // apps/cli/src/infra/commands/SkillsCommand.ts
12483
- var skillsCommand = (0, import_cmd_ts9.subcommands)({
12946
+ var skillsCommand = (0, import_cmd_ts10.subcommands)({
12484
12947
  name: "skills",
12485
12948
  description: "Manage skills in your Packmind organization",
12486
12949
  cmds: {
12487
- add: addSkillCommand
12950
+ add: addSkillCommand,
12951
+ init: installDefaultSkillsCommand
12952
+ }
12953
+ });
12954
+
12955
+ // apps/cli/src/infra/commands/StandardsCommand.ts
12956
+ var import_cmd_ts12 = __toESM(require_cjs());
12957
+
12958
+ // apps/cli/src/infra/commands/CreateStandardCommand.ts
12959
+ var import_cmd_ts11 = __toESM(require_cjs());
12960
+
12961
+ // apps/cli/src/infra/utils/readPlaybookFile.ts
12962
+ var fs13 = __toESM(require("fs/promises"));
12963
+
12964
+ // apps/cli/src/domain/entities/PlaybookDTO.ts
12965
+ var import_zod = require("zod");
12966
+ var playbookRuleExampleSchema = import_zod.z.object({
12967
+ positive: import_zod.z.string().describe("Valid example of the rule"),
12968
+ negative: import_zod.z.string().describe("Invalid example of the rule"),
12969
+ language: import_zod.z.string().describe("Programming language")
12970
+ });
12971
+ var playbookRuleSchema = import_zod.z.object({
12972
+ content: import_zod.z.string().min(1).describe("Rule description starting with action verb"),
12973
+ examples: playbookRuleExampleSchema.optional()
12974
+ });
12975
+ var playbookDTOSchema = import_zod.z.object({
12976
+ name: import_zod.z.string().min(1).describe("Standard name"),
12977
+ description: import_zod.z.string().min(1).describe("Standard description"),
12978
+ scope: import_zod.z.string().min(1).describe("Standard scope/context"),
12979
+ rules: import_zod.z.array(playbookRuleSchema).min(1).describe("Array of rules (minimum 1)")
12980
+ });
12981
+
12982
+ // apps/cli/src/infra/utils/playbookValidator.ts
12983
+ function validatePlaybook(data) {
12984
+ const result = playbookDTOSchema.safeParse(data);
12985
+ if (!result.success) {
12986
+ const errorList = result.error.issues;
12987
+ return {
12988
+ isValid: false,
12989
+ errors: errorList.map((e) => `${e.path.join(".")}: ${e.message}`)
12990
+ };
12991
+ }
12992
+ return {
12993
+ isValid: true,
12994
+ data: result.data
12995
+ };
12996
+ }
12997
+
12998
+ // apps/cli/src/infra/utils/readPlaybookFile.ts
12999
+ async function readPlaybookFile(filePath) {
13000
+ try {
13001
+ const content = await fs13.readFile(filePath, "utf-8");
13002
+ let parsed;
13003
+ try {
13004
+ parsed = JSON.parse(content);
13005
+ } catch (e) {
13006
+ return {
13007
+ isValid: false,
13008
+ errors: [
13009
+ `Invalid JSON: ${e instanceof Error ? e.message : "Unknown error"}`
13010
+ ]
13011
+ };
13012
+ }
13013
+ return validatePlaybook(parsed);
13014
+ } catch (e) {
13015
+ return {
13016
+ isValid: false,
13017
+ errors: [
13018
+ `Failed to read file: ${e instanceof Error ? e.message : "Unknown error"}`
13019
+ ]
13020
+ };
13021
+ }
13022
+ }
13023
+
13024
+ // apps/cli/src/infra/commands/createStandardHandler.ts
13025
+ async function createStandardHandler(filePath, useCase) {
13026
+ const readResult = await readPlaybookFile(filePath);
13027
+ if (!readResult.isValid) {
13028
+ return {
13029
+ success: false,
13030
+ error: `Validation failed: ${readResult.errors?.join(", ")}`
13031
+ };
13032
+ }
13033
+ if (!readResult.data) {
13034
+ return {
13035
+ success: false,
13036
+ error: "Failed to read playbook data"
13037
+ };
13038
+ }
13039
+ try {
13040
+ const result = await useCase.execute(readResult.data);
13041
+ return {
13042
+ success: true,
13043
+ standardId: result.standardId,
13044
+ standardName: result.name
13045
+ };
13046
+ } catch (e) {
13047
+ return {
13048
+ success: false,
13049
+ error: `Error creating standard: ${e instanceof Error ? e.message : "Unknown error"}`
13050
+ };
13051
+ }
13052
+ }
13053
+
13054
+ // apps/cli/src/application/useCases/CreateStandardFromPlaybookUseCase.ts
13055
+ var CreateStandardFromPlaybookUseCase = class {
13056
+ constructor(gateway) {
13057
+ this.gateway = gateway;
13058
+ }
13059
+ async execute(playbook) {
13060
+ const space = await this.gateway.getGlobalSpace();
13061
+ const standard = await this.gateway.createStandardInSpace(space.id, {
13062
+ name: playbook.name,
13063
+ description: playbook.description,
13064
+ scope: playbook.scope,
13065
+ rules: playbook.rules.map((r) => ({ content: r.content }))
13066
+ });
13067
+ const rulesWithExamples = playbook.rules.filter((r) => r.examples);
13068
+ if (rulesWithExamples.length > 0) {
13069
+ const createdRules = await this.gateway.getRulesForStandard(
13070
+ space.id,
13071
+ standard.id
13072
+ );
13073
+ for (let i = 0; i < playbook.rules.length; i++) {
13074
+ const rule = playbook.rules[i];
13075
+ if (rule.examples && createdRules[i]) {
13076
+ try {
13077
+ await this.gateway.addExampleToRule(
13078
+ space.id,
13079
+ standard.id,
13080
+ createdRules[i].id,
13081
+ rule.examples
13082
+ );
13083
+ } catch {
13084
+ }
13085
+ }
13086
+ }
13087
+ }
13088
+ return { standardId: standard.id, name: standard.name };
13089
+ }
13090
+ };
13091
+
13092
+ // apps/cli/src/infra/commands/CreateStandardCommand.ts
13093
+ var createStandardCommand = (0, import_cmd_ts11.command)({
13094
+ name: "create",
13095
+ description: "Create a coding standard from a playbook JSON file",
13096
+ args: {
13097
+ file: (0, import_cmd_ts11.positional)({
13098
+ displayName: "file",
13099
+ description: "Path to the playbook JSON file",
13100
+ type: import_cmd_ts11.string
13101
+ })
13102
+ },
13103
+ handler: async ({ file }) => {
13104
+ try {
13105
+ const packmindLogger = new PackmindLogger("PackmindCLI", "info" /* INFO */);
13106
+ const hexa = new PackmindCliHexa(packmindLogger);
13107
+ const gateway = hexa.getPackmindGateway();
13108
+ const useCase = new CreateStandardFromPlaybookUseCase(gateway);
13109
+ const result = await createStandardHandler(file, useCase);
13110
+ if (result.success) {
13111
+ logSuccessConsole(
13112
+ `Standard "${result.standardName}" created successfully (ID: ${result.standardId})`
13113
+ );
13114
+ process.exit(0);
13115
+ } else {
13116
+ logErrorConsole(`Failed to create standard: ${result.error}`);
13117
+ process.exit(1);
13118
+ }
13119
+ } catch (e) {
13120
+ logErrorConsole(
13121
+ `Error: ${e instanceof Error ? e.message : "Unknown error"}`
13122
+ );
13123
+ process.exit(1);
13124
+ }
13125
+ }
13126
+ });
13127
+
13128
+ // apps/cli/src/infra/commands/StandardsCommand.ts
13129
+ var standardsCommand = (0, import_cmd_ts12.subcommands)({
13130
+ name: "standards",
13131
+ description: "Manage coding standards",
13132
+ cmds: {
13133
+ create: createStandardCommand
13134
+ }
13135
+ });
13136
+
13137
+ // apps/cli/src/infra/commands/CommandsCommand.ts
13138
+ var import_cmd_ts14 = __toESM(require_cjs());
13139
+
13140
+ // apps/cli/src/infra/commands/CreateCommandCommand.ts
13141
+ var import_cmd_ts13 = __toESM(require_cjs());
13142
+
13143
+ // apps/cli/src/infra/utils/readCommandPlaybookFile.ts
13144
+ var fs14 = __toESM(require("fs/promises"));
13145
+
13146
+ // apps/cli/src/domain/entities/CommandPlaybookDTO.ts
13147
+ var import_zod2 = require("zod");
13148
+ var commandStepSchema = import_zod2.z.object({
13149
+ name: import_zod2.z.string().min(1).describe("Step name/title"),
13150
+ description: import_zod2.z.string().min(1).describe("Step description with implementation details"),
13151
+ codeSnippet: import_zod2.z.string().optional().describe("Optional code snippet demonstrating the step")
13152
+ });
13153
+ var commandPlaybookDTOSchema = import_zod2.z.object({
13154
+ name: import_zod2.z.string().min(1).describe("Command name"),
13155
+ summary: import_zod2.z.string().min(1).describe("Command summary describing intent and value"),
13156
+ whenToUse: import_zod2.z.array(import_zod2.z.string().min(1)).min(1).describe("Array of scenarios when this command is applicable (minimum 1)"),
13157
+ contextValidationCheckpoints: import_zod2.z.array(import_zod2.z.string().min(1)).min(1).describe(
13158
+ "Array of checkpoints to validate context before implementation (minimum 1)"
13159
+ ),
13160
+ steps: import_zod2.z.array(commandStepSchema).min(1).describe("Array of implementation steps (minimum 1)")
13161
+ });
13162
+
13163
+ // apps/cli/src/infra/utils/commandPlaybookValidator.ts
13164
+ function validateCommandPlaybook(data) {
13165
+ const result = commandPlaybookDTOSchema.safeParse(data);
13166
+ if (!result.success) {
13167
+ const errorList = result.error.issues;
13168
+ return {
13169
+ isValid: false,
13170
+ errors: errorList.map((e) => `${e.path.join(".")}: ${e.message}`)
13171
+ };
13172
+ }
13173
+ return {
13174
+ isValid: true,
13175
+ data: result.data
13176
+ };
13177
+ }
13178
+
13179
+ // apps/cli/src/infra/utils/readCommandPlaybookFile.ts
13180
+ async function readCommandPlaybookFile(filePath) {
13181
+ try {
13182
+ const content = await fs14.readFile(filePath, "utf-8");
13183
+ let parsed;
13184
+ try {
13185
+ parsed = JSON.parse(content);
13186
+ } catch (e) {
13187
+ return {
13188
+ isValid: false,
13189
+ errors: [
13190
+ `Invalid JSON: ${e instanceof Error ? e.message : "Unknown error"}`
13191
+ ]
13192
+ };
13193
+ }
13194
+ return validateCommandPlaybook(parsed);
13195
+ } catch (e) {
13196
+ return {
13197
+ isValid: false,
13198
+ errors: [
13199
+ `Failed to read file: ${e instanceof Error ? e.message : "Unknown error"}`
13200
+ ]
13201
+ };
13202
+ }
13203
+ }
13204
+
13205
+ // apps/cli/src/infra/commands/createCommandHandler.ts
13206
+ function buildWebappUrl(host, orgSlug, commandId) {
13207
+ return `${host}/org/${orgSlug}/space/global/commands/${commandId}`;
13208
+ }
13209
+ async function createCommandHandler(filePath, useCase) {
13210
+ const readResult = await readCommandPlaybookFile(filePath);
13211
+ if (!readResult.isValid) {
13212
+ return {
13213
+ success: false,
13214
+ error: `Validation failed: ${readResult.errors?.join(", ")}`
13215
+ };
13216
+ }
13217
+ if (!readResult.data) {
13218
+ return {
13219
+ success: false,
13220
+ error: "Failed to read command playbook data"
13221
+ };
13222
+ }
13223
+ try {
13224
+ const result = await useCase.execute(readResult.data);
13225
+ let webappUrl;
13226
+ const apiKey = loadApiKey();
13227
+ if (apiKey) {
13228
+ const decoded = decodeApiKey2(apiKey);
13229
+ if (decoded?.host && decoded?.jwt?.organization?.slug) {
13230
+ webappUrl = buildWebappUrl(
13231
+ decoded.host,
13232
+ decoded.jwt.organization.slug,
13233
+ result.commandId
13234
+ );
13235
+ }
13236
+ }
13237
+ return {
13238
+ success: true,
13239
+ commandId: result.commandId,
13240
+ commandName: result.name,
13241
+ webappUrl
13242
+ };
13243
+ } catch (e) {
13244
+ return {
13245
+ success: false,
13246
+ error: `Error creating command: ${e instanceof Error ? e.message : "Unknown error"}`
13247
+ };
13248
+ }
13249
+ }
13250
+
13251
+ // apps/cli/src/application/useCases/CreateCommandFromPlaybookUseCase.ts
13252
+ var CreateCommandFromPlaybookUseCase = class {
13253
+ constructor(gateway) {
13254
+ this.gateway = gateway;
13255
+ }
13256
+ async execute(playbook) {
13257
+ const space = await this.gateway.getGlobalSpace();
13258
+ const command12 = await this.gateway.createCommand(space.id, {
13259
+ name: playbook.name,
13260
+ summary: playbook.summary,
13261
+ whenToUse: playbook.whenToUse,
13262
+ contextValidationCheckpoints: playbook.contextValidationCheckpoints,
13263
+ steps: playbook.steps.map((step) => ({
13264
+ name: step.name,
13265
+ description: step.description,
13266
+ codeSnippet: step.codeSnippet
13267
+ }))
13268
+ });
13269
+ return {
13270
+ commandId: command12.id,
13271
+ name: command12.name,
13272
+ slug: command12.slug
13273
+ };
13274
+ }
13275
+ };
13276
+
13277
+ // apps/cli/src/infra/commands/CreateCommandCommand.ts
13278
+ var createCommandCommand = (0, import_cmd_ts13.command)({
13279
+ name: "create",
13280
+ description: "Create a command from a playbook JSON file",
13281
+ args: {
13282
+ file: (0, import_cmd_ts13.positional)({
13283
+ displayName: "file",
13284
+ description: "Path to the command playbook JSON file",
13285
+ type: import_cmd_ts13.string
13286
+ })
13287
+ },
13288
+ handler: async ({ file }) => {
13289
+ try {
13290
+ const packmindLogger = new PackmindLogger("PackmindCLI", "info" /* INFO */);
13291
+ const hexa = new PackmindCliHexa(packmindLogger);
13292
+ const gateway = hexa.getPackmindGateway();
13293
+ const useCase = new CreateCommandFromPlaybookUseCase(gateway);
13294
+ const result = await createCommandHandler(file, useCase);
13295
+ if (result.success) {
13296
+ logSuccessConsole(
13297
+ `Command "${result.commandName}" created successfully (ID: ${result.commandId})`
13298
+ );
13299
+ if (result.webappUrl) {
13300
+ logConsole("");
13301
+ logConsole(`View it in the webapp: ${result.webappUrl}`);
13302
+ }
13303
+ process.exit(0);
13304
+ } else {
13305
+ logErrorConsole(`Failed to create command: ${result.error}`);
13306
+ process.exit(1);
13307
+ }
13308
+ } catch (e) {
13309
+ logErrorConsole(
13310
+ `Error: ${e instanceof Error ? e.message : "Unknown error"}`
13311
+ );
13312
+ process.exit(1);
13313
+ }
13314
+ }
13315
+ });
13316
+
13317
+ // apps/cli/src/infra/commands/CommandsCommand.ts
13318
+ var commandsCommand = (0, import_cmd_ts14.subcommands)({
13319
+ name: "commands",
13320
+ description: "Manage commands",
13321
+ cmds: {
13322
+ create: createCommandCommand
12488
13323
  }
12489
13324
  });
12490
13325
 
@@ -12494,20 +13329,20 @@ function findEnvFile() {
12494
13329
  const currentDir = process.cwd();
12495
13330
  const gitService = new GitService();
12496
13331
  const gitRoot = gitService.getGitRepositoryRootSync(currentDir);
12497
- const filesystemRoot = path11.parse(currentDir).root;
13332
+ const filesystemRoot = path12.parse(currentDir).root;
12498
13333
  const stopDir = gitRoot ?? filesystemRoot;
12499
13334
  let searchDir = currentDir;
12500
- let parentDir = path11.dirname(searchDir);
13335
+ let parentDir = path12.dirname(searchDir);
12501
13336
  while (searchDir !== parentDir) {
12502
- const envPath2 = path11.join(searchDir, ".env");
12503
- if (fs12.existsSync(envPath2)) {
13337
+ const envPath2 = path12.join(searchDir, ".env");
13338
+ if (fs15.existsSync(envPath2)) {
12504
13339
  return envPath2;
12505
13340
  }
12506
13341
  if (searchDir === stopDir) {
12507
13342
  return null;
12508
13343
  }
12509
13344
  searchDir = parentDir;
12510
- parentDir = path11.dirname(searchDir);
13345
+ parentDir = path12.dirname(searchDir);
12511
13346
  }
12512
13347
  return null;
12513
13348
  }
@@ -12524,10 +13359,10 @@ if (hasEmbeddedWasmFiles()) {
12524
13359
  }
12525
13360
  var args = process.argv.slice(2);
12526
13361
  if (args.includes("--version") || args.includes("-v")) {
12527
- console.log(`packmind-cli version ${CLI_VERSION}`);
13362
+ logConsole(`packmind-cli version ${CLI_VERSION}`);
12528
13363
  process.exit(0);
12529
13364
  }
12530
- var app = (0, import_cmd_ts10.subcommands)({
13365
+ var app = (0, import_cmd_ts15.subcommands)({
12531
13366
  name: "packmind-cli",
12532
13367
  description: "Packmind CLI tool",
12533
13368
  cmds: {
@@ -12540,10 +13375,12 @@ var app = (0, import_cmd_ts10.subcommands)({
12540
13375
  logout: logoutCommand,
12541
13376
  whoami: whoamiCommand,
12542
13377
  "setup-mcp": setupMcpCommand,
12543
- skills: skillsCommand
13378
+ skills: skillsCommand,
13379
+ standards: standardsCommand,
13380
+ commands: commandsCommand
12544
13381
  }
12545
13382
  });
12546
- (0, import_cmd_ts10.run)(app, args).catch((error) => {
13383
+ (0, import_cmd_ts15.run)(app, args).catch((error) => {
12547
13384
  logErrorConsole(error.message);
12548
13385
  process.exit(1);
12549
13386
  });