@packmind/cli 0.9.0 → 0.10.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 +174 -85
  2. package/package.json +1 -1
package/main.cjs CHANGED
@@ -3852,7 +3852,7 @@ var require_package = __commonJS({
3852
3852
  "apps/cli/package.json"(exports2, module2) {
3853
3853
  module2.exports = {
3854
3854
  name: "@packmind/cli",
3855
- version: "0.9.0",
3855
+ version: "0.10.0",
3856
3856
  description: "A command-line interface for Packmind linting and code quality checks",
3857
3857
  private: false,
3858
3858
  bin: {
@@ -4034,8 +4034,23 @@ var UserJoinedOrganizationEvent = class extends PackmindEvent {
4034
4034
  }
4035
4035
  };
4036
4036
 
4037
- // packages/types/src/analytics/RecipeUsage.ts
4038
- var createRecipeUsageId = brandedIdFactory();
4037
+ // packages/types/src/accounts/events/TrialStartedEvent.ts
4038
+ var TrialStartedEvent = class extends PackmindEvent {
4039
+ static {
4040
+ this.eventName = "accounts.trial.started";
4041
+ }
4042
+ };
4043
+
4044
+ // packages/types/src/accounts/events/TrialAccountActivatedEvent.ts
4045
+ var TrialAccountActivatedEvent = class extends PackmindEvent {
4046
+ static {
4047
+ this.eventName = "accounts.trial.activated";
4048
+ }
4049
+ };
4050
+
4051
+ // packages/types/src/accounts/TrialActivationToken.ts
4052
+ var createTrialActivationTokenId = brandedIdFactory();
4053
+ var createTrialActivationToken = brandedIdFactory();
4039
4054
 
4040
4055
  // packages/types/src/recipes/RecipeId.ts
4041
4056
  var createRecipeId = brandedIdFactory();
@@ -9313,6 +9328,24 @@ function mergeSectionsIntoFileContent(existingContent, sections) {
9313
9328
  const endMarker = `<!-- end: ${section.key} -->`;
9314
9329
  const startIndex = result.indexOf(startMarker);
9315
9330
  const endIndex = result.indexOf(endMarker);
9331
+ if (section.content.trim() === "") {
9332
+ if (startIndex !== -1 && endIndex !== -1 && endIndex > startIndex) {
9333
+ const before = result.substring(0, startIndex);
9334
+ const after = result.substring(endIndex + endMarker.length);
9335
+ const trimmedBefore = before.trimEnd();
9336
+ const trimmedAfter = after.trimStart();
9337
+ if (trimmedBefore === "" && trimmedAfter === "") {
9338
+ result = "";
9339
+ } else if (trimmedBefore === "") {
9340
+ result = trimmedAfter;
9341
+ } else if (trimmedAfter === "") {
9342
+ result = trimmedBefore + "\n";
9343
+ } else {
9344
+ result = trimmedBefore + "\n" + trimmedAfter;
9345
+ }
9346
+ }
9347
+ continue;
9348
+ }
9316
9349
  if (startIndex !== -1 && endIndex !== -1 && endIndex > startIndex) {
9317
9350
  const before = result.substring(0, startIndex + startMarker.length);
9318
9351
  const after = result.substring(endIndex);
@@ -9448,18 +9481,26 @@ var InstallPackagesUseCase = class {
9448
9481
  sections
9449
9482
  );
9450
9483
  if (currentContent !== mergedContent) {
9451
- await fs4.writeFile(fullPath, mergedContent, "utf-8");
9452
- if (fileExists) {
9453
- result.filesUpdated++;
9484
+ if (this.isEffectivelyEmpty(mergedContent) && fileExists) {
9485
+ await fs4.unlink(fullPath);
9486
+ result.filesDeleted++;
9454
9487
  } else {
9455
- result.filesCreated++;
9488
+ await fs4.writeFile(fullPath, mergedContent, "utf-8");
9489
+ if (fileExists) {
9490
+ result.filesUpdated++;
9491
+ } else {
9492
+ result.filesCreated++;
9493
+ }
9456
9494
  }
9457
9495
  }
9458
9496
  }
9459
9497
  async deleteFile(baseDirectory, filePath, result) {
9460
9498
  const fullPath = path5.join(baseDirectory, filePath);
9461
- const fileExists = await this.fileExists(fullPath);
9462
- if (fileExists) {
9499
+ const stat4 = await fs4.stat(fullPath).catch(() => null);
9500
+ if (stat4?.isDirectory()) {
9501
+ await fs4.rm(fullPath, { recursive: true, force: true });
9502
+ result.filesDeleted++;
9503
+ } else if (stat4?.isFile()) {
9463
9504
  await fs4.unlink(fullPath);
9464
9505
  result.filesDeleted++;
9465
9506
  }
@@ -9511,6 +9552,17 @@ ${newSectionContent}
9511
9552
  ${endMarker}`;
9512
9553
  }
9513
9554
  }
9555
+ /**
9556
+ * Checks if content is effectively empty (only whitespace and empty section markers).
9557
+ * This helps determine if a file should be deleted after section removal.
9558
+ */
9559
+ isEffectivelyEmpty(content) {
9560
+ const withoutEmptySections = content.replace(
9561
+ /<!--\s*start:\s*[^-]+?\s*-->\s*<!--\s*end:\s*[^-]+?\s*-->/g,
9562
+ ""
9563
+ );
9564
+ return withoutEmptySections.trim() === "";
9565
+ }
9514
9566
  /**
9515
9567
  * Escapes special regex characters in a string
9516
9568
  */
@@ -9905,7 +9957,8 @@ var WhoamiUseCase = class {
9905
9957
  var ALL_AGENTS = [
9906
9958
  { type: "claude", name: "Claude Code" },
9907
9959
  { type: "cursor", name: "Cursor" },
9908
- { type: "vscode", name: "VS Code" }
9960
+ { type: "vscode", name: "VS Code" },
9961
+ { type: "continue", name: "Continue.dev" }
9909
9962
  ];
9910
9963
  var SetupMcpUseCase = class {
9911
9964
  constructor(deps) {
@@ -9963,6 +10016,8 @@ var McpConfigService = class {
9963
10016
  return this.installCursorMcp(config);
9964
10017
  case "vscode":
9965
10018
  return this.installVSCodeMcp(config);
10019
+ case "continue":
10020
+ return this.installContinueMcp(config);
9966
10021
  default:
9967
10022
  return { success: false, error: `Unknown agent: ${agent}` };
9968
10023
  }
@@ -10021,6 +10076,22 @@ var McpConfigService = class {
10021
10076
  return { success: false, error: errorMessage };
10022
10077
  }
10023
10078
  }
10079
+ installContinueMcp(config) {
10080
+ try {
10081
+ const continueDir = path7.join(this.projectDir, ".continue");
10082
+ const mcpServersDir = path7.join(continueDir, "mcpServers");
10083
+ if (!fs7.existsSync(mcpServersDir)) {
10084
+ fs7.mkdirSync(mcpServersDir, { recursive: true });
10085
+ }
10086
+ const continueConfigPath = path7.join(mcpServersDir, "packmind.yaml");
10087
+ const continueConfig = this.buildContinueYamlConfig(config);
10088
+ fs7.writeFileSync(continueConfigPath, continueConfig);
10089
+ return { success: true };
10090
+ } catch (error) {
10091
+ const errorMessage = error instanceof Error ? error.message : String(error);
10092
+ return { success: false, error: errorMessage };
10093
+ }
10094
+ }
10024
10095
  buildCursorConfig(config) {
10025
10096
  return {
10026
10097
  mcpServers: {
@@ -10047,6 +10118,19 @@ var McpConfigService = class {
10047
10118
  inputs: []
10048
10119
  };
10049
10120
  }
10121
+ buildContinueYamlConfig(config) {
10122
+ return `name: Packmind MCP Server
10123
+ version: 0.0.1
10124
+ schema: v1
10125
+ mcpServers:
10126
+ - name: Packmind
10127
+ type: streamable-http
10128
+ url: ${config.url}
10129
+ requestOptions:
10130
+ headers:
10131
+ Authorization: "Bearer ${config.accessToken}"
10132
+ `;
10133
+ }
10050
10134
  readExistingJsonConfig(filePath) {
10051
10135
  try {
10052
10136
  if (fs7.existsSync(filePath)) {
@@ -10810,6 +10894,34 @@ var path10 = __toESM(require("path"));
10810
10894
  var import_cmd_ts2 = __toESM(require_cjs());
10811
10895
 
10812
10896
  // apps/cli/src/infra/commands/installPackagesHandler.ts
10897
+ async function notifyDistributionIfInGitRepo(params) {
10898
+ const { packmindCliHexa, cwd, packages, log } = params;
10899
+ const gitRoot = await packmindCliHexa.tryGetGitRepositoryRoot(cwd);
10900
+ if (!gitRoot) {
10901
+ return false;
10902
+ }
10903
+ try {
10904
+ const gitRemoteUrl = packmindCliHexa.getGitRemoteUrlFromPath(gitRoot);
10905
+ const gitBranch = packmindCliHexa.getCurrentBranch(gitRoot);
10906
+ let relativePath = cwd.startsWith(gitRoot) ? cwd.slice(gitRoot.length) : "/";
10907
+ if (!relativePath.startsWith("/")) {
10908
+ relativePath = "/" + relativePath;
10909
+ }
10910
+ if (!relativePath.endsWith("/")) {
10911
+ relativePath = relativePath + "/";
10912
+ }
10913
+ await packmindCliHexa.notifyDistribution({
10914
+ distributedPackages: packages,
10915
+ gitRemoteUrl,
10916
+ gitBranch,
10917
+ relativePath
10918
+ });
10919
+ log("Successfully notified Packmind of the new distribution");
10920
+ return true;
10921
+ } catch {
10922
+ return false;
10923
+ }
10924
+ }
10813
10925
  async function listPackagesHandler(_args, deps) {
10814
10926
  const { packmindCliHexa, exit, log, error } = deps;
10815
10927
  try {
@@ -11025,29 +11137,14 @@ async function executeInstallForDirectory(directory, deps) {
11025
11137
  };
11026
11138
  }
11027
11139
  let notificationSent = false;
11028
- if (result.filesCreated > 0 || result.filesUpdated > 0) {
11029
- const gitRoot = await packmindCliHexa.tryGetGitRepositoryRoot(directory);
11030
- if (gitRoot) {
11031
- try {
11032
- const gitRemoteUrl = packmindCliHexa.getGitRemoteUrlFromPath(gitRoot);
11033
- const gitBranch = packmindCliHexa.getCurrentBranch(gitRoot);
11034
- let relativePath = directory.startsWith(gitRoot) ? directory.slice(gitRoot.length) : "/";
11035
- if (!relativePath.startsWith("/")) {
11036
- relativePath = "/" + relativePath;
11037
- }
11038
- if (!relativePath.endsWith("/")) {
11039
- relativePath = relativePath + "/";
11040
- }
11041
- await packmindCliHexa.notifyDistribution({
11042
- distributedPackages: configPackages,
11043
- gitRemoteUrl,
11044
- gitBranch,
11045
- relativePath
11046
- });
11047
- notificationSent = true;
11048
- } catch {
11140
+ if (result.filesCreated > 0 || result.filesUpdated > 0 || result.filesDeleted > 0) {
11141
+ notificationSent = await notifyDistributionIfInGitRepo({
11142
+ packmindCliHexa,
11143
+ cwd: directory,
11144
+ packages: configPackages,
11145
+ log: () => {
11049
11146
  }
11050
- }
11147
+ });
11051
11148
  }
11052
11149
  return {
11053
11150
  success: true,
@@ -11155,30 +11252,13 @@ added ${result.filesCreated} files, changed ${result.filesUpdated} files, remove
11155
11252
  };
11156
11253
  }
11157
11254
  let notificationSent = false;
11158
- if (result.filesCreated > 0 || result.filesUpdated > 0) {
11159
- const gitRoot = await packmindCliHexa.tryGetGitRepositoryRoot(cwd);
11160
- if (gitRoot) {
11161
- try {
11162
- const gitRemoteUrl = packmindCliHexa.getGitRemoteUrlFromPath(gitRoot);
11163
- const gitBranch = packmindCliHexa.getCurrentBranch(gitRoot);
11164
- let relativePath = cwd.startsWith(gitRoot) ? cwd.slice(gitRoot.length) : "/";
11165
- if (!relativePath.startsWith("/")) {
11166
- relativePath = "/" + relativePath;
11167
- }
11168
- if (!relativePath.endsWith("/")) {
11169
- relativePath = relativePath + "/";
11170
- }
11171
- await packmindCliHexa.notifyDistribution({
11172
- distributedPackages: allPackages,
11173
- gitRemoteUrl,
11174
- gitBranch,
11175
- relativePath
11176
- });
11177
- log("Successfully notified Packmind of the new distribution");
11178
- notificationSent = true;
11179
- } catch {
11180
- }
11181
- }
11255
+ if (result.filesCreated > 0 || result.filesUpdated > 0 || result.filesDeleted > 0) {
11256
+ notificationSent = await notifyDistributionIfInGitRepo({
11257
+ packmindCliHexa,
11258
+ cwd,
11259
+ packages: allPackages,
11260
+ log
11261
+ });
11182
11262
  }
11183
11263
  return {
11184
11264
  filesCreated: result.filesCreated,
@@ -11341,32 +11421,26 @@ async function uninstallPackagesHandler(args2, deps) {
11341
11421
  );
11342
11422
  let filesDeleted = 0;
11343
11423
  if (remainingPackages.length === 0) {
11344
- log("Removing all packages and cleaning up .packmind directory...");
11345
- const packmindDir = `${cwd}/.packmind`;
11346
- try {
11347
- const fs12 = await import("fs/promises");
11348
- const dirExists = await fs12.access(packmindDir).then(() => true).catch(() => false);
11349
- if (dirExists) {
11350
- const files = await fs12.readdir(packmindDir, { recursive: true });
11351
- filesDeleted = files.filter(
11352
- (f) => typeof f === "string" ? !f.endsWith("/") : true
11353
- ).length;
11354
- await fs12.rm(packmindDir, { recursive: true, force: true });
11355
- }
11356
- const agentsMdPath = `${cwd}/AGENTS.md`;
11357
- const agentsMdExists = await fs12.access(agentsMdPath).then(() => true).catch(() => false);
11358
- if (agentsMdExists) {
11359
- await fs12.unlink(agentsMdPath);
11360
- filesDeleted++;
11361
- }
11362
- } catch (err) {
11363
- error("\n\u26A0\uFE0F Warning: Failed to clean up some files:");
11364
- if (err instanceof Error) {
11365
- error(` ${err.message}`);
11366
- }
11367
- }
11424
+ log("Removing all packages and cleaning up...");
11425
+ const result = await packmindCliHexa.installPackages({
11426
+ baseDirectory: cwd,
11427
+ packagesSlugs: [],
11428
+ previousPackagesSlugs: configPackages
11429
+ });
11368
11430
  log(`
11369
- removed ${filesDeleted} files`);
11431
+ removed ${result.filesDeleted} files`);
11432
+ if (result.errors.length > 0) {
11433
+ log("\n\u26A0\uFE0F Errors encountered:");
11434
+ result.errors.forEach((err) => {
11435
+ log(` - ${err}`);
11436
+ });
11437
+ exit(1);
11438
+ return {
11439
+ filesDeleted: result.filesDeleted,
11440
+ packagesUninstalled: packagesToUninstall
11441
+ };
11442
+ }
11443
+ filesDeleted = result.filesDeleted;
11370
11444
  } else {
11371
11445
  const result = await packmindCliHexa.installPackages({
11372
11446
  baseDirectory: cwd,
@@ -11394,6 +11468,12 @@ removed ${result.filesDeleted} files`);
11394
11468
  filesDeleted = result.filesDeleted;
11395
11469
  }
11396
11470
  await packmindCliHexa.writeConfig(cwd, remainingPackages);
11471
+ await notifyDistributionIfInGitRepo({
11472
+ packmindCliHexa,
11473
+ cwd,
11474
+ packages: remainingPackages,
11475
+ log
11476
+ });
11397
11477
  log("");
11398
11478
  if (packagesToUninstall.length === 1) {
11399
11479
  log(`\u2713 Package '${packagesToUninstall[0]}' has been uninstalled.`);
@@ -11791,6 +11871,9 @@ var AgentDetectionService = class {
11791
11871
  if (this.isVSCodeAvailable()) {
11792
11872
  agents.push({ type: "vscode", name: "VS Code" });
11793
11873
  }
11874
+ if (this.isContinueAvailable()) {
11875
+ agents.push({ type: "continue", name: "Continue.dev" });
11876
+ }
11794
11877
  return agents;
11795
11878
  }
11796
11879
  isClaudeAvailable() {
@@ -11804,6 +11887,10 @@ var AgentDetectionService = class {
11804
11887
  const vscodeDir = path9.join(this.projectDir, ".vscode");
11805
11888
  return fs9.existsSync(vscodeDir);
11806
11889
  }
11890
+ isContinueAvailable() {
11891
+ const continueDir = path9.join(this.projectDir, ".continue");
11892
+ return fs9.existsSync(continueDir);
11893
+ }
11807
11894
  isCommandAvailable(command8) {
11808
11895
  try {
11809
11896
  const whichCommand = process.platform === "win32" ? "where" : "which";
@@ -11816,11 +11903,12 @@ var AgentDetectionService = class {
11816
11903
  };
11817
11904
 
11818
11905
  // apps/cli/src/infra/commands/SetupMcpCommand.ts
11819
- var VALID_AGENTS = ["copilot", "cursor", "claude"];
11906
+ var VALID_AGENTS = ["copilot", "cursor", "claude", "continue"];
11820
11907
  var agentArgToType = {
11821
11908
  copilot: "vscode",
11822
11909
  cursor: "cursor",
11823
- claude: "claude"
11910
+ claude: "claude",
11911
+ continue: "continue"
11824
11912
  };
11825
11913
  var AgentArgType = {
11826
11914
  from: async (input) => {
@@ -11836,7 +11924,8 @@ var AgentArgType = {
11836
11924
  var ALL_AGENTS2 = [
11837
11925
  { type: "claude", name: "Claude Code" },
11838
11926
  { type: "cursor", name: "Cursor" },
11839
- { type: "vscode", name: "VS Code" }
11927
+ { type: "vscode", name: "VS Code" },
11928
+ { type: "continue", name: "Continue.dev" }
11840
11929
  ];
11841
11930
  async function promptAgentsWithReadline(choices) {
11842
11931
  const input = fs10.createReadStream("/dev/tty");
@@ -11878,7 +11967,7 @@ var setupMcpCommand = (0, import_cmd_ts7.command)({
11878
11967
  type: (0, import_cmd_ts7.array)(AgentArgType),
11879
11968
  long: "target",
11880
11969
  short: "t",
11881
- description: "Target agent(s) to configure (copilot, cursor, or claude). Can be specified multiple times. If omitted, interactive mode is used."
11970
+ description: "Target agent(s) to configure (copilot, cursor, claude, or continue). Can be specified multiple times. If omitted, interactive mode is used."
11882
11971
  })
11883
11972
  },
11884
11973
  handler: async ({ targets }) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@packmind/cli",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "description": "A command-line interface for Packmind linting and code quality checks",
5
5
  "private": false,
6
6
  "bin": {