@jvittechs/jai1-cli 0.1.84 → 0.1.85

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
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/cli.ts
4
- import { Command as Command45 } from "commander";
4
+ import { Command as Command47 } from "commander";
5
5
 
6
6
  // src/errors/index.ts
7
7
  var Jai1Error = class extends Error {
@@ -33,7 +33,7 @@ var NetworkError = class extends Jai1Error {
33
33
  // package.json
34
34
  var package_default = {
35
35
  name: "@jvittechs/jai1-cli",
36
- version: "0.1.84",
36
+ version: "0.1.85",
37
37
  description: "A unified CLI tool for JV-IT TECHS developers to manage Jai1 Framework. Please contact TeamAI for usage instructions.",
38
38
  type: "module",
39
39
  bin: {
@@ -7238,14 +7238,417 @@ Quick Usage:
7238
7238
  return utilsCommand;
7239
7239
  }
7240
7240
 
7241
+ // src/commands/deps/index.ts
7242
+ import { Command as Command30 } from "commander";
7243
+
7244
+ // src/commands/deps/upgrade.ts
7245
+ import { Command as Command29 } from "commander";
7246
+ import { checkbox as checkbox3, confirm as confirm4 } from "@inquirer/prompts";
7247
+
7248
+ // src/services/deps.service.ts
7249
+ import { promises as fs9 } from "fs";
7250
+ import path6 from "path";
7251
+ import { execSync } from "child_process";
7252
+ import pLimit2 from "p-limit";
7253
+ var DepsService = class {
7254
+ versionCache = /* @__PURE__ */ new Map();
7255
+ /**
7256
+ * Đọc package.json từ thư mục
7257
+ */
7258
+ async readPackageJson(cwd) {
7259
+ const pkgPath = path6.join(cwd, "package.json");
7260
+ try {
7261
+ const content = await fs9.readFile(pkgPath, "utf-8");
7262
+ return JSON.parse(content);
7263
+ } catch (error) {
7264
+ if (error.code === "ENOENT") {
7265
+ throw new Error("Kh\xF4ng t\xECm th\u1EA5y package.json trong th\u01B0 m\u1EE5c hi\u1EC7n t\u1EA1i");
7266
+ }
7267
+ throw new Error(`L\u1ED7i \u0111\u1ECDc package.json: ${error.message}`);
7268
+ }
7269
+ }
7270
+ /**
7271
+ * Lấy version mới nhất từ npm registry
7272
+ */
7273
+ async fetchLatestVersion(packageName) {
7274
+ if (this.versionCache.has(packageName)) {
7275
+ return this.versionCache.get(packageName);
7276
+ }
7277
+ try {
7278
+ const response = await fetch(
7279
+ `https://registry.npmjs.org/${encodeURIComponent(packageName)}/latest`,
7280
+ { signal: AbortSignal.timeout(1e4) }
7281
+ );
7282
+ if (!response.ok) {
7283
+ return null;
7284
+ }
7285
+ const data = await response.json();
7286
+ this.versionCache.set(packageName, data.version);
7287
+ return data.version;
7288
+ } catch {
7289
+ return null;
7290
+ }
7291
+ }
7292
+ /**
7293
+ * Fetch nhiều packages cùng lúc với giới hạn concurrent
7294
+ */
7295
+ async fetchBulkVersions(packages, onProgress) {
7296
+ const limit = pLimit2(10);
7297
+ const total = packages.length;
7298
+ let completed = 0;
7299
+ const results = await Promise.all(
7300
+ packages.map(
7301
+ (pkg) => limit(async () => {
7302
+ const latest = await this.fetchLatestVersion(pkg.name);
7303
+ completed++;
7304
+ onProgress?.(completed, total);
7305
+ if (!latest) {
7306
+ return null;
7307
+ }
7308
+ const currentClean = this.stripSemverPrefix(pkg.current);
7309
+ const canUpgrade = this.isNewerVersion(latest, currentClean);
7310
+ return {
7311
+ name: pkg.name,
7312
+ current: pkg.current,
7313
+ latest,
7314
+ latestWithPrefix: this.preserveSemverPrefix(pkg.current, latest),
7315
+ type: pkg.type,
7316
+ canUpgrade
7317
+ };
7318
+ })
7319
+ )
7320
+ );
7321
+ return results.filter((r) => r !== null && r.canUpgrade);
7322
+ }
7323
+ /**
7324
+ * Loại bỏ semver prefix (^, ~, >=, etc.)
7325
+ */
7326
+ stripSemverPrefix(version) {
7327
+ return version.replace(/^[~^>=<]+/, "");
7328
+ }
7329
+ /**
7330
+ * Giữ nguyên semver prefix khi upgrade
7331
+ */
7332
+ preserveSemverPrefix(current, latest) {
7333
+ const match = current.match(/^([~^>=<]*)/);
7334
+ const prefix = match?.[1] || "";
7335
+ return prefix + latest;
7336
+ }
7337
+ /**
7338
+ * So sánh version để xác định có cần upgrade không
7339
+ */
7340
+ isNewerVersion(remote, local) {
7341
+ const remoteParts = remote.split(".").map(Number);
7342
+ const localParts = local.split(".").map(Number);
7343
+ for (let i = 0; i < 3; i++) {
7344
+ const r = remoteParts[i] || 0;
7345
+ const l = localParts[i] || 0;
7346
+ if (r > l) return true;
7347
+ if (r < l) return false;
7348
+ }
7349
+ return false;
7350
+ }
7351
+ /**
7352
+ * Detect package manager từ lock files
7353
+ * Priority:
7354
+ * 1. Lock file trong project
7355
+ * 2. pnpm nếu có cài đặt trong máy
7356
+ * 3. npm (fallback)
7357
+ */
7358
+ async detectPackageManager(cwd) {
7359
+ const lockFiles = [
7360
+ { file: "pnpm-lock.yaml", pm: "pnpm" },
7361
+ { file: "yarn.lock", pm: "yarn" },
7362
+ { file: "bun.lockb", pm: "bun" },
7363
+ { file: "package-lock.json", pm: "npm" }
7364
+ ];
7365
+ for (const { file, pm } of lockFiles) {
7366
+ try {
7367
+ await fs9.access(path6.join(cwd, file));
7368
+ return pm;
7369
+ } catch {
7370
+ }
7371
+ }
7372
+ const userAgent = process.env.npm_config_user_agent || "";
7373
+ if (userAgent.includes("pnpm")) return "pnpm";
7374
+ if (userAgent.includes("yarn")) return "yarn";
7375
+ if (userAgent.includes("bun")) return "bun";
7376
+ if (userAgent.includes("npm")) return "npm";
7377
+ if (this.isCommandAvailable("pnpm")) return "pnpm";
7378
+ return "npm";
7379
+ }
7380
+ /**
7381
+ * Kiểm tra command có sẵn trong hệ thống không
7382
+ */
7383
+ isCommandAvailable(command) {
7384
+ try {
7385
+ execSync(`${command} --version`, {
7386
+ stdio: ["pipe", "pipe", "pipe"]
7387
+ });
7388
+ return true;
7389
+ } catch {
7390
+ return false;
7391
+ }
7392
+ }
7393
+ /**
7394
+ * Tạo command để upgrade packages
7395
+ */
7396
+ getUpgradeCommands(packages, pm) {
7397
+ const deps = packages.filter((p) => p.type === "dep");
7398
+ const devDeps = packages.filter((p) => p.type === "dev");
7399
+ const formatPackages = (pkgs) => pkgs.map((p) => `${p.name}@${p.latestWithPrefix}`).join(" ");
7400
+ let depsCmd = null;
7401
+ let devDepsCmd = null;
7402
+ if (deps.length > 0) {
7403
+ const pkgList = formatPackages(deps);
7404
+ switch (pm) {
7405
+ case "pnpm":
7406
+ depsCmd = `pnpm add ${pkgList}`;
7407
+ break;
7408
+ case "yarn":
7409
+ depsCmd = `yarn add ${pkgList}`;
7410
+ break;
7411
+ case "bun":
7412
+ depsCmd = `bun add ${pkgList}`;
7413
+ break;
7414
+ default:
7415
+ depsCmd = `npm install ${pkgList}`;
7416
+ }
7417
+ }
7418
+ if (devDeps.length > 0) {
7419
+ const pkgList = formatPackages(devDeps);
7420
+ switch (pm) {
7421
+ case "pnpm":
7422
+ devDepsCmd = `pnpm add -D ${pkgList}`;
7423
+ break;
7424
+ case "yarn":
7425
+ devDepsCmd = `yarn add -D ${pkgList}`;
7426
+ break;
7427
+ case "bun":
7428
+ devDepsCmd = `bun add -D ${pkgList}`;
7429
+ break;
7430
+ default:
7431
+ devDepsCmd = `npm install -D ${pkgList}`;
7432
+ }
7433
+ }
7434
+ return { deps: depsCmd, devDeps: devDepsCmd };
7435
+ }
7436
+ /**
7437
+ * Thực thi upgrade command
7438
+ */
7439
+ executeUpgrade(command) {
7440
+ execSync(command, {
7441
+ stdio: "inherit",
7442
+ env: { ...process.env, FORCE_COLOR: "1" }
7443
+ });
7444
+ }
7445
+ };
7446
+
7447
+ // src/commands/deps/upgrade.ts
7448
+ var colors2 = {
7449
+ yellow: "\x1B[33m",
7450
+ green: "\x1B[32m",
7451
+ cyan: "\x1B[36m",
7452
+ red: "\x1B[31m",
7453
+ gray: "\x1B[90m",
7454
+ reset: "\x1B[0m",
7455
+ bold: "\x1B[1m",
7456
+ dim: "\x1B[2m"
7457
+ };
7458
+ function createDepsUpgradeCommand() {
7459
+ return new Command29("upgrade").description("Upgrade npm packages l\xEAn version m\u1EDBi nh\u1EA5t").option("--check", "Ch\u1EC9 ki\u1EC3m tra, kh\xF4ng upgrade").option("--all", "Upgrade t\u1EA5t c\u1EA3 kh\xF4ng c\u1EA7n ch\u1ECDn").option("--deps-only", "Ch\u1EC9 upgrade dependencies").option("--dev-only", "Ch\u1EC9 upgrade devDependencies").action(async (options) => {
7460
+ await handleDepsUpgrade(options);
7461
+ });
7462
+ }
7463
+ async function handleDepsUpgrade(options) {
7464
+ const depsService = new DepsService();
7465
+ const cwd = process.cwd();
7466
+ try {
7467
+ console.log(`
7468
+ ${colors2.cyan}\u{1F50D} \u0110ang \u0111\u1ECDc package.json...${colors2.reset}`);
7469
+ const pkg = await depsService.readPackageJson(cwd);
7470
+ const packagesToCheck = [];
7471
+ if (!options.devOnly && pkg.dependencies) {
7472
+ for (const [name, version] of Object.entries(pkg.dependencies)) {
7473
+ if (isNpmVersion(version)) {
7474
+ packagesToCheck.push({ name, current: version, type: "dep" });
7475
+ }
7476
+ }
7477
+ }
7478
+ if (!options.depsOnly && pkg.devDependencies) {
7479
+ for (const [name, version] of Object.entries(pkg.devDependencies)) {
7480
+ if (isNpmVersion(version)) {
7481
+ packagesToCheck.push({ name, current: version, type: "dev" });
7482
+ }
7483
+ }
7484
+ }
7485
+ if (packagesToCheck.length === 0) {
7486
+ console.log(`${colors2.yellow}\u26A0\uFE0F Kh\xF4ng t\xECm th\u1EA5y packages \u0111\u1EC3 ki\u1EC3m tra${colors2.reset}
7487
+ `);
7488
+ return;
7489
+ }
7490
+ const depsCount = packagesToCheck.filter((p) => p.type === "dep").length;
7491
+ const devCount = packagesToCheck.filter((p) => p.type === "dev").length;
7492
+ console.log(
7493
+ `${colors2.bold}\u{1F4E6} T\xECm th\u1EA5y ${depsCount} dependencies v\xE0 ${devCount} devDependencies${colors2.reset}
7494
+ `
7495
+ );
7496
+ console.log(`${colors2.cyan}\u23F3 Ki\u1EC3m tra phi\xEAn b\u1EA3n m\u1EDBi nh\u1EA5t...${colors2.reset}`);
7497
+ const upgradablePackages = await depsService.fetchBulkVersions(
7498
+ packagesToCheck,
7499
+ (completed, total) => {
7500
+ const progress = Math.round(completed / total * 100);
7501
+ const bar = "\u2588".repeat(Math.floor(progress / 5)) + "\u2591".repeat(20 - Math.floor(progress / 5));
7502
+ process.stdout.write(`\r[${bar}] ${completed}/${total} packages`);
7503
+ }
7504
+ );
7505
+ console.log("\n");
7506
+ if (upgradablePackages.length === 0) {
7507
+ console.log(`${colors2.green}\u2705 T\u1EA5t c\u1EA3 packages \u0111\xE3 l\xE0 phi\xEAn b\u1EA3n m\u1EDBi nh\u1EA5t!${colors2.reset}
7508
+ `);
7509
+ return;
7510
+ }
7511
+ displayUpgradeTable(upgradablePackages);
7512
+ if (options.check) {
7513
+ console.log(
7514
+ `${colors2.cyan}\u{1F4A1} Ch\u1EA1y "jai1 deps upgrade" \u0111\u1EC3 ti\u1EBFn h\xE0nh upgrade.${colors2.reset}
7515
+ `
7516
+ );
7517
+ return;
7518
+ }
7519
+ let selectedPackages;
7520
+ if (options.all) {
7521
+ selectedPackages = upgradablePackages;
7522
+ console.log(`${colors2.cyan}\u{1F4CB} \u0110\xE3 ch\u1ECDn t\u1EA5t c\u1EA3 ${selectedPackages.length} packages${colors2.reset}
7523
+ `);
7524
+ } else {
7525
+ try {
7526
+ const selected = await checkbox3({
7527
+ message: "Ch\u1ECDn packages \u0111\u1EC3 upgrade (ESC \u0111\u1EC3 h\u1EE7y):",
7528
+ choices: upgradablePackages.map((pkg2) => ({
7529
+ name: `${pkg2.name} (${pkg2.current} \u2192 ${pkg2.latestWithPrefix}) [${pkg2.type}]`,
7530
+ value: pkg2.name,
7531
+ checked: true
7532
+ // Mặc định chọn tất cả
7533
+ })),
7534
+ instructions: "\u2191\u2193 navigate \u2022 space select \u2022 a all \u2022 i invert \u2022 \u23CE submit \u2022 esc cancel"
7535
+ });
7536
+ if (selected.length === 0) {
7537
+ console.log(`${colors2.yellow}\u23F8\uFE0F Kh\xF4ng c\xF3 packages n\xE0o \u0111\u01B0\u1EE3c ch\u1ECDn${colors2.reset}
7538
+ `);
7539
+ return;
7540
+ }
7541
+ selectedPackages = upgradablePackages.filter((pkg2) => selected.includes(pkg2.name));
7542
+ } catch {
7543
+ console.log(`
7544
+ ${colors2.yellow}\u23F8\uFE0F \u0110\xE3 h\u1EE7y${colors2.reset}
7545
+ `);
7546
+ return;
7547
+ }
7548
+ }
7549
+ let shouldProceed;
7550
+ try {
7551
+ shouldProceed = await confirm4({
7552
+ message: `Ti\u1EBFn h\xE0nh upgrade ${selectedPackages.length} packages?`,
7553
+ default: true
7554
+ });
7555
+ } catch {
7556
+ console.log(`
7557
+ ${colors2.yellow}\u23F8\uFE0F \u0110\xE3 h\u1EE7y${colors2.reset}
7558
+ `);
7559
+ return;
7560
+ }
7561
+ if (!shouldProceed) {
7562
+ console.log(`${colors2.yellow}\u23F8\uFE0F Upgrade \u0111\xE3 h\u1EE7y${colors2.reset}
7563
+ `);
7564
+ return;
7565
+ }
7566
+ const pm = await depsService.detectPackageManager(cwd);
7567
+ console.log(`
7568
+ ${colors2.cyan}\u{1F527} Package manager: ${pm}${colors2.reset}`);
7569
+ console.log(`${colors2.cyan}\u{1F4E5} \u0110ang upgrade...${colors2.reset}
7570
+ `);
7571
+ const commands = depsService.getUpgradeCommands(selectedPackages, pm);
7572
+ try {
7573
+ if (commands.deps) {
7574
+ console.log(`${colors2.dim}$ ${commands.deps}${colors2.reset}
7575
+ `);
7576
+ depsService.executeUpgrade(commands.deps);
7577
+ }
7578
+ if (commands.devDeps) {
7579
+ console.log(`
7580
+ ${colors2.dim}$ ${commands.devDeps}${colors2.reset}
7581
+ `);
7582
+ depsService.executeUpgrade(commands.devDeps);
7583
+ }
7584
+ console.log(
7585
+ `
7586
+ ${colors2.green}\u2705 \u0110\xE3 upgrade ${selectedPackages.length} packages th\xE0nh c\xF4ng!${colors2.reset}
7587
+ `
7588
+ );
7589
+ } catch (error) {
7590
+ console.error(`
7591
+ ${colors2.red}\u274C L\u1ED7i khi upgrade:${colors2.reset}`);
7592
+ console.error(`${colors2.red}${error.message}${colors2.reset}
7593
+ `);
7594
+ console.log(`${colors2.yellow}\u{1F4A1} B\u1EA1n c\xF3 th\u1EC3 th\u1EED upgrade th\u1EE7 c\xF4ng:${colors2.reset}`);
7595
+ if (commands.deps) console.log(` ${colors2.cyan}${commands.deps}${colors2.reset}`);
7596
+ if (commands.devDeps) console.log(` ${colors2.cyan}${commands.devDeps}${colors2.reset}`);
7597
+ console.log("");
7598
+ process.exit(1);
7599
+ }
7600
+ } catch (error) {
7601
+ console.error(`
7602
+ ${colors2.red}\u274C ${error.message}${colors2.reset}
7603
+ `);
7604
+ process.exit(1);
7605
+ }
7606
+ }
7607
+ function isNpmVersion(version) {
7608
+ if (version.startsWith("git") || version.startsWith("github") || version.startsWith("file:") || version.startsWith("link:") || version.startsWith("workspace:") || version.includes("://")) {
7609
+ return false;
7610
+ }
7611
+ return true;
7612
+ }
7613
+ function displayUpgradeTable(packages) {
7614
+ console.log(`${colors2.bold}\u{1F4CA} C\xF3 th\u1EC3 upgrade:${colors2.reset}
7615
+ `);
7616
+ const nameWidth = Math.max(7, ...packages.map((p) => p.name.length));
7617
+ const currentWidth = Math.max(8, ...packages.map((p) => p.current.length));
7618
+ const latestWidth = Math.max(8, ...packages.map((p) => p.latestWithPrefix.length));
7619
+ const header = `\u2502 ${"Package".padEnd(nameWidth)} \u2502 ${"Hi\u1EC7n t\u1EA1i".padEnd(currentWidth)} \u2502 ${"M\u1EDBi nh\u1EA5t".padEnd(latestWidth)} \u2502 Lo\u1EA1i \u2502`;
7620
+ const separator = `\u251C${"\u2500".repeat(nameWidth + 2)}\u253C${"\u2500".repeat(currentWidth + 2)}\u253C${"\u2500".repeat(latestWidth + 2)}\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2524`;
7621
+ const topBorder = `\u250C${"\u2500".repeat(nameWidth + 2)}\u252C${"\u2500".repeat(currentWidth + 2)}\u252C${"\u2500".repeat(latestWidth + 2)}\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2510`;
7622
+ const bottomBorder = `\u2514${"\u2500".repeat(nameWidth + 2)}\u2534${"\u2500".repeat(currentWidth + 2)}\u2534${"\u2500".repeat(latestWidth + 2)}\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2518`;
7623
+ console.log(topBorder);
7624
+ console.log(header);
7625
+ console.log(separator);
7626
+ for (const pkg of packages) {
7627
+ const typeLabel = pkg.type === "dep" ? "dep " : "dev ";
7628
+ const typeColor = pkg.type === "dep" ? colors2.cyan : colors2.yellow;
7629
+ console.log(
7630
+ `\u2502 ${pkg.name.padEnd(nameWidth)} \u2502 ${colors2.gray}${pkg.current.padEnd(currentWidth)}${colors2.reset} \u2502 ${colors2.green}${pkg.latestWithPrefix.padEnd(latestWidth)}${colors2.reset} \u2502 ${typeColor}${typeLabel}${colors2.reset}\u2502`
7631
+ );
7632
+ }
7633
+ console.log(bottomBorder);
7634
+ console.log("");
7635
+ }
7636
+
7637
+ // src/commands/deps/index.ts
7638
+ function createDepsCommand() {
7639
+ const depsCommand = new Command30("deps").description("Qu\u1EA3n l\xFD dependencies trong project");
7640
+ depsCommand.addCommand(createDepsUpgradeCommand());
7641
+ return depsCommand;
7642
+ }
7643
+
7241
7644
  // src/commands/kit/index.ts
7242
- import { Command as Command32 } from "commander";
7645
+ import { Command as Command34 } from "commander";
7243
7646
 
7244
7647
  // src/commands/kit/list.ts
7245
- import { Command as Command29 } from "commander";
7648
+ import { Command as Command31 } from "commander";
7246
7649
 
7247
7650
  // src/services/starter-kit.service.ts
7248
- import { promises as fs9 } from "fs";
7651
+ import { promises as fs10 } from "fs";
7249
7652
  import { join as join4 } from "path";
7250
7653
  import AdmZip from "adm-zip";
7251
7654
  var StarterKitService = class {
@@ -7294,22 +7697,22 @@ var StarterKitService = class {
7294
7697
  }
7295
7698
  if (onProgress) onProgress(30);
7296
7699
  const tmpDir = join4(process.env.TMPDIR || "/tmp", "jai1-kits");
7297
- await fs9.mkdir(tmpDir, { recursive: true });
7700
+ await fs10.mkdir(tmpDir, { recursive: true });
7298
7701
  const tmpFile = join4(tmpDir, `${slug}.zip`);
7299
7702
  const buffer = await response.arrayBuffer();
7300
- await fs9.writeFile(tmpFile, Buffer.from(buffer));
7703
+ await fs10.writeFile(tmpFile, Buffer.from(buffer));
7301
7704
  if (onProgress) onProgress(60);
7302
7705
  const zip = new AdmZip(tmpFile);
7303
- await fs9.mkdir(targetDir, { recursive: true });
7706
+ await fs10.mkdir(targetDir, { recursive: true });
7304
7707
  zip.extractAllTo(targetDir, true);
7305
7708
  if (onProgress) onProgress(100);
7306
- await fs9.unlink(tmpFile);
7709
+ await fs10.unlink(tmpFile);
7307
7710
  }
7308
7711
  };
7309
7712
 
7310
7713
  // src/commands/kit/list.ts
7311
7714
  function createKitListCommand() {
7312
- return new Command29("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) => {
7715
+ return new Command31("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) => {
7313
7716
  const configService = new ConfigService();
7314
7717
  const config = await configService.load();
7315
7718
  if (!config) {
@@ -7346,9 +7749,9 @@ function createKitListCommand() {
7346
7749
  }
7347
7750
 
7348
7751
  // src/commands/kit/info.ts
7349
- import { Command as Command30 } from "commander";
7752
+ import { Command as Command32 } from "commander";
7350
7753
  function createKitInfoCommand() {
7351
- return new Command30("info").description("Show detailed information about a starter kit").argument("<slug>", "Starter kit slug").action(async (slug) => {
7754
+ return new Command32("info").description("Show detailed information about a starter kit").argument("<slug>", "Starter kit slug").action(async (slug) => {
7352
7755
  const configService = new ConfigService();
7353
7756
  const config = await configService.load();
7354
7757
  if (!config) {
@@ -7397,10 +7800,10 @@ Post-Init Commands:`);
7397
7800
  }
7398
7801
 
7399
7802
  // src/commands/kit/create.ts
7400
- import { Command as Command31 } from "commander";
7401
- import { promises as fs10 } from "fs";
7803
+ import { Command as Command33 } from "commander";
7804
+ import { promises as fs11 } from "fs";
7402
7805
  import { join as join5 } from "path";
7403
- import { select as select2, input, checkbox as checkbox3 } from "@inquirer/prompts";
7806
+ import { select as select2, input, checkbox as checkbox4 } from "@inquirer/prompts";
7404
7807
  import { execa as execa2 } from "execa";
7405
7808
 
7406
7809
  // src/services/hook-executor.service.ts
@@ -7442,7 +7845,7 @@ var HookExecutor = class {
7442
7845
 
7443
7846
  // src/commands/kit/create.ts
7444
7847
  function createKitCreateCommand() {
7445
- return new Command31("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) => {
7848
+ return new Command33("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) => {
7446
7849
  const configService = new ConfigService();
7447
7850
  const config = await configService.load();
7448
7851
  if (!config) {
@@ -7464,7 +7867,7 @@ function createKitCreateCommand() {
7464
7867
  }
7465
7868
  const targetDir = directory || join5(process.cwd(), options.name || slug);
7466
7869
  try {
7467
- await fs10.access(targetDir);
7870
+ await fs11.access(targetDir);
7468
7871
  throw new Error(`Directory already exists: ${targetDir}`);
7469
7872
  } catch (error) {
7470
7873
  if (error.code !== "ENOENT") {
@@ -7555,7 +7958,7 @@ function createKitCreateCommand() {
7555
7958
  }
7556
7959
  } else {
7557
7960
  const defaultTargets = kit.config.ide?.defaultTargets || [];
7558
- const answer = await checkbox3({
7961
+ const answer = await checkbox4({
7559
7962
  message: "Ch\u1ECDn IDE \u0111\u1EC3 sync framework:",
7560
7963
  choices: ideChoices.map((c) => ({
7561
7964
  ...c,
@@ -7582,7 +7985,7 @@ function createKitCreateCommand() {
7582
7985
  async function applyVariableSubstitution(dir, variables) {
7583
7986
  const files = await getAllFiles(dir);
7584
7987
  for (const file of files) {
7585
- let content = await fs10.readFile(file, "utf-8");
7988
+ let content = await fs11.readFile(file, "utf-8");
7586
7989
  let modified = false;
7587
7990
  for (const [key, value] of Object.entries(variables)) {
7588
7991
  const regex = new RegExp(`\\{\\{${key}\\}\\}`, "g");
@@ -7592,13 +7995,13 @@ async function applyVariableSubstitution(dir, variables) {
7592
7995
  }
7593
7996
  }
7594
7997
  if (modified) {
7595
- await fs10.writeFile(file, content, "utf-8");
7998
+ await fs11.writeFile(file, content, "utf-8");
7596
7999
  }
7597
8000
  }
7598
8001
  }
7599
8002
  async function getAllFiles(dir) {
7600
8003
  const files = [];
7601
- const entries = await fs10.readdir(dir, { withFileTypes: true });
8004
+ const entries = await fs11.readdir(dir, { withFileTypes: true });
7602
8005
  for (const entry of entries) {
7603
8006
  const fullPath = join5(dir, entry.name);
7604
8007
  if (entry.isDirectory()) {
@@ -7614,7 +8017,7 @@ async function getAllFiles(dir) {
7614
8017
 
7615
8018
  // src/commands/kit/index.ts
7616
8019
  function createKitCommand() {
7617
- const cmd = new Command32("kit").description("Manage starter kits for new projects").action(() => {
8020
+ const cmd = new Command34("kit").description("Manage starter kits for new projects").action(() => {
7618
8021
  cmd.help();
7619
8022
  });
7620
8023
  cmd.addCommand(createKitListCommand());
@@ -7624,10 +8027,10 @@ function createKitCommand() {
7624
8027
  }
7625
8028
 
7626
8029
  // src/commands/upgrade.ts
7627
- import { Command as Command33 } from "commander";
7628
- import { confirm as confirm4 } from "@inquirer/prompts";
7629
- import { execSync } from "child_process";
7630
- var colors2 = {
8030
+ import { Command as Command35 } from "commander";
8031
+ import { confirm as confirm5 } from "@inquirer/prompts";
8032
+ import { execSync as execSync2 } from "child_process";
8033
+ var colors3 = {
7631
8034
  yellow: "\x1B[33m",
7632
8035
  green: "\x1B[32m",
7633
8036
  cyan: "\x1B[36m",
@@ -7636,7 +8039,7 @@ var colors2 = {
7636
8039
  bold: "\x1B[1m"
7637
8040
  };
7638
8041
  function createUpgradeCommand() {
7639
- return new Command33("upgrade").description("Upgrade jai1-client to the latest version").option("--check", "Only check for updates without installing").option("--force", "Force upgrade without confirmation").action(async (options) => {
8042
+ return new Command35("upgrade").description("Upgrade jai1-client to the latest version").option("--check", "Only check for updates without installing").option("--force", "Force upgrade without confirmation").action(async (options) => {
7640
8043
  await handleUpgrade(options);
7641
8044
  });
7642
8045
  }
@@ -7647,7 +8050,7 @@ async function handleUpgrade(options) {
7647
8050
  throw new ValidationError('Not initialized. Run "jai1 auth" first.');
7648
8051
  }
7649
8052
  try {
7650
- console.log(`${colors2.cyan}\u{1F50D} Checking for updates...${colors2.reset}`);
8053
+ console.log(`${colors3.cyan}\u{1F50D} Checking for updates...${colors3.reset}`);
7651
8054
  const response = await fetch(`${config.apiUrl}/api/versions/client`, {
7652
8055
  headers: {
7653
8056
  "JAI1-Access-Key": config.accessKey
@@ -7662,47 +8065,47 @@ async function handleUpgrade(options) {
7662
8065
  const latestVersion = data.version;
7663
8066
  const currentVersion = package_default.version;
7664
8067
  console.log(`
7665
- ${colors2.bold}Current version:${colors2.reset} ${currentVersion}`);
7666
- console.log(`${colors2.bold}Latest version:${colors2.reset} ${latestVersion}
8068
+ ${colors3.bold}Current version:${colors3.reset} ${currentVersion}`);
8069
+ console.log(`${colors3.bold}Latest version:${colors3.reset} ${latestVersion}
7667
8070
  `);
7668
8071
  if (!isNewerVersion2(latestVersion, currentVersion)) {
7669
- console.log(`${colors2.green}\u2705 You're already on the latest version!${colors2.reset}
8072
+ console.log(`${colors3.green}\u2705 You're already on the latest version!${colors3.reset}
7670
8073
  `);
7671
8074
  return;
7672
8075
  }
7673
- console.log(`${colors2.yellow}\u256D\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\u2500\u2500\u2500\u2500\u2500\u256E${colors2.reset}`);
7674
- console.log(`${colors2.yellow}\u2502${colors2.reset} ${colors2.bold}\u2B06\uFE0F Update available!${colors2.reset} ${currentVersion} \u2192 ${colors2.cyan}${latestVersion}${colors2.reset} ${colors2.yellow}\u2502${colors2.reset}`);
7675
- console.log(`${colors2.yellow}\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\u2500\u2500\u2500\u2500\u2500\u256F${colors2.reset}
8076
+ console.log(`${colors3.yellow}\u256D\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\u2500\u2500\u2500\u2500\u2500\u256E${colors3.reset}`);
8077
+ console.log(`${colors3.yellow}\u2502${colors3.reset} ${colors3.bold}\u2B06\uFE0F Update available!${colors3.reset} ${currentVersion} \u2192 ${colors3.cyan}${latestVersion}${colors3.reset} ${colors3.yellow}\u2502${colors3.reset}`);
8078
+ console.log(`${colors3.yellow}\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\u2500\u2500\u2500\u2500\u2500\u256F${colors3.reset}
7676
8079
  `);
7677
8080
  if (options.check) {
7678
- console.log(`${colors2.cyan}Run "jai1 upgrade" to install the latest version.${colors2.reset}
8081
+ console.log(`${colors3.cyan}Run "jai1 upgrade" to install the latest version.${colors3.reset}
7679
8082
  `);
7680
8083
  return;
7681
8084
  }
7682
8085
  if (!options.force) {
7683
- const shouldUpdate = await confirm4({
8086
+ const shouldUpdate = await confirm5({
7684
8087
  message: "Update to the latest version now?",
7685
8088
  default: true
7686
8089
  });
7687
8090
  if (!shouldUpdate) {
7688
- console.log(`${colors2.yellow}\u23F8\uFE0F Upgrade cancelled.${colors2.reset}
8091
+ console.log(`${colors3.yellow}\u23F8\uFE0F Upgrade cancelled.${colors3.reset}
7689
8092
  `);
7690
8093
  return;
7691
8094
  }
7692
8095
  }
7693
8096
  console.log(`
7694
- ${colors2.cyan}\u{1F4E5} Installing latest version...${colors2.reset}
8097
+ ${colors3.cyan}\u{1F4E5} Installing latest version...${colors3.reset}
7695
8098
  `);
7696
8099
  try {
7697
8100
  const packageManager2 = detectPackageManager();
7698
8101
  const installCommand = getInstallCommand(packageManager2);
7699
- console.log(`${colors2.cyan}Using ${packageManager2}...${colors2.reset}`);
7700
- execSync(installCommand, {
8102
+ console.log(`${colors3.cyan}Using ${packageManager2}...${colors3.reset}`);
8103
+ execSync2(installCommand, {
7701
8104
  stdio: "inherit",
7702
8105
  env: { ...process.env, FORCE_COLOR: "1" }
7703
8106
  });
7704
8107
  console.log(`
7705
- ${colors2.green}\u2705 Successfully upgraded to version ${latestVersion}!${colors2.reset}
8108
+ ${colors3.green}\u2705 Successfully upgraded to version ${latestVersion}!${colors3.reset}
7706
8109
  `);
7707
8110
  trackAction("upgrade", {
7708
8111
  from_version: currentVersion,
@@ -7712,17 +8115,17 @@ ${colors2.green}\u2705 Successfully upgraded to version ${latestVersion}!${color
7712
8115
  disableUpdateCheck();
7713
8116
  } catch (error) {
7714
8117
  console.error(`
7715
- ${colors2.red}\u274C Upgrade failed!${colors2.reset}`);
7716
- console.error(`${colors2.red}Error: ${error instanceof Error ? error.message : "Unknown error"}${colors2.reset}
8118
+ ${colors3.red}\u274C Upgrade failed!${colors3.reset}`);
8119
+ console.error(`${colors3.red}Error: ${error instanceof Error ? error.message : "Unknown error"}${colors3.reset}
7717
8120
  `);
7718
- console.error(`${colors2.yellow}\u{1F4A1} You can try manually upgrading with:${colors2.reset}`);
8121
+ console.error(`${colors3.yellow}\u{1F4A1} You can try manually upgrading with:${colors3.reset}`);
7719
8122
  const manualCommands = {
7720
8123
  npm: `npm install -g @jvittechs/jai1-cli@latest`,
7721
8124
  pnpm: `pnpm add -g @jvittechs/jai1-cli@latest`,
7722
8125
  yarn: `yarn global add @jvittechs/jai1-cli@latest`,
7723
8126
  bun: `bun add -g @jvittechs/jai1-cli@latest`
7724
8127
  };
7725
- console.error(` ${colors2.cyan}${manualCommands[packageManager]}${colors2.reset}
8128
+ console.error(` ${colors3.cyan}${manualCommands[packageManager]}${colors3.reset}
7726
8129
  `);
7727
8130
  throw error;
7728
8131
  }
@@ -7746,7 +8149,7 @@ function isNewerVersion2(remote, local) {
7746
8149
  }
7747
8150
  function detectPackageManager() {
7748
8151
  try {
7749
- const jai1Path = execSync("which jai1 || where jai1", {
8152
+ const jai1Path = execSync2("which jai1 || where jai1", {
7750
8153
  encoding: "utf-8",
7751
8154
  stdio: ["pipe", "pipe", "ignore"]
7752
8155
  }).trim();
@@ -7784,11 +8187,11 @@ function getInstallCommand(packageManager2) {
7784
8187
  }
7785
8188
 
7786
8189
  // src/commands/clean.ts
7787
- import { Command as Command34 } from "commander";
7788
- import { confirm as confirm5, select as select3 } from "@inquirer/prompts";
8190
+ import { Command as Command36 } from "commander";
8191
+ import { confirm as confirm6, select as select3 } from "@inquirer/prompts";
7789
8192
  import { join as join6 } from "path";
7790
8193
  function createCleanCommand() {
7791
- return new Command34("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) => {
8194
+ return new Command36("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) => {
7792
8195
  await handleClean(options);
7793
8196
  });
7794
8197
  }
@@ -7883,7 +8286,7 @@ async function cleanTarget(target, skipConfirm) {
7883
8286
  }
7884
8287
  const countStr = info.count ? ` (${info.count} items)` : "";
7885
8288
  if (!skipConfirm) {
7886
- const confirmed = await confirm5({
8289
+ const confirmed = await confirm6({
7887
8290
  message: `Delete ${target.name}${countStr}?`,
7888
8291
  default: false
7889
8292
  });
@@ -7901,7 +8304,7 @@ async function cleanTarget(target, skipConfirm) {
7901
8304
  }
7902
8305
 
7903
8306
  // src/commands/redmine/check.ts
7904
- import { Command as Command35 } from "commander";
8307
+ import { Command as Command37 } from "commander";
7905
8308
 
7906
8309
  // src/services/redmine-config.service.ts
7907
8310
  import { readFile as readFile6 } from "fs/promises";
@@ -8002,7 +8405,7 @@ var RedmineConfigService = class {
8002
8405
  // src/api.ts
8003
8406
  import { fetch as fetch2 } from "undici";
8004
8407
  import pRetry2 from "p-retry";
8005
- import pLimit2 from "p-limit";
8408
+ import pLimit3 from "p-limit";
8006
8409
  var RedmineApiError = class extends Error {
8007
8410
  constructor(message, status, response) {
8008
8411
  super(message);
@@ -8020,10 +8423,10 @@ var RedmineApiClient = class {
8020
8423
  this.baseUrl = config.baseUrl.replace(/\/$/, "");
8021
8424
  this.apiAccessToken = config.apiAccessToken;
8022
8425
  this.retryConfig = config.defaults.retry;
8023
- this.concurrencyLimit = pLimit2(config.defaults.concurrency);
8426
+ this.concurrencyLimit = pLimit3(config.defaults.concurrency);
8024
8427
  }
8025
- async request(path7, options = {}) {
8026
- const url = `${this.baseUrl}${path7}`;
8428
+ async request(path8, options = {}) {
8429
+ const url = `${this.baseUrl}${path8}`;
8027
8430
  const headers = {
8028
8431
  "X-Redmine-API-Key": this.apiAccessToken,
8029
8432
  "Content-Type": "application/json",
@@ -8084,8 +8487,8 @@ var RedmineApiClient = class {
8084
8487
  if (include && include.length > 0) {
8085
8488
  params.append("include", include.join(","));
8086
8489
  }
8087
- const path7 = `/issues/${issueId}.json${params.toString() ? `?${params.toString()}` : ""}`;
8088
- return this.request(path7);
8490
+ const path8 = `/issues/${issueId}.json${params.toString() ? `?${params.toString()}` : ""}`;
8491
+ return this.request(path8);
8089
8492
  }
8090
8493
  async getIssues(projectId, options = {}) {
8091
8494
  const params = new URLSearchParams();
@@ -8105,8 +8508,8 @@ var RedmineApiClient = class {
8105
8508
  if (options.updatedSince) {
8106
8509
  params.append("updated_on", `>=${options.updatedSince}`);
8107
8510
  }
8108
- const path7 = `/issues.json?${params.toString()}`;
8109
- return this.request(path7);
8511
+ const path8 = `/issues.json?${params.toString()}`;
8512
+ return this.request(path8);
8110
8513
  }
8111
8514
  async getAllIssues(projectId, options = {}) {
8112
8515
  const pageSize = options.pageSize || 100;
@@ -8208,7 +8611,7 @@ async function checkConnectivity(config) {
8208
8611
 
8209
8612
  // src/commands/redmine/check.ts
8210
8613
  function createRedmineCheckCommand() {
8211
- const cmd = new Command35("check").description("Check Redmine connectivity").option("-c, --config <path>", "Config file path", "redmine.config.yaml").option("--json", "Output as JSON").action(async (options) => {
8614
+ const cmd = new Command37("check").description("Check Redmine connectivity").option("-c, --config <path>", "Config file path", "redmine.config.yaml").option("--json", "Output as JSON").action(async (options) => {
8212
8615
  await handleRedmineCheck(options);
8213
8616
  });
8214
8617
  return cmd;
@@ -8236,7 +8639,7 @@ async function handleRedmineCheck(options) {
8236
8639
  }
8237
8640
 
8238
8641
  // src/commands/redmine/sync-issue.ts
8239
- import { Command as Command36 } from "commander";
8642
+ import { Command as Command38 } from "commander";
8240
8643
 
8241
8644
  // src/sync-issue.ts
8242
8645
  import { resolve as resolve3, relative } from "path";
@@ -8612,7 +9015,7 @@ function extractIssueIdFromUrl(url) {
8612
9015
 
8613
9016
  // src/commands/redmine/sync-issue.ts
8614
9017
  function createSyncIssueCommand() {
8615
- const cmd = new Command36("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) => {
9018
+ const cmd = new Command38("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) => {
8616
9019
  await handleSyncIssue(options);
8617
9020
  });
8618
9021
  return cmd;
@@ -8656,7 +9059,7 @@ async function handleSyncIssue(options) {
8656
9059
  }
8657
9060
 
8658
9061
  // src/commands/redmine/sync-project.ts
8659
- import { Command as Command37 } from "commander";
9062
+ import { Command as Command39 } from "commander";
8660
9063
 
8661
9064
  // src/sync-project.ts
8662
9065
  async function syncProject(config, options = {}) {
@@ -8726,7 +9129,7 @@ async function syncProject(config, options = {}) {
8726
9129
 
8727
9130
  // src/commands/redmine/sync-project.ts
8728
9131
  function createSyncProjectCommand() {
8729
- const cmd = new Command37("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) => {
9132
+ const cmd = new Command39("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) => {
8730
9133
  await handleSyncProject(options);
8731
9134
  });
8732
9135
  return cmd;
@@ -8781,12 +9184,12 @@ async function handleSyncProject(options) {
8781
9184
  }
8782
9185
 
8783
9186
  // src/commands/framework/info.ts
8784
- import { Command as Command38 } from "commander";
8785
- import { promises as fs11 } from "fs";
9187
+ import { Command as Command40 } from "commander";
9188
+ import { promises as fs12 } from "fs";
8786
9189
  import { join as join7 } from "path";
8787
9190
  import { homedir as homedir5 } from "os";
8788
9191
  function createInfoCommand() {
8789
- const cmd = new Command38("info").description("Show jai1-client configuration and status").option("--json", "Output as JSON").option("--verbose", "Show detailed information").action(async (options) => {
9192
+ const cmd = new Command40("info").description("Show jai1-client configuration and status").option("--json", "Output as JSON").option("--verbose", "Show detailed information").action(async (options) => {
8790
9193
  await handleInfo(options);
8791
9194
  });
8792
9195
  return cmd;
@@ -8834,7 +9237,7 @@ function maskKey3(key) {
8834
9237
  async function getProjectStatus2() {
8835
9238
  const projectJai1 = join7(process.cwd(), ".jai1");
8836
9239
  try {
8837
- await fs11.access(projectJai1);
9240
+ await fs12.access(projectJai1);
8838
9241
  return { exists: true, version: "Synced" };
8839
9242
  } catch {
8840
9243
  return { exists: false };
@@ -8842,10 +9245,10 @@ async function getProjectStatus2() {
8842
9245
  }
8843
9246
 
8844
9247
  // src/commands/self-update.ts
8845
- import { Command as Command39 } from "commander";
8846
- import { confirm as confirm6 } from "@inquirer/prompts";
8847
- import { execSync as execSync2 } from "child_process";
8848
- var colors3 = {
9248
+ import { Command as Command41 } from "commander";
9249
+ import { confirm as confirm7 } from "@inquirer/prompts";
9250
+ import { execSync as execSync3 } from "child_process";
9251
+ var colors4 = {
8849
9252
  yellow: "\x1B[33m",
8850
9253
  green: "\x1B[32m",
8851
9254
  cyan: "\x1B[36m",
@@ -8854,7 +9257,7 @@ var colors3 = {
8854
9257
  bold: "\x1B[1m"
8855
9258
  };
8856
9259
  function createSelfUpdateCommand() {
8857
- return new Command39("self-update").description("Update jai1-client to the latest version").option("--check", "Only check for updates without installing").option("--force", "Force update without confirmation").action(async (options) => {
9260
+ return new Command41("self-update").description("Update jai1-client to the latest version").option("--check", "Only check for updates without installing").option("--force", "Force update without confirmation").action(async (options) => {
8858
9261
  await handleSelfUpdate(options);
8859
9262
  });
8860
9263
  }
@@ -8865,7 +9268,7 @@ async function handleSelfUpdate(options) {
8865
9268
  throw new ValidationError('Not initialized. Run "jai1 auth" first.');
8866
9269
  }
8867
9270
  try {
8868
- console.log(`${colors3.cyan}\u{1F50D} Checking for updates...${colors3.reset}`);
9271
+ console.log(`${colors4.cyan}\u{1F50D} Checking for updates...${colors4.reset}`);
8869
9272
  const response = await fetch(`${config.apiUrl}/api/versions/client`, {
8870
9273
  headers: {
8871
9274
  "JAI1-Access-Key": config.accessKey
@@ -8880,47 +9283,47 @@ async function handleSelfUpdate(options) {
8880
9283
  const latestVersion = data.version;
8881
9284
  const currentVersion = package_default.version;
8882
9285
  console.log(`
8883
- ${colors3.bold}Current version:${colors3.reset} ${currentVersion}`);
8884
- console.log(`${colors3.bold}Latest version:${colors3.reset} ${latestVersion}
9286
+ ${colors4.bold}Current version:${colors4.reset} ${currentVersion}`);
9287
+ console.log(`${colors4.bold}Latest version:${colors4.reset} ${latestVersion}
8885
9288
  `);
8886
9289
  if (!isNewerVersion3(latestVersion, currentVersion)) {
8887
- console.log(`${colors3.green}\u2705 You're already on the latest version!${colors3.reset}
9290
+ console.log(`${colors4.green}\u2705 You're already on the latest version!${colors4.reset}
8888
9291
  `);
8889
9292
  return;
8890
9293
  }
8891
- console.log(`${colors3.yellow}\u256D\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\u2500\u2500\u2500\u2500\u2500\u256E${colors3.reset}`);
8892
- console.log(`${colors3.yellow}\u2502${colors3.reset} ${colors3.bold}\u2B06\uFE0F Update available!${colors3.reset} ${currentVersion} \u2192 ${colors3.cyan}${latestVersion}${colors3.reset} ${colors3.yellow}\u2502${colors3.reset}`);
8893
- console.log(`${colors3.yellow}\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\u2500\u2500\u2500\u2500\u2500\u256F${colors3.reset}
9294
+ console.log(`${colors4.yellow}\u256D\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\u2500\u2500\u2500\u2500\u2500\u256E${colors4.reset}`);
9295
+ console.log(`${colors4.yellow}\u2502${colors4.reset} ${colors4.bold}\u2B06\uFE0F Update available!${colors4.reset} ${currentVersion} \u2192 ${colors4.cyan}${latestVersion}${colors4.reset} ${colors4.yellow}\u2502${colors4.reset}`);
9296
+ console.log(`${colors4.yellow}\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\u2500\u2500\u2500\u2500\u2500\u256F${colors4.reset}
8894
9297
  `);
8895
9298
  if (options.check) {
8896
- console.log(`${colors3.cyan}Run "jai1 self-update" to install the latest version.${colors3.reset}
9299
+ console.log(`${colors4.cyan}Run "jai1 self-update" to install the latest version.${colors4.reset}
8897
9300
  `);
8898
9301
  return;
8899
9302
  }
8900
9303
  if (!options.force) {
8901
- const shouldUpdate = await confirm6({
9304
+ const shouldUpdate = await confirm7({
8902
9305
  message: "Update to the latest version now?",
8903
9306
  default: true
8904
9307
  });
8905
9308
  if (!shouldUpdate) {
8906
- console.log(`${colors3.yellow}\u23F8\uFE0F Update cancelled.${colors3.reset}
9309
+ console.log(`${colors4.yellow}\u23F8\uFE0F Update cancelled.${colors4.reset}
8907
9310
  `);
8908
9311
  return;
8909
9312
  }
8910
9313
  }
8911
9314
  console.log(`
8912
- ${colors3.cyan}\u{1F4E5} Installing latest version...${colors3.reset}
9315
+ ${colors4.cyan}\u{1F4E5} Installing latest version...${colors4.reset}
8913
9316
  `);
8914
9317
  try {
8915
9318
  const packageManager2 = detectPackageManager2();
8916
9319
  const installCommand = getInstallCommand2(packageManager2);
8917
- console.log(`${colors3.cyan}Using ${packageManager2}...${colors3.reset}`);
8918
- execSync2(installCommand, {
9320
+ console.log(`${colors4.cyan}Using ${packageManager2}...${colors4.reset}`);
9321
+ execSync3(installCommand, {
8919
9322
  stdio: "inherit",
8920
9323
  env: { ...process.env, FORCE_COLOR: "1" }
8921
9324
  });
8922
9325
  console.log(`
8923
- ${colors3.green}\u2705 Successfully updated to version ${latestVersion}!${colors3.reset}
9326
+ ${colors4.green}\u2705 Successfully updated to version ${latestVersion}!${colors4.reset}
8924
9327
  `);
8925
9328
  trackAction("self_update", {
8926
9329
  from_version: currentVersion,
@@ -8930,11 +9333,11 @@ ${colors3.green}\u2705 Successfully updated to version ${latestVersion}!${colors
8930
9333
  disableUpdateCheck();
8931
9334
  } catch (error) {
8932
9335
  console.error(`
8933
- ${colors3.red}\u274C Update failed!${colors3.reset}`);
8934
- console.error(`${colors3.red}Error: ${error instanceof Error ? error.message : "Unknown error"}${colors3.reset}
9336
+ ${colors4.red}\u274C Update failed!${colors4.reset}`);
9337
+ console.error(`${colors4.red}Error: ${error instanceof Error ? error.message : "Unknown error"}${colors4.reset}
8935
9338
  `);
8936
- console.error(`${colors3.yellow}\u{1F4A1} You can try manually updating with:${colors3.reset}`);
8937
- console.error(` ${colors3.cyan}npm install -g @jvittechs/jai1-cli@latest${colors3.reset}
9339
+ console.error(`${colors4.yellow}\u{1F4A1} You can try manually updating with:${colors4.reset}`);
9340
+ console.error(` ${colors4.cyan}npm install -g @jvittechs/jai1-cli@latest${colors4.reset}
8938
9341
  `);
8939
9342
  throw error;
8940
9343
  }
@@ -8962,17 +9365,17 @@ function detectPackageManager2() {
8962
9365
  if (userAgent.includes("yarn")) return "yarn";
8963
9366
  if (userAgent.includes("bun")) return "bun";
8964
9367
  try {
8965
- execSync2("pnpm --version", { stdio: "ignore" });
9368
+ execSync3("pnpm --version", { stdio: "ignore" });
8966
9369
  return "pnpm";
8967
9370
  } catch {
8968
9371
  }
8969
9372
  try {
8970
- execSync2("yarn --version", { stdio: "ignore" });
9373
+ execSync3("yarn --version", { stdio: "ignore" });
8971
9374
  return "yarn";
8972
9375
  } catch {
8973
9376
  }
8974
9377
  try {
8975
- execSync2("bun --version", { stdio: "ignore" });
9378
+ execSync3("bun --version", { stdio: "ignore" });
8976
9379
  return "bun";
8977
9380
  } catch {
8978
9381
  }
@@ -8994,10 +9397,10 @@ function getInstallCommand2(packageManager2) {
8994
9397
  }
8995
9398
 
8996
9399
  // src/commands/clear-backups.ts
8997
- import { Command as Command40 } from "commander";
8998
- import { confirm as confirm7 } from "@inquirer/prompts";
9400
+ import { Command as Command42 } from "commander";
9401
+ import { confirm as confirm8 } from "@inquirer/prompts";
8999
9402
  function createClearBackupsCommand() {
9000
- return new Command40("clear-backups").description("Clear backup files").option("-y, --yes", "Skip confirmation").action(async (options) => {
9403
+ return new Command42("clear-backups").description("Clear backup files").option("-y, --yes", "Skip confirmation").action(async (options) => {
9001
9404
  const service = new ComponentsService();
9002
9405
  const backups = await service.listBackups(process.cwd());
9003
9406
  if (backups.length === 0) {
@@ -9013,7 +9416,7 @@ function createClearBackupsCommand() {
9013
9416
  }
9014
9417
  console.log();
9015
9418
  if (!options.yes) {
9016
- const ok = await confirm7({ message: "Delete all backups?", default: false });
9419
+ const ok = await confirm8({ message: "Delete all backups?", default: false });
9017
9420
  if (!ok) return;
9018
9421
  }
9019
9422
  await service.clearBackups(process.cwd());
@@ -9022,10 +9425,10 @@ function createClearBackupsCommand() {
9022
9425
  }
9023
9426
 
9024
9427
  // src/commands/vscode/index.ts
9025
- import { Command as Command41 } from "commander";
9026
- import { checkbox as checkbox4, confirm as confirm8, select as select4 } from "@inquirer/prompts";
9027
- import fs12 from "fs/promises";
9028
- import path6 from "path";
9428
+ import { Command as Command43 } from "commander";
9429
+ import { checkbox as checkbox5, confirm as confirm9, select as select4 } from "@inquirer/prompts";
9430
+ import fs13 from "fs/promises";
9431
+ import path7 from "path";
9029
9432
  import { existsSync as existsSync3 } from "fs";
9030
9433
  var PERFORMANCE_GROUPS2 = {
9031
9434
  telemetry: {
@@ -9162,7 +9565,7 @@ var PERFORMANCE_GROUPS2 = {
9162
9565
  }
9163
9566
  };
9164
9567
  function createVSCodeCommand() {
9165
- const vscodeCommand = new Command41("vscode").description("Qu\u1EA3n l\xFD c\xE0i \u0111\u1EB7t VSCode cho d\u1EF1 \xE1n hi\u1EC7n t\u1EA1i");
9568
+ const vscodeCommand = new Command43("vscode").description("Qu\u1EA3n l\xFD c\xE0i \u0111\u1EB7t VSCode cho d\u1EF1 \xE1n hi\u1EC7n t\u1EA1i");
9166
9569
  vscodeCommand.action(async () => {
9167
9570
  await interactiveMode2();
9168
9571
  });
@@ -9230,7 +9633,7 @@ async function selectGroupsToApply2(action) {
9230
9633
  value: key
9231
9634
  }));
9232
9635
  try {
9233
- const selectedGroups = await checkbox4({
9636
+ const selectedGroups = await checkbox5({
9234
9637
  message: `Ch\u1ECDn c\xE1c nh\xF3m \u0111\u1EC3 ${action === "enable" ? "enable" : "disable"} (SPACE \u0111\u1EC3 ch\u1ECDn, ENTER \u0111\u1EC3 x\xE1c nh\u1EADn):`,
9235
9638
  choices
9236
9639
  });
@@ -9245,8 +9648,8 @@ async function selectGroupsToApply2(action) {
9245
9648
  }
9246
9649
  }
9247
9650
  async function applyGroups2(groupKeys, action) {
9248
- const vscodeDir = path6.join(process.cwd(), ".vscode");
9249
- const settingsPath = path6.join(vscodeDir, "settings.json");
9651
+ const vscodeDir = path7.join(process.cwd(), ".vscode");
9652
+ const settingsPath = path7.join(vscodeDir, "settings.json");
9250
9653
  const invalidGroups = groupKeys.filter((key) => !PERFORMANCE_GROUPS2[key]);
9251
9654
  if (invalidGroups.length > 0) {
9252
9655
  console.log(`
@@ -9255,18 +9658,18 @@ async function applyGroups2(groupKeys, action) {
9255
9658
  return;
9256
9659
  }
9257
9660
  if (!existsSync3(vscodeDir)) {
9258
- await fs12.mkdir(vscodeDir, { recursive: true });
9661
+ await fs13.mkdir(vscodeDir, { recursive: true });
9259
9662
  console.log("\u{1F4C1} \u0110\xE3 t\u1EA1o th\u01B0 m\u1EE5c .vscode/");
9260
9663
  }
9261
9664
  let currentSettings = {};
9262
9665
  if (existsSync3(settingsPath)) {
9263
9666
  try {
9264
- const content = await fs12.readFile(settingsPath, "utf-8");
9667
+ const content = await fs13.readFile(settingsPath, "utf-8");
9265
9668
  currentSettings = JSON.parse(content);
9266
9669
  console.log("\u{1F4C4} \u0110\xE3 \u0111\u1ECDc c\xE0i \u0111\u1EB7t hi\u1EC7n t\u1EA1i t\u1EEB settings.json");
9267
9670
  } catch {
9268
9671
  console.warn("\u26A0\uFE0F Kh\xF4ng th\u1EC3 \u0111\u1ECDc settings.json (c\xF3 th\u1EC3 ch\u1EE9a comments).");
9269
- const confirmOverwrite = await confirm8({
9672
+ const confirmOverwrite = await confirm9({
9270
9673
  message: "Ghi \u0111\xE8 file settings.json hi\u1EC7n t\u1EA1i?",
9271
9674
  default: false
9272
9675
  });
@@ -9301,19 +9704,19 @@ async function applyGroups2(groupKeys, action) {
9301
9704
  }
9302
9705
  }
9303
9706
  }
9304
- await fs12.writeFile(settingsPath, JSON.stringify(newSettings, null, 2));
9707
+ await fs13.writeFile(settingsPath, JSON.stringify(newSettings, null, 2));
9305
9708
  console.log(`
9306
9709
  \u2705 \u0110\xE3 c\u1EADp nh\u1EADt c\xE0i \u0111\u1EB7t VSCode t\u1EA1i: ${settingsPath}`);
9307
9710
  console.log("\u{1F4A1} M\u1EB9o: Kh\u1EDFi \u0111\u1ED9ng l\u1EA1i VSCode \u0111\u1EC3 \xE1p d\u1EE5ng c\xE1c thay \u0111\u1ED5i.");
9308
9711
  }
9309
9712
  async function resetSettings2(groupKeys) {
9310
- const vscodeDir = path6.join(process.cwd(), ".vscode");
9311
- const settingsPath = path6.join(vscodeDir, "settings.json");
9713
+ const vscodeDir = path7.join(process.cwd(), ".vscode");
9714
+ const settingsPath = path7.join(vscodeDir, "settings.json");
9312
9715
  if (!existsSync3(settingsPath)) {
9313
9716
  console.log("\n\u26A0\uFE0F Kh\xF4ng t\xECm th\u1EA5y file settings.json");
9314
9717
  return;
9315
9718
  }
9316
- const confirmReset = await confirm8({
9719
+ const confirmReset = await confirm9({
9317
9720
  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(", ")}?`,
9318
9721
  default: false
9319
9722
  });
@@ -9322,7 +9725,7 @@ async function resetSettings2(groupKeys) {
9322
9725
  return;
9323
9726
  }
9324
9727
  if (groupKeys.length === 0) {
9325
- await fs12.unlink(settingsPath);
9728
+ await fs13.unlink(settingsPath);
9326
9729
  console.log("\n\u2705 \u0110\xE3 x\xF3a file settings.json");
9327
9730
  } else {
9328
9731
  await applyGroups2(groupKeys, "disable");
@@ -9333,9 +9736,9 @@ async function resetSettings2(groupKeys) {
9333
9736
  // src/commands/guide.ts
9334
9737
  import React40 from "react";
9335
9738
  import { render as render6 } from "ink";
9336
- import { Command as Command42 } from "commander";
9739
+ import { Command as Command44 } from "commander";
9337
9740
  function createGuideCommand() {
9338
- const cmd = new Command42("guide").description("Interactive guide center for Agentic Coding").option("--topic <topic>", "Open specific topic (intro, rules, workflows, prompts, skills)").action(async (options) => {
9741
+ const cmd = new Command44("guide").description("Interactive guide center for Agentic Coding").option("--topic <topic>", "Open specific topic (intro, rules, workflows, prompts, skills)").action(async (options) => {
9339
9742
  const { waitUntilExit } = render6(
9340
9743
  React40.createElement(GuideApp, {
9341
9744
  initialTopic: options.topic,
@@ -9352,9 +9755,9 @@ function createGuideCommand() {
9352
9755
  // src/commands/context.ts
9353
9756
  import React41 from "react";
9354
9757
  import { render as render7 } from "ink";
9355
- import { Command as Command43 } from "commander";
9758
+ import { Command as Command45 } from "commander";
9356
9759
  function createContextCommand() {
9357
- const cmd = new Command43("context").description("Kh\xE1m ph\xE1 v\xE0 qu\u1EA3n l\xFD context d\u1EF1 \xE1n cho c\xE1c IDE").option("--ide <ide>", "M\u1EDF tr\u1EF1c ti\u1EBFp IDE c\u1EE5 th\u1EC3 (cursor, windsurf, antigravity, jai1)").option("--type <type>", "Hi\u1EC3n th\u1ECB lo\u1EA1i context c\u1EE5 th\u1EC3 (rules, workflows, skills, agents, prompts)").option("--stats", "Hi\u1EC3n th\u1ECB th\u1ED1ng k\xEA context (non-interactive)").action(async (options) => {
9760
+ const cmd = new Command45("context").description("Kh\xE1m ph\xE1 v\xE0 qu\u1EA3n l\xFD context d\u1EF1 \xE1n cho c\xE1c IDE").option("--ide <ide>", "M\u1EDF tr\u1EF1c ti\u1EBFp IDE c\u1EE5 th\u1EC3 (cursor, windsurf, antigravity, jai1)").option("--type <type>", "Hi\u1EC3n th\u1ECB lo\u1EA1i context c\u1EE5 th\u1EC3 (rules, workflows, skills, agents, prompts)").option("--stats", "Hi\u1EC3n th\u1ECB th\u1ED1ng k\xEA context (non-interactive)").action(async (options) => {
9358
9761
  let initialIDE;
9359
9762
  if (options.ide) {
9360
9763
  const validIDEs = ["cursor", "windsurf", "antigravity", "jai1"];
@@ -9431,10 +9834,10 @@ async function printStats2() {
9431
9834
  }
9432
9835
 
9433
9836
  // src/commands/migrate-ide.ts
9434
- import { Command as Command44 } from "commander";
9435
- import { checkbox as checkbox5, confirm as confirm9 } from "@inquirer/prompts";
9837
+ import { Command as Command46 } from "commander";
9838
+ import { checkbox as checkbox6, confirm as confirm10 } from "@inquirer/prompts";
9436
9839
  function createMigrateIdeCommand() {
9437
- const cmd = new Command44("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) => {
9840
+ const cmd = new Command46("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) => {
9438
9841
  await runMigrateIde(options);
9439
9842
  });
9440
9843
  return cmd;
@@ -9462,7 +9865,7 @@ async function runMigrateIde(options) {
9462
9865
  value: ide
9463
9866
  };
9464
9867
  });
9465
- selectedIdes = await checkbox5({
9868
+ selectedIdes = await checkbox6({
9466
9869
  message: "Ch\u1ECDn IDE(s) \u0111\u1EC3 migrate (SPACE \u0111\u1EC3 ch\u1ECDn, ENTER \u0111\u1EC3 x\xE1c nh\u1EADn):",
9467
9870
  choices: ideChoices
9468
9871
  });
@@ -9481,7 +9884,7 @@ async function runMigrateIde(options) {
9481
9884
  { name: `Workflows (${content.workflows.length} files)`, value: "workflows" },
9482
9885
  { name: `Commands (${content.commands.length} files)`, value: "commands" }
9483
9886
  ];
9484
- selectedTypes = await checkbox5({
9887
+ selectedTypes = await checkbox6({
9485
9888
  message: "Ch\u1ECDn content types \u0111\u1EC3 migrate:",
9486
9889
  choices: typeChoices
9487
9890
  });
@@ -9503,7 +9906,7 @@ async function runMigrateIde(options) {
9503
9906
  if (options.dryRun) {
9504
9907
  console.log("\u{1F50D} DRY RUN - No files will be written\n");
9505
9908
  }
9506
- const confirmed = await confirm9({
9909
+ const confirmed = await confirm10({
9507
9910
  message: "Proceed with migration?",
9508
9911
  default: true
9509
9912
  });
@@ -9540,7 +9943,7 @@ async function runMigrateIde(options) {
9540
9943
  }
9541
9944
 
9542
9945
  // src/cli.ts
9543
- var program = new Command45();
9946
+ var program = new Command47();
9544
9947
  if (process.argv.includes("-v") || process.argv.includes("--version")) {
9545
9948
  console.log(package_default.version);
9546
9949
  if (!process.argv.includes("--skip-update-check")) {
@@ -9562,12 +9965,13 @@ program.addCommand(createOpenAiKeysCommand());
9562
9965
  program.addCommand(createStatsCommand());
9563
9966
  program.addCommand(createTranslateCommand());
9564
9967
  program.addCommand(createUtilsCommand());
9968
+ program.addCommand(createDepsCommand());
9565
9969
  program.addCommand(createKitCommand());
9566
9970
  program.addCommand(createUpgradeCommand());
9567
9971
  program.addCommand(createCleanCommand());
9568
- var redmineCommand = new Command45("redmine").description("Redmine context sync commands");
9972
+ var redmineCommand = new Command47("redmine").description("Redmine context sync commands");
9569
9973
  redmineCommand.addCommand(createRedmineCheckCommand());
9570
- var syncCommand = new Command45("sync").description("Sync Redmine issues to markdown files");
9974
+ var syncCommand = new Command47("sync").description("Sync Redmine issues to markdown files");
9571
9975
  syncCommand.addCommand(createSyncIssueCommand());
9572
9976
  syncCommand.addCommand(createSyncProjectCommand());
9573
9977
  redmineCommand.addCommand(syncCommand);
@@ -9607,6 +10011,7 @@ program.on("command:*", (operands) => {
9607
10011
  console.error(" translate Translate text, files, or folders using AI");
9608
10012
  console.error("");
9609
10013
  console.error(" \u{1F6E0}\uFE0F Developer Utilities");
10014
+ console.error(" deps Manage project dependencies");
9610
10015
  console.error(" utils Developer tools (password, uuid, hash, jwt, etc.)");
9611
10016
  console.error("");
9612
10017
  console.error(" \u{1F527} Maintenance");