@jvittechs/j 1.0.17 → 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 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.17",
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: {
@@ -1322,8 +1322,6 @@ ${bodyContent}
1322
1322
  }
1323
1323
  const lines = [
1324
1324
  "# AGENTS.md",
1325
- "",
1326
- "> Auto-generated by jai1 ide sync for OpenCode",
1327
1325
  ""
1328
1326
  ];
1329
1327
  for (const rule of rules) {
@@ -3441,13 +3439,14 @@ async function resetSettings(groupKeys) {
3441
3439
  import { Command as Command9 } from "commander";
3442
3440
  import { checkbox as checkbox2, confirm as confirm3 } from "@inquirer/prompts";
3443
3441
  function createSyncSubcommand() {
3444
- const cmd = new Command9("sync").description("Sync .jai1 content to IDE directories (Cursor, Windsurf, Claude Code, etc.)").option("--ide <ides...>", "Target IDEs (cursor, windsurf, antigravity, claudecode, opencode)").option("--type <types...>", "Content types (rules, workflows, commands)").option("--dry-run", "Preview changes without writing files").action(async (options) => {
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) => {
3445
3443
  await runSync(options);
3446
3444
  });
3447
3445
  return cmd;
3448
3446
  }
3449
3447
  async function runSync(options) {
3450
3448
  const service = new MigrateIdeService();
3449
+ const headless = options.yes === true;
3451
3450
  console.log("\n\u{1F504} Sync rules and workflows to IDE(s)\n");
3452
3451
  console.log("\u{1F4C1} Scanning .jai1/ directory...");
3453
3452
  console.log(" \u2022 .jai1/rule-preset/ (active rule preset)");
@@ -3463,8 +3462,14 @@ async function runSync(options) {
3463
3462
  console.log(`\u2713 Found: ${content.rules.length} rules, ${content.workflows.length} workflows
3464
3463
  `);
3465
3464
  let selectedIdes;
3466
- if (options.ide && options.ide.length > 0) {
3467
- selectedIdes = options.ide;
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
+ );
3468
3473
  } else {
3469
3474
  const ideChoices = getMigrationIDEs().map((ide) => {
3470
3475
  const config = IDE_MIGRATION_CONFIGS[ide];
@@ -3487,6 +3492,8 @@ async function runSync(options) {
3487
3492
  let selectedTypes;
3488
3493
  if (options.type && options.type.length > 0) {
3489
3494
  selectedTypes = options.type;
3495
+ } else if (headless) {
3496
+ selectedTypes = ["rules", "workflows", "commands"];
3490
3497
  } else {
3491
3498
  const typeChoices = [
3492
3499
  { name: `Rules (${content.rules.length} files)`, value: "rules" },
@@ -3516,13 +3523,15 @@ async function runSync(options) {
3516
3523
  if (options.dryRun) {
3517
3524
  console.log("\u{1F50D} DRY RUN - No files will be written\n");
3518
3525
  }
3519
- const confirmed = await confirm3({
3520
- message: "Proceed with sync?",
3521
- default: true
3522
- });
3523
- if (!confirmed) {
3524
- console.log("\n\u274C Sync cancelled.\n");
3525
- process.exit(0);
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
+ }
3526
3535
  }
3527
3536
  console.log("\n\u{1F504} Syncing...\n");
3528
3537
  let completed = 0;
@@ -11984,7 +11993,7 @@ async function applyAgentsMdFormat(bundle) {
11984
11993
  import { Command as Command63 } from "commander";
11985
11994
  import { promises as fs25 } from "fs";
11986
11995
  import { join as join15 } from "path";
11987
- import { select as select5, confirm as confirm11, checkbox as checkbox5 } from "@inquirer/prompts";
11996
+ import { search, confirm as confirm11, checkbox as checkbox5 } from "@inquirer/prompts";
11988
11997
 
11989
11998
  // src/services/rules-generator.service.ts
11990
11999
  var RulesGeneratorService = class {
@@ -12495,7 +12504,7 @@ Restoring backup from ${metadata.timestamp}...`);
12495
12504
 
12496
12505
  // src/commands/rules/apply.ts
12497
12506
  function createRulesApplyCommand() {
12498
- 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)").option("--skip-backup", "Skip backup creation").option("-y, --yes", "Skip all confirmations (auto mode)").action(async (presetSlug, options) => {
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) => {
12499
12508
  const configService = new ConfigService();
12500
12509
  const config = await configService.load();
12501
12510
  if (!config) {
@@ -12507,7 +12516,12 @@ function createRulesApplyCommand() {
12507
12516
  const skipBackup = options.skipBackup === true;
12508
12517
  let selectedIdes = [];
12509
12518
  if (options.ides) {
12510
- selectedIdes = options.ides.split(",").map((ide) => ide.trim()).filter((ide) => generatorService.isValidIde(ide));
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
+ }
12511
12525
  if (selectedIdes.length === 0) {
12512
12526
  throw new ValidationError("No valid IDE formats specified");
12513
12527
  }
@@ -12527,13 +12541,20 @@ function createRulesApplyCommand() {
12527
12541
  console.log("No presets available.");
12528
12542
  return;
12529
12543
  }
12530
- presetSlug = await select5({
12531
- message: "Select a preset:",
12532
- choices: data.presets.map((p) => ({
12533
- name: `${p.name} - ${p.description}`,
12534
- value: p.slug,
12535
- description: `v${p.version} | ${p.tags.join(", ")}`
12536
- })),
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
+ },
12537
12558
  theme: selectTheme
12538
12559
  });
12539
12560
  }
@@ -12556,7 +12577,9 @@ function createRulesApplyCommand() {
12556
12577
  console.log(` Files: ${Object.keys(bundle.files).length}`);
12557
12578
  if (selectedIdes.length === 0) {
12558
12579
  if (autoMode) {
12559
- selectedIdes = ["cursor"];
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
+ );
12560
12583
  } else {
12561
12584
  const detectionService = new IdeDetectionService();
12562
12585
  const suggestions = await detectionService.suggestIdes();
@@ -12733,13 +12756,52 @@ function createRulesApplyCommand() {
12733
12756
  console.log(' 3. Run "jai1 rules sync" to regenerate IDE outputs');
12734
12757
  console.log(" 4. Commit the rules to git");
12735
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
+ }
12736
12798
  });
12737
12799
  }
12738
12800
 
12739
12801
  // src/commands/rules/restore.ts
12740
12802
  import { Command as Command64 } from "commander";
12741
12803
  import { join as join16 } from "path";
12742
- import { select as select6, confirm as confirm12 } from "@inquirer/prompts";
12804
+ import { select as select5, confirm as confirm12 } from "@inquirer/prompts";
12743
12805
  function createRulesRestoreCommand() {
12744
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) => {
12745
12807
  const backupService = new BackupService();
@@ -12754,7 +12816,7 @@ function createRulesRestoreCommand() {
12754
12816
  console.log(`\u{1F4E6} Selected latest backup: ${selectedBackup.timestamp}`);
12755
12817
  } else {
12756
12818
  console.log("\u{1F4CB} Available backups:\n");
12757
- const backupTimestamp = await select6({
12819
+ const backupTimestamp = await select5({
12758
12820
  message: "Select a backup to restore:",
12759
12821
  choices: backups.map((backup) => ({
12760
12822
  name: formatBackupInfo(backup),
@@ -13333,7 +13395,7 @@ function getInstallCommand(packageManager2) {
13333
13395
 
13334
13396
  // src/commands/clean.ts
13335
13397
  import { Command as Command69 } from "commander";
13336
- import { confirm as confirm15, select as select7 } from "@inquirer/prompts";
13398
+ import { confirm as confirm15, select as select6 } from "@inquirer/prompts";
13337
13399
  import { join as join19 } from "path";
13338
13400
  function createCleanCommand() {
13339
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) => {
@@ -13397,7 +13459,7 @@ async function handleClean(options) {
13397
13459
  console.log(` Path: ${target.path}
13398
13460
  `);
13399
13461
  }
13400
- const action = await select7({
13462
+ const action = await select6({
13401
13463
  message: "What do you want to clean?",
13402
13464
  choices: [
13403
13465
  ...availableTargets.map(({ target, info }) => ({
@@ -14580,7 +14642,7 @@ function createClearBackupsCommand() {
14580
14642
 
14581
14643
  // src/commands/vscode/index.ts
14582
14644
  import { Command as Command76 } from "commander";
14583
- import { checkbox as checkbox7, confirm as confirm18, select as select8 } from "@inquirer/prompts";
14645
+ import { checkbox as checkbox7, confirm as confirm18, select as select7 } from "@inquirer/prompts";
14584
14646
  import fs29 from "fs/promises";
14585
14647
  import path12 from "path";
14586
14648
  import { existsSync as existsSync3 } from "fs";
@@ -14763,7 +14825,7 @@ async function interactiveMode2() {
14763
14825
  console.log("\u2502 \u2022 Nh\u1EA5n ENTER \u0111\u1EC3 x\xE1c nh\u1EADn v\xE0 \xE1p d\u1EE5ng \u2502");
14764
14826
  console.log("\u2502 \u2022 Nh\u1EA5n Ctrl+C \u0111\u1EC3 h\u1EE7y \u2502");
14765
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");
14766
- const action = await select8({
14828
+ const action = await select7({
14767
14829
  message: "B\u1EA1n mu\u1ED1n l\xE0m g\xEC?",
14768
14830
  choices: [
14769
14831
  { name: "\u2705 Enable c\xE1c nh\xF3m t\u1ED1i \u01B0u", value: "enable" },