@jvittechs/j 1.0.41 → 1.0.42

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
@@ -13,7 +13,7 @@ import {
13
13
  STATUS_ICONS,
14
14
  TaskService,
15
15
  createTaskSummaryCommand
16
- } from "./chunk-ZG3KLHJ4.js";
16
+ } from "./chunk-WPXT7BL7.js";
17
17
 
18
18
  // src/utils/node-version-check.ts
19
19
  import chalk from "chalk";
@@ -49,7 +49,7 @@ function checkNodeVersion() {
49
49
  }
50
50
 
51
51
  // src/cli.ts
52
- import { Command as Command87 } from "commander";
52
+ import { Command as Command89 } from "commander";
53
53
 
54
54
  // src/services/error-log.service.ts
55
55
  import { promises as fs } from "fs";
@@ -149,7 +149,7 @@ import { basename as basename5 } from "path";
149
149
  // package.json
150
150
  var package_default = {
151
151
  name: "@jvittechs/j",
152
- version: "1.0.41",
152
+ version: "1.0.42",
153
153
  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.",
154
154
  type: "module",
155
155
  bin: {
@@ -10801,7 +10801,7 @@ function createHooksCommand() {
10801
10801
  }
10802
10802
 
10803
10803
  // src/commands/tasks/index.ts
10804
- import { Command as Command59 } from "commander";
10804
+ import { Command as Command61 } from "commander";
10805
10805
 
10806
10806
  // src/commands/tasks/add.ts
10807
10807
  import { Command as Command48 } from "commander";
@@ -11338,9 +11338,165 @@ function createTaskParentsCommand() {
11338
11338
  });
11339
11339
  }
11340
11340
 
11341
+ // src/commands/tasks/cancel.ts
11342
+ import { Command as Command59 } from "commander";
11343
+ import chalk32 from "chalk";
11344
+ import { confirm as confirm10 } from "@inquirer/prompts";
11345
+ function createTaskCancelCommand() {
11346
+ return new Command59("cancel").description("Cancel a task (with dependency impact check)").argument("<id>", "Task ID (e.g. T-001)").option("-y, --yes", "Skip confirmation").option("-j, --json", "Output JSON").action(async (id, options) => {
11347
+ const service = new TaskService();
11348
+ try {
11349
+ const task = await service.findById(id);
11350
+ if (!task) {
11351
+ console.error(chalk32.red(`\u274C Task ${id} not found`));
11352
+ process.exit(1);
11353
+ }
11354
+ if (task.status === "cancelled") {
11355
+ console.error(chalk32.yellow(`\u26A0\uFE0F Task ${id} is already cancelled`));
11356
+ process.exit(0);
11357
+ }
11358
+ if (task.status === "done") {
11359
+ console.error(chalk32.red(`\u274C Task ${id} is already done \u2014 cannot cancel`));
11360
+ process.exit(1);
11361
+ }
11362
+ const dependents = await service.getDependents(id);
11363
+ const activeDependents = dependents.filter(
11364
+ (t) => t.status !== "done" && t.status !== "cancelled"
11365
+ );
11366
+ const icon = STATUS_ICONS[task.status] || "\u{1F4CB}";
11367
+ console.log(chalk32.bold(`
11368
+ \u26AB Cancel: ${icon} ${task.id} \u2014 ${task.title}
11369
+ `));
11370
+ if (activeDependents.length > 0) {
11371
+ console.log(chalk32.yellow(`\u26A0\uFE0F ${activeDependents.length} task(s) ph\u1EE5 thu\u1ED9c v\xE0o ${id}:`));
11372
+ for (const dep of activeDependents) {
11373
+ const depIcon = STATUS_ICONS[dep.status] || "\u{1F4CB}";
11374
+ console.log(` ${depIcon} ${chalk32.dim(dep.id)} ${dep.title}`);
11375
+ }
11376
+ console.log(
11377
+ chalk32.dim(
11378
+ `
11379
+ \u2192 Cancel s\u1EBD resolve dependency, c\xE1c task tr\xEAn c\xF3 th\u1EC3 \u0111\u01B0\u1EE3c unblock.`
11380
+ )
11381
+ );
11382
+ console.log();
11383
+ }
11384
+ if (!options.yes) {
11385
+ const proceed = await confirm10({
11386
+ message: `Cancel task ${id}?`,
11387
+ default: false
11388
+ });
11389
+ if (!proceed) {
11390
+ console.log(chalk32.dim("\u0110\xE3 hu\u1EF7."));
11391
+ return;
11392
+ }
11393
+ }
11394
+ const updated = await service.cancel(id);
11395
+ if (options.json) {
11396
+ console.log(JSON.stringify(updated, null, 2));
11397
+ return;
11398
+ }
11399
+ console.log(chalk32.green(`\u2705 ${updated.id}: ${updated.title} \u2192 cancelled`));
11400
+ } catch (error) {
11401
+ console.error(
11402
+ chalk32.red(`\u274C ${error instanceof Error ? error.message : String(error)}`)
11403
+ );
11404
+ process.exit(1);
11405
+ }
11406
+ });
11407
+ }
11408
+
11409
+ // src/commands/tasks/delete.ts
11410
+ import { Command as Command60 } from "commander";
11411
+ import chalk33 from "chalk";
11412
+ import { confirm as confirm11 } from "@inquirer/prompts";
11413
+ function createTaskDeleteCommand() {
11414
+ return new Command60("delete").description("Delete a task permanently (with dependency impact check)").argument("<id>", "Task ID (e.g. T-001)").option("-y, --yes", "Skip confirmation").option("-j, --json", "Output JSON before deletion").action(async (id, options) => {
11415
+ const service = new TaskService();
11416
+ try {
11417
+ const task = await service.findById(id);
11418
+ if (!task) {
11419
+ console.error(chalk33.red(`\u274C Task ${id} not found`));
11420
+ process.exit(1);
11421
+ }
11422
+ const dependents = await service.getDependents(id);
11423
+ const icon = STATUS_ICONS[task.status] || "\u{1F4CB}";
11424
+ console.log(chalk33.bold(`
11425
+ \u{1F5D1}\uFE0F Delete: ${icon} ${task.id} \u2014 ${task.title}
11426
+ `));
11427
+ console.log(` ${chalk33.dim("Status:")} ${task.status}`);
11428
+ console.log(` ${chalk33.dim("Parent:")} ${task.parent || "(none)"}`);
11429
+ if (task.depends_on.length > 0) {
11430
+ console.log(` ${chalk33.dim("Depends:")} ${task.depends_on.join(", ")}`);
11431
+ }
11432
+ console.log();
11433
+ if (dependents.length > 0) {
11434
+ const activeDependents = dependents.filter(
11435
+ (t) => t.status !== "done" && t.status !== "cancelled"
11436
+ );
11437
+ const resolvedDependents = dependents.filter(
11438
+ (t) => t.status === "done" || t.status === "cancelled"
11439
+ );
11440
+ console.log(
11441
+ chalk33.yellow(
11442
+ `\u26A0\uFE0F ${dependents.length} task(s) c\xF3 depends_on \u2192 ${id}:`
11443
+ )
11444
+ );
11445
+ for (const dep of dependents) {
11446
+ const depIcon = STATUS_ICONS[dep.status] || "\u{1F4CB}";
11447
+ console.log(` ${depIcon} ${chalk33.dim(dep.id)} ${dep.title}`);
11448
+ }
11449
+ console.log(
11450
+ chalk33.dim(
11451
+ `
11452
+ \u2192 Xo\xE1 s\u1EBD remove ${id} kh\u1ECFi depends_on c\u1EE7a c\xE1c task tr\xEAn.`
11453
+ )
11454
+ );
11455
+ if (activeDependents.length > 0) {
11456
+ console.log(
11457
+ chalk33.dim(
11458
+ ` \u2192 ${activeDependents.length} task(s) ch\u01B0a done c\xF3 th\u1EC3 b\u1ECB \u1EA3nh h\u01B0\u1EDFng (unblock).`
11459
+ )
11460
+ );
11461
+ }
11462
+ console.log();
11463
+ }
11464
+ if (!options.yes) {
11465
+ const proceed = await confirm11({
11466
+ message: `Xo\xE1 v\u0129nh vi\u1EC5n task ${id}?`,
11467
+ default: false
11468
+ });
11469
+ if (!proceed) {
11470
+ console.log(chalk33.dim("\u0110\xE3 hu\u1EF7."));
11471
+ return;
11472
+ }
11473
+ }
11474
+ if (options.json) {
11475
+ console.log(JSON.stringify({ deleted: task, dependentsUpdated: dependents.map((d) => d.id) }, null, 2));
11476
+ }
11477
+ await service.deleteTask(id);
11478
+ if (!options.json) {
11479
+ console.log(chalk33.green(`\u2705 \u0110\xE3 xo\xE1 ${task.id}: ${task.title}`));
11480
+ if (dependents.length > 0) {
11481
+ console.log(
11482
+ chalk33.dim(
11483
+ ` \u0110\xE3 c\u1EADp nh\u1EADt depends_on cho: ${dependents.map((d) => d.id).join(", ")}`
11484
+ )
11485
+ );
11486
+ }
11487
+ }
11488
+ } catch (error) {
11489
+ console.error(
11490
+ chalk33.red(`\u274C ${error instanceof Error ? error.message : String(error)}`)
11491
+ );
11492
+ process.exit(1);
11493
+ }
11494
+ });
11495
+ }
11496
+
11341
11497
  // src/commands/tasks/index.ts
