@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 +149 -41
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
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.
|
|
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,
|
|
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("
|
|
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 === "
|
|
926
|
-
else if (focusArea === "
|
|
927
|
-
else setFocusArea("
|
|
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 [
|
|
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:
|
|
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
|
-
|
|
2539
|
-
|
|
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
|
-
|
|
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
|
|
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("\
|
|
2749
|
-
console.log(
|
|
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(
|
|
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
|
|
9502
|
-
console.log(
|
|
9503
|
-
console.log(
|
|
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
|
|
9671
|
-
const
|
|
9672
|
-
if (
|
|
9673
|
-
const files = await fs16.readdir(
|
|
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(
|
|
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 .
|
|
9789
|
+
console.log(" \u2022 Edit source files in .jai1/rule-preset/ and sync again\n");
|
|
9715
9790
|
});
|
|
9716
9791
|
}
|
|
9717
|
-
async function checkPathExists(
|
|
9792
|
+
async function checkPathExists(absolutePath) {
|
|
9718
9793
|
try {
|
|
9719
|
-
await fs16.access(
|
|
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
|
-
|
|
9748
|
-
|
|
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(`
|
|
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) {
|