@jvittechs/j 1.0.16 → 1.0.18
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 +119 -43
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -169,7 +169,7 @@ import { basename as basename4 } from "path";
|
|
|
169
169
|
// package.json
|
|
170
170
|
var package_default = {
|
|
171
171
|
name: "@jvittechs/j",
|
|
172
|
-
version: "1.0.
|
|
172
|
+
version: "1.0.18",
|
|
173
173
|
description: "A unified CLI tool for JV-IT TECHS developers to manage Jai1 Framework. Supports both `j` and `jai1` commands. Please contact TeamAI for usage instructions.",
|
|
174
174
|
type: "module",
|
|
175
175
|
bin: {
|
|
@@ -1140,6 +1140,15 @@ function getMigrationIDEs() {
|
|
|
1140
1140
|
return Object.keys(IDE_MIGRATION_CONFIGS);
|
|
1141
1141
|
}
|
|
1142
1142
|
|
|
1143
|
+
// src/utils/heading-utils.ts
|
|
1144
|
+
function downshiftHeadings(content) {
|
|
1145
|
+
return content.replace(/^(#{1,5})\s/gm, (_match, hashes) => "#" + hashes + " ");
|
|
1146
|
+
}
|
|
1147
|
+
function extractBody(content) {
|
|
1148
|
+
const match = content.match(/^---\n[\s\S]*?\n---\n?([\s\S]*)$/);
|
|
1149
|
+
return match ? match[1].trim() : content.trim();
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1143
1152
|
// src/services/migrate-ide.service.ts
|
|
1144
1153
|
var MigrateIdeService = class {
|
|
1145
1154
|
projectPath;
|
|
@@ -1248,9 +1257,10 @@ var MigrateIdeService = class {
|
|
|
1248
1257
|
return items;
|
|
1249
1258
|
}
|
|
1250
1259
|
/**
|
|
1251
|
-
* Generate
|
|
1260
|
+
* Generate copied content for IDE rule file.
|
|
1261
|
+
* Reads the actual source file and combines IDE-specific frontmatter with the body content.
|
|
1252
1262
|
*/
|
|
1253
|
-
|
|
1263
|
+
async generateCopiedContent(ide, sourceItem) {
|
|
1254
1264
|
const config = IDE_MIGRATION_CONFIGS[ide];
|
|
1255
1265
|
if (!config) throw new Error(`Unknown IDE: ${ide}`);
|
|
1256
1266
|
const frontmatter = config.generateFrontmatter({
|
|
@@ -1260,14 +1270,15 @@ var MigrateIdeService = class {
|
|
|
1260
1270
|
alwaysApply: sourceItem.alwaysApply,
|
|
1261
1271
|
sourceFile: sourceItem.relativePath
|
|
1262
1272
|
});
|
|
1263
|
-
const
|
|
1273
|
+
const sourceContent = await fs5.readFile(sourceItem.filepath, "utf-8");
|
|
1274
|
+
const bodyContent = extractBody(sourceContent);
|
|
1264
1275
|
if (frontmatter) {
|
|
1265
1276
|
return `${frontmatter}
|
|
1266
1277
|
|
|
1267
|
-
${
|
|
1278
|
+
${bodyContent}
|
|
1268
1279
|
`;
|
|
1269
1280
|
}
|
|
1270
|
-
return `${
|
|
1281
|
+
return `${bodyContent}
|
|
1271
1282
|
`;
|
|
1272
1283
|
}
|
|
1273
1284
|
/**
|
|
@@ -1311,12 +1322,15 @@ ${reference}
|
|
|
1311
1322
|
}
|
|
1312
1323
|
const lines = [
|
|
1313
1324
|
"# AGENTS.md",
|
|
1314
|
-
"",
|
|
1315
|
-
"> Auto-generated by jai1 ide sync for OpenCode",
|
|
1316
1325
|
""
|
|
1317
1326
|
];
|
|
1318
1327
|
for (const rule of rules) {
|
|
1319
|
-
|
|
1328
|
+
const content = await fs5.readFile(rule.filepath, "utf-8");
|
|
1329
|
+
const body = extractBody(content);
|
|
1330
|
+
if (body.trim()) {
|
|
1331
|
+
lines.push(downshiftHeadings(body));
|
|
1332
|
+
lines.push("");
|
|
1333
|
+
}
|
|
1320
1334
|
}
|
|
1321
1335
|
lines.push("");
|
|
1322
1336
|
await fs5.writeFile(agentsPath, lines.join("\n"), "utf-8");
|
|
@@ -1372,8 +1386,8 @@ ${reference}
|
|
|
1372
1386
|
status = "updated";
|
|
1373
1387
|
} catch {
|
|
1374
1388
|
}
|
|
1375
|
-
const
|
|
1376
|
-
await fs5.writeFile(targetPath,
|
|
1389
|
+
const copiedContent = await this.generateCopiedContent(ide, item);
|
|
1390
|
+
await fs5.writeFile(targetPath, copiedContent, "utf-8");
|
|
1377
1391
|
return {
|
|
1378
1392
|
source: item,
|
|
1379
1393
|
targetIDE: ide,
|
|
@@ -3425,13 +3439,14 @@ async function resetSettings(groupKeys) {
|
|
|
3425
3439
|
import { Command as Command9 } from "commander";
|
|
3426
3440
|
import { checkbox as checkbox2, confirm as confirm3 } from "@inquirer/prompts";
|
|
3427
3441
|
function createSyncSubcommand() {
|
|
3428
|
-
const cmd = new Command9("sync").description("Sync .jai1 content to IDE directories (Cursor, Windsurf, Claude Code, etc.)").option("--
|
|
3442
|
+
const cmd = new Command9("sync").description("Sync .jai1 content to IDE directories (Cursor, Windsurf, Claude Code, etc.)").option("--ides <ides...>", "Target IDEs (cursor, windsurf, antigravity, claudecode, opencode)").option("--type <types...>", "Content types (rules, workflows, commands)").option("--dry-run", "Preview changes without writing files").option("-y, --yes", "Headless mode (skip all prompts)").option("--all", "Select all available IDEs").action(async (options) => {
|
|
3429
3443
|
await runSync(options);
|
|
3430
3444
|
});
|
|
3431
3445
|
return cmd;
|
|
3432
3446
|
}
|
|
3433
3447
|
async function runSync(options) {
|
|
3434
3448
|
const service = new MigrateIdeService();
|
|
3449
|
+
const headless = options.yes === true;
|
|
3435
3450
|
console.log("\n\u{1F504} Sync rules and workflows to IDE(s)\n");
|
|
3436
3451
|
console.log("\u{1F4C1} Scanning .jai1/ directory...");
|
|
3437
3452
|
console.log(" \u2022 .jai1/rule-preset/ (active rule preset)");
|
|
@@ -3447,8 +3462,14 @@ async function runSync(options) {
|
|
|
3447
3462
|
console.log(`\u2713 Found: ${content.rules.length} rules, ${content.workflows.length} workflows
|
|
3448
3463
|
`);
|
|
3449
3464
|
let selectedIdes;
|
|
3450
|
-
if (options.
|
|
3451
|
-
selectedIdes =
|
|
3465
|
+
if (options.all) {
|
|
3466
|
+
selectedIdes = getMigrationIDEs();
|
|
3467
|
+
} else if (options.ides && options.ides.length > 0) {
|
|
3468
|
+
selectedIdes = options.ides;
|
|
3469
|
+
} else if (headless) {
|
|
3470
|
+
throw new Error(
|
|
3471
|
+
"Headless mode (-y) requires --ides or --all flag.\nExamples:\n j ide sync --ides cursor windsurf -y\n j ide sync --all -y"
|
|
3472
|
+
);
|
|
3452
3473
|
} else {
|
|
3453
3474
|
const ideChoices = getMigrationIDEs().map((ide) => {
|
|
3454
3475
|
const config = IDE_MIGRATION_CONFIGS[ide];
|
|
@@ -3471,6 +3492,8 @@ async function runSync(options) {
|
|
|
3471
3492
|
let selectedTypes;
|
|
3472
3493
|
if (options.type && options.type.length > 0) {
|
|
3473
3494
|
selectedTypes = options.type;
|
|
3495
|
+
} else if (headless) {
|
|
3496
|
+
selectedTypes = ["rules", "workflows", "commands"];
|
|
3474
3497
|
} else {
|
|
3475
3498
|
const typeChoices = [
|
|
3476
3499
|
{ name: `Rules (${content.rules.length} files)`, value: "rules" },
|
|
@@ -3500,13 +3523,15 @@ async function runSync(options) {
|
|
|
3500
3523
|
if (options.dryRun) {
|
|
3501
3524
|
console.log("\u{1F50D} DRY RUN - No files will be written\n");
|
|
3502
3525
|
}
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3526
|
+
if (!headless) {
|
|
3527
|
+
const confirmed = await confirm3({
|
|
3528
|
+
message: "Proceed with sync?",
|
|
3529
|
+
default: true
|
|
3530
|
+
});
|
|
3531
|
+
if (!confirmed) {
|
|
3532
|
+
console.log("\n\u274C Sync cancelled.\n");
|
|
3533
|
+
process.exit(0);
|
|
3534
|
+
}
|
|
3510
3535
|
}
|
|
3511
3536
|
console.log("\n\u{1F504} Syncing...\n");
|
|
3512
3537
|
let completed = 0;
|
|
@@ -11968,7 +11993,7 @@ async function applyAgentsMdFormat(bundle) {
|
|
|
11968
11993
|
import { Command as Command63 } from "commander";
|
|
11969
11994
|
import { promises as fs25 } from "fs";
|
|
11970
11995
|
import { join as join15 } from "path";
|
|
11971
|
-
import {
|
|
11996
|
+
import { search, confirm as confirm11, checkbox as checkbox5 } from "@inquirer/prompts";
|
|
11972
11997
|
|
|
11973
11998
|
// src/services/rules-generator.service.ts
|
|
11974
11999
|
var RulesGeneratorService = class {
|
|
@@ -12053,7 +12078,7 @@ ${body.trim()}
|
|
|
12053
12078
|
`;
|
|
12054
12079
|
}
|
|
12055
12080
|
/**
|
|
12056
|
-
* Generate Antigravity format (.md files with trigger metadata +
|
|
12081
|
+
* Generate Antigravity format (.md files with trigger metadata + actual content)
|
|
12057
12082
|
*/
|
|
12058
12083
|
generateAntigravityFiles(bundle, format) {
|
|
12059
12084
|
const files = [];
|
|
@@ -12084,9 +12109,7 @@ ${body.trim()}
|
|
|
12084
12109
|
}
|
|
12085
12110
|
const antigravityFrontmatter = `---
|
|
12086
12111
|
trigger: ${trigger}
|
|
12087
|
-
|
|
12088
|
-
|
|
12089
|
-
@AGENTS.md`;
|
|
12112
|
+
---`;
|
|
12090
12113
|
return `${antigravityFrontmatter}
|
|
12091
12114
|
|
|
12092
12115
|
${body.trim()}
|
|
@@ -12156,7 +12179,7 @@ ${body.trim()}
|
|
|
12156
12179
|
const content = bundle.files[filename];
|
|
12157
12180
|
const withoutFrontmatter = this.removeFrontmatter(content);
|
|
12158
12181
|
if (withoutFrontmatter.trim()) {
|
|
12159
|
-
sections.push(withoutFrontmatter.trim());
|
|
12182
|
+
sections.push(downshiftHeadings(withoutFrontmatter.trim()));
|
|
12160
12183
|
sections.push("\n");
|
|
12161
12184
|
}
|
|
12162
12185
|
}
|
|
@@ -12481,7 +12504,7 @@ Restoring backup from ${metadata.timestamp}...`);
|
|
|
12481
12504
|
|
|
12482
12505
|
// src/commands/rules/apply.ts
|
|
12483
12506
|
function createRulesApplyCommand() {
|
|
12484
|
-
return new Command63("apply").description("Apply rule preset to project with multi-IDE support").argument("[preset]", "Preset slug to apply (optional)").option("--ides <ides>",
|
|
12507
|
+
return new Command63("apply").description("Apply rule preset to project with multi-IDE support").argument("[preset]", "Preset slug to apply (optional)").option("--ides <ides>", 'Comma-separated list of IDE formats (cursor,windsurf,antigravity,claude,agentsmd,gemini) or "all"').option("--skip-backup", "Skip backup creation").option("-y, --yes", "Skip all confirmations (auto mode)").action(async (presetSlug, options) => {
|
|
12485
12508
|
const configService = new ConfigService();
|
|
12486
12509
|
const config = await configService.load();
|
|
12487
12510
|
if (!config) {
|
|
@@ -12493,7 +12516,12 @@ function createRulesApplyCommand() {
|
|
|
12493
12516
|
const skipBackup = options.skipBackup === true;
|
|
12494
12517
|
let selectedIdes = [];
|
|
12495
12518
|
if (options.ides) {
|
|
12496
|
-
|
|
12519
|
+
const idesValue = options.ides;
|
|
12520
|
+
if (idesValue.toLowerCase() === "all") {
|
|
12521
|
+
selectedIdes = generatorService.getAvailableIdes();
|
|
12522
|
+
} else {
|
|
12523
|
+
selectedIdes = idesValue.split(",").map((ide) => ide.trim()).filter((ide) => generatorService.isValidIde(ide));
|
|
12524
|
+
}
|
|
12497
12525
|
if (selectedIdes.length === 0) {
|
|
12498
12526
|
throw new ValidationError("No valid IDE formats specified");
|
|
12499
12527
|
}
|
|
@@ -12513,13 +12541,20 @@ function createRulesApplyCommand() {
|
|
|
12513
12541
|
console.log("No presets available.");
|
|
12514
12542
|
return;
|
|
12515
12543
|
}
|
|
12516
|
-
presetSlug = await
|
|
12517
|
-
message: "
|
|
12518
|
-
|
|
12519
|
-
|
|
12520
|
-
|
|
12521
|
-
|
|
12522
|
-
|
|
12544
|
+
presetSlug = await search({
|
|
12545
|
+
message: "Search and select a preset (type keywords to filter):",
|
|
12546
|
+
source: async (input5) => {
|
|
12547
|
+
const keywords = (input5 || "").toLowerCase().split(/\s+/).filter(Boolean);
|
|
12548
|
+
const filtered = keywords.length === 0 ? data.presets : data.presets.filter((p) => {
|
|
12549
|
+
const searchable = [p.name, p.description, p.slug, ...p.tags].join(" ").toLowerCase();
|
|
12550
|
+
return keywords.every((kw) => searchable.includes(kw));
|
|
12551
|
+
});
|
|
12552
|
+
return filtered.map((p) => ({
|
|
12553
|
+
name: `${p.name} - ${p.description}`,
|
|
12554
|
+
value: p.slug,
|
|
12555
|
+
description: `v${p.version} | ${p.tags.join(", ")}`
|
|
12556
|
+
}));
|
|
12557
|
+
},
|
|
12523
12558
|
theme: selectTheme
|
|
12524
12559
|
});
|
|
12525
12560
|
}
|
|
@@ -12542,7 +12577,9 @@ function createRulesApplyCommand() {
|
|
|
12542
12577
|
console.log(` Files: ${Object.keys(bundle.files).length}`);
|
|
12543
12578
|
if (selectedIdes.length === 0) {
|
|
12544
12579
|
if (autoMode) {
|
|
12545
|
-
|
|
12580
|
+
throw new ValidationError(
|
|
12581
|
+
"Headless mode (-y) requires --ides flag.\nExamples:\n j rules apply <preset> --ides cursor,antigravity -y\n j rules apply <preset> --ides all -y"
|
|
12582
|
+
);
|
|
12546
12583
|
} else {
|
|
12547
12584
|
const detectionService = new IdeDetectionService();
|
|
12548
12585
|
const suggestions = await detectionService.suggestIdes();
|
|
@@ -12719,13 +12756,52 @@ function createRulesApplyCommand() {
|
|
|
12719
12756
|
console.log(' 3. Run "jai1 rules sync" to regenerate IDE outputs');
|
|
12720
12757
|
console.log(" 4. Commit the rules to git");
|
|
12721
12758
|
console.log(' 5. Use "jai1 ide status" to check IDE configuration\n');
|
|
12759
|
+
const migrationIdeIds = getMigrationIDEs();
|
|
12760
|
+
const ideSyncMap = {
|
|
12761
|
+
"cursor": "cursor",
|
|
12762
|
+
"windsurf": "windsurf",
|
|
12763
|
+
"antigravity": "antigravity",
|
|
12764
|
+
"claude": "claudecode",
|
|
12765
|
+
"agentsmd": "opencode",
|
|
12766
|
+
"opencode": "opencode"
|
|
12767
|
+
};
|
|
12768
|
+
const migrationIdes = resolvedIdes.map((ide) => ideSyncMap[ide]).filter((ide) => !!ide && migrationIdeIds.includes(ide)).filter((ide, index, self) => self.indexOf(ide) === index);
|
|
12769
|
+
if (migrationIdes.length > 0) {
|
|
12770
|
+
console.log("\u{1F504} Auto-syncing .jai1/ content to IDE(s)...\n");
|
|
12771
|
+
try {
|
|
12772
|
+
const migrateService = new MigrateIdeService();
|
|
12773
|
+
const content = await migrateService.scanJai1Content();
|
|
12774
|
+
if (content.totalCount > 0) {
|
|
12775
|
+
const contentTypes = ["rules", "workflows", "commands"];
|
|
12776
|
+
const results = await migrateService.migrate(
|
|
12777
|
+
migrationIdes,
|
|
12778
|
+
contentTypes,
|
|
12779
|
+
content,
|
|
12780
|
+
(result) => {
|
|
12781
|
+
const icon = result.status === "created" ? "\u2713" : result.status === "updated" ? "\u21BB" : result.status === "error" ? "\u2717" : "\u25CB";
|
|
12782
|
+
console.log(` ${icon} ${result.targetPath}`);
|
|
12783
|
+
}
|
|
12784
|
+
);
|
|
12785
|
+
const created = results.filter((r) => r.status === "created").length;
|
|
12786
|
+
const updated = results.filter((r) => r.status === "updated").length;
|
|
12787
|
+
console.log(`
|
|
12788
|
+
\u2705 IDE sync complete! (${created} created, ${updated} updated)
|
|
12789
|
+
`);
|
|
12790
|
+
} else {
|
|
12791
|
+
console.log(" No .jai1/ content found to sync.\n");
|
|
12792
|
+
}
|
|
12793
|
+
} catch (error) {
|
|
12794
|
+
console.warn("\u26A0\uFE0F IDE sync failed:", error instanceof Error ? error.message : error);
|
|
12795
|
+
console.log(' You can manually run "j ide sync" to retry.\n');
|
|
12796
|
+
}
|
|
12797
|
+
}
|
|
12722
12798
|
});
|
|
12723
12799
|
}
|
|
12724
12800
|
|
|
12725
12801
|
// src/commands/rules/restore.ts
|
|
12726
12802
|
import { Command as Command64 } from "commander";
|
|
12727
12803
|
import { join as join16 } from "path";
|
|
12728
|
-
import { select as
|
|
12804
|
+
import { select as select5, confirm as confirm12 } from "@inquirer/prompts";
|
|
12729
12805
|
function createRulesRestoreCommand() {
|
|
12730
12806
|
return new Command64("restore").description("Restore rules from a backup").option("--latest", "Restore the most recent backup").option("-y, --yes", "Skip confirmation").action(async (options) => {
|
|
12731
12807
|
const backupService = new BackupService();
|
|
@@ -12740,7 +12816,7 @@ function createRulesRestoreCommand() {
|
|
|
12740
12816
|
console.log(`\u{1F4E6} Selected latest backup: ${selectedBackup.timestamp}`);
|
|
12741
12817
|
} else {
|
|
12742
12818
|
console.log("\u{1F4CB} Available backups:\n");
|
|
12743
|
-
const backupTimestamp = await
|
|
12819
|
+
const backupTimestamp = await select5({
|
|
12744
12820
|
message: "Select a backup to restore:",
|
|
12745
12821
|
choices: backups.map((backup) => ({
|
|
12746
12822
|
name: formatBackupInfo(backup),
|
|
@@ -13319,7 +13395,7 @@ function getInstallCommand(packageManager2) {
|
|
|
13319
13395
|
|
|
13320
13396
|
// src/commands/clean.ts
|
|
13321
13397
|
import { Command as Command69 } from "commander";
|
|
13322
|
-
import { confirm as confirm15, select as
|
|
13398
|
+
import { confirm as confirm15, select as select6 } from "@inquirer/prompts";
|
|
13323
13399
|
import { join as join19 } from "path";
|
|
13324
13400
|
function createCleanCommand() {
|
|
13325
13401
|
return new Command69("clean").description("Clean up backups, cache, and temporary files").option("-y, --yes", "Skip confirmation").option("--backups", "Clean only backup files").option("--all", "Clean all (backups + cache)").action(async (options) => {
|
|
@@ -13383,7 +13459,7 @@ async function handleClean(options) {
|
|
|
13383
13459
|
console.log(` Path: ${target.path}
|
|
13384
13460
|
`);
|
|
13385
13461
|
}
|
|
13386
|
-
const action = await
|
|
13462
|
+
const action = await select6({
|
|
13387
13463
|
message: "What do you want to clean?",
|
|
13388
13464
|
choices: [
|
|
13389
13465
|
...availableTargets.map(({ target, info }) => ({
|
|
@@ -14566,7 +14642,7 @@ function createClearBackupsCommand() {
|
|
|
14566
14642
|
|
|
14567
14643
|
// src/commands/vscode/index.ts
|
|
14568
14644
|
import { Command as Command76 } from "commander";
|
|
14569
|
-
import { checkbox as checkbox7, confirm as confirm18, select as
|
|
14645
|
+
import { checkbox as checkbox7, confirm as confirm18, select as select7 } from "@inquirer/prompts";
|
|
14570
14646
|
import fs29 from "fs/promises";
|
|
14571
14647
|
import path12 from "path";
|
|
14572
14648
|
import { existsSync as existsSync3 } from "fs";
|
|
@@ -14749,7 +14825,7 @@ async function interactiveMode2() {
|
|
|
14749
14825
|
console.log("\u2502 \u2022 Nh\u1EA5n ENTER \u0111\u1EC3 x\xE1c nh\u1EADn v\xE0 \xE1p d\u1EE5ng \u2502");
|
|
14750
14826
|
console.log("\u2502 \u2022 Nh\u1EA5n Ctrl+C \u0111\u1EC3 h\u1EE7y \u2502");
|
|
14751
14827
|
console.log("\u2570\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256F\n");
|
|
14752
|
-
const action = await
|
|
14828
|
+
const action = await select7({
|
|
14753
14829
|
message: "B\u1EA1n mu\u1ED1n l\xE0m g\xEC?",
|
|
14754
14830
|
choices: [
|
|
14755
14831
|
{ name: "\u2705 Enable c\xE1c nh\xF3m t\u1ED1i \u01B0u", value: "enable" },
|