@jvittechs/j 1.0.61 → 1.0.63

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
@@ -10,14 +10,17 @@ import {
10
10
  createSettingsShowCommand
11
11
  } from "./chunk-5RDBJYO2.js";
12
12
  import {
13
- BLOCKED_ICON,
14
13
  CloudTaskProvider,
14
+ TaskService,
15
+ createTaskSummaryCommand
16
+ } from "./chunk-LZZF4JQS.js";
17
+ import {
18
+ BLOCKED_ICON,
15
19
  PRIORITY_ICONS,
16
20
  PRIORITY_LABELS,
17
21
  STATUS_ICONS,
18
- TaskService,
19
- createTaskSummaryCommand
20
- } from "./chunk-F6GY6L6O.js";
22
+ TaskSchema
23
+ } from "./chunk-WOAXYUZ6.js";
21
24
  import {
22
25
  ConfigService,
23
26
  SettingsService
@@ -157,7 +160,7 @@ import { basename as basename5 } from "path";
157
160
  // package.json
158
161
  var package_default = {
159
162
  name: "@jvittechs/j",
160
- version: "1.0.61",
163
+ version: "1.0.63",
161
164
  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.",
162
165
  type: "module",
163
166
  bin: {
@@ -11391,6 +11394,30 @@ async function registerProject(config, projectId, repoUrl, silent) {
11391
11394
  return null;
11392
11395
  }
11393
11396
  }
11397
+ async function syncLocalTasksToCloud(config, projectId, tasksPath, silent) {
11398
+ try {
11399
+ const { existsSync: existsSync7, readFileSync: readFileSync4 } = await import("fs");
11400
+ if (!existsSync7(tasksPath)) return;
11401
+ const content = readFileSync4(tasksPath, "utf-8").trim();
11402
+ if (!content) return;
11403
+ const { TaskSchema: TaskSchema2 } = await import("./task.types-M4GWGDMH.js");
11404
+ const lines = content.split("\n").filter(Boolean);
11405
+ const tasks = lines.map((line) => TaskSchema2.parse(JSON.parse(line)));
11406
+ if (tasks.length === 0) return;
11407
+ if (!silent) {
11408
+ console.log(chalk31.dim(` \u2191 Syncing ${tasks.length} local tasks to cloud...`));
11409
+ }
11410
+ const provider = new CloudTaskProvider(config, projectId);
11411
+ await provider.push(tasks);
11412
+ if (!silent) {
11413
+ console.log(chalk31.green(` \u2713 ${tasks.length} tasks synced to cloud`));
11414
+ }
11415
+ } catch {
11416
+ if (!silent) {
11417
+ console.log(chalk31.dim(" \u26A0\uFE0F Could not sync local tasks. Use j t sync --push later."));
11418
+ }
11419
+ }
11420
+ }
11394
11421
  function createSettingsInitCommand() {
11395
11422
  return new Command58("init").description("Kh\u1EDFi t\u1EA1o .jai1/settings.yaml").option("-f, --force", "Ghi \u0111\xE8 file c\u0169 n\u1EBFu \u0111\xE3 t\u1ED3n t\u1EA1i").option("--cloud", "Enable cloud task sync (non-interactive)").option("--no-interactive", "Kh\xF4ng h\u1ECFi, d\xF9ng flags/defaults").option("-j, --json", "Output JSON").action(async (options) => {
11396
11423
  try {
@@ -11449,9 +11476,18 @@ function createSettingsInitCommand() {
11449
11476
  repoUrl,
11450
11477
  !!options.json
11451
11478
  );
11479
+ const finalProjectId = registeredProjectId && registeredProjectId !== projectId ? registeredProjectId : projectId;
11452
11480
  if (registeredProjectId && registeredProjectId !== projectId) {
11453
11481
  await service.set("tasks.projectId", registeredProjectId);
11454
11482
  }
11483
+ if (registeredProjectId) {
11484
+ await syncLocalTasksToCloud(
11485
+ authResult.config,
11486
+ finalProjectId,
11487
+ service.getSettingsPath().replace(/settings\.yaml$/, "tasks.jsonl"),
11488
+ !!options.json
11489
+ );
11490
+ }
11455
11491
  }
11456
11492
  }
11457
11493
  const finalSettings = service.load();
@@ -11488,6 +11524,8 @@ function createSettingsInitCommand() {
11488
11524
  // src/commands/settings/set.ts
11489
11525
  import { Command as Command59 } from "commander";
11490
11526
  import chalk32 from "chalk";
11527
+ import { existsSync as existsSync4, readFileSync as readFileSync3 } from "fs";
11528
+ import { join as join9 } from "path";
11491
11529
  function createSettingsSetCommand() {
11492
11530
  return new Command59("set").description("Set a setting value (dot-notation)").argument("<key>", "Setting key (e.g., tasks.cloud)").argument("<value>", "Setting value").option("-j, --json", "Output JSON").action(async (key, value, options) => {
11493
11531
  try {
@@ -11513,15 +11551,29 @@ function createSettingsSetCommand() {
11513
11551
  const repoUrl = service.resolveGitRepoUrl();
11514
11552
  const projectId = service.getProjectId();
11515
11553
  if (repoUrl && projectId) {
11554
+ let finalProjectId = projectId;
11516
11555
  try {
11517
11556
  const provider = new CloudTaskProvider(config, projectId);
11518
11557
  const registeredId = await provider.ensureProjectRegistered(repoUrl);
11519
11558
  console.log(chalk32.green(" \u2713 Project registered on server"));
11520
11559
  if (registeredId && registeredId !== projectId) {
11521
11560
  await service.set("tasks.projectId", registeredId);
11522
- console.log(chalk32.dim(` Project ID: ${registeredId}`));
11523
- } else {
11524
- console.log(chalk32.dim(` Project: ${projectId}`));
11561
+ finalProjectId = registeredId;
11562
+ }
11563
+ console.log(chalk32.dim(` Project: ${finalProjectId}`));
11564
+ const tasksPath = join9(process.cwd(), ".jai1", "tasks.jsonl");
11565
+ if (existsSync4(tasksPath)) {
11566
+ const content = readFileSync3(tasksPath, "utf-8").trim();
11567
+ if (content) {
11568
+ const lines = content.split("\n").filter(Boolean);
11569
+ const tasks = lines.map((l) => TaskSchema.parse(JSON.parse(l)));
11570
+ if (tasks.length > 0) {
11571
+ console.log(chalk32.dim(` \u2191 Syncing ${tasks.length} local tasks to cloud...`));
11572
+ const p = new CloudTaskProvider(config, finalProjectId);
11573
+ await p.push(tasks);
11574
+ console.log(chalk32.green(` \u2713 ${tasks.length} tasks synced to cloud`));
11575
+ }
11576
+ }
11525
11577
  }
11526
11578
  } catch (error) {
11527
11579
  const msg = error instanceof Error ? error.message : String(error);
@@ -11673,6 +11725,9 @@ function printTaskLine(task, resolvedIds) {
11673
11725
  const blockedBy = task.depends_on.filter((id) => !resolvedIds.has(id));
11674
11726
  line += chalk35.red(` (blocked: ${blockedBy.join(", ")})`);
11675
11727
  }
11728
+ if (task.type && task.type !== "task") {
11729
+ line += chalk35.magenta(` {${task.type}}`);
11730
+ }
11676
11731
  if (task.parent) {
11677
11732
  line += chalk35.dim(` [${task.parent}]`);
11678
11733
  }
@@ -11965,7 +12020,8 @@ function createTaskSyncCommand() {
11965
12020
  const cloudTasks = await service.cloud.pull();
11966
12021
  console.log(chalk42.dim(` \u2193 ${cloudTasks.length} tasks fetched from cloud`));
11967
12022
  if (isFull) {
11968
- const localTasks = await service.readAll();
12023
+ const localTasks = await service.readLocal();
12024
+ console.log(chalk42.dim(` \u2190 ${localTasks.length} tasks in local file`));
11969
12025
  const localMap = new Map(localTasks.map((t) => [t.id, t]));
11970
12026
  const cloudMap = new Map(cloudTasks.map((t) => [t.id, t]));
11971
12027
  const merged = /* @__PURE__ */ new Map();
@@ -11987,7 +12043,7 @@ function createTaskSyncCommand() {
11987
12043
  console.log(chalk42.green(`\u2705 Pull complete: ${cloudTasks.length} tasks written`));
11988
12044
  }
11989
12045
  } else if (doPush) {
11990
- const localTasks = await service.readAll();
12046
+ const localTasks = await service.readLocal();
11991
12047
  await service.cloud.push(localTasks);
11992
12048
  console.log(chalk42.green(`\u2705 Push complete: ${localTasks.length} tasks uploaded`));
11993
12049
  }
@@ -12396,7 +12452,7 @@ function createTasksCommand() {
12396
12452
  cmd.addCommand(createTaskDeleteCommand());
12397
12453
  cmd.addCommand(createTaskGuideCommand());
12398
12454
  cmd.action(async () => {
12399
- const { handleTaskSummary } = await import("./summary-KFXQDFG6.js");
12455
+ const { handleTaskSummary } = await import("./summary-EJWKLQF4.js");
12400
12456
  await handleTaskSummary({ json: false });
12401
12457
  });
12402
12458
  return cmd;
@@ -12413,7 +12469,7 @@ import Table6 from "cli-table3";
12413
12469
 
12414
12470
  // src/services/starter-kit.service.ts
12415
12471
  import { promises as fs18 } from "fs";
12416
- import { join as join9 } from "path";
12472
+ import { join as join10 } from "path";
12417
12473
  import AdmZip from "adm-zip";
12418
12474
  var StarterKitService = class {
12419
12475
  /**
@@ -12460,9 +12516,9 @@ var StarterKitService = class {
12460
12516
  throw new NetworkError(`Failed to download kit: HTTP ${response.status}`);
12461
12517
  }
12462
12518
  if (onProgress) onProgress(30);
12463
- const tmpDir = join9(process.env.TMPDIR || "/tmp", "jai1-kits");
12519
+ const tmpDir = join10(process.env.TMPDIR || "/tmp", "jai1-kits");
12464
12520
  await fs18.mkdir(tmpDir, { recursive: true });
12465
- const tmpFile = join9(tmpDir, `${slug}.zip`);
12521
+ const tmpFile = join10(tmpDir, `${slug}.zip`);
12466
12522
  const buffer = await response.arrayBuffer();
12467
12523
  await fs18.writeFile(tmpFile, Buffer.from(buffer));
12468
12524
  if (onProgress) onProgress(60);
@@ -12595,7 +12651,7 @@ Post-Init Commands:`);
12595
12651
  // src/commands/kit/create.ts
12596
12652
  import { Command as Command78 } from "commander";
12597
12653
  import { promises as fs19 } from "fs";
12598
- import { join as join10 } from "path";
12654
+ import { join as join11 } from "path";
12599
12655
  import { select as select3, input as input2, checkbox as checkbox4 } from "@inquirer/prompts";
12600
12656
  import { execa as execa2 } from "execa";
12601
12657
 
@@ -12658,7 +12714,7 @@ function createKitCreateCommand() {
12658
12714
  }
12659
12715
  }
12660
12716
  }
12661
- const targetDir = directory || join10(process.cwd(), options.name || slug);
12717
+ const targetDir = directory || join11(process.cwd(), options.name || slug);
12662
12718
  try {
12663
12719
  await fs19.access(targetDir);
12664
12720
  throw new Error(`Directory already exists: ${targetDir}`);
@@ -12723,7 +12779,7 @@ function createKitCreateCommand() {
12723
12779
  );
12724
12780
  for (const filepath of expandedPaths) {
12725
12781
  console.log(` \u{1F4E5} Installing ${filepath}...`);
12726
- await componentsService.install(config, filepath, join10(targetDir, ".jai1"));
12782
+ await componentsService.install(config, filepath, join11(targetDir, ".jai1"));
12727
12783
  }
12728
12784
  console.log(" \u2713 Framework components applied");
12729
12785
  }
@@ -12803,7 +12859,7 @@ async function getAllFiles(dir) {
12803
12859
  const files = [];
12804
12860
  const entries = await fs19.readdir(dir, { withFileTypes: true });
12805
12861
  for (const entry of entries) {
12806
- const fullPath = join10(dir, entry.name);
12862
+ const fullPath = join11(dir, entry.name);
12807
12863
  if (entry.isDirectory()) {
12808
12864
  if (!entry.name.startsWith(".") && entry.name !== "node_modules") {
12809
12865
  files.push(...await getAllFiles(fullPath));
@@ -12919,20 +12975,20 @@ function createRulesListCommand() {
12919
12975
  // src/commands/rules/init.ts
12920
12976
  import { Command as Command81 } from "commander";
12921
12977
  import { promises as fs21 } from "fs";
12922
- import { join as join12 } from "path";
12978
+ import { join as join13 } from "path";
12923
12979
  import { select as select4, confirm as confirm15 } from "@inquirer/prompts";
12924
12980
 
12925
12981
  // src/services/project-config.service.ts
12926
12982
  import { promises as fs20 } from "fs";
12927
- import { join as join11 } from "path";
12983
+ import { join as join12 } from "path";
12928
12984
  var ProjectConfigService = class {
12929
12985
  projectRoot;
12930
12986
  configDir;
12931
12987
  configPath;
12932
12988
  constructor(projectRoot = process.cwd()) {
12933
12989
  this.projectRoot = projectRoot;
12934
- this.configDir = join11(this.projectRoot, ".jai1");
12935
- this.configPath = join11(this.configDir, "project.json");
12990
+ this.configDir = join12(this.projectRoot, ".jai1");
12991
+ this.configPath = join12(this.configDir, "project.json");
12936
12992
  }
12937
12993
  /**
12938
12994
  * Check if config file exists
@@ -13138,10 +13194,10 @@ function createRulesInitCommand() {
13138
13194
  });
13139
13195
  }
13140
13196
  async function applyCursorFormat(bundle) {
13141
- const rulesDir = join12(process.cwd(), ".cursor", "rules");
13197
+ const rulesDir = join13(process.cwd(), ".cursor", "rules");
13142
13198
  await fs21.mkdir(rulesDir, { recursive: true });
13143
13199
  for (const [filename, content] of Object.entries(bundle.files)) {
13144
- const filePath = join12(rulesDir, filename);
13200
+ const filePath = join13(rulesDir, filename);
13145
13201
  await fs21.writeFile(filePath, content, "utf-8");
13146
13202
  console.log(`\u2713 Created .cursor/rules/${filename}`);
13147
13203
  }
@@ -13176,7 +13232,7 @@ async function applyAgentsMdFormat(bundle) {
13176
13232
  // src/commands/rules/apply.ts
13177
13233
  import { Command as Command82 } from "commander";
13178
13234
  import { promises as fs23 } from "fs";
13179
- import { join as join14 } from "path";
13235
+ import { join as join15 } from "path";
13180
13236
  import { search, confirm as confirm16, checkbox as checkbox5 } from "@inquirer/prompts";
13181
13237
 
13182
13238
  // src/services/rules-generator.service.ts
@@ -13468,7 +13524,7 @@ Follow all instructions and patterns defined in AGENTS.md above.
13468
13524
 
13469
13525
  // src/services/backup.service.ts
13470
13526
  import { promises as fs22 } from "fs";
13471
- import { join as join13, dirname } from "path";
13527
+ import { join as join14, dirname } from "path";
13472
13528
  var BackupService = class {
13473
13529
  backupDir = ".jai1/backups";
13474
13530
  /**
@@ -13476,7 +13532,7 @@ var BackupService = class {
13476
13532
  */
13477
13533
  async createBackup(ides, presetSlug) {
13478
13534
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
13479
- const backupPath = join13(this.backupDir, timestamp);
13535
+ const backupPath = join14(this.backupDir, timestamp);
13480
13536
  const backedUpFiles = [];
13481
13537
  let hasContent = false;
13482
13538
  for (const ideId of ides) {
@@ -13485,7 +13541,7 @@ var BackupService = class {
13485
13541
  console.warn(`Unknown IDE format: ${ideId}, skipping backup`);
13486
13542
  continue;
13487
13543
  }
13488
- const rulesPath = format.rulesPath === "." ? process.cwd() : join13(process.cwd(), format.rulesPath);
13544
+ const rulesPath = format.rulesPath === "." ? process.cwd() : join14(process.cwd(), format.rulesPath);
13489
13545
  try {
13490
13546
  const exists = await this.pathExists(rulesPath);
13491
13547
  if (!exists) {
@@ -13503,14 +13559,14 @@ var BackupService = class {
13503
13559
  const files = await fs22.readdir(rulesPath);
13504
13560
  for (const file of files) {
13505
13561
  if (file.endsWith(format.fileExtension)) {
13506
- const originalPath = join13(rulesPath, file);
13507
- const relativePath = join13(format.rulesPath, file);
13508
- const destPath = join13(backupPath, ideId, file);
13562
+ const originalPath = join14(rulesPath, file);
13563
+ const relativePath = join14(format.rulesPath, file);
13564
+ const destPath = join14(backupPath, ideId, file);
13509
13565
  await fs22.mkdir(dirname(destPath), { recursive: true });
13510
13566
  await fs22.copyFile(originalPath, destPath);
13511
13567
  backedUpFiles.push({
13512
13568
  originalPath: relativePath,
13513
- backupPath: join13(ideId, file),
13569
+ backupPath: join14(ideId, file),
13514
13570
  ide: ideId
13515
13571
  });
13516
13572
  hasContent = true;
@@ -13533,7 +13589,7 @@ var BackupService = class {
13533
13589
  };
13534
13590
  await fs22.mkdir(backupPath, { recursive: true });
13535
13591
  await fs22.writeFile(
13536
- join13(backupPath, "metadata.json"),
13592
+ join14(backupPath, "metadata.json"),
13537
13593
  JSON.stringify(metadata, null, 2),
13538
13594
  "utf-8"
13539
13595
  );
@@ -13543,18 +13599,18 @@ var BackupService = class {
13543
13599
  * Backup a single file (for AGENTS.md, GEMINI.md)
13544
13600
  */
13545
13601
  async backupSingleFile(filename, backupPath, ideId, backedUpFiles) {
13546
- const originalPath = join13(process.cwd(), filename);
13602
+ const originalPath = join14(process.cwd(), filename);
13547
13603
  try {
13548
13604
  const exists = await this.pathExists(originalPath);
13549
13605
  if (!exists) {
13550
13606
  return;
13551
13607
  }
13552
- const destPath = join13(backupPath, ideId, filename);
13608
+ const destPath = join14(backupPath, ideId, filename);
13553
13609
  await fs22.mkdir(dirname(destPath), { recursive: true });
13554
13610
  await fs22.copyFile(originalPath, destPath);
13555
13611
  backedUpFiles.push({
13556
13612
  originalPath: filename,
13557
- backupPath: join13(ideId, filename),
13613
+ backupPath: join14(ideId, filename),
13558
13614
  ide: ideId
13559
13615
  });
13560
13616
  } catch (error) {
@@ -13564,14 +13620,14 @@ var BackupService = class {
13564
13620
  * Restore files from a backup
13565
13621
  */
13566
13622
  async restoreBackup(backupPath) {
13567
- const metadataPath = join13(backupPath, "metadata.json");
13623
+ const metadataPath = join14(backupPath, "metadata.json");
13568
13624
  const metadataContent = await fs22.readFile(metadataPath, "utf-8");
13569
13625
  const metadata = JSON.parse(metadataContent);
13570
13626
  console.log(`
13571
13627
  Restoring backup from ${metadata.timestamp}...`);
13572
13628
  for (const file of metadata.files) {
13573
- const sourcePath = join13(backupPath, file.backupPath);
13574
- const destPath = join13(process.cwd(), file.originalPath);
13629
+ const sourcePath = join14(backupPath, file.backupPath);
13630
+ const destPath = join14(process.cwd(), file.originalPath);
13575
13631
  await fs22.mkdir(dirname(destPath), { recursive: true });
13576
13632
  await fs22.copyFile(sourcePath, destPath);
13577
13633
  console.log(`\u2713 Restored ${file.originalPath}`);
@@ -13583,7 +13639,7 @@ Restoring backup from ${metadata.timestamp}...`);
13583
13639
  */
13584
13640
  async listBackups() {
13585
13641
  try {
13586
- const backupDirPath = join13(process.cwd(), this.backupDir);
13642
+ const backupDirPath = join14(process.cwd(), this.backupDir);
13587
13643
  const exists = await this.pathExists(backupDirPath);
13588
13644
  if (!exists) {
13589
13645
  return [];
@@ -13592,7 +13648,7 @@ Restoring backup from ${metadata.timestamp}...`);
13592
13648
  const backups = [];
13593
13649
  for (const entry of entries) {
13594
13650
  if (entry.isDirectory()) {
13595
- const metadataPath = join13(backupDirPath, entry.name, "metadata.json");
13651
+ const metadataPath = join14(backupDirPath, entry.name, "metadata.json");
13596
13652
  try {
13597
13653
  const metadataContent = await fs22.readFile(metadataPath, "utf-8");
13598
13654
  const metadata = JSON.parse(metadataContent);
@@ -13611,7 +13667,7 @@ Restoring backup from ${metadata.timestamp}...`);
13611
13667
  * Delete a specific backup
13612
13668
  */
13613
13669
  async deleteBackup(timestamp) {
13614
- const backupPath = join13(process.cwd(), this.backupDir, timestamp);
13670
+ const backupPath = join14(process.cwd(), this.backupDir, timestamp);
13615
13671
  await this.deleteDirectory(backupPath);
13616
13672
  }
13617
13673
  /**
@@ -13660,7 +13716,7 @@ Restoring backup from ${metadata.timestamp}...`);
13660
13716
  }
13661
13717
  const entries = await fs22.readdir(path13, { withFileTypes: true });
13662
13718
  for (const entry of entries) {
13663
- const fullPath = join13(path13, entry.name);
13719
+ const fullPath = join14(path13, entry.name);
13664
13720
  if (entry.isDirectory()) {
13665
13721
  await this.deleteDirectory(fullPath);
13666
13722
  } else {
@@ -13675,13 +13731,13 @@ Restoring backup from ${metadata.timestamp}...`);
13675
13731
  * Get backup directory path
13676
13732
  */
13677
13733
  getBackupDir() {
13678
- return join13(process.cwd(), this.backupDir);
13734
+ return join14(process.cwd(), this.backupDir);
13679
13735
  }
13680
13736
  /**
13681
13737
  * Ensure backup directory exists
13682
13738
  */
13683
13739
  async ensureBackupDir() {
13684
- const backupDirPath = join13(process.cwd(), this.backupDir);
13740
+ const backupDirPath = join14(process.cwd(), this.backupDir);
13685
13741
  await fs22.mkdir(backupDirPath, { recursive: true });
13686
13742
  }
13687
13743
  };
@@ -13854,20 +13910,20 @@ function createRulesApplyCommand() {
13854
13910
  }
13855
13911
  }
13856
13912
  console.log("\n\u{1F4DD} Applying preset...\n");
13857
- const rulePresetDir = join14(process.cwd(), ".jai1", "rule-preset");
13913
+ const rulePresetDir = join15(process.cwd(), ".jai1", "rule-preset");
13858
13914
  try {
13859
13915
  await fs23.rm(rulePresetDir, { recursive: true, force: true });
13860
13916
  } catch {
13861
13917
  }
13862
13918
  await fs23.mkdir(rulePresetDir, { recursive: true });
13863
13919
  await fs23.writeFile(
13864
- join14(rulePresetDir, "preset.json"),
13920
+ join15(rulePresetDir, "preset.json"),
13865
13921
  JSON.stringify(bundle.preset, null, 2),
13866
13922
  "utf-8"
13867
13923
  );
13868
13924
  for (const [filename, content] of Object.entries(bundle.files)) {
13869
- const filePath = join14(rulePresetDir, filename);
13870
- await fs23.mkdir(join14(filePath, ".."), { recursive: true });
13925
+ const filePath = join15(rulePresetDir, filename);
13926
+ await fs23.mkdir(join15(filePath, ".."), { recursive: true });
13871
13927
  await fs23.writeFile(filePath, content, "utf-8");
13872
13928
  }
13873
13929
  console.log(`\u2713 Saved preset to .jai1/rule-preset/`);
@@ -13876,8 +13932,8 @@ function createRulesApplyCommand() {
13876
13932
  try {
13877
13933
  const files = generatorService.generateForIde(bundle, ideId);
13878
13934
  for (const file of files) {
13879
- const fullPath = join14(process.cwd(), file.path);
13880
- await fs23.mkdir(join14(fullPath, ".."), { recursive: true });
13935
+ const fullPath = join15(process.cwd(), file.path);
13936
+ await fs23.mkdir(join15(fullPath, ".."), { recursive: true });
13881
13937
  await fs23.writeFile(fullPath, file.content, "utf-8");
13882
13938
  console.log(`\u2713 [${ideId}] ${file.path}`);
13883
13939
  allGeneratedFiles.push({
@@ -13984,7 +14040,7 @@ function createRulesApplyCommand() {
13984
14040
 
13985
14041
  // src/commands/rules/restore.ts
13986
14042
  import { Command as Command83 } from "commander";
13987
- import { join as join15 } from "path";
14043
+ import { join as join16 } from "path";
13988
14044
  import { select as select5, confirm as confirm17 } from "@inquirer/prompts";
13989
14045
  function createRulesRestoreCommand() {
13990
14046
  return new Command83("restore").description("Restore rules from a backup").option("--latest", "Restore the most recent backup").option("-y, --yes", "Skip confirmation").action(async (options) => {
@@ -14031,7 +14087,7 @@ function createRulesRestoreCommand() {
14031
14087
  }
14032
14088
  console.log("\n\u{1F504} Restoring backup...\n");
14033
14089
  try {
14034
- const backupPath = join15(backupService.getBackupDir(), selectedBackup.timestamp);
14090
+ const backupPath = join16(backupService.getBackupDir(), selectedBackup.timestamp);
14035
14091
  await backupService.restoreBackup(backupPath);
14036
14092
  console.log("\n\u2705 Backup restored successfully!\n");
14037
14093
  console.log("\u{1F4A1} Tip: Your IDE may need to be restarted to pick up the changes.");
@@ -14058,12 +14114,12 @@ function formatTimestamp(timestamp) {
14058
14114
  // src/commands/rules/sync.ts
14059
14115
  import { Command as Command84 } from "commander";
14060
14116
  import { promises as fs24 } from "fs";
14061
- import { join as join16 } from "path";
14117
+ import { join as join17 } from "path";
14062
14118
  import { checkbox as checkbox6, confirm as confirm18, Separator } from "@inquirer/prompts";
14063
14119
  function createRulesSyncCommand() {
14064
14120
  return new Command84("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) => {
14065
- const rulePresetDir = join16(process.cwd(), ".jai1", "rule-preset");
14066
- const presetJsonPath = join16(rulePresetDir, "preset.json");
14121
+ const rulePresetDir = join17(process.cwd(), ".jai1", "rule-preset");
14122
+ const presetJsonPath = join17(rulePresetDir, "preset.json");
14067
14123
  let presetExists = false;
14068
14124
  let presetData = null;
14069
14125
  try {
@@ -14200,7 +14256,7 @@ Current IDE(s): ${currentIdes.join(", ") || "none"}`);
14200
14256
  const files = await fs24.readdir(rulePresetDir);
14201
14257
  for (const file of files) {
14202
14258
  if (file.endsWith(".mdc") || file.endsWith(".md")) {
14203
- const filePath = join16(rulePresetDir, file);
14259
+ const filePath = join17(rulePresetDir, file);
14204
14260
  const content = await fs24.readFile(filePath, "utf-8");
14205
14261
  bundle.files[file] = content;
14206
14262
  }
@@ -14215,8 +14271,8 @@ Current IDE(s): ${currentIdes.join(", ") || "none"}`);
14215
14271
  }
14216
14272
  const files2 = generatorService.generateForIde(bundle, ideId);
14217
14273
  for (const file of files2) {
14218
- const fullPath = join16(process.cwd(), file.path);
14219
- await fs24.mkdir(join16(fullPath, ".."), { recursive: true });
14274
+ const fullPath = join17(process.cwd(), file.path);
14275
+ await fs24.mkdir(join17(fullPath, ".."), { recursive: true });
14220
14276
  await fs24.writeFile(fullPath, file.content, "utf-8");
14221
14277
  }
14222
14278
  console.log(`\u2713 ${format.name} - ${files2.length} files regenerated`);
@@ -14281,7 +14337,7 @@ function buildIdeChoices(currentIdes, detected, suggestions) {
14281
14337
  // src/commands/rules/info.ts
14282
14338
  import { Command as Command85 } from "commander";
14283
14339
  import { promises as fs25 } from "fs";
14284
- import { join as join17 } from "path";
14340
+ import { join as join18 } from "path";
14285
14341
  function createRulesInfoCommand() {
14286
14342
  return new Command85("info").description("Show current preset information").option("--json", "Output as JSON").action(async (options) => {
14287
14343
  const projectConfigService = new ProjectConfigService();
@@ -14296,8 +14352,8 @@ function createRulesInfoCommand() {
14296
14352
  return;
14297
14353
  }
14298
14354
  console.log("\u{1F4CB} Current Preset Information\n");
14299
- const rulePresetDir = join17(process.cwd(), ".jai1", "rule-preset");
14300
- const presetJsonPath = join17(rulePresetDir, "preset.json");
14355
+ const rulePresetDir = join18(process.cwd(), ".jai1", "rule-preset");
14356
+ const presetJsonPath = join18(rulePresetDir, "preset.json");
14301
14357
  let presetMetadata = null;
14302
14358
  let presetFiles = [];
14303
14359
  try {
@@ -14364,7 +14420,7 @@ Available Backups (${rulesConfig.backups.length}):`);
14364
14420
  }
14365
14421
  async function checkPathExists(path13) {
14366
14422
  try {
14367
- await fs25.access(join17(process.cwd(), path13));
14423
+ await fs25.access(join18(process.cwd(), path13));
14368
14424
  return true;
14369
14425
  } catch {
14370
14426
  return false;
@@ -14427,7 +14483,7 @@ import chalk51 from "chalk";
14427
14483
 
14428
14484
  // src/services/skills.service.ts
14429
14485
  import { promises as fs26 } from "fs";
14430
- import { join as join18 } from "path";
14486
+ import { join as join19 } from "path";
14431
14487
  import { execFile } from "child_process";
14432
14488
  import { promisify } from "util";
14433
14489
  var execFileAsync = promisify(execFile);
@@ -14463,14 +14519,14 @@ var SkillsService = class {
14463
14519
  * List locally installed skills from .jai1/skills/
14464
14520
  */
14465
14521
  async listLocal(projectRoot) {
14466
- const skillsDir = join18(projectRoot, ".jai1", "skills");
14522
+ const skillsDir = join19(projectRoot, ".jai1", "skills");
14467
14523
  const skills = [];
14468
14524
  try {
14469
14525
  const entries = await fs26.readdir(skillsDir, { withFileTypes: true });
14470
14526
  for (const entry of entries) {
14471
14527
  if (!entry.isDirectory()) continue;
14472
- const skillPath = join18(skillsDir, entry.name);
14473
- const skillMd = join18(skillPath, "SKILL.md");
14528
+ const skillPath = join19(skillsDir, entry.name);
14529
+ const skillMd = join19(skillPath, "SKILL.md");
14474
14530
  try {
14475
14531
  await fs26.access(skillMd);
14476
14532
  } catch {
@@ -14495,8 +14551,8 @@ var SkillsService = class {
14495
14551
  * Get detailed info for a single skill
14496
14552
  */
14497
14553
  async getSkillInfo(projectRoot, skillName) {
14498
- const skillPath = join18(projectRoot, ".jai1", "skills", skillName);
14499
- const skillMd = join18(skillPath, "SKILL.md");
14554
+ const skillPath = join19(projectRoot, ".jai1", "skills", skillName);
14555
+ const skillMd = join19(skillPath, "SKILL.md");
14500
14556
  try {
14501
14557
  await fs26.access(skillMd);
14502
14558
  } catch {
@@ -14571,22 +14627,22 @@ var SkillsService = class {
14571
14627
  * After npx skills add, copy newly installed skills from .agents/skills/ into .jai1/skills/
14572
14628
  */
14573
14629
  async copySkillshResultsToJai1(projectRoot, specificSkill) {
14574
- const jai1SkillsDir = join18(projectRoot, ".jai1", "skills");
14630
+ const jai1SkillsDir = join19(projectRoot, ".jai1", "skills");
14575
14631
  await fs26.mkdir(jai1SkillsDir, { recursive: true });
14576
- const universalDir = join18(projectRoot, ".agents", "skills");
14632
+ const universalDir = join19(projectRoot, ".agents", "skills");
14577
14633
  try {
14578
14634
  const entries = await fs26.readdir(universalDir, { withFileTypes: true });
14579
14635
  for (const entry of entries) {
14580
14636
  if (!entry.isDirectory()) continue;
14581
14637
  if (specificSkill && entry.name !== specificSkill) continue;
14582
- const srcSkill = join18(universalDir, entry.name);
14583
- const skillMd = join18(srcSkill, "SKILL.md");
14638
+ const srcSkill = join19(universalDir, entry.name);
14639
+ const skillMd = join19(srcSkill, "SKILL.md");
14584
14640
  try {
14585
14641
  await fs26.access(skillMd);
14586
14642
  } catch {
14587
14643
  continue;
14588
14644
  }
14589
- const targetSkill = join18(jai1SkillsDir, entry.name);
14645
+ const targetSkill = join19(jai1SkillsDir, entry.name);
14590
14646
  try {
14591
14647
  await fs26.access(targetSkill);
14592
14648
  } catch {
@@ -14625,7 +14681,7 @@ var SkillsService = class {
14625
14681
  const target = this.getIDETarget(ide);
14626
14682
  if (!target) continue;
14627
14683
  for (const skill of skillsToSync) {
14628
- const targetPath = join18(projectRoot, target.skillsPath, skill.slug);
14684
+ const targetPath = join19(projectRoot, target.skillsPath, skill.slug);
14629
14685
  try {
14630
14686
  let status = "created";
14631
14687
  try {
@@ -14689,7 +14745,7 @@ var SkillsService = class {
14689
14745
  const entries = await fs26.readdir(dirPath, { withFileTypes: true });
14690
14746
  for (const entry of entries) {
14691
14747
  if (entry.isDirectory()) {
14692
- count += await this.countFiles(join18(dirPath, entry.name));
14748
+ count += await this.countFiles(join19(dirPath, entry.name));
14693
14749
  } else {
14694
14750
  count++;
14695
14751
  }
@@ -14702,8 +14758,8 @@ var SkillsService = class {
14702
14758
  async copyDir(source, target) {
14703
14759
  const entries = await fs26.readdir(source, { withFileTypes: true });
14704
14760
  for (const entry of entries) {
14705
- const srcPath = join18(source, entry.name);
14706
- const tgtPath = join18(target, entry.name);
14761
+ const srcPath = join19(source, entry.name);
14762
+ const tgtPath = join19(target, entry.name);
14707
14763
  if (entry.isDirectory()) {
14708
14764
  await fs26.mkdir(tgtPath, { recursive: true });
14709
14765
  await this.copyDir(srcPath, tgtPath);
@@ -14777,7 +14833,7 @@ function createSkillsFindCommand() {
14777
14833
 
14778
14834
  // src/commands/skills/add.ts
14779
14835
  import { Command as Command88 } from "commander";
14780
- import { join as join19 } from "path";
14836
+ import { join as join20 } from "path";
14781
14837
  import chalk52 from "chalk";
14782
14838
  import { checkbox as checkbox7 } from "@inquirer/prompts";
14783
14839
  function createSkillsAddCommand() {
@@ -14799,7 +14855,7 @@ function createSkillsAddCommand() {
14799
14855
  }
14800
14856
  console.log(chalk52.cyan(`\u{1F4E6} \u0110ang c\xE0i \u0111\u1EB7t skill: ${name}...`));
14801
14857
  console.log();
14802
- const targetDir = join19(projectRoot, ".jai1");
14858
+ const targetDir = join20(projectRoot, ".jai1");
14803
14859
  await skillsService.installFromServer(config, name, targetDir);
14804
14860
  console.log(chalk52.green(`\u2705 \u0110\xE3 c\xE0i \u0111\u1EB7t skill "${name}" v\xE0o .jai1/skills/${name}/`));
14805
14861
  }
@@ -15289,8 +15345,8 @@ function getInstallCommand(packageManager2) {
15289
15345
  import { Command as Command94 } from "commander";
15290
15346
  import { confirm as confirm22, select as select6 } from "@inquirer/prompts";
15291
15347
  import { promises as fs27 } from "fs";
15292
- import { join as join20 } from "path";
15293
- import { existsSync as existsSync4 } from "fs";
15348
+ import { join as join21 } from "path";
15349
+ import { existsSync as existsSync5 } from "fs";
15294
15350
  function createCleanCommand() {
15295
15351
  return new Command94("clean").description("Clean up backups, cache, IDE configs, and .jai1 directory").option("-y, --yes", "Skip confirmation").option("--backups", "Clean only backup files").option("--jai1", "Clean only .jai1/ directory").option("--ide", "Clean only IDE directories (.cursor, .windsurf, .agent, .claude, .opencode)").option("--all", "Clean all (backups + .jai1 + IDE dirs)").action(async (options) => {
15296
15352
  await handleClean(options);
@@ -15303,7 +15359,7 @@ async function handleClean(options) {
15303
15359
  {
15304
15360
  name: "Backups",
15305
15361
  description: "Component backup files (.jai1_backup/)",
15306
- path: join20(cwd, ".jai1_backup"),
15362
+ path: join21(cwd, ".jai1_backup"),
15307
15363
  check: async () => {
15308
15364
  const backups = await service.listBackups(cwd);
15309
15365
  return { exists: backups.length > 0, count: backups.length };
@@ -15315,13 +15371,13 @@ async function handleClean(options) {
15315
15371
  {
15316
15372
  name: "Jai1 Config",
15317
15373
  description: "Jai1 framework config (.jai1/)",
15318
- path: join20(cwd, ".jai1"),
15374
+ path: join21(cwd, ".jai1"),
15319
15375
  check: async () => {
15320
- const exists = existsSync4(join20(cwd, ".jai1"));
15376
+ const exists = existsSync5(join21(cwd, ".jai1"));
15321
15377
  return { exists };
15322
15378
  },
15323
15379
  clean: async () => {
15324
- await fs27.rm(join20(cwd, ".jai1"), { recursive: true, force: true });
15380
+ await fs27.rm(join21(cwd, ".jai1"), { recursive: true, force: true });
15325
15381
  }
15326
15382
  }
15327
15383
  ];
@@ -15333,8 +15389,8 @@ async function handleClean(options) {
15333
15389
  { name: "OpenCode", dir: ".opencode" }
15334
15390
  ];
15335
15391
  for (const ide of ideDirectories) {
15336
- const idePath = join20(cwd, ide.dir);
15337
- if (existsSync4(idePath)) {
15392
+ const idePath = join21(cwd, ide.dir);
15393
+ if (existsSync5(idePath)) {
15338
15394
  targets.push({
15339
15395
  name: `IDE: ${ide.name}`,
15340
15396
  description: `${ide.name} IDE config (${ide.dir}/)`,
@@ -16342,7 +16398,7 @@ async function handleSyncProject(options) {
16342
16398
  // src/commands/framework/info.ts
16343
16399
  import { Command as Command98 } from "commander";
16344
16400
  import { promises as fs28 } from "fs";
16345
- import { join as join21 } from "path";
16401
+ import { join as join22 } from "path";
16346
16402
  import { homedir as homedir4 } from "os";
16347
16403
  function createInfoCommand() {
16348
16404
  const cmd = new Command98("info").description("Show client configuration and status").option("--json", "Output as JSON").option("--verbose", "Show detailed information").action(async (options) => {
@@ -16356,7 +16412,7 @@ async function handleInfo(options) {
16356
16412
  if (!config) {
16357
16413
  throw new ValidationError(`Not initialized. Run "${getCliName()} auth" first.`);
16358
16414
  }
16359
- const frameworkPath = join21(homedir4(), ".jai1", "framework");
16415
+ const frameworkPath = join22(homedir4(), ".jai1", "framework");
16360
16416
  const projectStatus = await getProjectStatus2();
16361
16417
  const info = {
16362
16418
  configPath: configService.getConfigPath(),
@@ -16391,7 +16447,7 @@ function maskKey4(key) {
16391
16447
  return "****" + key.slice(-4);
16392
16448
  }
16393
16449
  async function getProjectStatus2() {
16394
- const projectJai1 = join21(process.cwd(), ".jai1");
16450
+ const projectJai1 = join22(process.cwd(), ".jai1");
16395
16451
  try {
16396
16452
  await fs28.access(projectJai1);
16397
16453
  return { exists: true, version: "Synced" };
@@ -16585,7 +16641,7 @@ import { Command as Command101 } from "commander";
16585
16641
  import { checkbox as checkbox9, confirm as confirm25, select as select7 } from "@inquirer/prompts";
16586
16642
  import fs29 from "fs/promises";
16587
16643
  import path12 from "path";
16588
- import { existsSync as existsSync5 } from "fs";
16644
+ import { existsSync as existsSync6 } from "fs";
16589
16645
  var PERFORMANCE_GROUPS2 = {
16590
16646
  telemetry: {
16591
16647
  name: "Telemetry",
@@ -16815,12 +16871,12 @@ async function applyGroups2(groupKeys, action) {
16815
16871
  console.log(' \u{1F4A1} Ch\u1EA1y "jai1 vscode list" \u0111\u1EC3 xem danh s\xE1ch nh\xF3m c\xF3 s\u1EB5n.');
16816
16872
  return;
16817
16873
  }
16818
- if (!existsSync5(vscodeDir)) {
16874
+ if (!existsSync6(vscodeDir)) {
16819
16875
  await fs29.mkdir(vscodeDir, { recursive: true });
16820
16876
  console.log("\u{1F4C1} \u0110\xE3 t\u1EA1o th\u01B0 m\u1EE5c .vscode/");
16821
16877
  }
16822
16878
  let currentSettings = {};
16823
- if (existsSync5(settingsPath)) {
16879
+ if (existsSync6(settingsPath)) {
16824
16880
  try {
16825
16881
  const content = await fs29.readFile(settingsPath, "utf-8");
16826
16882
  currentSettings = JSON.parse(content);
@@ -16870,7 +16926,7 @@ async function applyGroups2(groupKeys, action) {
16870
16926
  async function resetSettings2(groupKeys) {
16871
16927
  const vscodeDir = path12.join(process.cwd(), ".vscode");
16872
16928
  const settingsPath = path12.join(vscodeDir, "settings.json");
16873
- if (!existsSync5(settingsPath)) {
16929
+ if (!existsSync6(settingsPath)) {
16874
16930
  console.log("\n\u26A0\uFE0F Kh\xF4ng t\xECm th\u1EA5y file settings.json");
16875
16931
  return;
16876
16932
  }