@jvittechs/j 1.0.17 → 1.0.19

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.19",
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) {
@@ -3068,17 +3066,19 @@ function renderIDEContext(ideContext) {
3068
3066
  function createContextCommand() {
3069
3067
  const cmd = new Command7("context").description("Visualize IDE context window token budget").argument("[ide]", "Show specific IDE only (cursor, windsurf, antigravity)").action(async (ideArg) => {
3070
3068
  const name = getCliName();
3071
- const validIDEs = ["cursor", "windsurf", "antigravity"];
3069
+ const allIDEs = ["cursor", "windsurf", "antigravity"];
3072
3070
  if (ideArg) {
3073
- if (!validIDEs.includes(ideArg)) {
3071
+ if (!allIDEs.includes(ideArg)) {
3074
3072
  console.error(chalk6.red(`\u274C Invalid IDE: ${ideArg}`));
3075
- console.error(chalk6.dim(` Valid IDEs: ${validIDEs.join(", ")}`));
3073
+ console.error(chalk6.dim(` Valid IDEs: ${allIDEs.join(", ")}`));
3076
3074
  console.error(chalk6.dim(` Usage: ${name} context [ide]`));
3077
3075
  process.exit(1);
3078
3076
  }
3079
3077
  }
3080
3078
  const scanner = new ContextScannerService();
3081
- const targetIDEs = ideArg ? [ideArg] : validIDEs;
3079
+ const detectedIDEs = await scanner.detectIDEs();
3080
+ const installedIDEs = detectedIDEs.filter((ide) => allIDEs.includes(ide));
3081
+ const targetIDEs = ideArg ? [ideArg] : installedIDEs;
3082
3082
  console.log("");
3083
3083
  console.log(` ${chalk6.bgGray.white.bold(" /context ")}`);
3084
3084
  let found = false;
@@ -3441,13 +3441,14 @@ async function resetSettings(groupKeys) {
3441
3441
  import { Command as Command9 } from "commander";
3442
3442
  import { checkbox as checkbox2, confirm as confirm3 } from "@inquirer/prompts";
3443
3443
  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) => {
3444
+ 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
3445
  await runSync(options);
3446
3446
  });
3447
3447
  return cmd;
3448
3448
  }
3449
3449
  async function runSync(options) {
3450
3450
  const service = new MigrateIdeService();
3451
+ const headless = options.yes === true;
3451
3452
  console.log("\n\u{1F504} Sync rules and workflows to IDE(s)\n");
3452
3453
  console.log("\u{1F4C1} Scanning .jai1/ directory...");
3453
3454
  console.log(" \u2022 .jai1/rule-preset/ (active rule preset)");
@@ -3463,8 +3464,14 @@ async function runSync(options) {
3463
3464
  console.log(`\u2713 Found: ${content.rules.length} rules, ${content.workflows.length} workflows
3464
3465
  `);
3465
3466
  let selectedIdes;
3466
- if (options.ide && options.ide.length > 0) {
3467
- selectedIdes = options.ide;
3467
+ if (options.all) {
3468
+ selectedIdes = getMigrationIDEs();
3469
+ } else if (options.ides && options.ides.length > 0) {
3470
+ selectedIdes = options.ides;
3471
+ } else if (headless) {
3472
+ throw new Error(
3473
+ "Headless mode (-y) requires --ides or --all flag.\nExamples:\n j ide sync --ides cursor windsurf -y\n j ide sync --all -y"
3474
+ );
3468
3475
  } else {
3469
3476
  const ideChoices = getMigrationIDEs().map((ide) => {
3470
3477
  const config = IDE_MIGRATION_CONFIGS[ide];
@@ -3487,6 +3494,8 @@ async function runSync(options) {
3487
3494
  let selectedTypes;
3488
3495
  if (options.type && options.type.length > 0) {
3489
3496
  selectedTypes = options.type;
3497
+ } else if (headless) {
3498
+ selectedTypes = ["rules", "workflows", "commands"];
3490
3499
  } else {
3491
3500
  const typeChoices = [
3492
3501
  { name: `Rules (${content.rules.length} files)`, value: "rules" },
@@ -3516,13 +3525,15 @@ async function runSync(options) {
3516
3525
  if (options.dryRun) {
3517
3526
  console.log("\u{1F50D} DRY RUN - No files will be written\n");
3518
3527
  }
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);
3528
+ if (!headless) {
3529
+ const confirmed = await confirm3({
3530
+ message: "Proceed with sync?",
3531
+ default: true
3532
+ });
3533
+ if (!confirmed) {
3534
+ console.log("\n\u274C Sync cancelled.\n");
3535
+ process.exit(0);
3536
+ }
3526
3537
  }
3527
3538
  console.log("\n\u{1F504} Syncing...\n");
3528
3539
  let completed = 0;
@@ -11984,7 +11995,7 @@ async function applyAgentsMdFormat(bundle) {
11984
11995
  import { Command as Command63 } from "commander";
11985
11996
  import { promises as fs25 } from "fs";
11986
11997
  import { join as join15 } from "path";
11987
- import { select as select5, confirm as confirm11, checkbox as checkbox5 } from "@inquirer/prompts";
11998
+ import { search, confirm as confirm11, checkbox as checkbox5 } from "@inquirer/prompts";
11988
11999
 
11989
12000
  // src/services/rules-generator.service.ts
11990
12001
  var RulesGeneratorService = class {
@@ -12495,7 +12506,7 @@ Restoring backup from ${metadata.timestamp}...`);
12495
12506
 
12496
12507
  // src/commands/rules/apply.ts
12497
12508
  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) => {
12509
+ 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
12510
  const configService = new ConfigService();
12500
12511
  const config = await configService.load();
12501
12512
  if (!config) {
@@ -12507,7 +12518,12 @@ function createRulesApplyCommand() {
12507
12518
  const skipBackup = options.skipBackup === true;
12508
12519
  let selectedIdes = [];
12509
12520
  if (options.ides) {
12510
- selectedIdes = options.ides.split(",").map((ide) => ide.trim()).filter((ide) => generatorService.isValidIde(ide));
12521
+ const idesValue = options.ides;
12522
+ if (idesValue.toLowerCase() === "all") {
12523
+ selectedIdes = generatorService.getAvailableIdes();
12524
+ } else {
12525
+ selectedIdes = idesValue.split(",").map((ide) => ide.trim()).filter((ide) => generatorService.isValidIde(ide));
12526
+ }
12511
12527
  if (selectedIdes.length === 0) {
12512
12528
  throw new ValidationError("No valid IDE formats specified");
12513
12529
  }
@@ -12527,13 +12543,20 @@ function createRulesApplyCommand() {
12527
12543
  console.log("No presets available.");
12528
12544
  return;
12529
12545
  }
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
- })),
12546
+ presetSlug = await search({
12547
+ message: "Search and select a preset (type keywords to filter):",
12548
+ source: async (input5) => {
12549
+ const keywords = (input5 || "").toLowerCase().split(/\s+/).filter(Boolean);
12550
+ const filtered = keywords.length === 0 ? data.presets : data.presets.filter((p) => {
12551
+ const searchable = [p.name, p.description, p.slug, ...p.tags].join(" ").toLowerCase();
12552
+ return keywords.every((kw) => searchable.includes(kw));
12553
+ });
12554
+ return filtered.map((p) => ({
12555
+ name: `${p.name} - ${p.description}`,
12556
+ value: p.slug,
12557
+ description: `v${p.version} | ${p.tags.join(", ")}`
12558
+ }));
12559
+ },
12537
12560
  theme: selectTheme
12538
12561
  });
12539
12562
  }
@@ -12556,7 +12579,9 @@ function createRulesApplyCommand() {
12556
12579
  console.log(` Files: ${Object.keys(bundle.files).length}`);
12557
12580
  if (selectedIdes.length === 0) {
12558
12581
  if (autoMode) {
12559
- selectedIdes = ["cursor"];
12582
+ throw new ValidationError(
12583
+ "Headless mode (-y) requires --ides flag.\nExamples:\n j rules apply <preset> --ides cursor,antigravity -y\n j rules apply <preset> --ides all -y"
12584
+ );
12560
12585
  } else {
12561
12586
  const detectionService = new IdeDetectionService();
12562
12587
  const suggestions = await detectionService.suggestIdes();
@@ -12733,13 +12758,52 @@ function createRulesApplyCommand() {
12733
12758
  console.log(' 3. Run "jai1 rules sync" to regenerate IDE outputs');
12734
12759
  console.log(" 4. Commit the rules to git");
12735
12760
  console.log(' 5. Use "jai1 ide status" to check IDE configuration\n');
12761
+ const migrationIdeIds = getMigrationIDEs();
12762
+ const ideSyncMap = {
12763
+ "cursor": "cursor",
12764
+ "windsurf": "windsurf",
12765
+ "antigravity": "antigravity",
12766
+ "claude": "claudecode",
12767
+ "agentsmd": "opencode",
12768
+ "opencode": "opencode"
12769
+ };
12770
+ const migrationIdes = resolvedIdes.map((ide) => ideSyncMap[ide]).filter((ide) => !!ide && migrationIdeIds.includes(ide)).filter((ide, index, self) => self.indexOf(ide) === index);
12771
+ if (migrationIdes.length > 0) {
12772
+ console.log("\u{1F504} Auto-syncing .jai1/ content to IDE(s)...\n");
12773
+ try {
12774
+ const migrateService = new MigrateIdeService();
12775
+ const content = await migrateService.scanJai1Content();
12776
+ if (content.totalCount > 0) {
12777
+ const contentTypes = ["rules", "workflows", "commands"];
12778
+ const results = await migrateService.migrate(
12779
+ migrationIdes,
12780
+ contentTypes,
12781
+ content,
12782
+ (result) => {
12783
+ const icon = result.status === "created" ? "\u2713" : result.status === "updated" ? "\u21BB" : result.status === "error" ? "\u2717" : "\u25CB";
12784
+ console.log(` ${icon} ${result.targetPath}`);
12785
+ }
12786
+ );
12787
+ const created = results.filter((r) => r.status === "created").length;
12788
+ const updated = results.filter((r) => r.status === "updated").length;
12789
+ console.log(`
12790
+ \u2705 IDE sync complete! (${created} created, ${updated} updated)
12791
+ `);
12792
+ } else {
12793
+ console.log(" No .jai1/ content found to sync.\n");
12794
+ }
12795
+ } catch (error) {
12796
+ console.warn("\u26A0\uFE0F IDE sync failed:", error instanceof Error ? error.message : error);
12797
+ console.log(' You can manually run "j ide sync" to retry.\n');
12798
+ }
12799
+ }
12736
12800
  });
12737
12801
  }
12738
12802
 
12739
12803
  // src/commands/rules/restore.ts
12740
12804
  import { Command as Command64 } from "commander";
12741
12805
  import { join as join16 } from "path";
12742
- import { select as select6, confirm as confirm12 } from "@inquirer/prompts";
12806
+ import { select as select5, confirm as confirm12 } from "@inquirer/prompts";
12743
12807
  function createRulesRestoreCommand() {
12744
12808
  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
12809
  const backupService = new BackupService();
@@ -12754,7 +12818,7 @@ function createRulesRestoreCommand() {
12754
12818
  console.log(`\u{1F4E6} Selected latest backup: ${selectedBackup.timestamp}`);
12755
12819
  } else {
12756
12820
  console.log("\u{1F4CB} Available backups:\n");
12757
- const backupTimestamp = await select6({
12821
+ const backupTimestamp = await select5({
12758
12822
  message: "Select a backup to restore:",
12759
12823
  choices: backups.map((backup) => ({
12760
12824
  name: formatBackupInfo(backup),
@@ -13333,7 +13397,7 @@ function getInstallCommand(packageManager2) {
13333
13397
 
13334
13398
  // src/commands/clean.ts
13335
13399
  import { Command as Command69 } from "commander";
13336
- import { confirm as confirm15, select as select7 } from "@inquirer/prompts";
13400
+ import { confirm as confirm15, select as select6 } from "@inquirer/prompts";
13337
13401
  import { join as join19 } from "path";
13338
13402
  function createCleanCommand() {
13339
13403
  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 +13461,7 @@ async function handleClean(options) {
13397
13461
  console.log(` Path: ${target.path}
13398
13462
  `);
13399
13463
  }
13400
- const action = await select7({
13464
+ const action = await select6({
13401
13465
  message: "What do you want to clean?",
13402
13466
  choices: [
13403
13467
  ...availableTargets.map(({ target, info }) => ({
@@ -14580,7 +14644,7 @@ function createClearBackupsCommand() {
14580
14644
 
14581
14645
  // src/commands/vscode/index.ts
14582
14646
  import { Command as Command76 } from "commander";
14583
- import { checkbox as checkbox7, confirm as confirm18, select as select8 } from "@inquirer/prompts";
14647
+ import { checkbox as checkbox7, confirm as confirm18, select as select7 } from "@inquirer/prompts";
14584
14648
  import fs29 from "fs/promises";
14585
14649
  import path12 from "path";
14586
14650
  import { existsSync as existsSync3 } from "fs";
@@ -14763,7 +14827,7 @@ async function interactiveMode2() {
14763
14827
  console.log("\u2502 \u2022 Nh\u1EA5n ENTER \u0111\u1EC3 x\xE1c nh\u1EADn v\xE0 \xE1p d\u1EE5ng \u2502");
14764
14828
  console.log("\u2502 \u2022 Nh\u1EA5n Ctrl+C \u0111\u1EC3 h\u1EE7y \u2502");
14765
14829
  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({
14830
+ const action = await select7({
14767
14831
  message: "B\u1EA1n mu\u1ED1n l\xE0m g\xEC?",
14768
14832
  choices: [
14769
14833
  { name: "\u2705 Enable c\xE1c nh\xF3m t\u1ED1i \u01B0u", value: "enable" },