11342
11498
  function createTasksCommand() {
11343
- const cmd = new Command59("tasks").alias("t").description("Task management \u2014 track, assign, and manage development tasks").hook("preAction", (thisCommand, actionCommand) => {
11499
+ const cmd = new Command61("tasks").alias("t").description("Task management \u2014 track, assign, and manage development tasks").hook("preAction", (thisCommand, actionCommand) => {
11344
11500
  if (actionCommand.name() !== "guide") {
11345
11501
  TaskService.ensureJai1Dir();
11346
11502
  }
@@ -11356,21 +11512,23 @@ function createTasksCommand() {
11356
11512
  cmd.addCommand(createTaskSyncCommand());
11357
11513
  cmd.addCommand(createTaskSummaryCommand());
11358
11514
  cmd.addCommand(createTaskParentsCommand());
11515
+ cmd.addCommand(createTaskCancelCommand());
11516
+ cmd.addCommand(createTaskDeleteCommand());
11359
11517
  cmd.addCommand(createTaskGuideCommand());
11360
11518
  cmd.action(async () => {
11361
- const { handleTaskSummary } = await import("./summary-AEJ34P4Q.js");
11519
+ const { handleTaskSummary } = await import("./summary-WWNFDPZX.js");
11362
11520
  await handleTaskSummary({ json: false });
11363
11521
  });
11364
11522
  return cmd;
11365
11523
  }
11366
11524
 
11367
11525
  // src/commands/kit/index.ts
11368
- import { Command as Command63 } from "commander";
11369
- import chalk33 from "chalk";
11526
+ import { Command as Command65 } from "commander";
11527
+ import chalk35 from "chalk";
11370
11528
 
11371
11529
  // src/commands/kit/list.ts
11372
- import { Command as Command60 } from "commander";
11373
- import chalk32 from "chalk";
11530
+ import { Command as Command62 } from "commander";
11531
+ import chalk34 from "chalk";
11374
11532
  import Table6 from "cli-table3";
11375
11533
 
11376
11534
  // src/services/starter-kit.service.ts
@@ -11438,13 +11596,13 @@ var StarterKitService = class {
11438
11596
 
11439
11597
  // src/commands/kit/list.ts
11440
11598
  function createKitListCommand() {
11441
- return new Command60("list").description("List available starter kits").option("-c, --category <category>", "Filter by category (backend, frontend, fullstack)").option("-s, --search <term>", "Search kits by name or description").action(async (options) => {
11599
+ return new Command62("list").description("List available starter kits").option("-c, --category <category>", "Filter by category (backend, frontend, fullstack)").option("-s, --search <term>", "Search kits by name or description").action(async (options) => {
11442
11600
  const configService = new ConfigService();
11443
11601
  const config = await configService.load();
11444
11602
  if (!config) {
11445
11603
  throw new ValidationError('Not initialized. Run "jai1 auth" first.');
11446
11604
  }
11447
- console.log(chalk32.cyan("\u{1F4E6} \u0110ang t\u1EA3i danh s\xE1ch starter kits..."));
11605
+ console.log(chalk34.cyan("\u{1F4E6} \u0110ang t\u1EA3i danh s\xE1ch starter kits..."));
11448
11606
  console.log();
11449
11607
  const kitService = new StarterKitService();
11450
11608
  const kits = await kitService.list(config, {
@@ -11452,9 +11610,9 @@ function createKitListCommand() {
11452
11610
  search: options.search
11453
11611
  });
11454
11612
  if (kits.length === 0) {
11455
- console.log(chalk32.yellow("Kh\xF4ng t\xECm th\u1EA5y starter kits n\xE0o."));
11613
+ console.log(chalk34.yellow("Kh\xF4ng t\xECm th\u1EA5y starter kits n\xE0o."));
11456
11614
  if (options.category || options.search) {
11457
- console.log(chalk32.dim("Th\u1EED b\u1ECF filter \u0111\u1EC3 xem t\u1EA5t c\u1EA3."));
11615
+ console.log(chalk34.dim("Th\u1EED b\u1ECF filter \u0111\u1EC3 xem t\u1EA5t c\u1EA3."));
11458
11616
  }
11459
11617
  return;
11460
11618
  }
@@ -11478,35 +11636,35 @@ function createKitListCommand() {
11478
11636
  const categoryKits = byCategory[category];
11479
11637
  const categoryIcon = category === "frontend" ? "\u{1F3A8}" : category === "backend" ? "\u2699\uFE0F" : category === "fullstack" ? "\u{1F680}" : "\u{1F4E6}";
11480
11638
  console.log(
11481
- chalk32.bold(`${categoryIcon} ${category.charAt(0).toUpperCase() + category.slice(1)}`)
11639
+ chalk34.bold(`${categoryIcon} ${category.charAt(0).toUpperCase() + category.slice(1)}`)
11482
11640
  );
11483
11641
  const table = new Table6({
11484
11642
  head: [
11485
- chalk32.cyan("Slug"),
11486
- chalk32.cyan("M\xF4 t\u1EA3"),
11487
- chalk32.cyan("Version")
11643
+ chalk34.cyan("Slug"),
11644
+ chalk34.cyan("M\xF4 t\u1EA3"),
11645
+ chalk34.cyan("Version")
11488
11646
  ],
11489
11647
  style: { head: [], border: ["gray"] }
11490
11648
  });
11491
11649
  for (const kit of categoryKits) {
11492
11650
  table.push([
11493
- chalk32.white(kit.slug),
11494
- chalk32.dim(kit.description.slice(0, 50)),
11495
- chalk32.green(`v${kit.version}`)
11651
+ chalk34.white(kit.slug),
11652
+ chalk34.dim(kit.description.slice(0, 50)),
11653
+ chalk34.green(`v${kit.version}`)
11496
11654
  ]);
11497
11655
  }
11498
11656
  console.log(table.toString());
11499
11657
  console.log();
11500
11658
  }
11501
- console.log(chalk32.dim(`T\u1ED5ng c\u1ED9ng: ${kits.length} starter kit(s)`));
11502
- console.log(chalk32.dim('\n\u{1F4A1} Ch\u1EA1y "jai1 kit create <slug>" \u0111\u1EC3 t\u1EA1o project m\u1EDBi'));
11659
+ console.log(chalk34.dim(`T\u1ED5ng c\u1ED9ng: ${kits.length} starter kit(s)`));
11660
+ console.log(chalk34.dim('\n\u{1F4A1} Ch\u1EA1y "jai1 kit create <slug>" \u0111\u1EC3 t\u1EA1o project m\u1EDBi'));
11503
11661
  });
11504
11662
  }
11505
11663
 
11506
11664
  // src/commands/kit/info.ts
11507
- import { Command as Command61 } from "commander";
11665
+ import { Command as Command63 } from "commander";
11508
11666
  function createKitInfoCommand() {
11509
- return new Command61("info").description("Show detailed information about a starter kit").argument("<slug>", "Starter kit slug").action(async (slug) => {
11667
+ return new Command63("info").description("Show detailed information about a starter kit").argument("<slug>", "Starter kit slug").action(async (slug) => {
11510
11668
  const configService = new ConfigService();
11511
11669
  const config = await configService.load();
11512
11670
  if (!config) {
@@ -11555,7 +11713,7 @@ Post-Init Commands:`);
11555
11713
  }
11556
11714
 
11557
11715
  // src/commands/kit/create.ts
11558
- import { Command as Command62 } from "commander";
11716
+ import { Command as Command64 } from "commander";
11559
11717
  import { promises as fs20 } from "fs";
11560
11718
  import { join as join11 } from "path";
11561
11719
  import { select as select3, input as input2, checkbox as checkbox4 } from "@inquirer/prompts";
@@ -11600,7 +11758,7 @@ var HookExecutor = class {
11600
11758
 
11601
11759
  // src/commands/kit/create.ts
11602
11760
  function createKitCreateCommand() {
11603
- return new Command62("create").description("Create a new project from a starter kit").argument("<slug>", "Starter kit slug").argument("[directory]", "Project directory (default: ./<slug>)").option("-y, --yes", "Auto mode - use defaults, no prompts").option("--name <name>", "Project name").option("--skip-install", "Skip dependency installation").option("--skip-git", "Skip git initialization").option("--skip-framework", "Skip framework apply").option("--skip-ide", "Skip IDE sync").action(async (slug, directory, options) => {
11761
+ return new Command64("create").description("Create a new project from a starter kit").argument("<slug>", "Starter kit slug").argument("[directory]", "Project directory (default: ./<slug>)").option("-y, --yes", "Auto mode - use defaults, no prompts").option("--name <name>", "Project name").option("--skip-install", "Skip dependency installation").option("--skip-git", "Skip git initialization").option("--skip-framework", "Skip framework apply").option("--skip-ide", "Skip IDE sync").action(async (slug, directory, options) => {
11604
11762
  const configService = new ConfigService();
11605
11763
  const config = await configService.load();
11606
11764
  if (!config) {
@@ -11779,23 +11937,23 @@ async function getAllFiles(dir) {
11779
11937
 
11780
11938
  // src/commands/kit/index.ts
11781
11939
  function showKitHelp() {
11782
- console.log(chalk33.bold.cyan("\u{1F4E6} jai1 kit") + chalk33.dim(" - Qu\u1EA3n l\xFD starter kits"));
11940
+ console.log(chalk35.bold.cyan("\u{1F4E6} jai1 kit") + chalk35.dim(" - Qu\u1EA3n l\xFD starter kits"));
11783
11941
  console.log();
11784
- console.log(chalk33.bold("C\xE1c l\u1EC7nh:"));
11785
- console.log(` ${chalk33.cyan("list")} Li\u1EC7t k\xEA c\xE1c starter kits c\xF3 s\u1EB5n`);
11786
- console.log(` ${chalk33.cyan("info")} Xem chi ti\u1EBFt m\u1ED9t starter kit`);
11787
- console.log(` ${chalk33.cyan("create")} T\u1EA1o project m\u1EDBi t\u1EEB starter kit`);
11942
+ console.log(chalk35.bold("C\xE1c l\u1EC7nh:"));
11943
+ console.log(` ${chalk35.cyan("list")} Li\u1EC7t k\xEA c\xE1c starter kits c\xF3 s\u1EB5n`);
11944
+ console.log(` ${chalk35.cyan("info")} Xem chi ti\u1EBFt m\u1ED9t starter kit`);
11945
+ console.log(` ${chalk35.cyan("create")} T\u1EA1o project m\u1EDBi t\u1EEB starter kit`);
11788
11946
  console.log();
11789
- console.log(chalk33.bold("V\xED d\u1EE5:"));
11790
- console.log(chalk33.dim(" $ jai1 kit list"));
11791
- console.log(chalk33.dim(" $ jai1 kit list --category frontend"));
11792
- console.log(chalk33.dim(" $ jai1 kit info next-tw4-shadcn"));
11793
- console.log(chalk33.dim(" $ jai1 kit create next-tw4-shadcn my-project"));
11947
+ console.log(chalk35.bold("V\xED d\u1EE5:"));
11948
+ console.log(chalk35.dim(" $ jai1 kit list"));
11949
+ console.log(chalk35.dim(" $ jai1 kit list --category frontend"));
11950
+ console.log(chalk35.dim(" $ jai1 kit info next-tw4-shadcn"));
11951
+ console.log(chalk35.dim(" $ jai1 kit create next-tw4-shadcn my-project"));
11794
11952
  console.log();
11795
- console.log(chalk33.dim('Ch\u1EA1y "jai1 kit <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt'));
11953
+ console.log(chalk35.dim('Ch\u1EA1y "jai1 kit <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt'));
11796
11954
  }
11797
11955
  function createKitCommand() {
11798
- const cmd = new Command63("kit").description("Manage starter kits for new projects").action(() => {
11956
+ const cmd = new Command65("kit").description("Manage starter kits for new projects").action(() => {
11799
11957
  showKitHelp();
11800
11958
  });
11801
11959
  cmd.addCommand(createKitListCommand());
@@ -11805,21 +11963,21 @@ function createKitCommand() {
11805
11963
  }
11806
11964
 
11807
11965
  // src/commands/rules/index.ts
11808
- import { Command as Command70 } from "commander";
11809
- import chalk35 from "chalk";
11966
+ import { Command as Command72 } from "commander";
11967
+ import chalk37 from "chalk";
11810
11968
 
11811
11969
  // src/commands/rules/list.ts
11812
- import { Command as Command64 } from "commander";
11813
- import chalk34 from "chalk";
11970
+ import { Command as Command66 } from "commander";
11971
+ import chalk36 from "chalk";
11814
11972
  import Table7 from "cli-table3";
11815
11973
  function createRulesListCommand() {
11816
- return new Command64("list").description("List available rule presets").option("--json", "Output as JSON").action(async (options) => {
11974
+ return new Command66("list").description("List available rule presets").option("--json", "Output as JSON").action(async (options) => {
11817
11975
  const configService = new ConfigService();
11818
11976
  const config = await configService.load();
11819
11977
  if (!config) {
11820
11978
  throw new ValidationError('Not initialized. Run "jai1 auth" first.');
11821
11979
  }
11822
- console.log(chalk34.cyan("\u{1F4CB} \u0110ang t\u1EA3i danh s\xE1ch rule presets..."));
11980
+ console.log(chalk36.cyan("\u{1F4CB} \u0110ang t\u1EA3i danh s\xE1ch rule presets..."));
11823
11981
  console.log();
11824
11982
  try {
11825
11983
  const response = await fetch(`${config.apiUrl}/api/rules/presets`, {
@@ -11836,23 +11994,23 @@ function createRulesListCommand() {
11836
11994
  return;
11837
11995
  }
11838
11996
  if (data.total === 0) {
11839
- console.log(chalk34.yellow("Kh\xF4ng c\xF3 presets n\xE0o."));
11997
+ console.log(chalk36.yellow("Kh\xF4ng c\xF3 presets n\xE0o."));
11840
11998
  return;
11841
11999
  }
11842
12000
  console.log(
11843
- chalk34.green(`\u2713 T\xECm th\u1EA5y ${chalk34.bold(data.total)} preset${data.total > 1 ? "s" : ""}`)
12001
+ chalk36.green(`\u2713 T\xECm th\u1EA5y ${chalk36.bold(data.total)} preset${data.total > 1 ? "s" : ""}`)
11844
12002
  );
11845
12003
  console.log();
11846
12004
  for (const preset of data.presets) {
11847
- console.log(chalk34.bold.cyan(`\u{1F4E6} ${preset.slug}`));
12005
+ console.log(chalk36.bold.cyan(`\u{1F4E6} ${preset.slug}`));
11848
12006
  const table = new Table7({
11849
12007
  style: { head: [], border: ["gray"], compact: true },
11850
12008
  colWidths: [15, 55]
11851
12009
  });
11852
12010
  table.push(
11853
- [chalk34.dim("T\xEAn"), chalk34.white(preset.name)],
11854
- [chalk34.dim("M\xF4 t\u1EA3"), chalk34.white(preset.description)],
11855
- [chalk34.dim("Version"), chalk34.green(`v${preset.version}`)]
12011
+ [chalk36.dim("T\xEAn"), chalk36.white(preset.name)],
12012
+ [chalk36.dim("M\xF4 t\u1EA3"), chalk36.white(preset.description)],
12013
+ [chalk36.dim("Version"), chalk36.green(`v${preset.version}`)]
11856
12014
  );
11857
12015
  const stackParts = [];
11858
12016
  if (preset.stack.frontend) stackParts.push(preset.stack.frontend);
@@ -11860,16 +12018,16 @@ function createRulesListCommand() {
11860
12018
  if (preset.stack.css) stackParts.push(preset.stack.css);
11861
12019
  if (preset.stack.database) stackParts.push(preset.stack.database);
11862
12020
  if (stackParts.length > 0) {
11863
- table.push([chalk34.dim("Stack"), chalk34.yellow(stackParts.join(" + "))]);
12021
+ table.push([chalk36.dim("Stack"), chalk36.yellow(stackParts.join(" + "))]);
11864
12022
  }
11865
12023
  table.push(
11866
- [chalk34.dim("Tags"), chalk34.dim(preset.tags.join(", ") || "-")],
11867
- [chalk34.dim("Downloads"), chalk34.white(preset.downloads.toString())]
12024
+ [chalk36.dim("Tags"), chalk36.dim(preset.tags.join(", ") || "-")],
12025
+ [chalk36.dim("Downloads"), chalk36.white(preset.downloads.toString())]
11868
12026
  );
11869
12027
  console.log(table.toString());
11870
12028
  console.log();
11871
12029
  }
11872
- console.log(chalk34.dim('\u{1F4A1} Ch\u1EA1y "jai1 rules apply <name>" \u0111\u1EC3 \xE1p d\u1EE5ng preset'));
12030
+ console.log(chalk36.dim('\u{1F4A1} Ch\u1EA1y "jai1 rules apply <name>" \u0111\u1EC3 \xE1p d\u1EE5ng preset'));
11873
12031
  } catch (error) {
11874
12032
  throw new Error(
11875
12033
  `L\u1ED7i khi t\u1EA3i presets: ${error instanceof Error ? error.message : String(error)}`
@@ -11879,10 +12037,10 @@ function createRulesListCommand() {
11879
12037
  }
11880
12038
 
11881
12039
  // src/commands/rules/init.ts
11882
- import { Command as Command65 } from "commander";
12040
+ import { Command as Command67 } from "commander";
11883
12041
  import { promises as fs22 } from "fs";
11884
12042
  import { join as join13 } from "path";
11885
- import { select as select4, confirm as confirm10 } from "@inquirer/prompts";
12043
+ import { select as select4, confirm as confirm12 } from "@inquirer/prompts";
11886
12044
 
11887
12045
  // src/services/project-config.service.ts
11888
12046
  import { promises as fs21 } from "fs";
@@ -12004,7 +12162,7 @@ var ProjectConfigService = class {
12004
12162
 
12005
12163
  // src/commands/rules/init.ts
12006
12164
  function createRulesInitCommand() {
12007
- return new Command65("init").description("Apply rule preset to project").option("--preset <slug>", "Preset slug to apply").option("--output <format>", "Output format: cursor, agents-md, both (default: cursor)", "cursor").option("-y, --yes", "Skip confirmations").action(async (options) => {
12165
+ return new Command67("init").description("Apply rule preset to project").option("--preset <slug>", "Preset slug to apply").option("--output <format>", "Output format: cursor, agents-md, both (default: cursor)", "cursor").option("-y, --yes", "Skip confirmations").action(async (options) => {
12008
12166
  const configService = new ConfigService();
12009
12167
  const config = await configService.load();
12010
12168
  if (!config) {
@@ -12066,7 +12224,7 @@ function createRulesInitCommand() {
12066
12224
  });
12067
12225
  }
12068
12226
  if (!options.yes) {
12069
- const proceed = await confirm10({
12227
+ const proceed = await confirm12({
12070
12228
  message: `Apply preset '${bundle.preset.name}' to current directory?`,
12071
12229
  default: true
12072
12230
  });
@@ -12136,10 +12294,10 @@ async function applyAgentsMdFormat(bundle) {
12136
12294
  }
12137
12295
 
12138
12296
  // src/commands/rules/apply.ts
12139
- import { Command as Command66 } from "commander";
12297
+ import { Command as Command68 } from "commander";
12140
12298
  import { promises as fs24 } from "fs";
12141
12299
  import { join as join15 } from "path";
12142
- import { search, confirm as confirm11, checkbox as checkbox5 } from "@inquirer/prompts";
12300
+ import { search, confirm as confirm13, checkbox as checkbox5 } from "@inquirer/prompts";
12143
12301
 
12144
12302
  // src/services/rules-generator.service.ts
12145
12303
  var RulesGeneratorService = class {
@@ -12650,7 +12808,7 @@ Restoring backup from ${metadata.timestamp}...`);
12650
12808
 
12651
12809
  // src/commands/rules/apply.ts
12652
12810
  function createRulesApplyCommand() {
12653
- return new Command66("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) => {
12811
+ return new Command68("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) => {
12654
12812
  const configService = new ConfigService();
12655
12813
  const config = await configService.load();
12656
12814
  if (!config) {
@@ -12806,7 +12964,7 @@ function createRulesApplyCommand() {
12806
12964
  if (backupPath) {
12807
12965
  console.log(` Backup: ${backupPath}`);
12808
12966
  }
12809
- const proceed = await confirm11({
12967
+ const proceed = await confirm13({
12810
12968
  message: "Apply these rules to the current directory?",
12811
12969
  default: true
12812
12970
  });
@@ -12945,11 +13103,11 @@ function createRulesApplyCommand() {
12945
13103
  }
12946
13104
 
12947
13105
  // src/commands/rules/restore.ts
12948
- import { Command as Command67 } from "commander";
13106
+ import { Command as Command69 } from "commander";
12949
13107
  import { join as join16 } from "path";
12950
- import { select as select5, confirm as confirm12 } from "@inquirer/prompts";
13108
+ import { select as select5, confirm as confirm14 } from "@inquirer/prompts";
12951
13109
  function createRulesRestoreCommand() {
12952
- return new Command67("restore").description("Restore rules from a backup").option("--latest", "Restore the most recent backup").option("-y, --yes", "Skip confirmation").action(async (options) => {
13110
+ return new Command69("restore").description("Restore rules from a backup").option("--latest", "Restore the most recent backup").option("-y, --yes", "Skip confirmation").action(async (options) => {
12953
13111
  const backupService = new BackupService();
12954
13112
  const backups = await backupService.listBackups();
12955
13113
  if (backups.length === 0) {
@@ -12982,7 +13140,7 @@ function createRulesRestoreCommand() {
12982
13140
  console.log(` IDEs: ${selectedBackup.ides.join(", ")}`);
12983
13141
  console.log(` Files: ${selectedBackup.files.length}`);
12984
13142
  if (!options.yes) {
12985
- const proceed = await confirm12({
13143
+ const proceed = await confirm14({
12986
13144
  message: "This will overwrite current rules. Continue?",
12987
13145
  default: false
12988
13146
  });
@@ -13018,12 +13176,12 @@ function formatTimestamp(timestamp) {
13018
13176
  }
13019
13177
 
13020
13178
  // src/commands/rules/sync.ts
13021
- import { Command as Command68 } from "commander";
13179
+ import { Command as Command70 } from "commander";
13022
13180
  import { promises as fs25 } from "fs";
13023
13181
  import { join as join17 } from "path";
13024
- import { checkbox as checkbox6, confirm as confirm13, Separator } from "@inquirer/prompts";
13182
+ import { checkbox as checkbox6, confirm as confirm15, Separator } from "@inquirer/prompts";
13025
13183
  function createRulesSyncCommand() {
13026
- return new Command68("sync").description("Regenerate rule outputs for all configured IDEs").option("--ides <ides>", "Comma-separated list of IDEs to sync (default: all configured)").option("--detect", "Auto-detect active IDEs instead of using config").option("-y, --yes", "Skip confirmations").action(async (options) => {
13184
+ return new Command70("sync").description("Regenerate rule outputs for all configured IDEs").option("--ides <ides>", "Comma-separated list of IDEs to sync (default: all configured)").option("--detect", "Auto-detect active IDEs instead of using config").option("-y, --yes", "Skip confirmations").action(async (options) => {
13027
13185
  const rulePresetDir = join17(process.cwd(), ".jai1", "rule-preset");
13028
13186
  const presetJsonPath = join17(rulePresetDir, "preset.json");
13029
13187
  let presetExists = false;
@@ -13072,7 +13230,7 @@ Detected ${detected.length} active IDE(s):
13072
13230
  console.log(` ${confidence} ${d.name} - ${d.ruleCount} rules`);
13073
13231
  });
13074
13232
  if (!options.yes) {
13075
- const proceed = await confirm13({
13233
+ const proceed = await confirm15({
13076
13234
  message: "\nSync these detected IDEs?",
13077
13235
  default: true
13078
13236
  });
@@ -13241,11 +13399,11 @@ function buildIdeChoices(currentIdes, detected, suggestions) {
13241
13399
  }
13242
13400
 
13243
13401
  // src/commands/rules/info.ts
13244
- import { Command as Command69 } from "commander";
13402
+ import { Command as Command71 } from "commander";
13245
13403
  import { promises as fs26 } from "fs";
13246
13404
  import { join as join18 } from "path";
13247
13405
  function createRulesInfoCommand() {
13248
- return new Command69("info").description("Show current preset information").option("--json", "Output as JSON").action(async (options) => {
13406
+ return new Command71("info").description("Show current preset information").option("--json", "Output as JSON").action(async (options) => {
13249
13407
  const projectConfigService = new ProjectConfigService();
13250
13408
  const rulesConfig = await projectConfigService.loadRules();
13251
13409
  if (!rulesConfig) {
@@ -13348,26 +13506,26 @@ async function checkIdeFilesExist(ideId, format) {
13348
13506
 
13349
13507
  // src/commands/rules/index.ts
13350
13508
  function showRulesHelp() {
13351
- console.log(chalk35.bold.cyan("\u{1F4CB} jai1 rules") + chalk35.dim(" - Qu\u1EA3n l\xFD rule presets cho AI agents"));
13509
+ console.log(chalk37.bold.cyan("\u{1F4CB} jai1 rules") + chalk37.dim(" - Qu\u1EA3n l\xFD rule presets cho AI agents"));
13352
13510
  console.log();
13353
- console.log(chalk35.bold("C\xE1c l\u1EC7nh:"));
13354
- console.log(` ${chalk35.cyan("list")} Li\u1EC7t k\xEA c\xE1c presets c\xF3 s\u1EB5n`);
13355
- console.log(` ${chalk35.cyan("info")} Xem chi ti\u1EBFt m\u1ED9t preset`);
13356
- console.log(` ${chalk35.cyan("init")} Kh\u1EDFi t\u1EA1o rules t\u1EEB preset`);
13357
- console.log(` ${chalk35.cyan("apply")} \xC1p d\u1EE5ng preset v\xE0o project`);
13358
- console.log(` ${chalk35.cyan("sync")} \u0110\u1ED3ng b\u1ED9 rules sang c\xE1c \u0111\u1ECBnh d\u1EA1ng IDE`);
13359
- console.log(` ${chalk35.cyan("restore")} Kh\xF4i ph\u1EE5c rules t\u1EEB backup`);
13511
+ console.log(chalk37.bold("C\xE1c l\u1EC7nh:"));
13512
+ console.log(` ${chalk37.cyan("list")} Li\u1EC7t k\xEA c\xE1c presets c\xF3 s\u1EB5n`);
13513
+ console.log(` ${chalk37.cyan("info")} Xem chi ti\u1EBFt m\u1ED9t preset`);
13514
+ console.log(` ${chalk37.cyan("init")} Kh\u1EDFi t\u1EA1o rules t\u1EEB preset`);
13515
+ console.log(` ${chalk37.cyan("apply")} \xC1p d\u1EE5ng preset v\xE0o project`);
13516
+ console.log(` ${chalk37.cyan("sync")} \u0110\u1ED3ng b\u1ED9 rules sang c\xE1c \u0111\u1ECBnh d\u1EA1ng IDE`);
13517
+ console.log(` ${chalk37.cyan("restore")} Kh\xF4i ph\u1EE5c rules t\u1EEB backup`);
13360
13518
  console.log();
13361
- console.log(chalk35.bold("V\xED d\u1EE5:"));
13362
- console.log(chalk35.dim(" $ jai1 rules list"));
13363
- console.log(chalk35.dim(" $ jai1 rules info react-typescript"));
13364
- console.log(chalk35.dim(" $ jai1 rules init --preset=react-typescript"));
13365
- console.log(chalk35.dim(" $ jai1 rules apply react-typescript"));
13519
+ console.log(chalk37.bold("V\xED d\u1EE5:"));
13520
+ console.log(chalk37.dim(" $ jai1 rules list"));
13521
+ console.log(chalk37.dim(" $ jai1 rules info react-typescript"));
13522
+ console.log(chalk37.dim(" $ jai1 rules init --preset=react-typescript"));
13523
+ console.log(chalk37.dim(" $ jai1 rules apply react-typescript"));
13366
13524
  console.log();
13367
- console.log(chalk35.dim('Ch\u1EA1y "jai1 rules <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt'));
13525
+ console.log(chalk37.dim('Ch\u1EA1y "jai1 rules <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt'));
13368
13526
  }
13369
13527
  function createRulesCommand() {
13370
- const rulesCommand = new Command70("rules").description("Manage rule presets for AI agents").action(() => {
13528
+ const rulesCommand = new Command72("rules").description("Manage rule presets for AI agents").action(() => {
13371
13529
  showRulesHelp();
13372
13530
  });
13373
13531
  rulesCommand.addCommand(createRulesListCommand());
@@ -13380,12 +13538,12 @@ function createRulesCommand() {
13380
13538
  }
13381
13539
 
13382
13540
  // src/commands/skills/index.ts
13383
- import { Command as Command76 } from "commander";
13384
- import chalk41 from "chalk";
13541
+ import { Command as Command78 } from "commander";
13542
+ import chalk43 from "chalk";
13385
13543
 
13386
13544
  // src/commands/skills/find.ts
13387
- import { Command as Command71 } from "commander";
13388
- import chalk36 from "chalk";
13545
+ import { Command as Command73 } from "commander";
13546
+ import chalk38 from "chalk";
13389
13547
  import Table8 from "cli-table3";
13390
13548
 
13391
13549
  // src/services/skills.service.ts
@@ -13679,7 +13837,7 @@ var SkillsService = class {
13679
13837
 
13680
13838
  // src/commands/skills/find.ts
13681
13839
  function createSkillsFindCommand() {
13682
- return new Command71("find").description("Search for skills on server or npm").argument("<query>", "Search query").option("--skillsh", "Search on npm skills registry instead of Jai1 server").option("--all", "Search on both Jai1 server and npm").action(async (query, options) => {
13840
+ return new Command73("find").description("Search for skills on server or npm").argument("<query>", "Search query").option("--skillsh", "Search on npm skills registry instead of Jai1 server").option("--all", "Search on both Jai1 server and npm").action(async (query, options) => {
13683
13841
  const searchNpm = options.skillsh || options.all;
13684
13842
  const searchServer = !options.skillsh || options.all;
13685
13843
  if (searchServer) {
@@ -13688,19 +13846,19 @@ function createSkillsFindCommand() {
13688
13846
  if (!config) {
13689
13847
  throw new ValidationError('Ch\u01B0a x\xE1c th\u1EF1c. Ch\u1EA1y "jai1 auth" tr\u01B0\u1EDBc.');
13690
13848
  }
13691
- console.log(chalk36.cyan("\u{1F50D} \u0110ang t\xECm ki\u1EBFm tr\xEAn Jai1 server..."));
13849
+ console.log(chalk38.cyan("\u{1F50D} \u0110ang t\xECm ki\u1EBFm tr\xEAn Jai1 server..."));
13692
13850
  console.log();
13693
13851
  const skillsService = new SkillsService();
13694
13852
  const results = await skillsService.searchFromServer(config, query);
13695
13853
  if (results.length === 0) {
13696
- console.log(chalk36.yellow("Kh\xF4ng t\xECm th\u1EA5y skills n\xE0o tr\xEAn server."));
13854
+ console.log(chalk38.yellow("Kh\xF4ng t\xECm th\u1EA5y skills n\xE0o tr\xEAn server."));
13697
13855
  } else {
13698
13856
  const table = new Table8({
13699
13857
  head: [
13700
- chalk36.cyan("T\xEAn"),
13701
- chalk36.cyan("M\xF4 t\u1EA3"),
13702
- chalk36.cyan("Version"),
13703
- chalk36.cyan("Downloads")
13858
+ chalk38.cyan("T\xEAn"),
13859
+ chalk38.cyan("M\xF4 t\u1EA3"),
13860
+ chalk38.cyan("Version"),
13861
+ chalk38.cyan("Downloads")
13704
13862
  ],
13705
13863
  style: { head: [], border: ["gray"] },
13706
13864
  colWidths: [25, 40, 10, 12]
@@ -13708,70 +13866,70 @@ function createSkillsFindCommand() {
13708
13866
  for (const skill of results) {
13709
13867
  const name = skill.filepath.replace("skills/", "");
13710
13868
  table.push([
13711
- chalk36.white(name),
13712
- chalk36.dim((skill.description || "").slice(0, 38)),
13713
- chalk36.green(skill.version || "-"),
13714
- chalk36.dim(String(skill.downloads || 0))
13869
+ chalk38.white(name),
13870
+ chalk38.dim((skill.description || "").slice(0, 38)),
13871
+ chalk38.green(skill.version || "-"),
13872
+ chalk38.dim(String(skill.downloads || 0))
13715
13873
  ]);
13716
13874
  }
13717
- console.log(chalk36.bold(`\u{1F4E6} Jai1 Server (${results.length} k\u1EBFt qu\u1EA3)`));
13875
+ console.log(chalk38.bold(`\u{1F4E6} Jai1 Server (${results.length} k\u1EBFt qu\u1EA3)`));
13718
13876
  console.log(table.toString());
13719
13877
  console.log();
13720
13878
  }
13721
13879
  }
13722
13880
  if (searchNpm) {
13723
- console.log(chalk36.cyan("\u{1F50D} \u0110ang t\xECm ki\u1EBFm tr\xEAn npm skills..."));
13881
+ console.log(chalk38.cyan("\u{1F50D} \u0110ang t\xECm ki\u1EBFm tr\xEAn npm skills..."));
13724
13882
  console.log();
13725
13883
  const skillsService = new SkillsService();
13726
13884
  try {
13727
13885
  const output = await skillsService.npmSkillsFind(query);
13728
- console.log(chalk36.bold("\u{1F310} npm Skills Registry"));
13886
+ console.log(chalk38.bold("\u{1F310} npm Skills Registry"));
13729
13887
  console.log(output);
13730
13888
  } catch (error) {
13731
- console.log(chalk36.yellow(
13889
+ console.log(chalk38.yellow(
13732
13890
  `Kh\xF4ng th\u1EC3 t\xECm ki\u1EBFm tr\xEAn npm: ${error instanceof Error ? error.message : String(error)}`
13733
13891
  ));
13734
13892
  }
13735
13893
  }
13736
13894
  if (searchServer && !searchNpm) {
13737
- console.log(chalk36.dim('\u{1F4A1} D\xF9ng "j skills add <t\xEAn>" \u0111\u1EC3 c\xE0i \u0111\u1EB7t t\u1EEB server'));
13895
+ console.log(chalk38.dim('\u{1F4A1} D\xF9ng "j skills add <t\xEAn>" \u0111\u1EC3 c\xE0i \u0111\u1EB7t t\u1EEB server'));
13738
13896
  } else if (searchNpm && !searchServer) {
13739
- console.log(chalk36.dim('\u{1F4A1} D\xF9ng "j skills add <owner/repo@skill> --skillsh" \u0111\u1EC3 c\xE0i \u0111\u1EB7t'));
13897
+ console.log(chalk38.dim('\u{1F4A1} D\xF9ng "j skills add <owner/repo@skill> --skillsh" \u0111\u1EC3 c\xE0i \u0111\u1EB7t'));
13740
13898
  } else {
13741
- console.log(chalk36.dim("\u{1F4A1} C\xE0i \u0111\u1EB7t:"));
13742
- console.log(chalk36.dim(" Server: j skills add <t\xEAn>"));
13743
- console.log(chalk36.dim(" Skills.sh: j skills add <owner/repo@skill> --skillsh"));
13899
+ console.log(chalk38.dim("\u{1F4A1} C\xE0i \u0111\u1EB7t:"));
13900
+ console.log(chalk38.dim(" Server: j skills add <t\xEAn>"));
13901
+ console.log(chalk38.dim(" Skills.sh: j skills add <owner/repo@skill> --skillsh"));
13744
13902
  }
13745
13903
  });
13746
13904
  }
13747
13905
 
13748
13906
  // src/commands/skills/add.ts
13749
- import { Command as Command72 } from "commander";
13907
+ import { Command as Command74 } from "commander";
13750
13908
  import { join as join20 } from "path";
13751
- import chalk37 from "chalk";
13909
+ import chalk39 from "chalk";
13752
13910
  import { checkbox as checkbox7 } from "@inquirer/prompts";
13753
13911
  function createSkillsAddCommand() {
13754
- return new Command72("add").description("Install a skill to .jai1/skills/").argument("<name>", "Skill name or source (npm: GitHub shorthand, URL)").option("--skillsh", "Install from npm skills registry instead of Jai1 server").option("--sync", "Auto-sync to IDE(s) after install").option("--ides <ides...>", "Target IDEs for sync (cursor, windsurf, antigravity, claudecode, opencode)").option("--all", "Sync to all available IDEs").option("-y, --yes", "Headless mode (skip all prompts)").action(async (name, options) => {
13912
+ return new Command74("add").description("Install a skill to .jai1/skills/").argument("<name>", "Skill name or source (npm: GitHub shorthand, URL)").option("--skillsh", "Install from npm skills registry instead of Jai1 server").option("--sync", "Auto-sync to IDE(s) after install").option("--ides <ides...>", "Target IDEs for sync (cursor, windsurf, antigravity, claudecode, opencode)").option("--all", "Sync to all available IDEs").option("-y, --yes", "Headless mode (skip all prompts)").action(async (name, options) => {
13755
13913
  const skillsService = new SkillsService();
13756
13914
  const projectRoot = process.cwd();
13757
13915
  const headless = options.yes === true;
13758
13916
  if (options.skillsh) {
13759
- console.log(chalk37.cyan(`\u{1F310} \u0110ang c\xE0i \u0111\u1EB7t skill t\u1EEB npm: ${name}...`));
13917
+ console.log(chalk39.cyan(`\u{1F310} \u0110ang c\xE0i \u0111\u1EB7t skill t\u1EEB npm: ${name}...`));
13760
13918
  console.log();
13761
13919
  const output = await skillsService.npmSkillsAdd(name, projectRoot);
13762
13920
  console.log(output);
13763
- console.log(chalk37.green("\u2705 C\xE0i \u0111\u1EB7t t\u1EEB npm th\xE0nh c\xF4ng!"));
13921
+ console.log(chalk39.green("\u2705 C\xE0i \u0111\u1EB7t t\u1EEB npm th\xE0nh c\xF4ng!"));
13764
13922
  } else {
13765
13923
  const configService = new ConfigService();
13766
13924
  const config = await configService.load();
13767
13925
  if (!config) {
13768
13926
  throw new ValidationError('Ch\u01B0a x\xE1c th\u1EF1c. Ch\u1EA1y "jai1 auth" tr\u01B0\u1EDBc.');
13769
13927
  }
13770
- console.log(chalk37.cyan(`\u{1F4E6} \u0110ang c\xE0i \u0111\u1EB7t skill: ${name}...`));
13928
+ console.log(chalk39.cyan(`\u{1F4E6} \u0110ang c\xE0i \u0111\u1EB7t skill: ${name}...`));
13771
13929
  console.log();
13772
13930
  const targetDir = join20(projectRoot, ".jai1");
13773
13931
  await skillsService.installFromServer(config, name, targetDir);
13774
- console.log(chalk37.green(`\u2705 \u0110\xE3 c\xE0i \u0111\u1EB7t skill "${name}" v\xE0o .jai1/skills/${name}/`));
13932
+ console.log(chalk39.green(`\u2705 \u0110\xE3 c\xE0i \u0111\u1EB7t skill "${name}" v\xE0o .jai1/skills/${name}/`));
13775
13933
  }
13776
13934
  console.log();
13777
13935
  if (options.sync) {
@@ -13796,7 +13954,7 @@ function createSkillsAddCommand() {
13796
13954
  });
13797
13955
  }
13798
13956
  if (selectedIdes.length > 0) {
13799
- console.log(chalk37.cyan("\u{1F504} \u0110ang sync sang IDE(s)..."));
13957
+ console.log(chalk39.cyan("\u{1F504} \u0110ang sync sang IDE(s)..."));
13800
13958
  console.log();
13801
13959
  const slug = name.includes("/") ? name.split("/").pop() : name;
13802
13960
  const result = await skillsService.syncToIdes(
@@ -13809,24 +13967,24 @@ function createSkillsAddCommand() {
13809
13967
  }
13810
13968
  );
13811
13969
  console.log();
13812
- console.log(chalk37.green(`\u2705 Sync ho\xE0n t\u1EA5t! Created: ${result.created}, Updated: ${result.updated}`));
13970
+ console.log(chalk39.green(`\u2705 Sync ho\xE0n t\u1EA5t! Created: ${result.created}, Updated: ${result.updated}`));
13813
13971
  if (result.errors > 0) {
13814
- console.log(chalk37.yellow(`\u26A0\uFE0F Errors: ${result.errors}`));
13972
+ console.log(chalk39.yellow(`\u26A0\uFE0F Errors: ${result.errors}`));
13815
13973
  }
13816
13974
  }
13817
13975
  } else {
13818
- console.log(chalk37.dim('\u{1F4A1} Ch\u1EA1y "j skills sync" \u0111\u1EC3 \u0111\u1ED3ng b\u1ED9 sang IDE(s)'));
13819
- console.log(chalk37.dim(' ho\u1EB7c "j ide sync" \u0111\u1EC3 sync to\xE0n b\u1ED9 .jai1/'));
13976
+ console.log(chalk39.dim('\u{1F4A1} Ch\u1EA1y "j skills sync" \u0111\u1EC3 \u0111\u1ED3ng b\u1ED9 sang IDE(s)'));
13977
+ console.log(chalk39.dim(' ho\u1EB7c "j ide sync" \u0111\u1EC3 sync to\xE0n b\u1ED9 .jai1/'));
13820
13978
  }
13821
13979
  });
13822
13980
  }
13823
13981
 
13824
13982
  // src/commands/skills/list.ts
13825
- import { Command as Command73 } from "commander";
13826
- import chalk38 from "chalk";
13983
+ import { Command as Command75 } from "commander";
13984
+ import chalk40 from "chalk";
13827
13985
  import Table9 from "cli-table3";
13828
13986
  function createSkillsListCommand() {
13829
- return new Command73("list").description("List installed skills or available skills on server").option("--available", "List all skills available on Jai1 server").option("-s, --search <term>", "Search skills by name or description").action(async (options) => {
13987
+ return new Command75("list").description("List installed skills or available skills on server").option("--available", "List all skills available on Jai1 server").option("-s, --search <term>", "Search skills by name or description").action(async (options) => {
13830
13988
  const skillsService = new SkillsService();
13831
13989
  if (options.available) {
13832
13990
  const configService = new ConfigService();
@@ -13834,19 +13992,19 @@ function createSkillsListCommand() {
13834
13992
  if (!config) {
13835
13993
  throw new ValidationError('Ch\u01B0a x\xE1c th\u1EF1c. Ch\u1EA1y "jai1 auth" tr\u01B0\u1EDBc.');
13836
13994
  }
13837
- console.log(chalk38.cyan("\u{1F4E6} \u0110ang t\u1EA3i danh s\xE1ch skills t\u1EEB server..."));
13995
+ console.log(chalk40.cyan("\u{1F4E6} \u0110ang t\u1EA3i danh s\xE1ch skills t\u1EEB server..."));
13838
13996
  console.log();
13839
13997
  const results = await skillsService.searchFromServer(config, options.search);
13840
13998
  if (results.length === 0) {
13841
- console.log(chalk38.yellow("Kh\xF4ng t\xECm th\u1EA5y skills n\xE0o."));
13999
+ console.log(chalk40.yellow("Kh\xF4ng t\xECm th\u1EA5y skills n\xE0o."));
13842
14000
  return;
13843
14001
  }
13844
14002
  const table = new Table9({
13845
14003
  head: [
13846
- chalk38.cyan("T\xEAn"),
13847
- chalk38.cyan("M\xF4 t\u1EA3"),
13848
- chalk38.cyan("Version"),
13849
- chalk38.cyan("Downloads")
14004
+ chalk40.cyan("T\xEAn"),
14005
+ chalk40.cyan("M\xF4 t\u1EA3"),
14006
+ chalk40.cyan("Version"),
14007
+ chalk40.cyan("Downloads")
13850
14008
  ],
13851
14009
  style: { head: [], border: ["gray"] },
13852
14010
  colWidths: [28, 40, 10, 12]
@@ -13854,63 +14012,63 @@ function createSkillsListCommand() {
13854
14012
  for (const skill of results) {
13855
14013
  const name = skill.filepath.replace("skills/", "");
13856
14014
  table.push([
13857
- chalk38.white(name),
13858
- chalk38.dim((skill.description || "").slice(0, 38)),
13859
- chalk38.green(skill.version || "-"),
13860
- chalk38.dim(String(skill.downloads || 0))
14015
+ chalk40.white(name),
14016
+ chalk40.dim((skill.description || "").slice(0, 38)),
14017
+ chalk40.green(skill.version || "-"),
14018
+ chalk40.dim(String(skill.downloads || 0))
13861
14019
  ]);
13862
14020
  }
13863
14021
  console.log(table.toString());
13864
14022
  console.log();
13865
- console.log(chalk38.dim(`T\u1ED5ng c\u1ED9ng: ${results.length} skill(s)`));
13866
- console.log(chalk38.dim('\n\u{1F4A1} D\xF9ng "j skills add <t\xEAn>" \u0111\u1EC3 c\xE0i \u0111\u1EB7t'));
14023
+ console.log(chalk40.dim(`T\u1ED5ng c\u1ED9ng: ${results.length} skill(s)`));
14024
+ console.log(chalk40.dim('\n\u{1F4A1} D\xF9ng "j skills add <t\xEAn>" \u0111\u1EC3 c\xE0i \u0111\u1EB7t'));
13867
14025
  } else {
13868
14026
  const projectRoot = process.cwd();
13869
14027
  const skills = await skillsService.listLocal(projectRoot);
13870
14028
  if (skills.length === 0) {
13871
- console.log(chalk38.yellow("Ch\u01B0a c\xF3 skills n\xE0o \u0111\u01B0\u1EE3c c\xE0i \u0111\u1EB7t."));
14029
+ console.log(chalk40.yellow("Ch\u01B0a c\xF3 skills n\xE0o \u0111\u01B0\u1EE3c c\xE0i \u0111\u1EB7t."));
13872
14030
  console.log();
13873
- console.log(chalk38.dim('\u{1F4A1} D\xF9ng "j skills add <t\xEAn>" \u0111\u1EC3 c\xE0i \u0111\u1EB7t'));
13874
- console.log(chalk38.dim(' ho\u1EB7c "j skills list --available" \u0111\u1EC3 xem skills c\xF3 s\u1EB5n'));
14031
+ console.log(chalk40.dim('\u{1F4A1} D\xF9ng "j skills add <t\xEAn>" \u0111\u1EC3 c\xE0i \u0111\u1EB7t'));
14032
+ console.log(chalk40.dim(' ho\u1EB7c "j skills list --available" \u0111\u1EC3 xem skills c\xF3 s\u1EB5n'));
13875
14033
  return;
13876
14034
  }
13877
- console.log(chalk38.bold.cyan("\u{1F6E0} Skills \u0111\xE3 c\xE0i \u0111\u1EB7t"));
14035
+ console.log(chalk40.bold.cyan("\u{1F6E0} Skills \u0111\xE3 c\xE0i \u0111\u1EB7t"));
13878
14036
  console.log();
13879
14037
  const table = new Table9({
13880
14038
  head: [
13881
- chalk38.cyan("T\xEAn"),
13882
- chalk38.cyan("M\xF4 t\u1EA3"),
13883
- chalk38.cyan("Files")
14039
+ chalk40.cyan("T\xEAn"),
14040
+ chalk40.cyan("M\xF4 t\u1EA3"),
14041
+ chalk40.cyan("Files")
13884
14042
  ],
13885
14043
  style: { head: [], border: ["gray"] },
13886
14044
  colWidths: [28, 45, 8]
13887
14045
  });
13888
14046
  for (const skill of skills) {
13889
14047
  table.push([
13890
- chalk38.white(skill.slug),
13891
- chalk38.dim(skill.description.slice(0, 43)),
13892
- chalk38.dim(String(skill.fileCount))
14048
+ chalk40.white(skill.slug),
14049
+ chalk40.dim(skill.description.slice(0, 43)),
14050
+ chalk40.dim(String(skill.fileCount))
13893
14051
  ]);
13894
14052
  }
13895
14053
  console.log(table.toString());
13896
14054
  console.log();
13897
- console.log(chalk38.dim(`T\u1ED5ng c\u1ED9ng: ${skills.length} skill(s)`));
13898
- console.log(chalk38.dim('\n\u{1F4A1} D\xF9ng "j skills sync" \u0111\u1EC3 \u0111\u1ED3ng b\u1ED9 sang IDE(s)'));
14055
+ console.log(chalk40.dim(`T\u1ED5ng c\u1ED9ng: ${skills.length} skill(s)`));
14056
+ console.log(chalk40.dim('\n\u{1F4A1} D\xF9ng "j skills sync" \u0111\u1EC3 \u0111\u1ED3ng b\u1ED9 sang IDE(s)'));
13899
14057
  }
13900
14058
  });
13901
14059
  }
13902
14060
 
13903
14061
  // src/commands/skills/info.ts
13904
- import { Command as Command74 } from "commander";
13905
- import chalk39 from "chalk";
14062
+ import { Command as Command76 } from "commander";
14063
+ import chalk41 from "chalk";
13906
14064
  function createSkillsInfoCommand() {
13907
- return new Command74("info").description("Show detailed information about a skill").argument("<name>", "Skill name").option("--server", "Show info from Jai1 server instead of local").action(async (name, options) => {
14065
+ return new Command76("info").description("Show detailed information about a skill").argument("<name>", "Skill name").option("--server", "Show info from Jai1 server instead of local").action(async (name, options) => {
13908
14066
  const skillsService = new SkillsService();
13909
14067
  if (options.server) {
13910
14068
  const configService = new ConfigService();
13911
14069
  const config = await configService.load();
13912
14070
  if (!config) {
13913
- console.log(chalk39.red('\u274C Ch\u01B0a x\xE1c th\u1EF1c. Ch\u1EA1y "jai1 auth" tr\u01B0\u1EDBc.'));
14071
+ console.log(chalk41.red('\u274C Ch\u01B0a x\xE1c th\u1EF1c. Ch\u1EA1y "jai1 auth" tr\u01B0\u1EDBc.'));
13914
14072
  process.exit(1);
13915
14073
  }
13916
14074
  const filepath = name.startsWith("skills/") ? name : `skills/${name}`;
@@ -13919,7 +14077,7 @@ function createSkillsInfoCommand() {
13919
14077
  try {
13920
14078
  const component = await componentsService.get(config, filepath);
13921
14079
  console.log(`
13922
- \u{1F6E0} ${chalk39.bold(component.name || name)}
14080
+ \u{1F6E0} ${chalk41.bold(component.name || name)}
13923
14081
  `);
13924
14082
  console.log(`Filepath: ${component.filepath}`);
13925
14083
  console.log(`Version: ${component.version}`);
@@ -13932,47 +14090,47 @@ function createSkillsInfoCommand() {
13932
14090
  }
13933
14091
  console.log(`Type: ${component.contentType}`);
13934
14092
  console.log();
13935
- console.log(chalk39.dim('\u{1F4A1} D\xF9ng "j skills add ' + name + '" \u0111\u1EC3 c\xE0i \u0111\u1EB7t'));
14093
+ console.log(chalk41.dim('\u{1F4A1} D\xF9ng "j skills add ' + name + '" \u0111\u1EC3 c\xE0i \u0111\u1EB7t'));
13936
14094
  } catch (error) {
13937
- console.log(chalk39.red(`\u274C Kh\xF4ng t\xECm th\u1EA5y skill "${name}" tr\xEAn server.`));
14095
+ console.log(chalk41.red(`\u274C Kh\xF4ng t\xECm th\u1EA5y skill "${name}" tr\xEAn server.`));
13938
14096
  process.exit(1);
13939
14097
  }
13940
14098
  } else {
13941
14099
  const projectRoot = process.cwd();
13942
14100
  const skill = await skillsService.getSkillInfo(projectRoot, name);
13943
14101
  if (!skill) {
13944
- console.log(chalk39.red(`\u274C Skill "${name}" ch\u01B0a \u0111\u01B0\u1EE3c c\xE0i \u0111\u1EB7t.`));
13945
- console.log(chalk39.dim('\u{1F4A1} D\xF9ng "j skills info ' + name + ' --server" \u0111\u1EC3 xem tr\xEAn server'));
13946
- console.log(chalk39.dim(' ho\u1EB7c "j skills add ' + name + '" \u0111\u1EC3 c\xE0i \u0111\u1EB7t'));
14102
+ console.log(chalk41.red(`\u274C Skill "${name}" ch\u01B0a \u0111\u01B0\u1EE3c c\xE0i \u0111\u1EB7t.`));
14103
+ console.log(chalk41.dim('\u{1F4A1} D\xF9ng "j skills info ' + name + ' --server" \u0111\u1EC3 xem tr\xEAn server'));
14104
+ console.log(chalk41.dim(' ho\u1EB7c "j skills add ' + name + '" \u0111\u1EC3 c\xE0i \u0111\u1EB7t'));
13947
14105
  process.exit(1);
13948
14106
  }
13949
14107
  console.log(`
13950
- \u{1F6E0} ${chalk39.bold(skill.name)}
14108
+ \u{1F6E0} ${chalk41.bold(skill.name)}
13951
14109
  `);
13952
14110
  console.log(`Slug: ${skill.slug}`);
13953
- console.log(`Description: ${skill.description || chalk39.dim("(none)")}`);
14111
+ console.log(`Description: ${skill.description || chalk41.dim("(none)")}`);
13954
14112
  console.log(`Path: ${skill.path}`);
13955
14113
  console.log(`Files: ${skill.fileCount}`);
13956
14114
  console.log();
13957
- console.log(chalk39.dim('\u{1F4A1} D\xF9ng "j skills sync" \u0111\u1EC3 \u0111\u1ED3ng b\u1ED9 sang IDE(s)'));
14115
+ console.log(chalk41.dim('\u{1F4A1} D\xF9ng "j skills sync" \u0111\u1EC3 \u0111\u1ED3ng b\u1ED9 sang IDE(s)'));
13958
14116
  }
13959
14117
  });
13960
14118
  }
13961
14119
 
13962
14120
  // src/commands/skills/sync.ts
13963
- import { Command as Command75 } from "commander";
13964
- import chalk40 from "chalk";
13965
- import { confirm as confirm15, checkbox as checkbox8 } from "@inquirer/prompts";
14121
+ import { Command as Command77 } from "commander";
14122
+ import chalk42 from "chalk";
14123
+ import { confirm as confirm17, checkbox as checkbox8 } from "@inquirer/prompts";
13966
14124
  function createSkillsSyncCommand() {
13967
- return new Command75("sync").description("Sync skills from .jai1/skills/ to IDE directories").option("--ides <ides...>", "Target IDEs (cursor, windsurf, antigravity, claudecode, opencode)").option("--skills <skills...>", "Specific skill slugs to sync (default: all)").option("--all", "Select all available IDEs").option("--dry-run", "Preview changes without writing files").option("-y, --yes", "Headless mode (skip all prompts)").action(async (options) => {
14125
+ return new Command77("sync").description("Sync skills from .jai1/skills/ to IDE directories").option("--ides <ides...>", "Target IDEs (cursor, windsurf, antigravity, claudecode, opencode)").option("--skills <skills...>", "Specific skill slugs to sync (default: all)").option("--all", "Select all available IDEs").option("--dry-run", "Preview changes without writing files").option("-y, --yes", "Headless mode (skip all prompts)").action(async (options) => {
13968
14126
  const skillsService = new SkillsService();
13969
14127
  const projectRoot = process.cwd();
13970
14128
  const headless = options.yes === true;
13971
- console.log(chalk40.bold.cyan("\n\u{1F504} Sync skills sang IDE(s)\n"));
14129
+ console.log(chalk42.bold.cyan("\n\u{1F504} Sync skills sang IDE(s)\n"));
13972
14130
  const localSkills = await skillsService.listLocal(projectRoot);
13973
14131
  if (localSkills.length === 0) {
13974
- console.log(chalk40.yellow("\u26A0\uFE0F Kh\xF4ng c\xF3 skills n\xE0o trong .jai1/skills/"));
13975
- console.log(chalk40.dim('\u{1F4A1} Ch\u1EA1y "j skills add <t\xEAn>" \u0111\u1EC3 c\xE0i \u0111\u1EB7t skills tr\u01B0\u1EDBc'));
14132
+ console.log(chalk42.yellow("\u26A0\uFE0F Kh\xF4ng c\xF3 skills n\xE0o trong .jai1/skills/"));
14133
+ console.log(chalk42.dim('\u{1F4A1} Ch\u1EA1y "j skills add <t\xEAn>" \u0111\u1EC3 c\xE0i \u0111\u1EB7t skills tr\u01B0\u1EDBc'));
13976
14134
  process.exit(1);
13977
14135
  }
13978
14136
  console.log(`\u{1F4C1} T\xECm th\u1EA5y ${localSkills.length} skill(s) trong .jai1/skills/`);
@@ -14004,7 +14162,7 @@ function createSkillsSyncCommand() {
14004
14162
  theme: checkboxTheme
14005
14163
  });
14006
14164
  if (selectedIdes.length === 0) {
14007
- console.log(chalk40.yellow("\n\u26A0\uFE0F Ch\u01B0a ch\u1ECDn IDE n\xE0o!"));
14165
+ console.log(chalk42.yellow("\n\u26A0\uFE0F Ch\u01B0a ch\u1ECDn IDE n\xE0o!"));
14008
14166
  process.exit(0);
14009
14167
  }
14010
14168
  }
@@ -14019,34 +14177,34 @@ function createSkillsSyncCommand() {
14019
14177
  console.log(` Total: ${totalFiles} skill folder(s) s\u1EBD \u0111\u01B0\u1EE3c sync
14020
14178
  `);
14021
14179
  if (options.dryRun) {
14022
- console.log(chalk40.dim("\u{1F50D} DRY RUN - Kh\xF4ng c\xF3 file n\xE0o \u0111\u01B0\u1EE3c ghi\n"));
14180
+ console.log(chalk42.dim("\u{1F50D} DRY RUN - Kh\xF4ng c\xF3 file n\xE0o \u0111\u01B0\u1EE3c ghi\n"));
14023
14181
  return;
14024
14182
  }
14025
14183
  if (!headless) {
14026
- const confirmed = await confirm15({
14184
+ const confirmed = await confirm17({
14027
14185
  message: "Ti\u1EBFp t\u1EE5c sync?",
14028
14186
  default: true
14029
14187
  });
14030
14188
  if (!confirmed) {
14031
- console.log(chalk40.yellow("\n\u274C \u0110\xE3 h\u1EE7y sync.\n"));
14189
+ console.log(chalk42.yellow("\n\u274C \u0110\xE3 h\u1EE7y sync.\n"));
14032
14190
  process.exit(0);
14033
14191
  }
14034
14192
  }
14035
- console.log(chalk40.cyan("\n\u{1F504} \u0110ang sync...\n"));
14193
+ console.log(chalk42.cyan("\n\u{1F504} \u0110ang sync...\n"));
14036
14194
  const result = await skillsService.syncToIdes(
14037
14195
  projectRoot,
14038
14196
  selectedIdes,
14039
14197
  selectedSlugs,
14040
14198
  (res) => {
14041
14199
  const icon = res.status === "created" ? "\u2713" : res.status === "updated" ? "\u21BB" : "\u2717";
14042
- const statusColor = res.status === "error" ? chalk40.red : chalk40.green;
14043
- console.log(` ${statusColor(icon)} ${res.ide}: ${res.skill} \u2192 ${chalk40.dim(res.path)}`);
14200
+ const statusColor = res.status === "error" ? chalk42.red : chalk42.green;
14201
+ console.log(` ${statusColor(icon)} ${res.ide}: ${res.skill} \u2192 ${chalk42.dim(res.path)}`);
14044
14202
  if (res.status === "error" && res.error) {
14045
- console.log(` ${chalk40.red("Error:")} ${res.error}`);
14203
+ console.log(` ${chalk42.red("Error:")} ${res.error}`);
14046
14204
  }
14047
14205
  }
14048
14206
  );
14049
- console.log(chalk40.green("\n\u2705 Sync ho\xE0n t\u1EA5t!\n"));
14207
+ console.log(chalk42.green("\n\u2705 Sync ho\xE0n t\u1EA5t!\n"));
14050
14208
  console.log(` Created: ${result.created}`);
14051
14209
  console.log(` Updated: ${result.updated}`);
14052
14210
  if (result.errors > 0) {
@@ -14059,27 +14217,27 @@ function createSkillsSyncCommand() {
14059
14217
  // src/commands/skills/index.ts
14060
14218
  function showSkillsHelp() {
14061
14219
  const cli = getCliName();
14062
- console.log(chalk41.bold.cyan("\u{1F6E0} " + cli + " skills") + chalk41.dim(" - Qu\u1EA3n l\xFD agent skills"));
14220
+ console.log(chalk43.bold.cyan("\u{1F6E0} " + cli + " skills") + chalk43.dim(" - Qu\u1EA3n l\xFD agent skills"));
14063
14221
  console.log();
14064
- console.log(chalk41.bold("C\xE1c l\u1EC7nh:"));
14065
- console.log(` ${chalk41.cyan("find")} T\xECm ki\u1EBFm skills tr\xEAn server ho\u1EB7c npm`);
14066
- console.log(` ${chalk41.cyan("add")} C\xE0i \u0111\u1EB7t skill v\xE0o .jai1/skills/`);
14067
- console.log(` ${chalk41.cyan("list")} Li\u1EC7t k\xEA skills \u0111\xE3 c\xE0i ho\u1EB7c c\xF3 s\u1EB5n`);
14068
- console.log(` ${chalk41.cyan("info")} Xem chi ti\u1EBFt m\u1ED9t skill`);
14069
- console.log(` ${chalk41.cyan("sync")} \u0110\u1ED3ng b\u1ED9 skills sang c\xE1c IDE`);
14222
+ console.log(chalk43.bold("C\xE1c l\u1EC7nh:"));
14223
+ console.log(` ${chalk43.cyan("find")} T\xECm ki\u1EBFm skills tr\xEAn server ho\u1EB7c npm`);
14224
+ console.log(` ${chalk43.cyan("add")} C\xE0i \u0111\u1EB7t skill v\xE0o .jai1/skills/`);
14225
+ console.log(` ${chalk43.cyan("list")} Li\u1EC7t k\xEA skills \u0111\xE3 c\xE0i ho\u1EB7c c\xF3 s\u1EB5n`);
14226
+ console.log(` ${chalk43.cyan("info")} Xem chi ti\u1EBFt m\u1ED9t skill`);
14227
+ console.log(` ${chalk43.cyan("sync")} \u0110\u1ED3ng b\u1ED9 skills sang c\xE1c IDE`);
14070
14228
  console.log();
14071
- console.log(chalk41.bold("V\xED d\u1EE5:"));
14072
- console.log(chalk41.dim(` $ ${cli} skills find audit`));
14073
- console.log(chalk41.dim(` $ ${cli} skills find "react" --skillsh`));
14074
- console.log(chalk41.dim(` $ ${cli} skills add brainstorming`));
14075
- console.log(chalk41.dim(` $ ${cli} skills add vercel/next-skills --skillsh`));
14076
- console.log(chalk41.dim(` $ ${cli} skills list`));
14077
- console.log(chalk41.dim(` $ ${cli} skills sync --all -y`));
14229
+ console.log(chalk43.bold("V\xED d\u1EE5:"));
14230
+ console.log(chalk43.dim(` $ ${cli} skills find audit`));
14231
+ console.log(chalk43.dim(` $ ${cli} skills find "react" --skillsh`));
14232
+ console.log(chalk43.dim(` $ ${cli} skills add brainstorming`));
14233
+ console.log(chalk43.dim(` $ ${cli} skills add vercel/next-skills --skillsh`));
14234
+ console.log(chalk43.dim(` $ ${cli} skills list`));
14235
+ console.log(chalk43.dim(` $ ${cli} skills sync --all -y`));
14078
14236
  console.log();
14079
- console.log(chalk41.dim(`Ch\u1EA1y "${cli} skills <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt`));
14237
+ console.log(chalk43.dim(`Ch\u1EA1y "${cli} skills <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt`));
14080
14238
  }
14081
14239
  function createSkillsCommand() {
14082
- const cmd = new Command76("skills").alias("s").description("Manage agent skills (search, install, sync to IDEs)").action(() => {
14240
+ const cmd = new Command78("skills").alias("s").description("Manage agent skills (search, install, sync to IDEs)").action(() => {
14083
14241
  showSkillsHelp();
14084
14242
  });
14085
14243
  cmd.addCommand(createSkillsFindCommand());
@@ -14091,8 +14249,8 @@ function createSkillsCommand() {
14091
14249
  }
14092
14250
 
14093
14251
  // src/commands/upgrade.ts
14094
- import { Command as Command77 } from "commander";
14095
- import { confirm as confirm16 } from "@inquirer/prompts";
14252
+ import { Command as Command79 } from "commander";
14253
+ import { confirm as confirm18 } from "@inquirer/prompts";
14096
14254
  import { execSync as execSync5 } from "child_process";
14097
14255
  var colors2 = {
14098
14256
  yellow: "\x1B[33m",
@@ -14103,7 +14261,7 @@ var colors2 = {
14103
14261
  bold: "\x1B[1m"
14104
14262
  };
14105
14263
  function createUpgradeCommand() {
14106
- return new Command77("upgrade").description("Upgrade CLI client to the latest version").option("--check", "Only check for updates without installing").option("--force", "Force upgrade without confirmation").action(async (options) => {
14264
+ return new Command79("upgrade").description("Upgrade CLI client to the latest version").option("--check", "Only check for updates without installing").option("--force", "Force upgrade without confirmation").action(async (options) => {
14107
14265
  await handleUpgrade(options);
14108
14266
  });
14109
14267
  }
@@ -14147,7 +14305,7 @@ ${colors2.bold}Current version:${colors2.reset} ${currentVersion}`);
14147
14305
  return;
14148
14306
  }
14149
14307
  if (!options.force) {
14150
- const shouldUpdate = await confirm16({
14308
+ const shouldUpdate = await confirm18({
14151
14309
  message: "Update to the latest version now?",
14152
14310
  default: true
14153
14311
  });
@@ -14251,11 +14409,11 @@ function getInstallCommand(packageManager2) {
14251
14409
  }
14252
14410
 
14253
14411
  // src/commands/clean.ts
14254
- import { Command as Command78 } from "commander";
14255
- import { confirm as confirm17, select as select6 } from "@inquirer/prompts";
14412
+ import { Command as Command80 } from "commander";
14413
+ import { confirm as confirm19, select as select6 } from "@inquirer/prompts";
14256
14414
  import { join as join21 } from "path";
14257
14415
  function createCleanCommand() {
14258
- return new Command78("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) => {
14416
+ return new Command80("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) => {
14259
14417
  await handleClean(options);
14260
14418
  });
14261
14419
  }
@@ -14351,7 +14509,7 @@ async function cleanTarget(target, skipConfirm) {
14351
14509
  }
14352
14510
  const countStr = info.count ? ` (${info.count} items)` : "";
14353
14511
  if (!skipConfirm) {
14354
- const confirmed = await confirm17({
14512
+ const confirmed = await confirm19({
14355
14513
  message: `Delete ${target.name}${countStr}?`,
14356
14514
  default: false
14357
14515
  });
@@ -14369,7 +14527,7 @@ async function cleanTarget(target, skipConfirm) {
14369
14527
  }
14370
14528
 
14371
14529
  // src/commands/redmine/check.ts
14372
- import { Command as Command79 } from "commander";
14530
+ import { Command as Command81 } from "commander";
14373
14531
 
14374
14532
  // src/services/redmine-config.service.ts
14375
14533
  import { readFile as readFile7 } from "fs/promises";
@@ -14676,7 +14834,7 @@ async function checkConnectivity(config) {
14676
14834
 
14677
14835
  // src/commands/redmine/check.ts
14678
14836
  function createRedmineCheckCommand() {
14679
- const cmd = new Command79("check").description("Check Redmine connectivity").option("-c, --config <path>", "Config file path", "redmine.config.yaml").option("--json", "Output as JSON").action(async (options) => {
14837
+ const cmd = new Command81("check").description("Check Redmine connectivity").option("-c, --config <path>", "Config file path", "redmine.config.yaml").option("--json", "Output as JSON").action(async (options) => {
14680
14838
  await handleRedmineCheck(options);
14681
14839
  });
14682
14840
  return cmd;
@@ -14704,7 +14862,7 @@ async function handleRedmineCheck(options) {
14704
14862
  }
14705
14863
 
14706
14864
  // src/commands/redmine/sync-issue.ts
14707
- import { Command as Command80 } from "commander";
14865
+ import { Command as Command82 } from "commander";
14708
14866
 
14709
14867
  // src/sync-issue.ts
14710
14868
  import { resolve as resolve3, relative } from "path";
@@ -15088,7 +15246,7 @@ function extractIssueIdFromUrl(url) {
15088
15246
 
15089
15247
  // src/commands/redmine/sync-issue.ts
15090
15248
  function createSyncIssueCommand() {
15091
- const cmd = new Command80("issue").description("Sync a single issue").option("-i, --id <number>", "Issue ID").option("-u, --url <url>", "Issue URL").option("--dry-run", "Preview without making changes").option("-c, --config <path>", "Config file path").option("-o, --output-dir <path>", "Output directory").option("--json", "Output as JSON").action(async (options) => {
15249
+ const cmd = new Command82("issue").description("Sync a single issue").option("-i, --id <number>", "Issue ID").option("-u, --url <url>", "Issue URL").option("--dry-run", "Preview without making changes").option("-c, --config <path>", "Config file path").option("-o, --output-dir <path>", "Output directory").option("--json", "Output as JSON").action(async (options) => {
15092
15250
  await handleSyncIssue(options);
15093
15251
  });
15094
15252
  return cmd;
@@ -15132,7 +15290,7 @@ async function handleSyncIssue(options) {
15132
15290
  }
15133
15291
 
15134
15292
  // src/commands/redmine/sync-project.ts
15135
- import { Command as Command81 } from "commander";
15293
+ import { Command as Command83 } from "commander";
15136
15294
 
15137
15295
  // src/sync-project.ts
15138
15296
  async function syncProject(config, options = {}) {
@@ -15202,7 +15360,7 @@ async function syncProject(config, options = {}) {
15202
15360
 
15203
15361
  // src/commands/redmine/sync-project.ts
15204
15362
  function createSyncProjectCommand() {
15205
- const cmd = new Command81("project").description("Sync all issues in a project").option("-s, --status <status>", "Filter by status (default: *)", "*").option("--updated-since <date>", "Only sync issues updated since YYYY-MM-DD").option("--concurrency <number>", "Number of concurrent requests").option("--page-size <number>", "Page size for API requests").option("--dry-run", "Preview without making changes").option("-c, --config <path>", "Config file path").option("-o, --output-dir <path>", "Output directory").option("--json", "Output as JSON").action(async (options) => {
15363
+ const cmd = new Command83("project").description("Sync all issues in a project").option("-s, --status <status>", "Filter by status (default: *)", "*").option("--updated-since <date>", "Only sync issues updated since YYYY-MM-DD").option("--concurrency <number>", "Number of concurrent requests").option("--page-size <number>", "Page size for API requests").option("--dry-run", "Preview without making changes").option("-c, --config <path>", "Config file path").option("-o, --output-dir <path>", "Output directory").option("--json", "Output as JSON").action(async (options) => {
15206
15364
  await handleSyncProject(options);
15207
15365
  });
15208
15366
  return cmd;
@@ -15257,12 +15415,12 @@ async function handleSyncProject(options) {
15257
15415
  }
15258
15416
 
15259
15417
  // src/commands/framework/info.ts
15260
- import { Command as Command82 } from "commander";
15418
+ import { Command as Command84 } from "commander";
15261
15419
  import { promises as fs28 } from "fs";
15262
15420
  import { join as join22 } from "path";
15263
15421
  import { homedir as homedir5 } from "os";
15264
15422
  function createInfoCommand() {
15265
- const cmd = new Command82("info").description("Show client configuration and status").option("--json", "Output as JSON").option("--verbose", "Show detailed information").action(async (options) => {
15423
+ const cmd = new Command84("info").description("Show client configuration and status").option("--json", "Output as JSON").option("--verbose", "Show detailed information").action(async (options) => {
15266
15424
  await handleInfo(options);
15267
15425
  });
15268
15426
  return cmd;
@@ -15318,8 +15476,8 @@ async function getProjectStatus2() {
15318
15476
  }
15319
15477
 
15320
15478
  // src/commands/self-update.ts
15321
- import { Command as Command83 } from "commander";
15322
- import { confirm as confirm18 } from "@inquirer/prompts";
15479
+ import { Command as Command85 } from "commander";
15480
+ import { confirm as confirm20 } from "@inquirer/prompts";
15323
15481
  import { execSync as execSync6 } from "child_process";
15324
15482
  var colors3 = {
15325
15483
  yellow: "\x1B[33m",
@@ -15330,7 +15488,7 @@ var colors3 = {
15330
15488
  bold: "\x1B[1m"
15331
15489
  };
15332
15490
  function createSelfUpdateCommand() {
15333
- return new Command83("self-update").description("Update CLI client to the latest version").option("--check", "Only check for updates without installing").option("--force", "Force update without confirmation").action(async (options) => {
15491
+ return new Command85("self-update").description("Update CLI client to the latest version").option("--check", "Only check for updates without installing").option("--force", "Force update without confirmation").action(async (options) => {
15334
15492
  await handleSelfUpdate(options);
15335
15493
  });
15336
15494
  }
@@ -15374,7 +15532,7 @@ ${colors3.bold}Current version:${colors3.reset} ${currentVersion}`);
15374
15532
  return;
15375
15533
  }
15376
15534
  if (!options.force) {
15377
- const shouldUpdate = await confirm18({
15535
+ const shouldUpdate = await confirm20({
15378
15536
  message: "Update to the latest version now?",
15379
15537
  default: true
15380
15538
  });
@@ -15470,10 +15628,10 @@ function getInstallCommand2(packageManager2) {
15470
15628
  }
15471
15629
 
15472
15630
  // src/commands/clear-backups.ts
15473
- import { Command as Command84 } from "commander";
15474
- import { confirm as confirm19 } from "@inquirer/prompts";
15631
+ import { Command as Command86 } from "commander";
15632
+ import { confirm as confirm21 } from "@inquirer/prompts";
15475
15633
  function createClearBackupsCommand() {
15476
- return new Command84("clear-backups").description("Clear backup files").option("-y, --yes", "Skip confirmation").action(async (options) => {
15634
+ return new Command86("clear-backups").description("Clear backup files").option("-y, --yes", "Skip confirmation").action(async (options) => {
15477
15635
  const service = new ComponentsService();
15478
15636
  const backups = await service.listBackups(process.cwd());
15479
15637
  if (backups.length === 0) {
@@ -15489,7 +15647,7 @@ function createClearBackupsCommand() {
15489
15647
  }
15490
15648
  console.log();
15491
15649
  if (!options.yes) {
15492
- const ok = await confirm19({ message: "Delete all backups?", default: false });
15650
+ const ok = await confirm21({ message: "Delete all backups?", default: false });
15493
15651
  if (!ok) return;
15494
15652
  }
15495
15653
  await service.clearBackups(process.cwd());
@@ -15498,8 +15656,8 @@ function createClearBackupsCommand() {
15498
15656
  }
15499
15657
 
15500
15658
  // src/commands/vscode/index.ts
15501
- import { Command as Command85 } from "commander";
15502
- import { checkbox as checkbox9, confirm as confirm20, select as select7 } from "@inquirer/prompts";
15659
+ import { Command as Command87 } from "commander";
15660
+ import { checkbox as checkbox9, confirm as confirm22, select as select7 } from "@inquirer/prompts";
15503
15661
  import fs29 from "fs/promises";
15504
15662
  import path12 from "path";
15505
15663
  import { existsSync as existsSync4 } from "fs";
@@ -15638,7 +15796,7 @@ var PERFORMANCE_GROUPS2 = {
15638
15796
  }
15639
15797
  };
15640
15798
  function createVSCodeCommand() {
15641
- const vscodeCommand = new Command85("vscode").description("Qu\u1EA3n l\xFD c\xE0i \u0111\u1EB7t VSCode cho d\u1EF1 \xE1n hi\u1EC7n t\u1EA1i");
15799
+ const vscodeCommand = new Command87("vscode").description("Qu\u1EA3n l\xFD c\xE0i \u0111\u1EB7t VSCode cho d\u1EF1 \xE1n hi\u1EC7n t\u1EA1i");
15642
15800
  vscodeCommand.action(async () => {
15643
15801
  await interactiveMode2();
15644
15802
  });
@@ -15744,7 +15902,7 @@ async function applyGroups2(groupKeys, action) {
15744
15902
  console.log("\u{1F4C4} \u0110\xE3 \u0111\u1ECDc c\xE0i \u0111\u1EB7t hi\u1EC7n t\u1EA1i t\u1EEB settings.json");
15745
15903
  } catch {
15746
15904
  console.warn("\u26A0\uFE0F Kh\xF4ng th\u1EC3 \u0111\u1ECDc settings.json (c\xF3 th\u1EC3 ch\u1EE9a comments).");
15747
- const confirmOverwrite = await confirm20({
15905
+ const confirmOverwrite = await confirm22({
15748
15906
  message: "Ghi \u0111\xE8 file settings.json hi\u1EC7n t\u1EA1i?",
15749
15907
  default: false
15750
15908
  });
@@ -15791,7 +15949,7 @@ async function resetSettings2(groupKeys) {
15791
15949
  console.log("\n\u26A0\uFE0F Kh\xF4ng t\xECm th\u1EA5y file settings.json");
15792
15950
  return;
15793
15951
  }
15794
- const confirmReset = await confirm20({
15952
+ const confirmReset = await confirm22({
15795
15953
  message: groupKeys.length === 0 ? "Reset T\u1EA4T C\u1EA2 settings v\u1EC1 m\u1EB7c \u0111\u1ECBnh (x\xF3a to\xE0n b\u1ED9 file)?" : `Reset c\xE1c nh\xF3m: ${groupKeys.join(", ")}?`,
15796
15954
  default: false
15797
15955
  });
@@ -15809,10 +15967,10 @@ async function resetSettings2(groupKeys) {
15809
15967
  }
15810
15968
 
15811
15969
  // src/commands/migrate-ide.ts
15812
- import { Command as Command86 } from "commander";
15813
- import { checkbox as checkbox10, confirm as confirm21 } from "@inquirer/prompts";
15970
+ import { Command as Command88 } from "commander";
15971
+ import { checkbox as checkbox10, confirm as confirm23 } from "@inquirer/prompts";
15814
15972
  function createMigrateIdeCommand() {
15815
- const cmd = new Command86("migrate-ide").description("Migrate .jai1 rules v\xE0 workflows sang IDEs (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) => {
15973
+ const cmd = new Command88("migrate-ide").description("Migrate .jai1 rules v\xE0 workflows sang IDEs (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) => {
15816
15974
  await runMigrateIde(options);
15817
15975
  });
15818
15976
  return cmd;
@@ -15883,7 +16041,7 @@ async function runMigrateIde(options) {
15883
16041
  if (options.dryRun) {
15884
16042
  console.log("\u{1F50D} DRY RUN - No files will be written\n");
15885
16043
  }
15886
- const confirmed = await confirm21({
16044
+ const confirmed = await confirm23({
15887
16045
  message: "Proceed with migration?",
15888
16046
  default: true
15889
16047
  });
@@ -15921,20 +16079,20 @@ async function runMigrateIde(options) {
15921
16079
 
15922
16080
  // src/utils/help-formatter.ts
15923
16081
  import boxen4 from "boxen";
15924
- import chalk42 from "chalk";
16082
+ import chalk44 from "chalk";
15925
16083
  import gradient from "gradient-string";
15926
16084
  import figlet from "figlet";
15927
16085
  function showCustomHelp(version) {
15928
16086
  const title = figlet.textSync("JAI1", { font: "Small" });
15929
16087
  console.log(gradient.pastel(title));
15930
16088
  console.log(
15931
- boxen4(chalk42.cyan(`Agentic Coding CLI v${version}`), {
16089
+ boxen4(chalk44.cyan(`Agentic Coding CLI v${version}`), {
15932
16090
  padding: { left: 1, right: 1, top: 0, bottom: 0 },
15933
16091
  borderStyle: "round",
15934
16092
  borderColor: "cyan"
15935
16093
  })
15936
16094
  );
15937
- console.log(chalk42.bold("\n\u{1F527} Thi\u1EBFt l\u1EADp & Th\xF4ng tin"));
16095
+ console.log(chalk44.bold("\n\u{1F527} Thi\u1EBFt l\u1EADp & Th\xF4ng tin"));
15938
16096
  console.log(" auth X\xE1c th\u1EF1c v\xE0 c\u1EA5u h\xECnh client");
15939
16097
  console.log(" status Hi\u1EC3n th\u1ECB tr\u1EA1ng th\xE1i c\u1EA5u h\xECnh");
15940
16098
  console.log(" client-info T\u1EA1o th\xF4ng tin client \u0111\u1EC3 g\u1EEDi \u0111\u1ED9i ph\xE1t tri\u1EC3n");
@@ -15942,43 +16100,43 @@ function showCustomHelp(version) {
15942
16100
  console.log(" guide H\u01B0\u1EDBng d\u1EABn s\u1EED d\u1EE5ng nhanh");
15943
16101
  console.log(" quickstart B\u1EAFt \u0111\u1EA7u t\u1EEB \u0111\xE2u? (theo t\xECnh hu\u1ED1ng)");
15944
16102
  console.log(" doctor Chu\u1EA9n \u0111o\xE1n project hi\u1EC7n t\u1EA1i");
15945
- console.log(chalk42.bold("\n\u{1F4E6} Qu\u1EA3n l\xFD Components"));
16103
+ console.log(chalk44.bold("\n\u{1F4E6} Qu\u1EA3n l\xFD Components"));
15946
16104
  console.log(" apply C\xE0i \u0111\u1EB7t components (interactive)");
15947
16105
  console.log(" update C\u1EADp nh\u1EADt components \u0111\xE3 c\xE0i");
15948
16106
  console.log(" check Ki\u1EC3m tra c\u1EADp nh\u1EADt t\u1EEB server");
15949
- console.log(chalk42.bold("\n\u{1F5A5}\uFE0F IDE & T\xEDch h\u1EE3p"));
16107
+ console.log(chalk44.bold("\n\u{1F5A5}\uFE0F IDE & T\xEDch h\u1EE3p"));
15950
16108
  console.log(" ide L\u1EC7nh c\u1EA5u h\xECnh IDE");
15951
16109
  console.log(" chat Chat AI v\u1EDBi Jai1 LLM Proxy");
15952
16110
  console.log(" openai-keys Th\xF4ng tin API credentials");
15953
- console.log(chalk42.bold("\n\u{1F916} AI Tools"));
16111
+ console.log(chalk44.bold("\n\u{1F916} AI Tools"));
15954
16112
  console.log(" translate D\u1ECBch v\u0103n b\u1EA3n/file b\u1EB1ng AI");
15955
16113
  console.log(" image T\u1EA1o \u1EA3nh (Coming Soon)");
15956
16114
  console.log(" stats Th\u1ED1ng k\xEA s\u1EED d\u1EE5ng LLM");
15957
16115
  console.log(" feedback G\u1EEDi b\xE1o c\xE1o/\u0111\u1EC1 xu\u1EA5t");
15958
- console.log(chalk42.bold("\n\u{1F4C1} Project"));
16116
+ console.log(chalk44.bold("\n\u{1F4C1} Project"));
15959
16117
  console.log(" kit Qu\u1EA3n l\xFD starter kits");
15960
16118
  console.log(" tasks (t) Qu\u1EA3n l\xFD tasks ph\xE1t tri\u1EC3n");
15961
16119
  console.log(" rules Qu\u1EA3n l\xFD rule presets");
15962
16120
  console.log(" deps Qu\u1EA3n l\xFD dependencies");
15963
16121
  console.log(" redmine Redmine context sync");
15964
- console.log(chalk42.bold("\n\u2699\uFE0F B\u1EA3o tr\xEC"));
16122
+ console.log(chalk44.bold("\n\u2699\uFE0F B\u1EA3o tr\xEC"));
15965
16123
  console.log(" upgrade C\u1EADp nh\u1EADt CLI client");
15966
16124
  console.log(" clean D\u1ECDn d\u1EB9p cache/backup");
15967
16125
  console.log(" utils Developer utilities");
15968
16126
  const name = getCliName();
15969
- console.log(chalk42.dim(`
16127
+ console.log(chalk44.dim(`
15970
16128
  S\u1EED d\u1EE5ng: ${name} [l\u1EC7nh] --help \u0111\u1EC3 xem chi ti\u1EBFt`));
15971
16129
  }
15972
16130
  function showUnknownCommand(commandName) {
15973
- console.error(chalk42.red(`\u274C L\u1EC7nh kh\xF4ng t\u1ED3n t\u1EA1i: ${commandName}`));
16131
+ console.error(chalk44.red(`\u274C L\u1EC7nh kh\xF4ng t\u1ED3n t\u1EA1i: ${commandName}`));
15974
16132
  const name = getCliName();
15975
- console.error(chalk42.dim(`
16133
+ console.error(chalk44.dim(`
15976
16134
  G\u1EE3i \xFD: Ch\u1EA1y ${name} --help \u0111\u1EC3 xem danh s\xE1ch l\u1EC7nh`));
15977
16135
  }
15978
16136
 
15979
16137
  // src/cli.ts
15980
16138
  checkNodeVersion();
15981
- var program = new Command87();
16139
+ var program = new Command89();
15982
16140
  if (process.argv.includes("-v") || process.argv.includes("--version")) {
15983
16141
  console.log(package_default.version);
15984
16142
  if (!process.argv.includes("--skip-update-check")) {
@@ -16020,9 +16178,9 @@ program.addCommand(createSkillsCommand());
16020
16178
  program.addCommand(createHooksCommand());
16021
16179
  program.addCommand(createUpgradeCommand());
16022
16180
  program.addCommand(createCleanCommand());
16023
- var redmineCommand = new Command87("redmine").description("Redmine context sync commands");
16181
+ var redmineCommand = new Command89("redmine").description("Redmine context sync commands");
16024
16182
  redmineCommand.addCommand(createRedmineCheckCommand());
16025
- var syncCommand = new Command87("sync").description("Sync Redmine issues to markdown files");
16183
+ var syncCommand = new Command89("sync").description("Sync Redmine issues to markdown files");
16026
16184
  syncCommand.addCommand(createSyncIssueCommand());
16027
16185
  syncCommand.addCommand(createSyncProjectCommand());
16028
16186
  redmineCommand.addCommand(syncCommand);