@jvittechs/jai1-cli 0.1.89 → 0.1.91

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.
package/dist/cli.js CHANGED
@@ -33,7 +33,7 @@ var NetworkError = class extends Jai1Error {
33
33
  // package.json
34
34
  var package_default = {
35
35
  name: "@jvittechs/jai1-cli",
36
- version: "0.1.89",
36
+ version: "0.1.91",
37
37
  description: "A unified CLI tool for JV-IT TECHS developers to manage Jai1 Framework. Please contact TeamAI for usage instructions.",
38
38
  type: "module",
39
39
  bin: {
@@ -539,7 +539,11 @@ var ComponentsService = class {
539
539
  const bundleJson = gunzipSync(compressed).toString("utf-8");
540
540
  checksumContent = bundleJson;
541
541
  const bundle = JSON.parse(bundleJson);
542
- const presetDir = join2(targetDir, filepath);
542
+ const presetDir = join2(targetDir, "rule-preset");
543
+ try {
544
+ await fs2.rm(presetDir, { recursive: true, force: true });
545
+ } catch {
546
+ }
543
547
  await fs2.mkdir(presetDir, { recursive: true });
544
548
  await fs2.writeFile(
545
549
  join2(presetDir, "preset.json"),
@@ -879,7 +883,7 @@ var UnifiedApplyApp = ({
879
883
  const [searchQuery, setSearchQuery] = useState("");
880
884
  const [selectedPaths, setSelectedPaths] = useState(/* @__PURE__ */ new Set());
881
885
  const [cursorIndex, setCursorIndex] = useState(0);
882
- const [focusArea, setFocusArea] = useState("components");
886
+ const [focusArea, setFocusArea] = useState("packages");
883
887
  const [selectedPackageIndex, setSelectedPackageIndex] = useState(0);
884
888
  const [installProgress, setInstallProgress] = useState([]);
885
889
  const [installStats, setInstallStats] = useState({ total: 0, completed: 0, added: 0, updated: 0, failed: 0 });
@@ -922,9 +926,9 @@ var UnifiedApplyApp = ({
922
926
  return;
923
927
  }
924
928
  if (key.tab) {
925
- if (focusArea === "search") setFocusArea("packages");
926
- else if (focusArea === "packages") setFocusArea("components");
927
- else setFocusArea("search");
929
+ if (focusArea === "packages") setFocusArea("components");
930
+ else if (focusArea === "components") setFocusArea("search");
931
+ else setFocusArea("packages");
928
932
  return;
929
933
  }
930
934
  if (key.escape || input4 === "q") {
@@ -937,6 +941,19 @@ var UnifiedApplyApp = ({
937
941
  }
938
942
  return;
939
943
  }
944
+ if (focusArea !== "search") {
945
+ if (input4 === "a") {
946
+ setSelectedPaths((prev) => {
947
+ const next = new Set(prev);
948
+ filteredComponents.forEach((c) => next.add(c.filepath));
949
+ return next;
950
+ });
951
+ return;
952
+ } else if (input4 === "c") {
953
+ setSelectedPaths(/* @__PURE__ */ new Set());
954
+ return;
955
+ }
956
+ }
940
957
  if (focusArea === "components") {
941
958
  if (key.upArrow) {
942
959
  setCursorIndex((prev) => Math.max(0, prev - 1));
@@ -955,14 +972,6 @@ var UnifiedApplyApp = ({
955
972
  return next;
956
973
  });
957
974
  }
958
- } else if (input4 === "a") {
959
- setSelectedPaths((prev) => {
960
- const next = new Set(prev);
961
- filteredComponents.forEach((c) => next.add(c.filepath));
962
- return next;
963
- });
964
- } else if (input4 === "c") {
965
- setSelectedPaths(/* @__PURE__ */ new Set());
966
975
  }
967
976
  }
968
977
  if (focusArea === "packages") {
@@ -1067,7 +1076,7 @@ var UnifiedApplyApp = ({
1067
1076
  const isChecked = selectedPaths.has(comp.filepath);
1068
1077
  const isInstalled = installedPaths.has(comp.filepath);
1069
1078
  return /* @__PURE__ */ React3.createElement(Box2, { key: comp.filepath }, /* @__PURE__ */ React3.createElement(Text3, { color: isCursor ? "cyan" : "white" }, isCursor ? "\u276F " : " ", isChecked ? "[\u2713]" : "[ ]", " ", comp.filepath), /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, " ", isInstalled ? "\u2713 installed" : "\u25CB new"));
1070
- }), filteredComponents.length === 0 && /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, "No components match your search")), selectedPaths.size > 0 && /* @__PURE__ */ React3.createElement(Box2, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React3.createElement(Text3, { bold: true }, "Selected: ", selectedPaths.size, " components"), /* @__PURE__ */ React3.createElement(Box2, { flexDirection: "column", marginLeft: 2 }, Array.from(selectedPaths).slice(0, 4).map((fp) => /* @__PURE__ */ React3.createElement(Text3, { key: fp, dimColor: true }, "\u{1F4CC} ", fp)), selectedPaths.size > 4 && /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, " ... and ", selectedPaths.size - 4, " more"))), /* @__PURE__ */ React3.createElement(Box2, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 1 }, /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, "[Tab] Switch area \xB7 [\u2191\u2193] Navigate \xB7 [\u2423] Toggle \xB7 [a] Select all \xB7 [c] Clear \xB7 [Enter] Apply \xB7 [q] Quit")));
1079
+ }), filteredComponents.length === 0 && /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, "No components match your search")), selectedPaths.size > 0 && /* @__PURE__ */ React3.createElement(Box2, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React3.createElement(Text3, { bold: true }, "Selected: ", selectedPaths.size, " components"), /* @__PURE__ */ React3.createElement(Box2, { flexDirection: "column", marginLeft: 2 }, Array.from(selectedPaths).slice(0, 4).map((fp) => /* @__PURE__ */ React3.createElement(Text3, { key: fp, dimColor: true }, "\u{1F4CC} ", fp)), selectedPaths.size > 4 && /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, " ... and ", selectedPaths.size - 4, " more"))), /* @__PURE__ */ React3.createElement(Box2, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 1 }, /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, "[Tab] Switch area \xB7 [\u2191\u2193/\u2190\u2192] Navigate \xB7 [\u2423] Toggle \xB7 [A] Select all \xB7 [C] Clear \xB7 [Enter] Apply \xB7 [Q] Quit")));
1071
1080
  };
