@jvittechs/jai1-cli 0.1.100 → 0.1.102

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
@@ -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.100",
36
+ version: "0.1.102",
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: {
@@ -88,6 +88,7 @@ var package_default = {
88
88
  cronstrue: "^2.50.0",
89
89
  execa: "^9.6.1",
90
90
  "gray-matter": "^4.0.3",
91
+ ignore: "^7.0.5",
91
92
  ink: "^5.0.1",
92
93
  "ink-spinner": "^5.0.0",
93
94
  "ink-text-input": "^6.0.0",
@@ -3389,9 +3390,9 @@ var IdeDetectionService = class {
3389
3390
  /**
3390
3391
  * Check if a path exists
3391
3392
  */
3392
- async pathExists(path9) {
3393
+ async pathExists(path10) {
3393
3394
  try {
3394
- await fs7.access(path9);
3395
+ await fs7.access(path10);
3395
3396
  return true;
3396
3397
  } catch {
3397
3398
  return false;
@@ -5113,8 +5114,8 @@ var ChatApp = ({ service, initialModel }) => {
5113
5114
 
5114
5115
  // src/server/web-chat-server.ts
5115
5116
  import http from "http";
5116
- import fs8 from "fs";
5117
- import path4 from "path";
5117
+ import fs9 from "fs";
5118
+ import path5 from "path";
5118
5119
  import { fileURLToPath } from "url";
5119
5120
 
5120
5121
  // src/server/session.ts
@@ -5246,9 +5247,363 @@ var SessionManager = class {
5246
5247
  }
5247
5248
  };
5248
5249
 
5250
+ // src/server/file-service.ts
5251
+ import fs8 from "fs";
5252
+ import path4 from "path";
5253
+ import ignore from "ignore";
5254
+ var ALWAYS_EXCLUDED = [
5255
+ "node_modules",
5256
+ "vendor",
5257
+ ".git",
5258
+ ".env",
5259
+ ".env.*",
5260
+ ".env.local",
5261
+ ".env.*.local",
5262
+ "dist",
5263
+ "build",
5264
+ ".next",
5265
+ ".nuxt",
5266
+ ".output",
5267
+ ".cache",
5268
+ "*.lock",
5269
+ "package-lock.json",
5270
+ "pnpm-lock.yaml",
5271
+ "yarn.lock",
5272
+ "composer.lock",
5273
+ ".DS_Store",
5274
+ "Thumbs.db",
5275
+ "*.log",
5276
+ "*.tmp",
5277
+ "*.temp",
5278
+ ".idea",
5279
+ ".vscode",
5280
+ "*.min.js",
5281
+ "*.min.css",
5282
+ "*.map",
5283
+ "coverage",
5284
+ ".nyc_output",
5285
+ "__pycache__",
5286
+ "*.pyc",
5287
+ ".pytest_cache",
5288
+ ".mypy_cache"
5289
+ ];
5290
+ var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
5291
+ // Web
5292
+ ".html",
5293
+ ".htm",
5294
+ ".css",
5295
+ ".scss",
5296
+ ".sass",
5297
+ ".less",
5298
+ ".js",
5299
+ ".jsx",
5300
+ ".ts",
5301
+ ".tsx",
5302
+ ".mjs",
5303
+ ".cjs",
5304
+ ".vue",
5305
+ ".svelte",
5306
+ ".astro",
5307
+ // Data
5308
+ ".json",
5309
+ ".yaml",
5310
+ ".yml",
5311
+ ".toml",
5312
+ ".xml",
5313
+ ".csv",
5314
+ // Docs
5315
+ ".md",
5316
+ ".mdx",
5317
+ ".txt",
5318
+ ".rst",
5319
+ ".adoc",
5320
+ // Config
5321
+ ".env.example",
5322
+ ".gitignore",
5323
+ ".dockerignore",
5324
+ ".npmrc",
5325
+ ".nvmrc",
5326
+ ".editorconfig",
5327
+ ".prettierrc",
5328
+ ".eslintrc",
5329
+ ".babelrc",
5330
+ // Server
5331
+ ".php",
5332
+ ".py",
5333
+ ".rb",
5334
+ ".go",
5335
+ ".java",
5336
+ ".kt",
5337
+ ".scala",
5338
+ ".rs",
5339
+ ".swift",
5340
+ ".c",
5341
+ ".cpp",
5342
+ ".h",
5343
+ ".hpp",
5344
+ ".cs",
5345
+ // Shell
5346
+ ".sh",
5347
+ ".bash",
5348
+ ".zsh",
5349
+ ".fish",
5350
+ ".ps1",
5351
+ ".bat",
5352
+ ".cmd",
5353
+ // Database
5354
+ ".sql",
5355
+ ".prisma",
5356
+ ".graphql",
5357
+ ".gql",
5358
+ // Other
5359
+ ".dockerfile",
5360
+ ".makefile",
5361
+ ".rake",
5362
+ ".gradle"
5363
+ ]);
5364
+ var TEXT_FILES = /* @__PURE__ */ new Set([
5365
+ "Makefile",
5366
+ "Dockerfile",
5367
+ "Vagrantfile",
5368
+ "Gemfile",
5369
+ "Rakefile",
5370
+ "Procfile",
5371
+ "Brewfile",
5372
+ ".gitignore",
5373
+ ".dockerignore",
5374
+ ".npmrc",
5375
+ ".nvmrc",
5376
+ ".env.example",
5377
+ "LICENSE",
5378
+ "README",
5379
+ "CHANGELOG",
5380
+ "CONTRIBUTING",
5381
+ "AUTHORS",
5382
+ "CODEOWNERS"
5383
+ ]);
5384
+ function getLanguage(filePath) {
5385
+ const ext = path4.extname(filePath).toLowerCase();
5386
+ const langMap = {
5387
+ ".ts": "typescript",
5388
+ ".tsx": "typescript",
5389
+ ".js": "javascript",
5390
+ ".jsx": "javascript",
5391
+ ".mjs": "javascript",
5392
+ ".cjs": "javascript",
5393
+ ".py": "python",
5394
+ ".rb": "ruby",
5395
+ ".php": "php",
5396
+ ".java": "java",
5397
+ ".kt": "kotlin",
5398
+ ".go": "go",
5399
+ ".rs": "rust",
5400
+ ".swift": "swift",
5401
+ ".c": "c",
5402
+ ".h": "c",
5403
+ ".cpp": "cpp",
5404
+ ".hpp": "cpp",
5405
+ ".cs": "csharp",
5406
+ ".css": "css",
5407
+ ".scss": "scss",
5408
+ ".sass": "sass",
5409
+ ".less": "less",
5410
+ ".html": "html",
5411
+ ".htm": "html",
5412
+ ".vue": "vue",
5413
+ ".svelte": "svelte",
5414
+ ".json": "json",
5415
+ ".yaml": "yaml",
5416
+ ".yml": "yaml",
5417
+ ".xml": "xml",
5418
+ ".md": "markdown",
5419
+ ".mdx": "markdown",
5420
+ ".sql": "sql",
5421
+ ".graphql": "graphql",
5422
+ ".gql": "graphql",
5423
+ ".sh": "bash",
5424
+ ".bash": "bash",
5425
+ ".zsh": "bash",
5426
+ ".dockerfile": "dockerfile",
5427
+ ".prisma": "prisma"
5428
+ };
5429
+ return langMap[ext] || "text";
5430
+ }
5431
+ function isTextFile(filePath) {
5432
+ const ext = path4.extname(filePath).toLowerCase();
5433
+ const name = path4.basename(filePath);
5434
+ if (TEXT_FILES.has(name)) return true;
5435
+ if (ext && TEXT_EXTENSIONS.has(ext)) return true;
5436
+ if (name.endsWith("rc") || name.endsWith("config")) return true;
5437
+ return false;
5438
+ }
5439
+ var FileService = class {
5440
+ workingDir;
5441
+ maxFileSize;
5442
+ maxFilesPerRequest;
5443
+ maxSearchResults;
5444
+ ignoreFilter;
5445
+ constructor(options) {
5446
+ this.workingDir = path4.resolve(options.workingDir);
5447
+ this.maxFileSize = options.maxFileSize ?? 1024 * 1024;
5448
+ this.maxFilesPerRequest = options.maxFilesPerRequest ?? 5;
5449
+ this.maxSearchResults = options.maxSearchResults ?? 20;
5450
+ this.ignoreFilter = ignore();
5451
+ this.loadIgnorePatterns();
5452
+ }
5453
+ /**
5454
+ * Load ignore patterns from .gitignore and add always-excluded patterns
5455
+ */
5456
+ loadIgnorePatterns() {
5457
+ this.ignoreFilter.add(ALWAYS_EXCLUDED);
5458
+ const gitignorePath = path4.join(this.workingDir, ".gitignore");
5459
+ try {
5460
+ if (fs8.existsSync(gitignorePath)) {
5461
+ const content = fs8.readFileSync(gitignorePath, "utf-8");
5462
+ this.ignoreFilter.add(content);
5463
+ }
5464
+ } catch {
5465
+ }
5466
+ }
5467
+ /**
5468
+ * Check if a path should be ignored
5469
+ */
5470
+ isIgnored(relativePath) {
5471
+ const normalizedPath = relativePath.replace(/\\/g, "/");
5472
+ return this.ignoreFilter.ignores(normalizedPath);
5473
+ }
5474
+ /**
5475
+ * Validate path is within working directory (prevent path traversal)
5476
+ */
5477
+ validatePath(relativePath) {
5478
+ const cleanPath = relativePath.replace(/^\/+/, "");
5479
+ const absolutePath = path4.resolve(this.workingDir, cleanPath);
5480
+ if (!absolutePath.startsWith(this.workingDir + path4.sep) && absolutePath !== this.workingDir) {
5481
+ throw new Error("Path traversal detected");
5482
+ }
5483
+ return absolutePath;
5484
+ }
5485
+ /**
5486
+ * Get relative path from working directory
5487
+ */
5488
+ getRelativePath(absolutePath) {
5489
+ return path4.relative(this.workingDir, absolutePath);
5490
+ }
5491
+ /**
5492
+ * Search files matching a query (for autocomplete)
5493
+ * Returns files where path contains the query string
5494
+ */
5495
+ async searchFiles(query, limit) {
5496
+ const maxResults = Math.min(limit ?? this.maxSearchResults, 50);
5497
+ const results = [];
5498
+ const normalizedQuery = query.toLowerCase().replace(/\\/g, "/");
5499
+ const searchDir = async (dirPath, depth = 0) => {
5500
+ if (depth > 10 || results.length >= maxResults) return;
5501
+ try {
5502
+ const entries = await fs8.promises.readdir(dirPath, { withFileTypes: true });
5503
+ for (const entry of entries) {
5504
+ if (results.length >= maxResults) break;
5505
+ const entryPath = path4.join(dirPath, entry.name);
5506
+ const relativePath = this.getRelativePath(entryPath);
5507
+ if (this.isIgnored(relativePath)) continue;
5508
+ const normalizedRelPath = relativePath.toLowerCase().replace(/\\/g, "/");
5509
+ if (normalizedRelPath.includes(normalizedQuery)) {
5510
+ if (entry.isFile() && isTextFile(entry.name)) {
5511
+ try {
5512
+ const stat = await fs8.promises.stat(entryPath);
5513
+ results.push({
5514
+ path: relativePath,
5515
+ name: entry.name,
5516
+ size: stat.size,
5517
+ type: "file",
5518
+ extension: path4.extname(entry.name).slice(1) || void 0
5519
+ });
5520
+ } catch {
5521
+ }
5522
+ }
5523
+ }
5524
+ if (entry.isDirectory()) {
5525
+ await searchDir(entryPath, depth + 1);
5526
+ }
5527
+ }
5528
+ } catch {
5529
+ }
5530
+ };
5531
+ await searchDir(this.workingDir);
5532
+ results.sort((a, b) => {
5533
+ if (a.path.length !== b.path.length) {
5534
+ return a.path.length - b.path.length;
5535
+ }
5536
+ return a.path.localeCompare(b.path);
5537
+ });
5538
+ return results;
5539
+ }
5540
+ /**
5541
+ * Read a single file
5542
+ */
5543
+ async readFile(relativePath) {
5544
+ const absolutePath = this.validatePath(relativePath);
5545
+ const normalizedRelPath = this.getRelativePath(absolutePath);
5546
+ if (this.isIgnored(normalizedRelPath)) {
5547
+ throw new Error("File is excluded by ignore rules");
5548
+ }
5549
+ if (!isTextFile(absolutePath)) {
5550
+ throw new Error("Only text files can be read");
5551
+ }
5552
+ const stat = await fs8.promises.stat(absolutePath);
5553
+ if (!stat.isFile()) {
5554
+ throw new Error("Path is not a file");
5555
+ }
5556
+ if (stat.size > this.maxFileSize) {
5557
+ throw new Error(`File exceeds maximum size of ${Math.round(this.maxFileSize / 1024)}KB`);
5558
+ }
5559
+ const content = await fs8.promises.readFile(absolutePath, "utf-8");
5560
+ return {
5561
+ path: normalizedRelPath,
5562
+ content,
5563
+ size: stat.size,
5564
+ language: getLanguage(absolutePath)
5565
+ };
5566
+ }
5567
+ /**
5568
+ * Read multiple files (batch)
5569
+ */
5570
+ async readFiles(relativePaths) {
5571
+ const paths = relativePaths.slice(0, this.maxFilesPerRequest);
5572
+ const results = await Promise.all(
5573
+ paths.map(async (filePath) => {
5574
+ try {
5575
+ const content = await this.readFile(filePath);
5576
+ return content;
5577
+ } catch (error) {
5578
+ return {
5579
+ path: filePath,
5580
+ content: "",
5581
+ size: 0,
5582
+ language: "text",
5583
+ error: error instanceof Error ? error.message : "Unknown error"
5584
+ };
5585
+ }
5586
+ })
5587
+ );
5588
+ return results;
5589
+ }
5590
+ /**
5591
+ * Get working directory info
5592
+ */
5593
+ getWorkingDir() {
5594
+ return this.workingDir;
5595
+ }
5596
+ /**
5597
+ * Get max files per request limit
5598
+ */
5599
+ getMaxFilesLimit() {
5600
+ return this.maxFilesPerRequest;
5601
+ }
5602
+ };
5603
+
5249
5604
  // src/server/web-chat-server.ts
5250
5605
  var __filename = fileURLToPath(import.meta.url);
5251
- var __dirname = path4.dirname(__filename);
5606
+ var __dirname = path5.dirname(__filename);
5252
5607
  var MIME_TYPES = {
5253
5608
  ".html": "text/html",
5254
5609
  ".css": "text/css",
@@ -5322,22 +5677,23 @@ function createWebChatServer(options) {
5322
5677
  const sessionManager = new SessionManager();
5323
5678
  let server = null;
5324
5679
  let session = null;
5325
- const staticDir = path4.join(__dirname, "web-chat");
5680
+ const fileService = new FileService({ workingDir: process.cwd() });
5681
+ const staticDir = path5.join(__dirname, "web-chat");
5326
5682
  async function serveStaticFile(res, filePath) {
5327
- const fullPath = path4.join(staticDir, filePath);
5683
+ const fullPath = path5.join(staticDir, filePath);
5328
5684
  if (!fullPath.startsWith(staticDir)) {
5329
5685
  sendError(res, 403, "ERR-WC-006", "Forbidden");
5330
5686
  return;
5331
5687
  }
5332
5688
  try {
5333
- const stat = await fs8.promises.stat(fullPath);
5689
+ const stat = await fs9.promises.stat(fullPath);
5334
5690
  if (!stat.isFile()) {
5335
5691
  sendError(res, 404, "ERR-WC-007", "Not found");
5336
5692
  return;
5337
5693
  }
5338
- const ext = path4.extname(fullPath);
5694
+ const ext = path5.extname(fullPath);
5339
5695
  const contentType = MIME_TYPES[ext] || "application/octet-stream";
5340
- const content = await fs8.promises.readFile(fullPath);
5696
+ const content = await fs9.promises.readFile(fullPath);
5341
5697
  res.writeHead(200, { "Content-Type": contentType });
5342
5698
  res.end(content);
5343
5699
  } catch (error) {
@@ -5440,6 +5796,83 @@ function createWebChatServer(options) {
5440
5796
  }
5441
5797
  return;
5442
5798
  }
5799
+ if (pathname === "/api/files/search" && req.method === "GET") {
5800
+ try {
5801
+ const url = new URL(req.url || "/", `http://${req.headers.host}`);
5802
+ const query = url.searchParams.get("q") || "";
5803
+ const limit = parseInt(url.searchParams.get("limit") || "10", 10);
5804
+ if (!query || query.length < 1) {
5805
+ sendJson(res, 200, { success: true, data: { files: [] } });
5806
+ return;
5807
+ }
5808
+ const files = await fileService.searchFiles(query, Math.min(limit, 20));
5809
+ sendJson(res, 200, {
5810
+ success: true,
5811
+ data: { files }
5812
+ });
5813
+ } catch (error) {
5814
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
5815
+ sendError(res, 500, "ERR-WC-011", `File search failed: ${errorMessage}`);
5816
+ }
5817
+ return;
5818
+ }
5819
+ if (pathname === "/api/files/read" && req.method === "GET") {
5820
+ try {
5821
+ const url = new URL(req.url || "/", `http://${req.headers.host}`);
5822
+ const filePath = url.searchParams.get("path");
5823
+ if (!filePath) {
5824
+ sendError(res, 400, "ERR-WC-012", "Missing file path");
5825
+ return;
5826
+ }
5827
+ const fileContent = await fileService.readFile(filePath);
5828
+ sendJson(res, 200, {
5829
+ success: true,
5830
+ data: fileContent
5831
+ });
5832
+ } catch (error) {
5833
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
5834
+ if (errorMessage.includes("Path traversal")) {
5835
+ sendError(res, 403, "ERR-WC-013", "Access denied");
5836
+ } else if (errorMessage.includes("ENOENT")) {
5837
+ sendError(res, 404, "ERR-WC-014", "File not found");
5838
+ } else {
5839
+ sendError(res, 400, "ERR-WC-015", errorMessage);
5840
+ }
5841
+ }
5842
+ return;
5843
+ }
5844
+ if (pathname === "/api/files/batch" && req.method === "POST") {
5845
+ try {
5846
+ const body = await parseJsonBody(req);
5847
+ if (!body.paths || !Array.isArray(body.paths) || body.paths.length === 0) {
5848
+ sendError(res, 400, "ERR-WC-016", "Missing or invalid paths array");
5849
+ return;
5850
+ }
5851
+ if (body.paths.length > fileService.getMaxFilesLimit()) {
5852
+ sendError(res, 400, "ERR-WC-017", `Maximum ${fileService.getMaxFilesLimit()} files allowed per request`);
5853
+ return;
5854
+ }
5855
+ const files = await fileService.readFiles(body.paths);
5856
+ sendJson(res, 200, {
5857
+ success: true,
5858
+ data: { files }
5859
+ });
5860
+ } catch (error) {
5861
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
5862
+ sendError(res, 500, "ERR-WC-018", `Batch read failed: ${errorMessage}`);
5863
+ }
5864
+ return;
5865
+ }
5866
+ if (pathname === "/api/files/info" && req.method === "GET") {
5867
+ sendJson(res, 200, {
5868
+ success: true,
5869
+ data: {
5870
+ workingDir: fileService.getWorkingDir(),
5871
+ maxFiles: fileService.getMaxFilesLimit()
5872
+ }
5873
+ });
5874
+ return;
5875
+ }
5443
5876
  if (pathname === "/api/chat" && req.method === "POST") {
5444
5877
  try {
5445
5878
  const body = await parseJsonBody(req);
@@ -5793,8 +6226,8 @@ function createStatsCommand() {
5793
6226
  import { Command as Command15 } from "commander";
5794
6227
 
5795
6228
  // src/services/translation.service.ts
5796
- import { promises as fs9 } from "fs";
5797
- import path5 from "path";
6229
+ import { promises as fs10 } from "fs";
6230
+ import path6 from "path";
5798
6231
  import pLimit from "p-limit";
5799
6232
  import pRetry from "p-retry";
5800
6233
  var TRANSLATABLE_EXTS = [".md", ".txt", ".json", ".yaml", ".yml"];
@@ -5812,7 +6245,7 @@ var TranslationService = class {
5812
6245
  */
5813
6246
  async detectInputType(input5) {
5814
6247
  try {
5815
- const stat = await fs9.stat(input5);
6248
+ const stat = await fs10.stat(input5);
5816
6249
  if (stat.isDirectory()) return "folder";
5817
6250
  if (stat.isFile()) return "file";
5818
6251
  } catch {
@@ -5849,13 +6282,13 @@ var TranslationService = class {
5849
6282
  */
5850
6283
  async translateFile(filePath) {
5851
6284
  try {
5852
- const content = await fs9.readFile(filePath, "utf-8");
5853
- const ext = path5.extname(filePath).toLowerCase();
6285
+ const content = await fs10.readFile(filePath, "utf-8");
6286
+ const ext = path6.extname(filePath).toLowerCase();
5854
6287
  const fileType = this.getFileType(ext);
5855
6288
  const translatedContent = await this.translateWithRetry(content, fileType);
5856
6289
  const outputPath = this.generateOutputPath(filePath);
5857
6290
  if (!this.options.dryRun) {
5858
- await fs9.writeFile(outputPath, translatedContent, "utf-8");
6291
+ await fs10.writeFile(outputPath, translatedContent, "utf-8");
5859
6292
  }
5860
6293
  return {
5861
6294
  inputPath: filePath,
@@ -5910,27 +6343,27 @@ var TranslationService = class {
5910
6343
  if (this.options.output) {
5911
6344
  return this.options.output;
5912
6345
  }
5913
- const ext = path5.extname(inputPath);
5914
- const base = path5.basename(inputPath, ext);
5915
- const dir = path5.dirname(inputPath);
6346
+ const ext = path6.extname(inputPath);
6347
+ const base = path6.basename(inputPath, ext);
6348
+ const dir = path6.dirname(inputPath);
5916
6349
  const lang = this.options.to;
5917
- return path5.join(dir, `${base}.${lang}${ext}`);
6350
+ return path6.join(dir, `${base}.${lang}${ext}`);
5918
6351
  }
5919
6352
  /**
5920
6353
  * Discover translatable files in folder recursively
5921
6354
  */
5922
6355
  async discoverFiles(folderPath) {
5923
- const entries = await fs9.readdir(folderPath, { withFileTypes: true });
6356
+ const entries = await fs10.readdir(folderPath, { withFileTypes: true });
5924
6357
  const files = [];
5925
6358
  for (const entry of entries) {
5926
- const fullPath = path5.join(folderPath, entry.name);
6359
+ const fullPath = path6.join(folderPath, entry.name);
5927
6360
  if (entry.isDirectory()) {
5928
6361
  if (!entry.name.startsWith(".") && entry.name !== "node_modules") {
5929
6362
  const subFiles = await this.discoverFiles(fullPath);
5930
6363
  files.push(...subFiles);
5931
6364
  }
5932
6365
  } else if (entry.isFile()) {
5933
- const ext = path5.extname(entry.name).toLowerCase();
6366
+ const ext = path6.extname(entry.name).toLowerCase();
5934
6367
  if (TRANSLATABLE_EXTS.includes(ext)) {
5935
6368
  if (!this.isTranslatedFile(entry.name)) {
5936
6369
  files.push(fullPath);
@@ -6432,7 +6865,7 @@ function createImageCommand() {
6432
6865
  import { Command as Command21 } from "commander";
6433
6866
  import { select as select2, input, confirm as confirm5 } from "@inquirer/prompts";
6434
6867
  import os from "os";
6435
- import { promises as fs10 } from "fs";
6868
+ import { promises as fs11 } from "fs";
6436
6869
  import { join as join5 } from "path";
6437
6870
  async function collectContext() {
6438
6871
  const context = {
@@ -6440,12 +6873,12 @@ async function collectContext() {
6440
6873
  };
6441
6874
  try {
6442
6875
  const packageJsonPath = new URL("../../package.json", import.meta.url);
6443
- const packageJson = JSON.parse(await fs10.readFile(packageJsonPath, "utf-8"));
6876
+ const packageJson = JSON.parse(await fs11.readFile(packageJsonPath, "utf-8"));
6444
6877
  context.cli_version = packageJson.version;
6445
6878
  } catch {
6446
6879
  }
6447
6880
  try {
6448
- const projectPackageJson = await fs10.readFile(join5(process.cwd(), "package.json"), "utf-8");
6881
+ const projectPackageJson = await fs11.readFile(join5(process.cwd(), "package.json"), "utf-8");
6449
6882
  const projectData = JSON.parse(projectPackageJson);
6450
6883
  context.project_name = projectData.name;
6451
6884
  } catch {
@@ -6516,11 +6949,7 @@ async function handleInteractiveFeedback(config) {
6516
6949
  return true;
6517
6950
  }
6518
6951
  });
6519
- const includeContext = await confirm5({
6520
- message: "Include system context (OS, CLI version)?",
6521
- default: true
6522
- });
6523
- const context = includeContext ? await collectContext() : void 0;
6952
+ const context = await collectContext();
6524
6953
  console.log("\n\u{1F4CB} Summary:\n");
6525
6954
  console.log(`Type: ${type}`);
6526
6955
  console.log(`Title: ${title}`);
@@ -8701,8 +9130,8 @@ var HttpView = () => {
8701
9130
  import React37, { useState as useState24 } from "react";
8702
9131
  import { Box as Box27, Text as Text28, useInput as useInput22 } from "ink";
8703
9132
  import TextInput14 from "ink-text-input";
8704
- import * as fs11 from "fs";
8705
- import * as path6 from "path";
9133
+ import * as fs12 from "fs";
9134
+ import * as path7 from "path";
8706
9135
  var MarkdownView = () => {
8707
9136
  const [filePath, setFilePath] = useState24("");
8708
9137
  const [content, setContent] = useState24("");
@@ -8722,12 +9151,12 @@ var MarkdownView = () => {
8722
9151
  }
8723
9152
  try {
8724
9153
  setError("");
8725
- const resolvedPath = path6.resolve(filePath);
8726
- if (!fs11.existsSync(resolvedPath)) {
9154
+ const resolvedPath = path7.resolve(filePath);
9155
+ if (!fs12.existsSync(resolvedPath)) {
8727
9156
  setError(`File not found: ${resolvedPath}`);
8728
9157
  return;
8729
9158
  }
8730
- let fileContent = fs11.readFileSync(resolvedPath, "utf-8");
9159
+ let fileContent = fs12.readFileSync(resolvedPath, "utf-8");
8731
9160
  fileContent = fileContent.replace(/```mermaid\n([\s\S]*?)```/g, (match, code) => {
8732
9161
  return `
8733
9162
  \u{1F3A8} **Mermaid Diagram**
@@ -9008,8 +9437,8 @@ import { Command as Command36 } from "commander";
9008
9437
  import { checkbox as checkbox3, confirm as confirm6 } from "@inquirer/prompts";
9009
9438
 
9010
9439
  // src/services/deps.service.ts
9011
- import { promises as fs12 } from "fs";
9012
- import path7 from "path";
9440
+ import { promises as fs13 } from "fs";
9441
+ import path8 from "path";
9013
9442
  import { execSync } from "child_process";
9014
9443
  import pLimit2 from "p-limit";
9015
9444
  var DepsService = class {
@@ -9018,9 +9447,9 @@ var DepsService = class {
9018
9447
  * Đọc package.json từ thư mục
9019
9448
  */
9020
9449
  async readPackageJson(cwd) {
9021
- const pkgPath = path7.join(cwd, "package.json");
9450
+ const pkgPath = path8.join(cwd, "package.json");
9022
9451
  try {
9023
- const content = await fs12.readFile(pkgPath, "utf-8");
9452
+ const content = await fs13.readFile(pkgPath, "utf-8");
9024
9453
  return JSON.parse(content);
9025
9454
  } catch (error) {
9026
9455
  if (error.code === "ENOENT") {
@@ -9126,7 +9555,7 @@ var DepsService = class {
9126
9555
  ];
9127
9556
  for (const { file, pm } of lockFiles) {
9128
9557
  try {
9129
- await fs12.access(path7.join(cwd, file));
9558
+ await fs13.access(path8.join(cwd, file));
9130
9559
  return pm;
9131
9560
  } catch {
9132
9561
  }
@@ -9410,7 +9839,7 @@ import { Command as Command41 } from "commander";
9410
9839
  import { Command as Command38 } from "commander";
9411
9840
 
9412
9841
  // src/services/starter-kit.service.ts
9413
- import { promises as fs13 } from "fs";
9842
+ import { promises as fs14 } from "fs";
9414
9843
  import { join as join6 } from "path";
9415
9844
  import AdmZip from "adm-zip";
9416
9845
  var StarterKitService = class {
@@ -9459,16 +9888,16 @@ var StarterKitService = class {
9459
9888
  }
9460
9889
  if (onProgress) onProgress(30);
9461
9890
  const tmpDir = join6(process.env.TMPDIR || "/tmp", "jai1-kits");
9462
- await fs13.mkdir(tmpDir, { recursive: true });
9891
+ await fs14.mkdir(tmpDir, { recursive: true });
9463
9892
  const tmpFile = join6(tmpDir, `${slug}.zip`);
9464
9893
  const buffer = await response.arrayBuffer();
9465
- await fs13.writeFile(tmpFile, Buffer.from(buffer));
9894
+ await fs14.writeFile(tmpFile, Buffer.from(buffer));
9466
9895
  if (onProgress) onProgress(60);
9467
9896
  const zip = new AdmZip(tmpFile);
9468
- await fs13.mkdir(targetDir, { recursive: true });
9897
+ await fs14.mkdir(targetDir, { recursive: true });
9469
9898
  zip.extractAllTo(targetDir, true);
9470
9899
  if (onProgress) onProgress(100);
9471
- await fs13.unlink(tmpFile);
9900
+ await fs14.unlink(tmpFile);
9472
9901
  }
9473
9902
  };
9474
9903
 
@@ -9563,7 +9992,7 @@ Post-Init Commands:`);
9563
9992
 
9564
9993
  // src/commands/kit/create.ts
9565
9994
  import { Command as Command40 } from "commander";
9566
- import { promises as fs14 } from "fs";
9995
+ import { promises as fs15 } from "fs";
9567
9996
  import { join as join7 } from "path";
9568
9997
  import { select as select3, input as input2, checkbox as checkbox4 } from "@inquirer/prompts";
9569
9998
  import { execa as execa2 } from "execa";
@@ -9629,7 +10058,7 @@ function createKitCreateCommand() {
9629
10058
  }
9630
10059
  const targetDir = directory || join7(process.cwd(), options.name || slug);
9631
10060
  try {
9632
- await fs14.access(targetDir);
10061
+ await fs15.access(targetDir);
9633
10062
  throw new Error(`Directory already exists: ${targetDir}`);
9634
10063
  } catch (error) {
9635
10064
  if (error.code !== "ENOENT") {
@@ -9747,7 +10176,7 @@ function createKitCreateCommand() {
9747
10176
  async function applyVariableSubstitution(dir, variables) {
9748
10177
  const files = await getAllFiles(dir);
9749
10178
  for (const file of files) {
9750
- let content = await fs14.readFile(file, "utf-8");
10179
+ let content = await fs15.readFile(file, "utf-8");
9751
10180
  let modified = false;
9752
10181
  for (const [key, value] of Object.entries(variables)) {
9753
10182
  const regex = new RegExp(`\\{\\{${key}\\}\\}`, "g");
@@ -9757,13 +10186,13 @@ async function applyVariableSubstitution(dir, variables) {
9757
10186
  }
9758
10187
  }
9759
10188
  if (modified) {
9760
- await fs14.writeFile(file, content, "utf-8");
10189
+ await fs15.writeFile(file, content, "utf-8");
9761
10190
  }
9762
10191
  }
9763
10192
  }
9764
10193
  async function getAllFiles(dir) {
9765
10194
  const files = [];
9766
- const entries = await fs14.readdir(dir, { withFileTypes: true });
10195
+ const entries = await fs15.readdir(dir, { withFileTypes: true });
9767
10196
  for (const entry of entries) {
9768
10197
  const fullPath = join7(dir, entry.name);
9769
10198
  if (entry.isDirectory()) {
@@ -9850,7 +10279,7 @@ function createRulesListCommand() {
9850
10279
 
9851
10280
  // src/commands/rules/init.ts
9852
10281
  import { Command as Command43 } from "commander";
9853
- import { promises as fs15 } from "fs";
10282
+ import { promises as fs16 } from "fs";
9854
10283
  import { join as join8 } from "path";
9855
10284
  import { select as select4, confirm as confirm7 } from "@inquirer/prompts";
9856
10285
  function createRulesInitCommand() {
@@ -9936,7 +10365,7 @@ function createRulesInitCommand() {
9936
10365
  appliedAt: (/* @__PURE__ */ new Date()).toISOString(),
9937
10366
  customContext: "09-custom.mdc"
9938
10367
  };
9939
- await fs15.writeFile("jai1-rules.json", JSON.stringify(projectConfig, null, 2));
10368
+ await fs16.writeFile("jai1-rules.json", JSON.stringify(projectConfig, null, 2));
9940
10369
  console.log("\u2713 Created jai1-rules.json");
9941
10370
  console.log("\n\u2705 Preset applied successfully!\n");
9942
10371
  console.log("Next steps:");
@@ -9947,10 +10376,10 @@ function createRulesInitCommand() {
9947
10376
  }
9948
10377
  async function applyCursorFormat(bundle) {
9949
10378
  const rulesDir = join8(process.cwd(), ".cursor", "rules");
9950
- await fs15.mkdir(rulesDir, { recursive: true });
10379
+ await fs16.mkdir(rulesDir, { recursive: true });
9951
10380
  for (const [filename, content] of Object.entries(bundle.files)) {
9952
10381
  const filePath = join8(rulesDir, filename);
9953
- await fs15.writeFile(filePath, content, "utf-8");
10382
+ await fs16.writeFile(filePath, content, "utf-8");
9954
10383
  console.log(`\u2713 Created .cursor/rules/${filename}`);
9955
10384
  }
9956
10385
  }
@@ -9977,13 +10406,13 @@ async function applyAgentsMdFormat(bundle) {
9977
10406
  }
9978
10407
  }
9979
10408
  const agentsMd = sections.join("\n");
9980
- await fs15.writeFile("AGENTS.md", agentsMd, "utf-8");
10409
+ await fs16.writeFile("AGENTS.md", agentsMd, "utf-8");
9981
10410
  console.log("\u2713 Created AGENTS.md");
9982
10411
  }
9983
10412
 
9984
10413
  // src/commands/rules/apply.ts
9985
10414
  import { Command as Command44 } from "commander";
9986
- import { promises as fs17 } from "fs";
10415
+ import { promises as fs18 } from "fs";
9987
10416
  import { join as join10 } from "path";
9988
10417
  import { select as select5, confirm as confirm8, checkbox as checkbox5 } from "@inquirer/prompts";
9989
10418
 
@@ -10344,7 +10773,7 @@ Follow all instructions and patterns defined in AGENTS.md above.
10344
10773
  };
10345
10774
 
10346
10775
  // src/services/backup.service.ts
10347
- import { promises as fs16 } from "fs";
10776
+ import { promises as fs17 } from "fs";
10348
10777
  import { join as join9, dirname } from "path";
10349
10778
  var BackupService = class {
10350
10779
  backupDir = ".jai1/backups";
@@ -10375,16 +10804,16 @@ var BackupService = class {
10375
10804
  await this.backupSingleFile("GEMINI.md", backupPath, ideId, backedUpFiles);
10376
10805
  hasContent = true;
10377
10806
  } else {
10378
- const stats = await fs16.stat(rulesPath);
10807
+ const stats = await fs17.stat(rulesPath);
10379
10808
  if (stats.isDirectory()) {
10380
- const files = await fs16.readdir(rulesPath);
10809
+ const files = await fs17.readdir(rulesPath);
10381
10810
  for (const file of files) {
10382
10811
  if (file.endsWith(format.fileExtension)) {
10383
10812
  const originalPath = join9(rulesPath, file);
10384
10813
  const relativePath = join9(format.rulesPath, file);
10385
10814
  const destPath = join9(backupPath, ideId, file);
10386
- await fs16.mkdir(dirname(destPath), { recursive: true });
10387
- await fs16.copyFile(originalPath, destPath);
10815
+ await fs17.mkdir(dirname(destPath), { recursive: true });
10816
+ await fs17.copyFile(originalPath, destPath);
10388
10817
  backedUpFiles.push({
10389
10818
  originalPath: relativePath,
10390
10819
  backupPath: join9(ideId, file),
@@ -10408,8 +10837,8 @@ var BackupService = class {
10408
10837
  ides,
10409
10838
  files: backedUpFiles
10410
10839
  };
10411
- await fs16.mkdir(backupPath, { recursive: true });
10412
- await fs16.writeFile(
10840
+ await fs17.mkdir(backupPath, { recursive: true });
10841
+ await fs17.writeFile(
10413
10842
  join9(backupPath, "metadata.json"),
10414
10843
  JSON.stringify(metadata, null, 2),
10415
10844
  "utf-8"
@@ -10427,8 +10856,8 @@ var BackupService = class {
10427
10856
  return;
10428
10857
  }
10429
10858
  const destPath = join9(backupPath, ideId, filename);
10430
- await fs16.mkdir(dirname(destPath), { recursive: true });
10431
- await fs16.copyFile(originalPath, destPath);
10859
+ await fs17.mkdir(dirname(destPath), { recursive: true });
10860
+ await fs17.copyFile(originalPath, destPath);
10432
10861
  backedUpFiles.push({
10433
10862
  originalPath: filename,
10434
10863
  backupPath: join9(ideId, filename),
@@ -10442,15 +10871,15 @@ var BackupService = class {
10442
10871
  */
10443
10872
  async restoreBackup(backupPath) {
10444
10873
  const metadataPath = join9(backupPath, "metadata.json");
10445
- const metadataContent = await fs16.readFile(metadataPath, "utf-8");
10874
+ const metadataContent = await fs17.readFile(metadataPath, "utf-8");
10446
10875
  const metadata = JSON.parse(metadataContent);
10447
10876
  console.log(`
10448
10877
  Restoring backup from ${metadata.timestamp}...`);
10449
10878
  for (const file of metadata.files) {
10450
10879
  const sourcePath = join9(backupPath, file.backupPath);
10451
10880
  const destPath = join9(process.cwd(), file.originalPath);
10452
- await fs16.mkdir(dirname(destPath), { recursive: true });
10453
- await fs16.copyFile(sourcePath, destPath);
10881
+ await fs17.mkdir(dirname(destPath), { recursive: true });
10882
+ await fs17.copyFile(sourcePath, destPath);
10454
10883
  console.log(`\u2713 Restored ${file.originalPath}`);
10455
10884
  }
10456
10885
  console.log("\n\u2705 Backup restored successfully!");
@@ -10465,13 +10894,13 @@ Restoring backup from ${metadata.timestamp}...`);
10465
10894
  if (!exists) {
10466
10895
  return [];
10467
10896
  }
10468
- const entries = await fs16.readdir(backupDirPath, { withFileTypes: true });
10897
+ const entries = await fs17.readdir(backupDirPath, { withFileTypes: true });
10469
10898
  const backups = [];
10470
10899
  for (const entry of entries) {
10471
10900
  if (entry.isDirectory()) {
10472
10901
  const metadataPath = join9(backupDirPath, entry.name, "metadata.json");
10473
10902
  try {
10474
- const metadataContent = await fs16.readFile(metadataPath, "utf-8");
10903
+ const metadataContent = await fs17.readFile(metadataPath, "utf-8");
10475
10904
  const metadata = JSON.parse(metadataContent);
10476
10905
  backups.push(metadata);
10477
10906
  } catch {
@@ -10518,9 +10947,9 @@ Restoring backup from ${metadata.timestamp}...`);
10518
10947
  /**
10519
10948
  * Check if a path exists
10520
10949
  */
10521
- async pathExists(path9) {
10950
+ async pathExists(path10) {
10522
10951
  try {
10523
- await fs16.access(path9);
10952
+ await fs17.access(path10);
10524
10953
  return true;
10525
10954
  } catch {
10526
10955
  return false;
@@ -10529,22 +10958,22 @@ Restoring backup from ${metadata.timestamp}...`);
10529
10958
  /**
10530
10959
  * Recursively delete a directory
10531
10960
  */
10532
- async deleteDirectory(path9) {
10961
+ async deleteDirectory(path10) {
10533
10962
  try {
10534
- const exists = await this.pathExists(path9);
10963
+ const exists = await this.pathExists(path10);
10535
10964
  if (!exists) {
10536
10965
  return;
10537
10966
  }
10538
- const entries = await fs16.readdir(path9, { withFileTypes: true });
10967
+ const entries = await fs17.readdir(path10, { withFileTypes: true });
10539
10968
  for (const entry of entries) {
10540
- const fullPath = join9(path9, entry.name);
10969
+ const fullPath = join9(path10, entry.name);
10541
10970
  if (entry.isDirectory()) {
10542
10971
  await this.deleteDirectory(fullPath);
10543
10972
  } else {
10544
- await fs16.unlink(fullPath);
10973
+ await fs17.unlink(fullPath);
10545
10974
  }
10546
10975
  }
10547
- await fs16.rmdir(path9);
10976
+ await fs17.rmdir(path10);
10548
10977
  } catch (error) {
10549
10978
  }
10550
10979
  }
@@ -10559,7 +10988,7 @@ Restoring backup from ${metadata.timestamp}...`);
10559
10988
  */
10560
10989
  async ensureBackupDir() {
10561
10990
  const backupDirPath = join9(process.cwd(), this.backupDir);
10562
- await fs16.mkdir(backupDirPath, { recursive: true });
10991
+ await fs17.mkdir(backupDirPath, { recursive: true });
10563
10992
  }
10564
10993
  };
10565
10994
 
@@ -10717,19 +11146,19 @@ function createRulesApplyCommand() {
10717
11146
  console.log("\n\u{1F4DD} Applying preset...\n");
10718
11147
  const rulePresetDir = join10(process.cwd(), ".jai1", "rule-preset");
10719
11148
  try {
10720
- await fs17.rm(rulePresetDir, { recursive: true, force: true });
11149
+ await fs18.rm(rulePresetDir, { recursive: true, force: true });
10721
11150
  } catch {
10722
11151
  }
10723
- await fs17.mkdir(rulePresetDir, { recursive: true });
10724
- await fs17.writeFile(
11152
+ await fs18.mkdir(rulePresetDir, { recursive: true });
11153
+ await fs18.writeFile(
10725
11154
  join10(rulePresetDir, "preset.json"),
10726
11155
  JSON.stringify(bundle.preset, null, 2),
10727
11156
  "utf-8"
10728
11157
  );
10729
11158
  for (const [filename, content] of Object.entries(bundle.files)) {
10730
11159
  const filePath = join10(rulePresetDir, filename);
10731
- await fs17.mkdir(join10(filePath, ".."), { recursive: true });
10732
- await fs17.writeFile(filePath, content, "utf-8");
11160
+ await fs18.mkdir(join10(filePath, ".."), { recursive: true });
11161
+ await fs18.writeFile(filePath, content, "utf-8");
10733
11162
  }
10734
11163
  console.log(`\u2713 Saved preset to .jai1/rule-preset/`);
10735
11164
  const allGeneratedFiles = [];
@@ -10738,8 +11167,8 @@ function createRulesApplyCommand() {
10738
11167
  const files = generatorService.generateForIde(bundle, ideId);
10739
11168
  for (const file of files) {
10740
11169
  const fullPath = join10(process.cwd(), file.path);
10741
- await fs17.mkdir(join10(fullPath, ".."), { recursive: true });
10742
- await fs17.writeFile(fullPath, file.content, "utf-8");
11170
+ await fs18.mkdir(join10(fullPath, ".."), { recursive: true });
11171
+ await fs18.writeFile(fullPath, file.content, "utf-8");
10743
11172
  console.log(`\u2713 [${ideId}] ${file.path}`);
10744
11173
  allGeneratedFiles.push({
10745
11174
  ide: ideId,
@@ -10767,7 +11196,7 @@ function createRulesApplyCommand() {
10767
11196
  };
10768
11197
  try {
10769
11198
  const existingConfigPath = join10(process.cwd(), "jai1-rules.json");
10770
- const existingConfigContent = await fs17.readFile(existingConfigPath, "utf-8");
11199
+ const existingConfigContent = await fs18.readFile(existingConfigPath, "utf-8");
10771
11200
  const existingConfig = JSON.parse(existingConfigContent);
10772
11201
  if (existingConfig.backups && existingConfig.backups.length > 0) {
10773
11202
  projectConfig.backups = [
@@ -10778,7 +11207,7 @@ function createRulesApplyCommand() {
10778
11207
  }
10779
11208
  } catch {
10780
11209
  }
10781
- await fs17.writeFile(
11210
+ await fs18.writeFile(
10782
11211
  join10(process.cwd(), "jai1-rules.json"),
10783
11212
  JSON.stringify(projectConfig, null, 2),
10784
11213
  "utf-8"
@@ -10883,7 +11312,7 @@ function formatTimestamp(timestamp) {
10883
11312
 
10884
11313
  // src/commands/rules/sync.ts
10885
11314
  import { Command as Command46 } from "commander";
10886
- import { promises as fs18 } from "fs";
11315
+ import { promises as fs19 } from "fs";
10887
11316
  import { join as join12 } from "path";
10888
11317
  import { confirm as confirm10 } from "@inquirer/prompts";
10889
11318
  function createRulesSyncCommand() {
@@ -10891,7 +11320,7 @@ function createRulesSyncCommand() {
10891
11320
  const configPath = join12(process.cwd(), "jai1-rules.json");
10892
11321
  let projectConfig;
10893
11322
  try {
10894
- const configContent = await fs18.readFile(configPath, "utf-8");
11323
+ const configContent = await fs19.readFile(configPath, "utf-8");
10895
11324
  projectConfig = JSON.parse(configContent);
10896
11325
  } catch {
10897
11326
  throw new ValidationError(
@@ -10974,11 +11403,11 @@ Detected ${detected.length} active IDE(s):
10974
11403
  const rulePresetDir = join12(process.cwd(), ".jai1", "rule-preset");
10975
11404
  const presetExists = await checkPathExists(rulePresetDir);
10976
11405
  if (presetExists) {
10977
- const files = await fs18.readdir(rulePresetDir);
11406
+ const files = await fs19.readdir(rulePresetDir);
10978
11407
  for (const file of files) {
10979
11408
  if (file.endsWith(".mdc")) {
10980
11409
  const filePath = join12(rulePresetDir, file);
10981
- const content = await fs18.readFile(filePath, "utf-8");
11410
+ const content = await fs19.readFile(filePath, "utf-8");
10982
11411
  bundle.files[file] = content;
10983
11412
  }
10984
11413
  }
@@ -10998,8 +11427,8 @@ Detected ${detected.length} active IDE(s):
10998
11427
  const files = generatorService.generateForIde(bundle, ideId);
10999
11428
  for (const file of files) {
11000
11429
  const fullPath = join12(process.cwd(), file.path);
11001
- await fs18.mkdir(join12(fullPath, ".."), { recursive: true });
11002
- await fs18.writeFile(fullPath, file.content, "utf-8");
11430
+ await fs19.mkdir(join12(fullPath, ".."), { recursive: true });
11431
+ await fs19.writeFile(fullPath, file.content, "utf-8");
11003
11432
  }
11004
11433
  console.log(`\u2713 ${format.name} - ${files.length} files regenerated`);
11005
11434
  } catch (error) {
@@ -11008,7 +11437,7 @@ Detected ${detected.length} active IDE(s):
11008
11437
  }
11009
11438
  if (JSON.stringify(projectConfig.ides) !== JSON.stringify(idesToSync)) {
11010
11439
  projectConfig.ides = idesToSync;
11011
- await fs18.writeFile(
11440
+ await fs19.writeFile(
11012
11441
  join12(process.cwd(), "jai1-rules.json"),
11013
11442
  JSON.stringify(projectConfig, null, 2),
11014
11443
  "utf-8"
@@ -11024,7 +11453,7 @@ Detected ${detected.length} active IDE(s):
11024
11453
  }
11025
11454
  async function checkPathExists(absolutePath) {
11026
11455
  try {
11027
- await fs18.access(absolutePath);
11456
+ await fs19.access(absolutePath);
11028
11457
  return true;
11029
11458
  } catch {
11030
11459
  return false;
@@ -11033,14 +11462,14 @@ async function checkPathExists(absolutePath) {
11033
11462
 
11034
11463
  // src/commands/rules/info.ts
11035
11464
  import { Command as Command47 } from "commander";
11036
- import { promises as fs19 } from "fs";
11465
+ import { promises as fs20 } from "fs";
11037
11466
  import { join as join13 } from "path";
11038
11467
  function createRulesInfoCommand() {
11039
11468
  return new Command47("info").description("Show current preset information").option("--json", "Output as JSON").action(async (options) => {
11040
11469
  const configPath = join13(process.cwd(), "jai1-rules.json");
11041
11470
  let projectConfig;
11042
11471
  try {
11043
- const configContent = await fs19.readFile(configPath, "utf-8");
11472
+ const configContent = await fs20.readFile(configPath, "utf-8");
11044
11473
  projectConfig = JSON.parse(configContent);
11045
11474
  } catch {
11046
11475
  throw new ValidationError(
@@ -11057,9 +11486,9 @@ function createRulesInfoCommand() {
11057
11486
  let presetMetadata = null;
11058
11487
  let presetFiles = [];
11059
11488
  try {
11060
- const presetContent = await fs19.readFile(presetJsonPath, "utf-8");
11489
+ const presetContent = await fs20.readFile(presetJsonPath, "utf-8");
11061
11490
  presetMetadata = JSON.parse(presetContent);
11062
- const files = await fs19.readdir(rulePresetDir);
11491
+ const files = await fs20.readdir(rulePresetDir);
11063
11492
  presetFiles = files.filter((f) => f.endsWith(".mdc"));
11064
11493
  } catch {
11065
11494
  }
@@ -11118,9 +11547,9 @@ Available Backups (${projectConfig.backups.length}):`);
11118
11547
  console.log(' \u2022 "jai1 rules apply" - Apply a different preset (replaces current)');
11119
11548
  });
11120
11549
  }
11121
- async function checkPathExists2(path9) {
11550
+ async function checkPathExists2(path10) {
11122
11551
  try {
11123
- await fs19.access(join13(process.cwd(), path9));
11552
+ await fs20.access(join13(process.cwd(), path10));
11124
11553
  return true;
11125
11554
  } catch {
11126
11555
  return false;
@@ -11551,8 +11980,8 @@ var RedmineApiClient = class {
11551
11980
  this.retryConfig = config.defaults.retry;
11552
11981
  this.concurrencyLimit = pLimit3(config.defaults.concurrency);
11553
11982
  }
11554
- async request(path9, options = {}) {
11555
- const url = `${this.baseUrl}${path9}`;
11983
+ async request(path10, options = {}) {
11984
+ const url = `${this.baseUrl}${path10}`;
11556
11985
  const headers = {
11557
11986
  "X-Redmine-API-Key": this.apiAccessToken,
11558
11987
  "Content-Type": "application/json",
@@ -11613,8 +12042,8 @@ var RedmineApiClient = class {
11613
12042
  if (include && include.length > 0) {
11614
12043
  params.append("include", include.join(","));
11615
12044
  }
11616
- const path9 = `/issues/${issueId}.json${params.toString() ? `?${params.toString()}` : ""}`;
11617
- return this.request(path9);
12045
+ const path10 = `/issues/${issueId}.json${params.toString() ? `?${params.toString()}` : ""}`;
12046
+ return this.request(path10);
11618
12047
  }
11619
12048
  async getIssues(projectId, options = {}) {
11620
12049
  const params = new URLSearchParams();
@@ -11634,8 +12063,8 @@ var RedmineApiClient = class {
11634
12063
  if (options.updatedSince) {
11635
12064
  params.append("updated_on", `>=${options.updatedSince}`);
11636
12065
  }
11637
- const path9 = `/issues.json?${params.toString()}`;
11638
- return this.request(path9);
12066
+ const path10 = `/issues.json?${params.toString()}`;
12067
+ return this.request(path10);
11639
12068
  }
11640
12069
  async getAllIssues(projectId, options = {}) {
11641
12070
  const pageSize = options.pageSize || 100;
@@ -12319,7 +12748,7 @@ async function handleSyncProject(options) {
12319
12748
 
12320
12749
  // src/commands/framework/info.ts
12321
12750
  import { Command as Command54 } from "commander";
12322
- import { promises as fs20 } from "fs";
12751
+ import { promises as fs21 } from "fs";
12323
12752
  import { join as join15 } from "path";
12324
12753
  import { homedir as homedir5 } from "os";
12325
12754
  function createInfoCommand() {
@@ -12371,7 +12800,7 @@ function maskKey3(key) {
12371
12800
  async function getProjectStatus2() {
12372
12801
  const projectJai1 = join15(process.cwd(), ".jai1");
12373
12802
  try {
12374
- await fs20.access(projectJai1);
12803
+ await fs21.access(projectJai1);
12375
12804
  return { exists: true, version: "Synced" };
12376
12805
  } catch {
12377
12806
  return { exists: false };
@@ -12561,8 +12990,8 @@ function createClearBackupsCommand() {
12561
12990
  // src/commands/vscode/index.ts
12562
12991
  import { Command as Command57 } from "commander";
12563
12992
  import { checkbox as checkbox7, confirm as confirm15, select as select8 } from "@inquirer/prompts";
12564
- import fs21 from "fs/promises";
12565
- import path8 from "path";
12993
+ import fs22 from "fs/promises";
12994
+ import path9 from "path";
12566
12995
  import { existsSync as existsSync3 } from "fs";
12567
12996
  var PERFORMANCE_GROUPS2 = {
12568
12997
  telemetry: {
@@ -12782,8 +13211,8 @@ async function selectGroupsToApply2(action) {
12782
13211
  }
12783
13212
  }
12784
13213
  async function applyGroups2(groupKeys, action) {
12785
- const vscodeDir = path8.join(process.cwd(), ".vscode");
12786
- const settingsPath = path8.join(vscodeDir, "settings.json");
13214
+ const vscodeDir = path9.join(process.cwd(), ".vscode");
13215
+ const settingsPath = path9.join(vscodeDir, "settings.json");
12787
13216
  const invalidGroups = groupKeys.filter((key) => !PERFORMANCE_GROUPS2[key]);
12788
13217
  if (invalidGroups.length > 0) {
12789
13218
  console.log(`
@@ -12792,13 +13221,13 @@ async function applyGroups2(groupKeys, action) {
12792
13221
  return;
12793
13222
  }
12794
13223
  if (!existsSync3(vscodeDir)) {
12795
- await fs21.mkdir(vscodeDir, { recursive: true });
13224
+ await fs22.mkdir(vscodeDir, { recursive: true });
12796
13225
  console.log("\u{1F4C1} \u0110\xE3 t\u1EA1o th\u01B0 m\u1EE5c .vscode/");
12797
13226
  }
12798
13227
  let currentSettings = {};
12799
13228
  if (existsSync3(settingsPath)) {
12800
13229
  try {
12801
- const content = await fs21.readFile(settingsPath, "utf-8");
13230
+ const content = await fs22.readFile(settingsPath, "utf-8");
12802
13231
  currentSettings = JSON.parse(content);
12803
13232
  console.log("\u{1F4C4} \u0110\xE3 \u0111\u1ECDc c\xE0i \u0111\u1EB7t hi\u1EC7n t\u1EA1i t\u1EEB settings.json");
12804
13233
  } catch {
@@ -12838,14 +13267,14 @@ async function applyGroups2(groupKeys, action) {
12838
13267
  }
12839
13268
  }
12840
13269
  }
12841
- await fs21.writeFile(settingsPath, JSON.stringify(newSettings, null, 2));
13270
+ await fs22.writeFile(settingsPath, JSON.stringify(newSettings, null, 2));
12842
13271
  console.log(`
12843
13272
  \u2705 \u0110\xE3 c\u1EADp nh\u1EADt c\xE0i \u0111\u1EB7t VSCode t\u1EA1i: ${settingsPath}`);
12844
13273
  console.log("\u{1F4A1} M\u1EB9o: Kh\u1EDFi \u0111\u1ED9ng l\u1EA1i VSCode \u0111\u1EC3 \xE1p d\u1EE5ng c\xE1c thay \u0111\u1ED5i.");
12845
13274
  }
12846
13275
  async function resetSettings2(groupKeys) {
12847
- const vscodeDir = path8.join(process.cwd(), ".vscode");
12848
- const settingsPath = path8.join(vscodeDir, "settings.json");
13276
+ const vscodeDir = path9.join(process.cwd(), ".vscode");
13277
+ const settingsPath = path9.join(vscodeDir, "settings.json");
12849
13278
  if (!existsSync3(settingsPath)) {
12850
13279
  console.log("\n\u26A0\uFE0F Kh\xF4ng t\xECm th\u1EA5y file settings.json");
12851
13280
  return;
@@ -12859,7 +13288,7 @@ async function resetSettings2(groupKeys) {
12859
13288
  return;
12860
13289
  }
12861
13290
  if (groupKeys.length === 0) {
12862
- await fs21.unlink(settingsPath);
13291
+ await fs22.unlink(settingsPath);
12863
13292
  console.log("\n\u2705 \u0110\xE3 x\xF3a file settings.json");
12864
13293
  } else {
12865
13294
  await applyGroups2(groupKeys, "disable");