1072
1081
 
1073
1082
  // src/commands/apply.ts
@@ -2529,17 +2538,20 @@ trigger: ${trigger}
2529
2538
  name: "Claude Code",
2530
2539
  icon: "\u{1F916}",
2531
2540
  basePath: ".claude",
2532
- rulesPath: null,
2541
+ rulesPath: "rules",
2533
2542
  workflowsPath: null,
2534
2543
  commandsPath: "commands",
2535
2544
  fileExtension: ".md",
2536
2545
  generateFrontmatter: (opts) => {
2546
+ const lines = ["---"];
2537
2547
  if (opts.description) {
2538
- return `---
2539
- description: ${opts.description}
2540
- ---`;
2548
+ lines.push(`description: ${opts.description}`);
2549
+ }
2550
+ if (opts.globs && opts.globs.length > 0) {
2551
+ lines.push(`paths: ${opts.globs.join(", ")}`);
2541
2552
  }
2542
- return "";
2553
+ lines.push("---");
2554
+ return lines.join("\n");
2543
2555
  }
2544
2556
  },
2545
2557
  opencode: {
@@ -2575,7 +2587,9 @@ var MigrateIdeService = class {
2575
2587
  * Scan .jai1/ directory for content
2576
2588
  */
2577
2589
  async scanJai1Content() {
2578
- const rules = await this.scanContentType("rules");
2590
+ const manualRules = await this.scanContentType("rules");
2591
+ const presetRules = await this.scanRulePreset();
2592
+ const rules = [...presetRules, ...manualRules];
2579
2593
  const workflows = await this.scanContentType("workflows");
2580
2594
  const commands = [];
2581
2595
  return {
@@ -2585,6 +2599,42 @@ var MigrateIdeService = class {
2585
2599
  totalCount: rules.length + workflows.length + commands.length
2586
2600
  };
2587
2601
  }
2602
+ /**
2603
+ * Scan .jai1/rule-preset/ directory for rule preset files
2604
+ */
2605
+ async scanRulePreset() {
2606
+ const items = [];
2607
+ const presetDir = path3.join(this.jai1Path, "rule-preset");
2608
+ try {
2609
+ await fs6.access(presetDir);
2610
+ } catch {
2611
+ return items;
2612
+ }
2613
+ const files = await fs6.readdir(presetDir);
2614
+ for (const file of files) {
2615
+ if (!file.endsWith(".mdc")) continue;
2616
+ const filepath = path3.join(presetDir, file);
2617
+ const stat = await fs6.stat(filepath);
2618
+ if (!stat.isFile()) continue;
2619
+ const content = await fs6.readFile(filepath, "utf-8");
2620
+ let frontmatter = {};
2621
+ try {
2622
+ const { data } = matter2(content);
2623
+ frontmatter = data;
2624
+ } catch {
2625
+ }
2626
+ items.push({
2627
+ type: "rules",
2628
+ name: path3.basename(file, ".mdc"),
2629
+ filepath,
2630
+ relativePath: path3.relative(this.projectPath, filepath),
2631
+ description: frontmatter.description,
2632
+ globs: this.extractGlobs(frontmatter),
2633
+ alwaysApply: this.extractAlwaysApply(frontmatter)
2634
+ });
2635
+ }
2636
+ return items;
2637
+ }
2588
2638
  /**
2589
2639
  * Scan a specific content type
2590
2640
  */
@@ -2708,7 +2758,7 @@ ${reference}
2708
2758
  contentPath = config.rulesPath;
2709
2759
  break;
2710
2760
  case "workflows":
2711
- contentPath = config.workflowsPath;
2761
+ contentPath = config.workflowsPath ?? config.commandsPath;
2712
2762
  break;
2713
2763
  case "commands":
2714
2764
  contentPath = config.commandsPath;
@@ -2743,13 +2793,17 @@ async function runSync(options) {
2743
2793
  const service = new MigrateIdeService();
2744
2794
  console.log("\n\u{1F504} Sync rules and workflows to IDE(s)\n");
2745
2795
  console.log("\u{1F4C1} Scanning .jai1/ directory...");
2796
+ console.log(" \u2022 .jai1/rule-preset/ (active rule preset)");
2797
+ console.log(" \u2022 .jai1/rules/ (manual rules)");
2798
+ console.log(" \u2022 .jai1/workflows/\n");
2746
2799
  const content = await service.scanJai1Content();
2747
2800
  if (content.totalCount === 0) {
2748
- console.log("\n\u26A0\uFE0F No content found in .jai1/");
2749
- console.log(" \u{1F4A1} Create files in .jai1/rules/ or .jai1/workflows/ first.\n");
2801
+ console.log("\u26A0\uFE0F No content found in .jai1/");
2802
+ console.log(' \u{1F4A1} Run "jai1 rules apply" to apply a rule preset, or');
2803
+ console.log(" \u{1F4A1} Create files in .jai1/rules/ or .jai1/workflows/\n");
2750
2804
  process.exit(1);
2751
2805
  }
2752
- console.log(` Found: ${content.rules.length} rules, ${content.workflows.length} workflows
2806
+ console.log(`\u2713 Found: ${content.rules.length} rules, ${content.workflows.length} workflows
2753
2807
  `);
2754
2808
  let selectedIdes;
2755
2809
  if (options.ide && options.ide.length > 0) {
@@ -9428,6 +9482,23 @@ function createRulesApplyCommand() {
9428
9482
  }
9429
9483
  }
9430
9484
  console.log("\n\u{1F4DD} Applying preset...\n");
9485
+ const rulePresetDir = join9(process.cwd(), ".jai1", "rule-preset");
9486
+ try {
9487
+ await fs15.rm(rulePresetDir, { recursive: true, force: true });
9488
+ } catch {
9489
+ }
9490
+ await fs15.mkdir(rulePresetDir, { recursive: true });
9491
+ await fs15.writeFile(
9492
+ join9(rulePresetDir, "preset.json"),
9493
+ JSON.stringify(bundle.preset, null, 2),
9494
+ "utf-8"
9495
+ );
9496
+ for (const [filename, content] of Object.entries(bundle.files)) {
9497
+ const filePath = join9(rulePresetDir, filename);
9498
+ await fs15.mkdir(join9(filePath, ".."), { recursive: true });
9499
+ await fs15.writeFile(filePath, content, "utf-8");
9500
+ }
9501
+ console.log(`\u2713 Saved preset to .jai1/rule-preset/`);
9431
9502
  const allGeneratedFiles = [];
9432
9503
  for (const ideId of resolvedIdes) {
9433
9504
  try {
@@ -9498,9 +9569,9 @@ function createRulesApplyCommand() {
9498
9569
  }
9499
9570
  console.log("\n\u{1F4DD} Next steps:");
9500
9571
  console.log(" 1. Review generated files in your IDE");
9501
- console.log(" 2. Edit custom rules if needed (look for 09-custom.*)");
9502
- console.log(" 3. Commit the rules to git");
9503
- console.log(' 4. Use "jai1 rules sync" to regenerate after editing');
9572
+ console.log(" 2. Edit rules in .jai1/rule-preset/ (source of truth)");
9573
+ console.log(' 3. Run "jai1 rules sync" to regenerate IDE outputs');
9574
+ console.log(" 4. Commit the rules to git");
9504
9575
  console.log(' 5. Use "jai1 ide status" to check IDE configuration\n');
9505
9576
  });
9506
9577
  }
@@ -9667,17 +9738,21 @@ Detected ${detected.length} active IDE(s):
9667
9738
  throw new Error(`Failed to fetch preset: ${presetResponse.statusText}`);
9668
9739
  }
9669
9740
  const bundle = await presetResponse.json();
9670
- const sourceDir = join11(process.cwd(), ".cursor", "rules");
9671
- const sourceExists = await checkPathExists(sourceDir);
9672
- if (sourceExists) {
9673
- const files = await fs16.readdir(sourceDir);
9741
+ const rulePresetDir = join11(process.cwd(), ".jai1", "rule-preset");
9742
+ const presetExists = await checkPathExists(rulePresetDir);
9743
+ if (presetExists) {
9744
+ const files = await fs16.readdir(rulePresetDir);
9674
9745
  for (const file of files) {
9675
9746
  if (file.endsWith(".mdc")) {
9676
- const filePath = join11(sourceDir, file);
9747
+ const filePath = join11(rulePresetDir, file);
9677
9748
  const content = await fs16.readFile(filePath, "utf-8");
9678
9749
  bundle.files[file] = content;
9679
9750
  }
9680
9751
  }
9752
+ } else {
9753
+ console.log("\n\u26A0\uFE0F No rule preset found in .jai1/rule-preset/");
9754
+ console.log(' Run "jai1 rules apply" first to apply a preset.\n');
9755
+ return;
9681
9756
  }
9682
9757
  const generatorService = new RulesGeneratorService();
9683
9758
  for (const ideId of idesToSync) {
@@ -9711,12 +9786,12 @@ Detected ${detected.length} active IDE(s):
9711
9786
  console.log("\u{1F4A1} Next steps:");
9712
9787
  console.log(" \u2022 Your IDE may need to be restarted to pick up changes");
9713
9788
  console.log(' \u2022 Use "jai1 ide status" to verify IDE configuration');
9714
- console.log(" \u2022 Edit source files in .cursor/rules/ and sync again\n");
9789
+ console.log(" \u2022 Edit source files in .jai1/rule-preset/ and sync again\n");
9715
9790
  });
9716
9791
  }
9717
- async function checkPathExists(path8) {
9792
+ async function checkPathExists(absolutePath) {
9718
9793
  try {
9719
- await fs16.access(join11(process.cwd(), path8));
9794
+ await fs16.access(absolutePath);
9720
9795
  return true;
9721
9796
  } catch {
9722
9797
  return false;
@@ -9744,10 +9819,43 @@ function createRulesInfoCommand() {
9744
9819
  return;
9745
9820
  }
9746
9821
  console.log("\u{1F4CB} Current Preset Information\n");
9747
- console.log(`Preset: ${projectConfig.preset}`);
9748
- console.log(`Version: ${projectConfig.version}`);
9822
+ const rulePresetDir = join12(process.cwd(), ".jai1", "rule-preset");
9823
+ const presetJsonPath = join12(rulePresetDir, "preset.json");
9824
+ let presetMetadata = null;
9825
+ let presetFiles = [];
9826
+ try {
9827
+ const presetContent = await fs17.readFile(presetJsonPath, "utf-8");
9828
+ presetMetadata = JSON.parse(presetContent);
9829
+ const files = await fs17.readdir(rulePresetDir);
9830
+ presetFiles = files.filter((f) => f.endsWith(".mdc"));
9831
+ } catch {
9832
+ }
9833
+ if (presetMetadata) {
9834
+ console.log(`Preset: ${presetMetadata.name} (${presetMetadata.slug})`);
9835
+ console.log(`Version: ${presetMetadata.version}`);
9836
+ console.log(`Description: ${presetMetadata.description}`);
9837
+ if (presetMetadata.tags && presetMetadata.tags.length > 0) {
9838
+ console.log(`Tags: ${presetMetadata.tags.join(", ")}`);
9839
+ }
9840
+ } else {
9841
+ console.log(`Preset: ${projectConfig.preset}`);
9842
+ console.log(`Version: ${projectConfig.version}`);
9843
+ }
9749
9844
  console.log(`Applied at: ${new Date(projectConfig.appliedAt).toLocaleString()}`);
9750
- console.log(`Custom rules: ${projectConfig.customContext}`);
9845
+ console.log(`
9846
+ Source of Truth:`);
9847
+ if (presetFiles.length > 0) {
9848
+ console.log(` \u{1F4C1} .jai1/rule-preset/ (${presetFiles.length} files)`);
9849
+ for (const file of presetFiles.slice(0, 5)) {
9850
+ console.log(` \u2022 ${file}`);
9851
+ }
9852
+ if (presetFiles.length > 5) {
9853
+ console.log(` ... and ${presetFiles.length - 5} more`);
9854
+ }
9855
+ } else {
9856
+ console.log(` \u26A0\uFE0F .jai1/rule-preset/ not found`);
9857
+ console.log(` Run "jai1 rules apply" to create it`);
9858
+ }
9751
9859
  if (projectConfig.ides && projectConfig.ides.length > 0) {
9752
9860
  console.log(`
9753
9861
  Configured IDEs (${projectConfig.ides.length}):`);
@@ -9772,9 +9880,9 @@ Available Backups (${projectConfig.backups.length}):`);
9772
9880
  }
9773
9881
  }
9774
9882
  console.log("\n\u2139\uFE0F Commands:");
9775
- console.log(' \u2022 "jai1 rules sync" - Regenerate outputs after editing');
9883
+ console.log(' \u2022 "jai1 rules sync" - Regenerate IDE outputs after editing .jai1/rule-preset/');
9776
9884
  console.log(' \u2022 "jai1 rules restore" - Restore from backup');
9777
- console.log(' \u2022 "jai1 rules apply" - Apply a different preset');
9885
+ console.log(' \u2022 "jai1 rules apply" - Apply a different preset (replaces current)');
9778
9886
  });
9779
9887
  }
9780
9888
  async function checkPathExists2(path8) {