@jvittechs/jai1-cli 0.1.99 → 0.1.101

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 Command60 } from "commander";
4
+ import { Command as Command61 } 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.99",
36
+ version: "0.1.101",
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",
@@ -1322,9 +1323,9 @@ var UnifiedApplyApp = ({
1322
1323
  (c) => c.filepath.toLowerCase().includes(query) || c.tags?.some((t) => t.toLowerCase().includes(query))
1323
1324
  );
1324
1325
  }, [components, searchQuery]);
1325
- useInput((input4, key) => {
1326
+ useInput((input5, key) => {
1326
1327
  if (viewState === "done") {
1327
- if (key.return || input4 === "q" || key.escape) {
1328
+ if (key.return || input5 === "q" || key.escape) {
1328
1329
  onExit();
1329
1330
  }
1330
1331
  return;
@@ -1332,7 +1333,7 @@ var UnifiedApplyApp = ({
1332
1333
  if (viewState === "summary") {
1333
1334
  if (key.return) {
1334
1335
  setViewState("ide-sync");
1335
- } else if (input4 === "s" || input4 === "q" || key.escape) {
1336
+ } else if (input5 === "s" || input5 === "q" || key.escape) {
1336
1337
  onExit();
1337
1338
  }
1338
1339
  return;
@@ -1342,7 +1343,7 @@ var UnifiedApplyApp = ({
1342
1343
  setIdeCursorIndex((prev) => Math.max(0, prev - 1));
1343
1344
  } else if (key.downArrow) {
1344
1345
  setIdeCursorIndex((prev) => Math.min(availableIdes.length - 1, prev + 1));
1345
- } else if (input4 === " ") {
1346
+ } else if (input5 === " ") {
1346
1347
  const ide = availableIdes[ideCursorIndex];
1347
1348
  if (ide) {
1348
1349
  setSelectedIdes((prev) => {
@@ -1355,15 +1356,15 @@ var UnifiedApplyApp = ({
1355
1356
  return next;
1356
1357
  });
1357
1358
  }
1358
- } else if (input4 === "a") {
1359
+ } else if (input5 === "a") {
1359
1360
  setSelectedIdes(new Set(availableIdes));
1360
- } else if (input4 === "c") {
1361
+ } else if (input5 === "c") {
1361
1362
  setSelectedIdes(/* @__PURE__ */ new Set());
1362
1363
  } else if (key.return) {
1363
1364
  if (selectedIdes.size > 0) {
1364
1365
  handleIdeSync();
1365
1366
  }
1366
- } else if (input4 === "s" || input4 === "q" || key.escape) {
1367
+ } else if (input5 === "s" || input5 === "q" || key.escape) {
1367
1368
  onExit();
1368
1369
  }
1369
1370
  return;
@@ -1380,7 +1381,7 @@ var UnifiedApplyApp = ({
1380
1381
  else setFocusArea("packages");
1381
1382
  return;
1382
1383
  }
1383
- if (key.escape || input4 === "q") {
1384
+ if (key.escape || input5 === "q") {
1384
1385
  onExit();
1385
1386
  return;
1386
1387
  }
@@ -1391,14 +1392,14 @@ var UnifiedApplyApp = ({
1391
1392
  return;
1392
1393
  }
1393
1394
  if (focusArea !== "search") {
1394
- if (input4 === "a") {
1395
+ if (input5 === "a") {
1395
1396
  setSelectedPaths((prev) => {
1396
1397
  const next = new Set(prev);
1397
1398
  filteredComponents.forEach((c) => next.add(c.filepath));
1398
1399
  return next;
1399
1400
  });
1400
1401
  return;
1401
- } else if (input4 === "c") {
1402
+ } else if (input5 === "c") {
1402
1403
  setSelectedPaths(/* @__PURE__ */ new Set());
1403
1404
  return;
1404
1405
  }
@@ -1408,7 +1409,7 @@ var UnifiedApplyApp = ({
1408
1409
  setCursorIndex((prev) => Math.max(0, prev - 1));
1409
1410
  } else if (key.downArrow) {
1410
1411
  setCursorIndex((prev) => Math.min(filteredComponents.length - 1, prev + 1));
1411
- } else if (input4 === " ") {
1412
+ } else if (input5 === " ") {
1412
1413
  const current = filteredComponents[cursorIndex];
1413
1414
  if (current) {
1414
1415
  setSelectedPaths((prev) => {
@@ -1428,7 +1429,7 @@ var UnifiedApplyApp = ({
1428
1429
  setSelectedPackageIndex((prev) => Math.max(0, prev - 1));
1429
1430
  } else if (key.rightArrow) {
1430
1431
  setSelectedPackageIndex((prev) => Math.min(tags.length - 1, prev + 1));
1431
- } else if (input4 === " " || key.return) {
1432
+ } else if (input5 === " " || key.return) {
1432
1433
  const tag = tags[selectedPackageIndex];
1433
1434
  if (tag) {
1434
1435
  const packageComponents = components.filter((c) => c.tags?.includes(tag.tag));
@@ -1860,7 +1861,7 @@ var MainMenuView = ({ ideContexts, onSelect }) => {
1860
1861
  available: ideContexts.some((ctx) => ctx.ide === "jai1")
1861
1862
  }
1862
1863
  ];
1863
- useInput2((input4, key) => {
1864
+ useInput2((input5, key) => {
1864
1865
  if (key.upArrow) {
1865
1866
  setSelectedIndex((prev) => Math.max(0, prev - 1));
1866
1867
  } else if (key.downArrow) {
@@ -1962,13 +1963,13 @@ var IDEOverviewView = ({
1962
1963
  count: ideContext.stats.byType.context
1963
1964
  });
1964
1965
  }
1965
- useInput3((input4, key) => {
1966
+ useInput3((input5, key) => {
1966
1967
  if (key.tab || key.rightArrow) {
1967
1968
  setSelectedTabIndex((prev) => Math.min(tabs.length - 1, prev + 1));
1968
1969
  } else if (key.leftArrow) {
1969
1970
  setSelectedTabIndex((prev) => Math.max(0, prev - 1));
1970
1971
  }
1971
- const num = parseInt(input4, 10);
1972
+ const num = parseInt(input5, 10);
1972
1973
  if (!isNaN(num) && num >= 1 && num <= tabs.length) {
1973
1974
  setSelectedTabIndex(num - 1);
1974
1975
  }
@@ -2030,7 +2031,7 @@ import React7, { useState as useState4 } from "react";
2030
2031
  import { Box as Box5, Text as Text6, useInput as useInput4 } from "ink";
2031
2032
  var ListView = ({ items, contentType, onSelect, onBack }) => {
2032
2033
  const [selectedIndex, setSelectedIndex] = useState4(0);
2033
- useInput4((input4, key) => {
2034
+ useInput4((input5, key) => {
2034
2035
  if (key.upArrow) {
2035
2036
  setSelectedIndex((prev) => Math.max(0, prev - 1));
2036
2037
  } else if (key.downArrow) {
@@ -2081,18 +2082,18 @@ var DetailView = ({ item, scrollPosition: initialScroll, onBack }) => {
2081
2082
  const [scrollPosition, setScrollPosition] = useState5(initialScroll);
2082
2083
  const maxVisibleLines = 25;
2083
2084
  const maxScroll = Math.max(0, item.previewLines.length - maxVisibleLines);
2084
- useInput5((input4, key) => {
2085
- if (key.upArrow || input4 === "k") {
2085
+ useInput5((input5, key) => {
2086
+ if (key.upArrow || input5 === "k") {
2086
2087
  setScrollPosition((prev) => Math.max(0, prev - 1));
2087
- } else if (key.downArrow || input4 === "j") {
2088
+ } else if (key.downArrow || input5 === "j") {
2088
2089
  setScrollPosition((prev) => Math.min(maxScroll, prev + 1));
2089
- } else if (key.pageDown || input4 === "d") {
2090
+ } else if (key.pageDown || input5 === "d") {
2090
2091
  setScrollPosition((prev) => Math.min(maxScroll, prev + 5));
2091
- } else if (key.pageUp || input4 === "u") {
2092
+ } else if (key.pageUp || input5 === "u") {
2092
2093
  setScrollPosition((prev) => Math.max(0, prev - 5));
2093
- } else if (input4 === "g") {
2094
+ } else if (input5 === "g") {
2094
2095
  setScrollPosition(0);
2095
- } else if (input4 === "G") {
2096
+ } else if (input5 === "G") {
2096
2097
  setScrollPosition(maxScroll);
2097
2098
  } else if (key.escape || key.backspace) {
2098
2099
  onBack();
@@ -2496,8 +2497,8 @@ var ContextApp = ({ initialIDE, initialType, onExit }) => {
2496
2497
  setLoading(false);
2497
2498
  });
2498
2499
  }, [initialIDE]);
2499
- useInput6((input4, key) => {
2500
- if (input4 === "q") {
2500
+ useInput6((input5, key) => {
2501
+ if (input5 === "q") {
2501
2502
  onExit();
2502
2503
  return;
2503
2504
  }
@@ -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;
@@ -3616,7 +3617,7 @@ var MENU_ITEMS = [
3616
3617
  ];
3617
3618
  var MenuView = ({ onSelect }) => {
3618
3619
  const [selectedIndex, setSelectedIndex] = useState7(0);
3619
- useInput7((input4, key) => {
3620
+ useInput7((input5, key) => {
3620
3621
  if (key.upArrow) {
3621
3622
  setSelectedIndex((prev) => Math.max(0, prev - 1));
3622
3623
  } else if (key.downArrow) {
@@ -4229,7 +4230,7 @@ var AgenticGuideView = ({ onBack }) => {
4229
4230
  const [isTyping, setIsTyping] = useState8(false);
4230
4231
  const [selectedSuggestion, setSelectedSuggestion] = useState8(0);
4231
4232
  const [focusArea, setFocusArea] = useState8("input");
4232
- useInput8((input4, key) => {
4233
+ useInput8((input5, key) => {
4233
4234
  if (key.escape) {
4234
4235
  onBack();
4235
4236
  return;
@@ -4361,7 +4362,7 @@ var GuideApp = ({ initialTopic, onExit }) => {
4361
4362
  setCurrentTopic(TOPIC_MAP[initialTopic]);
4362
4363
  }
4363
4364
  }, [initialTopic]);
4364
- useInput9((input4, key) => {
4365
+ useInput9((input5, key) => {
4365
4366
  if (key.escape || currentTopic !== "menu" && key.backspace) {
4366
4367
  if (currentTopic === "menu") {
4367
4368
  onExit();
@@ -4371,7 +4372,7 @@ var GuideApp = ({ initialTopic, onExit }) => {
4371
4372
  }
4372
4373
  return;
4373
4374
  }
4374
- if (input4 === "q") {
4375
+ if (input5 === "q") {
4375
4376
  onExit();
4376
4377
  return;
4377
4378
  }
@@ -4890,7 +4891,7 @@ var ModelSelector = ({
4890
4891
  const allowedModels = models.filter((m) => m.allowed);
4891
4892
  const currentIndex = allowedModels.findIndex((m) => m.id === currentModel);
4892
4893
  const [selectedIndex, setSelectedIndex] = useState12(Math.max(0, currentIndex));
4893
- useInput10((input4, key) => {
4894
+ useInput10((input5, key) => {
4894
4895
  if (key.escape) {
4895
4896
  onCancel();
4896
4897
  return;
@@ -5016,7 +5017,7 @@ var ChatApp = ({ service, initialModel }) => {
5016
5017
  }
5017
5018
  return false;
5018
5019
  }, [refetch, exit]);
5019
- useInput11((input4, key) => {
5020
+ useInput11((input5, key) => {
5020
5021
  if (showSlashMenu) {
5021
5022
  if (key.upArrow) {
5022
5023
  setSlashMenuIndex((i) => Math.max(0, i - 1));
@@ -5044,7 +5045,7 @@ var ChatApp = ({ service, initialModel }) => {
5044
5045
  }
5045
5046
  return;
5046
5047
  }
5047
- if (currentView === "error" && (key.return || input4 === "r")) {
5048
+ if (currentView === "error" && (key.return || input5 === "r")) {
5048
5049
  setCurrentView("loading");
5049
5050
  refetch();
5050
5051
  return;
@@ -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"];
@@ -5810,9 +6243,9 @@ var TranslationService = class {
5810
6243
  /**
5811
6244
  * Detect input type
5812
6245
  */
5813
- async detectInputType(input4) {
6246
+ async detectInputType(input5) {
5814
6247
  try {
5815
- const stat = await fs9.stat(input4);
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);
@@ -6044,7 +6477,7 @@ Return ONLY the translated content, no explanations.`;
6044
6477
  };
6045
6478
 
6046
6479
  // src/commands/translate.ts
6047
- async function handleTranslate(input4, options) {
6480
+ async function handleTranslate(input5, options) {
6048
6481
  const configService = new ConfigService();
6049
6482
  const config = await configService.load();
6050
6483
  if (!config) {
@@ -6052,16 +6485,16 @@ async function handleTranslate(input4, options) {
6052
6485
  }
6053
6486
  const llmService = new LlmProxyService(config);
6054
6487
  const translationService = new TranslationService(llmService, options, options.model);
6055
- const inputType = await translationService.detectInputType(input4);
6488
+ const inputType = await translationService.detectInputType(input5);
6056
6489
  switch (inputType) {
6057
6490
  case "text":
6058
- await handleTextTranslation(translationService, input4, options);
6491
+ await handleTextTranslation(translationService, input5, options);
6059
6492
  break;
6060
6493
  case "file":
6061
- await handleFileTranslation(translationService, input4, options);
6494
+ await handleFileTranslation(translationService, input5, options);
6062
6495
  break;
6063
6496
  case "folder":
6064
- await handleFolderTranslation(translationService, input4, options);
6497
+ await handleFolderTranslation(translationService, input5, options);
6065
6498
  break;
6066
6499
  }
6067
6500
  }
@@ -6138,8 +6571,8 @@ async function handleFolderTranslation(service, folderPath, options) {
6138
6571
  }
6139
6572
  }
6140
6573
  function createTranslateCommand() {
6141
- const cmd = new Command15("translate").description("D\u1ECBch v\u0103n b\u1EA3n, file ho\u1EB7c th\u01B0 m\u1EE5c b\u1EB1ng AI").argument("<input>", "Chu\u1ED7i v\u0103n b\u1EA3n, \u0111\u01B0\u1EDDng d\u1EABn file ho\u1EB7c th\u01B0 m\u1EE5c").option("--to <language>", "M\xE3 ng\xF4n ng\u1EEF \u0111\xEDch (m\u1EB7c \u0111\u1ECBnh: vi)", "vi").option("-o, --output <path>", "\u0110\u01B0\u1EDDng d\u1EABn output (file/th\u01B0 m\u1EE5c)").option("--dry-run", "Xem tr\u01B0\u1EDBc kh\xF4ng l\u01B0u file").option("--concurrency <number>", "S\u1ED1 file x\u1EED l\xFD song song (m\u1EB7c \u0111\u1ECBnh: 3)", "3").option("--model <model>", "Model LLM (m\u1EB7c \u0111\u1ECBnh: gpt-5.1-codex-mini)").option("--json", "Xu\u1EA5t k\u1EBFt qu\u1EA3 d\u1EA1ng JSON").action(async (input4, options) => {
6142
- await handleTranslate(input4, options);
6574
+ const cmd = new Command15("translate").description("D\u1ECBch v\u0103n b\u1EA3n, file ho\u1EB7c th\u01B0 m\u1EE5c b\u1EB1ng AI").argument("<input>", "Chu\u1ED7i v\u0103n b\u1EA3n, \u0111\u01B0\u1EDDng d\u1EABn file ho\u1EB7c th\u01B0 m\u1EE5c").option("--to <language>", "M\xE3 ng\xF4n ng\u1EEF \u0111\xEDch (m\u1EB7c \u0111\u1ECBnh: vi)", "vi").option("-o, --output <path>", "\u0110\u01B0\u1EDDng d\u1EABn output (file/th\u01B0 m\u1EE5c)").option("--dry-run", "Xem tr\u01B0\u1EDBc kh\xF4ng l\u01B0u file").option("--concurrency <number>", "S\u1ED1 file x\u1EED l\xFD song song (m\u1EB7c \u0111\u1ECBnh: 3)", "3").option("--model <model>", "Model LLM (m\u1EB7c \u0111\u1ECBnh: gpt-5.1-codex-mini)").option("--json", "Xu\u1EA5t k\u1EBFt qu\u1EA3 d\u1EA1ng JSON").action(async (input5, options) => {
6575
+ await handleTranslate(input5, options);
6143
6576
  });
6144
6577
  return cmd;
6145
6578
  }
@@ -6428,11 +6861,226 @@ function createImageCommand() {
6428
6861
  return cmd;
6429
6862
  }
6430
6863
 
6864
+ // src/commands/feedback.ts
6865
+ import { Command as Command21 } from "commander";
6866
+ import { select as select2, input, confirm as confirm5 } from "@inquirer/prompts";
6867
+ import os from "os";
6868
+ import { promises as fs11 } from "fs";
6869
+ import { join as join5 } from "path";
6870
+ async function collectContext() {
6871
+ const context = {
6872
+ os: `${os.platform()} ${os.release()}`
6873
+ };
6874
+ try {
6875
+ const packageJsonPath = new URL("../../package.json", import.meta.url);
6876
+ const packageJson = JSON.parse(await fs11.readFile(packageJsonPath, "utf-8"));
6877
+ context.cli_version = packageJson.version;
6878
+ } catch {
6879
+ }
6880
+ try {
6881
+ const projectPackageJson = await fs11.readFile(join5(process.cwd(), "package.json"), "utf-8");
6882
+ const projectData = JSON.parse(projectPackageJson);
6883
+ context.project_name = projectData.name;
6884
+ } catch {
6885
+ }
6886
+ return context;
6887
+ }
6888
+ async function submitFeedback(apiUrl, accessKey, data) {
6889
+ const response = await fetch(`${apiUrl}/api/feedback`, {
6890
+ method: "POST",
6891
+ headers: {
6892
+ "Content-Type": "application/json",
6893
+ "JAI1-Access-Key": accessKey
6894
+ },
6895
+ body: JSON.stringify({
6896
+ type: data.type,
6897
+ title: data.title,
6898
+ message: data.message,
6899
+ context: data.context,
6900
+ source: "cli"
6901
+ })
6902
+ });
6903
+ const result = await response.json();
6904
+ if (!response.ok) {
6905
+ return { success: false, error: result.error || "Failed to submit feedback" };
6906
+ }
6907
+ return { success: true, feedback_id: result.data.feedback_id };
6908
+ }
6909
+ async function handleInteractiveFeedback(config) {
6910
+ console.log("\u{1F4DD} Submit Feedback to Jai1\n");
6911
+ const type = await select2({
6912
+ message: "What type of feedback?",
6913
+ choices: [
6914
+ {
6915
+ name: "\u{1F41B} Bug Report - Report an error or issue",
6916
+ value: "bug"
6917
+ },
6918
+ {
6919
+ name: "\u{1F4A1} Feature Request - Suggest a new feature",
6920
+ value: "feature"
6921
+ },
6922
+ {
6923
+ name: "\u{1F4DD} Suggestion - Share ideas or improvements",
6924
+ value: "suggestion"
6925
+ }
6926
+ ]
6927
+ });
6928
+ const title = await input({
6929
+ message: "Title (max 200 characters):",
6930
+ validate: (value) => {
6931
+ if (!value || value.trim().length === 0) {
6932
+ return "Title is required";
6933
+ }
6934
+ if (value.length > 200) {
6935
+ return "Title must be 200 characters or less";
6936
+ }
6937
+ return true;
6938
+ }
6939
+ });
6940
+ const message = await input({
6941
+ message: "Description (max 4000 characters):",
6942
+ validate: (value) => {
6943
+ if (!value || value.trim().length === 0) {
6944
+ return "Description is required";
6945
+ }
6946
+ if (value.length > 4e3) {
6947
+ return "Description must be 4000 characters or less";
6948
+ }
6949
+ return true;
6950
+ }
6951
+ });
6952
+ const context = await collectContext();
6953
+ console.log("\n\u{1F4CB} Summary:\n");
6954
+ console.log(`Type: ${type}`);
6955
+ console.log(`Title: ${title}`);
6956
+ console.log(`Description: ${message.substring(0, 100)}${message.length > 100 ? "..." : ""}`);
6957
+ if (context) {
6958
+ console.log(`Context: OS: ${context.os}, CLI: ${context.cli_version || "unknown"}`);
6959
+ }
6960
+ const confirmed = await confirm5({
6961
+ message: "\nSubmit feedback?",
6962
+ default: true
6963
+ });
6964
+ if (!confirmed) {
6965
+ console.log("\n\u274C Cancelled.");
6966
+ return;
6967
+ }
6968
+ console.log("\n\u23F3 Submitting feedback...");
6969
+ try {
6970
+ const result = await submitFeedback(config.apiUrl, config.accessKey, {
6971
+ type,
6972
+ title: title.trim(),
6973
+ message: message.trim(),
6974
+ context
6975
+ });
6976
+ if (result.success) {
6977
+ console.log(`
6978
+ \u2705 Feedback submitted successfully!`);
6979
+ console.log(` Feedback ID: ${result.feedback_id}
6980
+ `);
6981
+ console.log(" Thank you for your feedback! We will review it soon.");
6982
+ } else {
6983
+ console.error(`
6984
+ \u274C Failed to submit feedback: ${result.error}`);
6985
+ process.exit(1);
6986
+ }
6987
+ } catch (error) {
6988
+ console.error("\n\u274C Network error:", error instanceof Error ? error.message : String(error));
6989
+ process.exit(1);
6990
+ }
6991
+ }
6992
+ async function handleNonInteractiveFeedback(config, options) {
6993
+ if (!options.type || !options.title || !options.message) {
6994
+ throw new ValidationError("Missing required fields: --type, --title, --message");
6995
+ }
6996
+ const validTypes = ["bug", "feature", "suggestion"];
6997
+ if (!validTypes.includes(options.type)) {
6998
+ throw new ValidationError(`Invalid type. Must be one of: ${validTypes.join(", ")}`);
6999
+ }
7000
+ if (options.title.length > 200) {
7001
+ throw new ValidationError("Title must be 200 characters or less");
7002
+ }
7003
+ if (options.message.length > 4e3) {
7004
+ throw new ValidationError("Message must be 4000 characters or less");
7005
+ }
7006
+ let context;
7007
+ if (!options.noContext) {
7008
+ context = await collectContext();
7009
+ if (options.context) {
7010
+ try {
7011
+ const customContext = JSON.parse(options.context);
7012
+ context = { ...context, ...customContext };
7013
+ } catch {
7014
+ throw new ValidationError("Invalid JSON in --context");
7015
+ }
7016
+ }
7017
+ }
7018
+ try {
7019
+ const result = await submitFeedback(config.apiUrl, config.accessKey, {
7020
+ type: options.type,
7021
+ title: options.title.trim(),
7022
+ message: options.message.trim(),
7023
+ context
7024
+ });
7025
+ if (result.success) {
7026
+ if (options.json) {
7027
+ console.log(JSON.stringify({ success: true, feedback_id: result.feedback_id }));
7028
+ } else {
7029
+ console.log(`\u2705 Feedback submitted: ${result.feedback_id}`);
7030
+ }
7031
+ } else {
7032
+ if (options.json) {
7033
+ console.log(JSON.stringify({ success: false, error: result.error }));
7034
+ } else {
7035
+ console.error(`\u274C Error: ${result.error}`);
7036
+ }
7037
+ process.exit(1);
7038
+ }
7039
+ } catch (error) {
7040
+ if (options.json) {
7041
+ console.log(JSON.stringify({ success: false, error: error instanceof Error ? error.message : "Unknown error" }));
7042
+ } else {
7043
+ console.error("\u274C Error:", error instanceof Error ? error.message : String(error));
7044
+ }
7045
+ process.exit(1);
7046
+ }
7047
+ }
7048
+ async function handleFeedbackCommand(options) {
7049
+ const configService = new ConfigService();
7050
+ const config = await configService.load();
7051
+ if (!config) {
7052
+ throw new ValidationError('Not initialized. Run "jai1 auth" first.');
7053
+ }
7054
+ let stdinMessage = "";
7055
+ if (!process.stdin.isTTY && !options.message) {
7056
+ const chunks = [];
7057
+ for await (const chunk of process.stdin) {
7058
+ chunks.push(chunk);
7059
+ }
7060
+ stdinMessage = Buffer.concat(chunks).toString("utf-8").trim();
7061
+ }
7062
+ if (stdinMessage) {
7063
+ options.message = stdinMessage;
7064
+ }
7065
+ const isInteractive = !options.type && !options.title && !options.message;
7066
+ if (isInteractive) {
7067
+ await handleInteractiveFeedback(config);
7068
+ } else {
7069
+ await handleNonInteractiveFeedback(config, options);
7070
+ }
7071
+ }
7072
+ function createFeedbackCommand() {
7073
+ const cmd = new Command21("feedback").alias("report").description("Submit bug reports, feature requests, or suggestions").option("--type <type>", "Feedback type: bug, feature, suggestion").option("--title <title>", "Feedback title (max 200 chars)").option("--message <message>", "Feedback message (max 4000 chars)").option("--context <json>", "Additional context as JSON").option("--no-context", "Do not include automatic context").option("--json", "Output JSON format").action(async (options) => {
7074
+ await handleFeedbackCommand(options);
7075
+ });
7076
+ return cmd;
7077
+ }
7078
+
6431
7079
  // src/commands/utils/index.ts
6432
- import { Command as Command34 } from "commander";
7080
+ import { Command as Command35 } from "commander";
6433
7081
 
6434
7082
  // src/commands/utils/password.ts
6435
- import { Command as Command21 } from "commander";
7083
+ import { Command as Command22 } from "commander";
6436
7084
 
6437
7085
  // src/services/utils.service.ts
6438
7086
  import crypto2 from "crypto";
@@ -6483,12 +7131,12 @@ var UtilsService = class {
6483
7131
  /**
6484
7132
  * Hash text or file using specified algorithm
6485
7133
  */
6486
- async hash(input4, algorithm) {
7134
+ async hash(input5, algorithm) {
6487
7135
  if (algorithm === "bcrypt") {
6488
7136
  throw new Error("Use hashBcrypt for bcrypt algorithm");
6489
7137
  }
6490
7138
  const hash = crypto2.createHash(algorithm);
6491
- hash.update(input4);
7139
+ hash.update(input5);
6492
7140
  return hash.digest("hex");
6493
7141
  }
6494
7142
  /**
@@ -6501,14 +7149,14 @@ var UtilsService = class {
6501
7149
  /**
6502
7150
  * Hash using bcrypt
6503
7151
  */
6504
- async hashBcrypt(input4, rounds = 10) {
6505
- return bcrypt.hash(input4, rounds);
7152
+ async hashBcrypt(input5, rounds = 10) {
7153
+ return bcrypt.hash(input5, rounds);
6506
7154
  }
6507
7155
  /**
6508
7156
  * Base64 encode
6509
7157
  */
6510
- base64Encode(input4, urlSafe = false) {
6511
- const buffer = typeof input4 === "string" ? Buffer.from(input4, "utf-8") : input4;
7158
+ base64Encode(input5, urlSafe = false) {
7159
+ const buffer = typeof input5 === "string" ? Buffer.from(input5, "utf-8") : input5;
6512
7160
  let encoded = buffer.toString("base64");
6513
7161
  if (urlSafe) {
6514
7162
  encoded = encoded.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
@@ -6518,8 +7166,8 @@ var UtilsService = class {
6518
7166
  /**
6519
7167
  * Base64 decode
6520
7168
  */
6521
- base64Decode(input4) {
6522
- let normalized = input4.replace(/-/g, "+").replace(/_/g, "/");
7169
+ base64Decode(input5) {
7170
+ let normalized = input5.replace(/-/g, "+").replace(/_/g, "/");
6523
7171
  while (normalized.length % 4) {
6524
7172
  normalized += "=";
6525
7173
  }
@@ -6648,14 +7296,14 @@ var UtilsService = class {
6648
7296
  /**
6649
7297
  * URL encode
6650
7298
  */
6651
- urlEncode(input4, full = false) {
6652
- return full ? encodeURI(input4) : encodeURIComponent(input4);
7299
+ urlEncode(input5, full = false) {
7300
+ return full ? encodeURI(input5) : encodeURIComponent(input5);
6653
7301
  }
6654
7302
  /**
6655
7303
  * URL decode
6656
7304
  */
6657
- urlDecode(input4, full = false) {
6658
- return full ? decodeURI(input4) : decodeURIComponent(input4);
7305
+ urlDecode(input5, full = false) {
7306
+ return full ? decodeURI(input5) : decodeURIComponent(input5);
6659
7307
  }
6660
7308
  /**
6661
7309
  * Format bytes to human-readable size
@@ -6701,7 +7349,7 @@ async function handlePasswordGeneration(options) {
6701
7349
  }
6702
7350
  }
6703
7351
  function createPasswordCommand() {
6704
- const cmd = new Command21("password").description("Generate secure random password").option("-l, --length <number>", "Password length", "16").option("--no-lowercase", "Exclude lowercase letters").option("--no-uppercase", "Exclude uppercase letters").option("--no-digits", "Exclude digits").option("--no-symbols", "Exclude symbols").option("--symbol-chars <chars>", "Custom symbol characters").option("-c, --count <number>", "Number of passwords to generate", "1").addHelpText("after", `
7352
+ const cmd = new Command22("password").description("Generate secure random password").option("-l, --length <number>", "Password length", "16").option("--no-lowercase", "Exclude lowercase letters").option("--no-uppercase", "Exclude uppercase letters").option("--no-digits", "Exclude digits").option("--no-symbols", "Exclude symbols").option("--symbol-chars <chars>", "Custom symbol characters").option("-c, --count <number>", "Number of passwords to generate", "1").addHelpText("after", `
6705
7353
  Examples:
6706
7354
  $ jai1 utils password
6707
7355
  $ jai1 utils password --length 24
@@ -6719,7 +7367,7 @@ Examples:
6719
7367
  }
6720
7368
 
6721
7369
  // src/commands/utils/uuid.ts
6722
- import { Command as Command22 } from "commander";
7370
+ import { Command as Command23 } from "commander";
6723
7371
  async function handleUuidGeneration(options) {
6724
7372
  const service = new UtilsService();
6725
7373
  try {
@@ -6747,7 +7395,7 @@ async function handleUuidGeneration(options) {
6747
7395
  }
6748
7396
  }
6749
7397
  function createUuidCommand() {
6750
- const cmd = new Command22("uuid").description("Generate UUID v4 identifier").option("-c, --count <number>", "Number of UUIDs to generate", "1").option("--uppercase", "Output in uppercase").option("--no-hyphens", "Remove hyphens from output").addHelpText("after", `
7398
+ const cmd = new Command23("uuid").description("Generate UUID v4 identifier").option("-c, --count <number>", "Number of UUIDs to generate", "1").option("--uppercase", "Output in uppercase").option("--no-hyphens", "Remove hyphens from output").addHelpText("after", `
6751
7399
  Examples:
6752
7400
  $ jai1 utils uuid
6753
7401
  $ jai1 utils uuid --count 10
@@ -6764,8 +7412,8 @@ Examples:
6764
7412
  }
6765
7413
 
6766
7414
  // src/commands/utils/hash.ts
6767
- import { Command as Command23 } from "commander";
6768
- async function handleHashGeneration(input4, options) {
7415
+ import { Command as Command24 } from "commander";
7416
+ async function handleHashGeneration(input5, options) {
6769
7417
  const service = new UtilsService();
6770
7418
  try {
6771
7419
  let hash;
@@ -6776,14 +7424,14 @@ async function handleHashGeneration(input4, options) {
6776
7424
  }
6777
7425
  hash = await service.hashFile(options.file, options.algorithm);
6778
7426
  } else {
6779
- if (!input4) {
7427
+ if (!input5) {
6780
7428
  console.error("\u274C Please provide input text or use --file option");
6781
7429
  process.exit(1);
6782
7430
  }
6783
7431
  if (options.algorithm === "bcrypt") {
6784
- hash = await service.hashBcrypt(input4, options.rounds);
7432
+ hash = await service.hashBcrypt(input5, options.rounds);
6785
7433
  } else {
6786
- hash = await service.hash(input4, options.algorithm);
7434
+ hash = await service.hash(input5, options.algorithm);
6787
7435
  }
6788
7436
  }
6789
7437
  console.log("\u{1F512} Hash Result:");
@@ -6804,7 +7452,7 @@ async function handleHashGeneration(input4, options) {
6804
7452
  }
6805
7453
  }
6806
7454
  function createHashCommand() {
6807
- const cmd = new Command23("hash").description("Generate hash (MD5, SHA, bcrypt)").argument("[input]", "Text to hash").option(
7455
+ const cmd = new Command24("hash").description("Generate hash (MD5, SHA, bcrypt)").argument("[input]", "Text to hash").option(
6808
7456
  "-a, --algorithm <algorithm>",
6809
7457
  "Hash algorithm (md5, sha1, sha256, sha512, bcrypt)",
6810
7458
  "sha256"
@@ -6816,8 +7464,8 @@ Examples:
6816
7464
  $ jai1 utils hash "password" --algorithm bcrypt --rounds 12
6817
7465
  $ jai1 utils hash --file ./myfile.txt
6818
7466
  $ jai1 utils hash --file ./image.png --algorithm sha512
6819
- `).action(async (input4, options) => {
6820
- await handleHashGeneration(input4, {
7467
+ `).action(async (input5, options) => {
7468
+ await handleHashGeneration(input5, {
6821
7469
  ...options,
6822
7470
  rounds: parseInt(options.rounds, 10)
6823
7471
  });
@@ -6826,9 +7474,9 @@ Examples:
6826
7474
  }
6827
7475
 
6828
7476
  // src/commands/utils/base64-encode.ts
6829
- import { Command as Command24 } from "commander";
7477
+ import { Command as Command25 } from "commander";
6830
7478
  import { readFile as readFile2 } from "fs/promises";
6831
- async function handleBase64Encode(input4, options) {
7479
+ async function handleBase64Encode(input5, options) {
6832
7480
  const service = new UtilsService();
6833
7481
  try {
6834
7482
  let encoded;
@@ -6836,11 +7484,11 @@ async function handleBase64Encode(input4, options) {
6836
7484
  const content = await readFile2(options.file);
6837
7485
  encoded = service.base64Encode(content, options.urlSafe);
6838
7486
  } else {
6839
- if (!input4) {
7487
+ if (!input5) {
6840
7488
  console.error("\u274C Please provide input text or use --file option");
6841
7489
  process.exit(1);
6842
7490
  }
6843
- encoded = service.base64Encode(input4, options.urlSafe);
7491
+ encoded = service.base64Encode(input5, options.urlSafe);
6844
7492
  }
6845
7493
  console.log("\u{1F4DD} Base64 Encoded:");
6846
7494
  console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
@@ -6859,33 +7507,33 @@ async function handleBase64Encode(input4, options) {
6859
7507
  }
6860
7508
  }
6861
7509
  function createBase64EncodeCommand() {
6862
- const cmd = new Command24("base64-encode").description("Encode text or file to Base64").argument("[input]", "Text to encode").option("-f, --file <path>", "Encode file contents").option("--url-safe", "Use URL-safe Base64 encoding").addHelpText("after", `
7510
+ const cmd = new Command25("base64-encode").description("Encode text or file to Base64").argument("[input]", "Text to encode").option("-f, --file <path>", "Encode file contents").option("--url-safe", "Use URL-safe Base64 encoding").addHelpText("after", `
6863
7511
  Examples:
6864
7512
  $ jai1 utils base64-encode "hello world"
6865
7513
  $ jai1 utils base64-encode "hello world" --url-safe
6866
7514
  $ jai1 utils base64-encode --file ./document.txt
6867
7515
  $ jai1 utils base64-encode --file ./image.png
6868
- `).action(async (input4, options) => {
6869
- await handleBase64Encode(input4, options);
7516
+ `).action(async (input5, options) => {
7517
+ await handleBase64Encode(input5, options);
6870
7518
  });
6871
7519
  return cmd;
6872
7520
  }
6873
7521
 
6874
7522
  // src/commands/utils/base64-decode.ts
6875
- import { Command as Command25 } from "commander";
7523
+ import { Command as Command26 } from "commander";
6876
7524
  import { readFile as readFile3, writeFile } from "fs/promises";
6877
- async function handleBase64Decode(input4, options) {
7525
+ async function handleBase64Decode(input5, options) {
6878
7526
  const service = new UtilsService();
6879
7527
  try {
6880
7528
  let encodedInput;
6881
7529
  if (options.file) {
6882
7530
  encodedInput = await readFile3(options.file, "utf-8");
6883
7531
  } else {
6884
- if (!input4) {
7532
+ if (!input5) {
6885
7533
  console.error("\u274C Please provide Base64 input or use --file option");
6886
7534
  process.exit(1);
6887
7535
  }
6888
- encodedInput = input4;
7536
+ encodedInput = input5;
6889
7537
  }
6890
7538
  const decoded = service.base64Decode(encodedInput.trim());
6891
7539
  if (options.output) {
@@ -6904,20 +7552,20 @@ async function handleBase64Decode(input4, options) {
6904
7552
  }
6905
7553
  }
6906
7554
  function createBase64DecodeCommand() {
6907
- const cmd = new Command25("base64-decode").description("Decode Base64 string").argument("[input]", "Base64 string to decode").option("-f, --file <path>", "Decode from file").option("-o, --output <path>", "Write decoded output to file").addHelpText("after", `
7555
+ const cmd = new Command26("base64-decode").description("Decode Base64 string").argument("[input]", "Base64 string to decode").option("-f, --file <path>", "Decode from file").option("-o, --output <path>", "Write decoded output to file").addHelpText("after", `
6908
7556
  Examples:
6909
7557
  $ jai1 utils base64-decode "aGVsbG8gd29ybGQ="
6910
7558
  $ jai1 utils base64-decode --file ./encoded.txt
6911
7559
  $ jai1 utils base64-decode "aGVsbG8=" --output ./decoded.txt
6912
7560
  $ jai1 utils base64-decode --file ./encoded.txt --output ./image.png
6913
- `).action(async (input4, options) => {
6914
- await handleBase64Decode(input4, options);
7561
+ `).action(async (input5, options) => {
7562
+ await handleBase64Decode(input5, options);
6915
7563
  });
6916
7564
  return cmd;
6917
7565
  }
6918
7566
 
6919
7567
  // src/commands/utils/http.ts
6920
- import { Command as Command26 } from "commander";
7568
+ import { Command as Command27 } from "commander";
6921
7569
  import { readFile as readFile4 } from "fs/promises";
6922
7570
  async function handleHttpRequest(url, options) {
6923
7571
  const service = new UtilsService();
@@ -6983,7 +7631,7 @@ async function handleHttpRequest(url, options) {
6983
7631
  }
6984
7632
  }
6985
7633
  function createHttpCommand() {
6986
- const cmd = new Command26("http").description("Make HTTP request with formatted output").argument("<url>", "Target URL").option("-X, --method <method>", "HTTP method", "GET").option("-H, --header <header...>", "Request headers (repeatable)").option("-d, --data <data>", "Request body (JSON string)").option("--file <path>", "Read body from file").option("--timeout <ms>", "Request timeout in milliseconds", "30000").option("--no-follow", "Do not follow redirects").option("--only-headers", "Show only response headers").option("--only-body", "Show only response body").addHelpText("after", `
7634
+ const cmd = new Command27("http").description("Make HTTP request with formatted output").argument("<url>", "Target URL").option("-X, --method <method>", "HTTP method", "GET").option("-H, --header <header...>", "Request headers (repeatable)").option("-d, --data <data>", "Request body (JSON string)").option("--file <path>", "Read body from file").option("--timeout <ms>", "Request timeout in milliseconds", "30000").option("--no-follow", "Do not follow redirects").option("--only-headers", "Show only response headers").option("--only-body", "Show only response body").addHelpText("after", `
6987
7635
  Examples:
6988
7636
  $ jai1 utils http https://api.example.com/users
6989
7637
  $ jai1 utils http https://api.example.com/users -X POST -d '{"name":"John"}'
@@ -7001,7 +7649,7 @@ Examples:
7001
7649
  }
7002
7650
 
7003
7651
  // src/commands/utils/jwt.ts
7004
- import { Command as Command27 } from "commander";
7652
+ import { Command as Command28 } from "commander";
7005
7653
  async function handleJwtDecode(token) {
7006
7654
  const service = new UtilsService();
7007
7655
  try {
@@ -7040,7 +7688,7 @@ async function handleJwtEncode(options) {
7040
7688
  }
7041
7689
  }
7042
7690
  function createJwtCommand() {
7043
- const jwtCommand = new Command27("jwt").description("Decode and encode JWT tokens");
7691
+ const jwtCommand = new Command28("jwt").description("Decode and encode JWT tokens");
7044
7692
  jwtCommand.command("decode").description("Decode JWT token").argument("<token>", "JWT token to decode").addHelpText("after", `
7045
7693
  Examples:
7046
7694
  $ jai1 utils jwt decode "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
@@ -7061,11 +7709,11 @@ Examples:
7061
7709
  }
7062
7710
 
7063
7711
  // src/commands/utils/unix-time.ts
7064
- import { Command as Command28 } from "commander";
7065
- async function handleUnixTime(input4, options) {
7712
+ import { Command as Command29 } from "commander";
7713
+ async function handleUnixTime(input5, options) {
7066
7714
  const service = new UtilsService();
7067
7715
  try {
7068
- if (!input4) {
7716
+ if (!input5) {
7069
7717
  const now = /* @__PURE__ */ new Date();
7070
7718
  const timestamp = service.dateToUnix(now, options.ms);
7071
7719
  console.log("\u{1F552} Current Unix Timestamp:");
@@ -7075,8 +7723,8 @@ async function handleUnixTime(input4, options) {
7075
7723
  console.log(` ISO: ${now.toISOString()}`);
7076
7724
  console.log(` Local: ${now.toLocaleString()}`);
7077
7725
  console.log();
7078
- } else if (/^\d+$/.test(input4)) {
7079
- const timestamp = parseInt(input4, 10);
7726
+ } else if (/^\d+$/.test(input5)) {
7727
+ const timestamp = parseInt(input5, 10);
7080
7728
  const date = service.unixToDate(timestamp, options.ms);
7081
7729
  console.log("\u{1F552} Unix Timestamp to Date:");
7082
7730
  console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
@@ -7089,7 +7737,7 @@ async function handleUnixTime(input4, options) {
7089
7737
  }
7090
7738
  console.log();
7091
7739
  } else {
7092
- const date = new Date(input4);
7740
+ const date = new Date(input5);
7093
7741
  if (isNaN(date.getTime())) {
7094
7742
  console.error("\u274C Invalid date format");
7095
7743
  process.exit(1);
@@ -7097,7 +7745,7 @@ async function handleUnixTime(input4, options) {
7097
7745
  const timestamp = service.dateToUnix(date, options.ms);
7098
7746
  console.log("\u{1F552} Date to Unix Timestamp:");
7099
7747
  console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
7100
- console.log(` Input: ${input4}`);
7748
+ console.log(` Input: ${input5}`);
7101
7749
  console.log(` Parsed: ${date.toISOString()}`);
7102
7750
  console.log();
7103
7751
  console.log(` ${timestamp}${options.ms ? " (ms)" : ""}`);
@@ -7109,7 +7757,7 @@ async function handleUnixTime(input4, options) {
7109
7757
  }
7110
7758
  }
7111
7759
  function createUnixTimeCommand() {
7112
- const cmd = new Command28("unix-time").description("Convert unix timestamps to/from dates").argument("[input]", "Unix timestamp or date string").option("-f, --format <format>", "Output format (iso, local, utc)", "iso").option("--ms", "Use milliseconds instead of seconds").addHelpText("after", `
7760
+ const cmd = new Command29("unix-time").description("Convert unix timestamps to/from dates").argument("[input]", "Unix timestamp or date string").option("-f, --format <format>", "Output format (iso, local, utc)", "iso").option("--ms", "Use milliseconds instead of seconds").addHelpText("after", `
7113
7761
  Examples:
7114
7762
  $ jai1 utils unix-time
7115
7763
  $ jai1 utils unix-time 1702550400
@@ -7117,14 +7765,14 @@ Examples:
7117
7765
  $ jai1 utils unix-time "2024-01-15 10:30:00"
7118
7766
  $ jai1 utils unix-time "2024-01-15" --format local
7119
7767
  $ jai1 utils unix-time --ms
7120
- `).action(async (input4, options) => {
7121
- await handleUnixTime(input4, options);
7768
+ `).action(async (input5, options) => {
7769
+ await handleUnixTime(input5, options);
7122
7770
  });
7123
7771
  return cmd;
7124
7772
  }
7125
7773
 
7126
7774
  // src/commands/utils/timezone.ts
7127
- import { Command as Command29 } from "commander";
7775
+ import { Command as Command30 } from "commander";
7128
7776
  async function handleTimezoneConversion(time, options) {
7129
7777
  const service = new UtilsService();
7130
7778
  try {
@@ -7161,7 +7809,7 @@ async function handleTimezoneConversion(time, options) {
7161
7809
  }
7162
7810
  }
7163
7811
  function createTimezoneCommand() {
7164
- const cmd = new Command29("timezone").description("Convert time between timezones").argument("[time]", 'Time to convert (e.g., "2024-01-15 10:00")').option("--from <timezone>", "Source timezone").option("--to <timezone>", "Target timezone").option("--list", "Show available timezones").addHelpText("after", `
7812
+ const cmd = new Command30("timezone").description("Convert time between timezones").argument("[time]", 'Time to convert (e.g., "2024-01-15 10:00")').option("--from <timezone>", "Source timezone").option("--to <timezone>", "Target timezone").option("--list", "Show available timezones").addHelpText("after", `
7165
7813
  Examples:
7166
7814
  $ jai1 utils timezone --list
7167
7815
  $ jai1 utils timezone "2024-01-15 10:00" --from "America/New_York" --to "Asia/Tokyo"
@@ -7174,11 +7822,11 @@ Examples:
7174
7822
  }
7175
7823
 
7176
7824
  // src/commands/utils/url-encode.ts
7177
- import { Command as Command30 } from "commander";
7178
- async function handleUrlEncode(input4, options) {
7825
+ import { Command as Command31 } from "commander";
7826
+ async function handleUrlEncode(input5, options) {
7179
7827
  const service = new UtilsService();
7180
7828
  try {
7181
- const encoded = service.urlEncode(input4, options.full);
7829
+ const encoded = service.urlEncode(input5, options.full);
7182
7830
  console.log("\u{1F517} URL Encoded:");
7183
7831
  console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
7184
7832
  if (options.full) {
@@ -7195,24 +7843,24 @@ async function handleUrlEncode(input4, options) {
7195
7843
  }
7196
7844
  }
7197
7845
  function createUrlEncodeCommand() {
7198
- const cmd = new Command30("url-encode").description("Encode URL component or full URL").argument("<input>", "Text to encode").option("--full", "Encode full URL (use encodeURI instead of encodeURIComponent)").addHelpText("after", `
7846
+ const cmd = new Command31("url-encode").description("Encode URL component or full URL").argument("<input>", "Text to encode").option("--full", "Encode full URL (use encodeURI instead of encodeURIComponent)").addHelpText("after", `
7199
7847
  Examples:
7200
7848
  $ jai1 utils url-encode "hello world"
7201
7849
  $ jai1 utils url-encode "hello world & test"
7202
7850
  $ jai1 utils url-encode "name=John Doe&age=30"
7203
7851
  $ jai1 utils url-encode "https://example.com/path with spaces" --full
7204
- `).showHelpAfterError("(add --help for additional examples)").action(async (input4, options) => {
7205
- await handleUrlEncode(input4, options);
7852
+ `).showHelpAfterError("(add --help for additional examples)").action(async (input5, options) => {
7853
+ await handleUrlEncode(input5, options);
7206
7854
  });
7207
7855
  return cmd;
7208
7856
  }
7209
7857
 
7210
7858
  // src/commands/utils/url-decode.ts
7211
- import { Command as Command31 } from "commander";
7212
- async function handleUrlDecode(input4, options) {
7859
+ import { Command as Command32 } from "commander";
7860
+ async function handleUrlDecode(input5, options) {
7213
7861
  const service = new UtilsService();
7214
7862
  try {
7215
- const decoded = service.urlDecode(input4, options.full);
7863
+ const decoded = service.urlDecode(input5, options.full);
7216
7864
  console.log("\u{1F517} URL Decoded:");
7217
7865
  console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
7218
7866
  if (options.full) {
@@ -7229,20 +7877,20 @@ async function handleUrlDecode(input4, options) {
7229
7877
  }
7230
7878
  }
7231
7879
  function createUrlDecodeCommand() {
7232
- const cmd = new Command31("url-decode").description("Decode URL-encoded string").argument("<input>", "Text to decode").option("--full", "Decode full URL (use decodeURI instead of decodeURIComponent)").addHelpText("after", `
7880
+ const cmd = new Command32("url-decode").description("Decode URL-encoded string").argument("<input>", "Text to decode").option("--full", "Decode full URL (use decodeURI instead of decodeURIComponent)").addHelpText("after", `
7233
7881
  Examples:
7234
7882
  $ jai1 utils url-decode "hello%20world"
7235
7883
  $ jai1 utils url-decode "hello%20world%20%26%20test"
7236
7884
  $ jai1 utils url-decode "name%3DJohn%20Doe%26age%3D30"
7237
7885
  $ jai1 utils url-decode "https://example.com/path%20with%20spaces" --full
7238
- `).showHelpAfterError("(add --help for additional examples)").action(async (input4, options) => {
7239
- await handleUrlDecode(input4, options);
7886
+ `).showHelpAfterError("(add --help for additional examples)").action(async (input5, options) => {
7887
+ await handleUrlDecode(input5, options);
7240
7888
  });
7241
7889
  return cmd;
7242
7890
  }
7243
7891
 
7244
7892
  // src/commands/utils/cron.ts
7245
- import { Command as Command32 } from "commander";
7893
+ import { Command as Command33 } from "commander";
7246
7894
  import cronstrue from "cronstrue";
7247
7895
  async function handleCronParse(expression) {
7248
7896
  try {
@@ -7285,7 +7933,7 @@ async function handleCronParse(expression) {
7285
7933
  }
7286
7934
  }
7287
7935
  function createCronCommand() {
7288
- const cmd = new Command32("cron").description("Parse and explain cron expression").argument("<expression>", 'Cron expression (e.g., "0 5 * * *")').addHelpText("after", `
7936
+ const cmd = new Command33("cron").description("Parse and explain cron expression").argument("<expression>", 'Cron expression (e.g., "0 5 * * *")').addHelpText("after", `
7289
7937
  Examples:
7290
7938
  $ jai1 utils cron "0 5 * * *"
7291
7939
  $ jai1 utils cron "*/15 * * * *"
@@ -7299,7 +7947,7 @@ Examples:
7299
7947
  }
7300
7948
 
7301
7949
  // src/commands/utils/markdown-preview.ts
7302
- import { Command as Command33 } from "commander";
7950
+ import { Command as Command34 } from "commander";
7303
7951
  import { readFile as readFile5 } from "fs/promises";
7304
7952
  import { marked } from "marked";
7305
7953
  import TerminalRenderer from "marked-terminal";
@@ -7338,7 +7986,7 @@ ${code.trim()}
7338
7986
  }
7339
7987
  }
7340
7988
  function createMarkdownPreviewCommand() {
7341
- const cmd = new Command33("markdown-preview").description("Preview markdown file in terminal").argument("<file>", "Markdown file path").option("--raw", "Show raw markdown instead of rendered").addHelpText("after", `
7989
+ const cmd = new Command34("markdown-preview").description("Preview markdown file in terminal").argument("<file>", "Markdown file path").option("--raw", "Show raw markdown instead of rendered").addHelpText("after", `
7342
7990
  Examples:
7343
7991
  $ jai1 utils markdown-preview README.md
7344
7992
  $ jai1 utils markdown-preview ./docs/guide.md
@@ -7372,14 +8020,14 @@ var PasswordView = () => {
7372
8020
  React27.useEffect(() => {
7373
8021
  handleGenerate();
7374
8022
  }, []);
7375
- useInput12((input4, key) => {
8023
+ useInput12((input5, key) => {
7376
8024
  if (key.tab) {
7377
8025
  if (focusedField === "length") setFocusedField("count");
7378
8026
  else if (focusedField === "count") setFocusedField("generate");
7379
8027
  else setFocusedField("length");
7380
8028
  } else if (key.return) {
7381
8029
  handleGenerate();
7382
- } else if (input4 === "c" && passwords.length > 0) {
8030
+ } else if (input5 === "c" && passwords.length > 0) {
7383
8031
  handleCopy(0);
7384
8032
  }
7385
8033
  });
@@ -7462,7 +8110,7 @@ var UuidView = () => {
7462
8110
  React28.useEffect(() => {
7463
8111
  handleGenerate();
7464
8112
  }, []);
7465
- useInput13((input4, key) => {
8113
+ useInput13((input5, key) => {
7466
8114
  if (key.tab) {
7467
8115
  const fields = ["count", "uppercase", "hyphens", "generate"];
7468
8116
  const currentIndex = fields.indexOf(focusedField);
@@ -7475,7 +8123,7 @@ var UuidView = () => {
7475
8123
  } else {
7476
8124
  handleGenerate();
7477
8125
  }
7478
- } else if (input4 === "c" && uuids.length > 0) {
8126
+ } else if (input5 === "c" && uuids.length > 0) {
7479
8127
  handleCopy(0);
7480
8128
  }
7481
8129
  });
@@ -7550,7 +8198,7 @@ var HashView = () => {
7550
8198
  React29.useEffect(() => {
7551
8199
  handleGenerate();
7552
8200
  }, []);
7553
- useInput14((input4, key) => {
8201
+ useInput14((input5, key) => {
7554
8202
  if (key.tab) {
7555
8203
  const fields = ["text", "algorithm", "generate"];
7556
8204
  const currentIndex = fields.indexOf(focusedField);
@@ -7563,7 +8211,7 @@ var HashView = () => {
7563
8211
  } else if (key.rightArrow && focusedField === "algorithm") {
7564
8212
  const currentIndex = ALGORITHMS.indexOf(algorithm);
7565
8213
  setAlgorithm(ALGORITHMS[(currentIndex + 1) % ALGORITHMS.length]);
7566
- } else if (input4 === "c" && hash) {
8214
+ } else if (input5 === "c" && hash) {
7567
8215
  handleCopy();
7568
8216
  }
7569
8217
  });
@@ -7629,7 +8277,7 @@ import React30, { useState as useState17 } from "react";
7629
8277
  import { Box as Box20, Text as Text21, useInput as useInput15 } from "ink";
7630
8278
  import TextInput7 from "ink-text-input";
7631
8279
  var Base64View = () => {
7632
- const [input4, setInput] = useState17("");
8280
+ const [input5, setInput] = useState17("");
7633
8281
  const [mode, setMode] = useState17("encode");
7634
8282
  const [urlSafe, setUrlSafe] = useState17(false);
7635
8283
  const [result, setResult] = useState17("");
@@ -7637,7 +8285,7 @@ var Base64View = () => {
7637
8285
  const [focusedField, setFocusedField] = useState17("input");
7638
8286
  const [copied, setCopied] = useState17(false);
7639
8287
  const service = new UtilsService();
7640
- useInput15((input5, key) => {
8288
+ useInput15((input6, key) => {
7641
8289
  if (key.tab) {
7642
8290
  const fields = ["input", "mode", "urlsafe", "convert"];
7643
8291
  const currentIndex = fields.indexOf(focusedField);
@@ -7652,22 +8300,22 @@ var Base64View = () => {
7652
8300
  } else {
7653
8301
  handleConvert();
7654
8302
  }
7655
- } else if (input5 === "c" && result) {
8303
+ } else if (input6 === "c" && result) {
7656
8304
  handleCopy();
7657
8305
  }
7658
8306
  });
7659
8307
  const handleConvert = () => {
7660
- if (!input4) {
8308
+ if (!input5) {
7661
8309
  setError("Input cannot be empty");
7662
8310
  return;
7663
8311
  }
7664
8312
  try {
7665
8313
  setError("");
7666
8314
  if (mode === "encode") {
7667
- const encoded = service.base64Encode(input4, urlSafe);
8315
+ const encoded = service.base64Encode(input5, urlSafe);
7668
8316
  setResult(encoded);
7669
8317
  } else {
7670
- const decoded = service.base64Decode(input4);
8318
+ const decoded = service.base64Decode(input5);
7671
8319
  setResult(decoded.toString("utf-8"));
7672
8320
  }
7673
8321
  setCopied(false);
@@ -7696,7 +8344,7 @@ var Base64View = () => {
7696
8344
  marginBottom: 1
7697
8345
  },
7698
8346
  /* @__PURE__ */ React30.createElement(Text21, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
7699
- /* @__PURE__ */ React30.createElement(Box20, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React30.createElement(Box20, { marginBottom: 0 }, /* @__PURE__ */ React30.createElement(Text21, { color: focusedField === "input" ? "green" : void 0 }, focusedField === "input" ? "\u25B6 " : " ", "Input text:")), /* @__PURE__ */ React30.createElement(Box20, { marginLeft: 2, width: 60 }, focusedField === "input" ? /* @__PURE__ */ React30.createElement(TextInput7, { value: input4, onChange: setInput, placeholder: "Enter text..." }) : /* @__PURE__ */ React30.createElement(Text21, { dimColor: !input4 }, input4 || "(empty)"))),
8347
+ /* @__PURE__ */ React30.createElement(Box20, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React30.createElement(Box20, { marginBottom: 0 }, /* @__PURE__ */ React30.createElement(Text21, { color: focusedField === "input" ? "green" : void 0 }, focusedField === "input" ? "\u25B6 " : " ", "Input text:")), /* @__PURE__ */ React30.createElement(Box20, { marginLeft: 2, width: 60 }, focusedField === "input" ? /* @__PURE__ */ React30.createElement(TextInput7, { value: input5, onChange: setInput, placeholder: "Enter text..." }) : /* @__PURE__ */ React30.createElement(Text21, { dimColor: !input5 }, input5 || "(empty)"))),
7700
8348
  /* @__PURE__ */ React30.createElement(Box20, { marginBottom: 1 }, /* @__PURE__ */ React30.createElement(Box20, { width: 20 }, /* @__PURE__ */ React30.createElement(Text21, { color: focusedField === "mode" ? "green" : void 0 }, focusedField === "mode" ? "\u25B6 " : " ", "Mode:")), /* @__PURE__ */ React30.createElement(Text21, { bold: true, color: focusedField === "mode" ? "yellow" : void 0 }, mode === "encode" ? "ENCODE" : "DECODE"), focusedField === "mode" && /* @__PURE__ */ React30.createElement(Text21, { dimColor: true }, " (Enter to toggle)")),
7701
8349
  mode === "encode" && /* @__PURE__ */ React30.createElement(Box20, { marginBottom: 1 }, /* @__PURE__ */ React30.createElement(Text21, { color: focusedField === "urlsafe" ? "green" : void 0 }, focusedField === "urlsafe" ? "\u25B6 " : " ", "[", urlSafe ? "\u2713" : " ", "] URL-Safe (+ \u2192 -, / \u2192 _)")),
7702
8350
  /* @__PURE__ */ React30.createElement(Box20, { marginTop: 1 }, /* @__PURE__ */ React30.createElement(
@@ -7741,14 +8389,14 @@ import React31, { useState as useState18 } from "react";
7741
8389
  import { Box as Box21, Text as Text22, useInput as useInput16 } from "ink";
7742
8390
  import TextInput8 from "ink-text-input";
7743
8391
  var UrlView = () => {
7744
- const [input4, setInput] = useState18("");
8392
+ const [input5, setInput] = useState18("");
7745
8393
  const [mode, setMode] = useState18("encode");
7746
8394
  const [fullUrl, setFullUrl] = useState18(false);
7747
8395
  const [result, setResult] = useState18("");
7748
8396
  const [focusedField, setFocusedField] = useState18("input");
7749
8397
  const [copied, setCopied] = useState18(false);
7750
8398
  const service = new UtilsService();
7751
- useInput16((input5, key) => {
8399
+ useInput16((input6, key) => {
7752
8400
  if (key.tab) {
7753
8401
  const fields = ["input", "mode", "full", "convert"];
7754
8402
  const currentIndex = fields.indexOf(focusedField);
@@ -7762,17 +8410,17 @@ var UrlView = () => {
7762
8410
  } else {
7763
8411
  handleConvert();
7764
8412
  }
7765
- } else if (input5 === "c" && result) {
8413
+ } else if (input6 === "c" && result) {
7766
8414
  handleCopy();
7767
8415
  }
7768
8416
  });
7769
8417
  const handleConvert = () => {
7770
- if (!input4) return;
8418
+ if (!input5) return;
7771
8419
  if (mode === "encode") {
7772
- const encoded = fullUrl ? service.urlEncode(input4, true) : service.urlEncode(input4, false);
8420
+ const encoded = fullUrl ? service.urlEncode(input5, true) : service.urlEncode(input5, false);
7773
8421
  setResult(encoded);
7774
8422
  } else {
7775
- const decoded = fullUrl ? service.urlDecode(input4, true) : service.urlDecode(input4, false);
8423
+ const decoded = fullUrl ? service.urlDecode(input5, true) : service.urlDecode(input5, false);
7776
8424
  setResult(decoded);
7777
8425
  }
7778
8426
  setCopied(false);
@@ -7797,7 +8445,7 @@ var UrlView = () => {
7797
8445
  marginBottom: 1
7798
8446
  },
7799
8447
  /* @__PURE__ */ React31.createElement(Text22, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
7800
- /* @__PURE__ */ React31.createElement(Box21, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React31.createElement(Box21, { marginBottom: 0 }, /* @__PURE__ */ React31.createElement(Text22, { color: focusedField === "input" ? "green" : void 0 }, focusedField === "input" ? "\u25B6 " : " ", "Input text:")), /* @__PURE__ */ React31.createElement(Box21, { marginLeft: 2, width: 60 }, focusedField === "input" ? /* @__PURE__ */ React31.createElement(TextInput8, { value: input4, onChange: setInput, placeholder: "Enter text or URL..." }) : /* @__PURE__ */ React31.createElement(Text22, { dimColor: !input4 }, input4 || "(empty)"))),
8448
+ /* @__PURE__ */ React31.createElement(Box21, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React31.createElement(Box21, { marginBottom: 0 }, /* @__PURE__ */ React31.createElement(Text22, { color: focusedField === "input" ? "green" : void 0 }, focusedField === "input" ? "\u25B6 " : " ", "Input text:")), /* @__PURE__ */ React31.createElement(Box21, { marginLeft: 2, width: 60 }, focusedField === "input" ? /* @__PURE__ */ React31.createElement(TextInput8, { value: input5, onChange: setInput, placeholder: "Enter text or URL..." }) : /* @__PURE__ */ React31.createElement(Text22, { dimColor: !input5 }, input5 || "(empty)"))),
7801
8449
  /* @__PURE__ */ React31.createElement(Box21, { marginBottom: 1 }, /* @__PURE__ */ React31.createElement(Box21, { width: 20 }, /* @__PURE__ */ React31.createElement(Text22, { color: focusedField === "mode" ? "green" : void 0 }, focusedField === "mode" ? "\u25B6 " : " ", "Mode:")), /* @__PURE__ */ React31.createElement(Text22, { bold: true, color: focusedField === "mode" ? "yellow" : void 0 }, mode === "encode" ? "ENCODE" : "DECODE"), focusedField === "mode" && /* @__PURE__ */ React31.createElement(Text22, { dimColor: true }, " (Enter to toggle)")),
7802
8450
  /* @__PURE__ */ React31.createElement(Box21, { marginBottom: 1 }, /* @__PURE__ */ React31.createElement(Text22, { color: focusedField === "full" ? "green" : void 0 }, focusedField === "full" ? "\u25B6 " : " ", "[", fullUrl ? "\u2713" : " ", "] Full URL (encode/decode entire URL)")),
7803
8451
  /* @__PURE__ */ React31.createElement(Box21, { marginTop: 1 }, /* @__PURE__ */ React31.createElement(
@@ -7831,7 +8479,7 @@ import React32, { useState as useState19 } from "react";
7831
8479
  import { Box as Box22, Text as Text23, useInput as useInput17 } from "ink";
7832
8480
  import TextInput9 from "ink-text-input";
7833
8481
  var UnixTimeView = () => {
7834
- const [input4, setInput] = useState19("");
8482
+ const [input5, setInput] = useState19("");
7835
8483
  const [mode, setMode] = useState19("now");
7836
8484
  const [format, setFormat] = useState19("iso");
7837
8485
  const [useMs, setUseMs] = useState19(false);
@@ -7840,7 +8488,7 @@ var UnixTimeView = () => {
7840
8488
  const [focusedField, setFocusedField] = useState19("mode");
7841
8489
  const [copied, setCopied] = useState19(false);
7842
8490
  const service = new UtilsService();
7843
- useInput17((input5, key) => {
8491
+ useInput17((input6, key) => {
7844
8492
  if (key.tab) {
7845
8493
  const fields = mode === "now" ? ["mode", "ms", "convert"] : mode === "to-human" ? ["mode", "input", "format", "convert"] : ["mode", "input", "convert"];
7846
8494
  const currentIndex = fields.indexOf(focusedField);
@@ -7861,7 +8509,7 @@ var UnixTimeView = () => {
7861
8509
  } else {
7862
8510
  handleConvert();
7863
8511
  }
7864
- } else if (input5 === "c" && result) {
8512
+ } else if (input6 === "c" && result) {
7865
8513
  handleCopy();
7866
8514
  }
7867
8515
  });
@@ -7872,18 +8520,18 @@ var UnixTimeView = () => {
7872
8520
  const timestamp = service.unixTimeCurrent(useMs);
7873
8521
  setResult(timestamp.toString());
7874
8522
  } else if (mode === "to-human") {
7875
- if (!input4) {
8523
+ if (!input5) {
7876
8524
  setError("Please enter a timestamp");
7877
8525
  return;
7878
8526
  }
7879
- const human = service.unixTimeToHuman(parseInt(input4, 10), format);
8527
+ const human = service.unixTimeToHuman(parseInt(input5, 10), format);
7880
8528
  setResult(human);
7881
8529
  } else {
7882
- if (!input4) {
8530
+ if (!input5) {
7883
8531
  setError("Please enter a date string");
7884
8532
  return;
7885
8533
  }
7886
- const timestamp = service.unixTimeFromString(input4);
8534
+ const timestamp = service.unixTimeFromString(input5);
7887
8535
  setResult(timestamp.toString());
7888
8536
  }
7889
8537
  setCopied(false);
@@ -7916,11 +8564,11 @@ var UnixTimeView = () => {
7916
8564
  mode !== "now" && /* @__PURE__ */ React32.createElement(Box22, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React32.createElement(Box22, { marginBottom: 0 }, /* @__PURE__ */ React32.createElement(Text23, { color: focusedField === "input" ? "green" : void 0 }, focusedField === "input" ? "\u25B6 " : " ", mode === "to-human" ? "Timestamp:" : "Date string:")), /* @__PURE__ */ React32.createElement(Box22, { marginLeft: 2, width: 50 }, focusedField === "input" ? /* @__PURE__ */ React32.createElement(
7917
8565
  TextInput9,
7918
8566
  {
7919
- value: input4,
8567
+ value: input5,
7920
8568
  onChange: setInput,
7921
8569
  placeholder: mode === "to-human" ? "1702550400" : "2024-01-15 10:30:00"
7922
8570
  }
7923
- ) : /* @__PURE__ */ React32.createElement(Text23, { dimColor: !input4 }, input4 || "(empty)"))),
8571
+ ) : /* @__PURE__ */ React32.createElement(Text23, { dimColor: !input5 }, input5 || "(empty)"))),
7924
8572
  mode === "to-human" && /* @__PURE__ */ React32.createElement(Box22, { marginBottom: 1 }, /* @__PURE__ */ React32.createElement(Box22, { width: 20 }, /* @__PURE__ */ React32.createElement(Text23, { color: focusedField === "format" ? "green" : void 0 }, focusedField === "format" ? "\u25B6 " : " ", "Format:")), /* @__PURE__ */ React32.createElement(Text23, { bold: true, color: focusedField === "format" ? "yellow" : void 0 }, format.toUpperCase()), focusedField === "format" && /* @__PURE__ */ React32.createElement(Text23, { dimColor: true }, " (Enter to cycle)")),
7925
8573
  mode === "now" && /* @__PURE__ */ React32.createElement(Box22, { marginBottom: 1 }, /* @__PURE__ */ React32.createElement(Text23, { color: focusedField === "ms" ? "green" : void 0 }, focusedField === "ms" ? "\u25B6 " : " ", "[", useMs ? "\u2713" : " ", "] Milliseconds")),
7926
8574
  /* @__PURE__ */ React32.createElement(Box22, { marginTop: 1 }, /* @__PURE__ */ React32.createElement(
@@ -7974,7 +8622,7 @@ var JwtView = () => {
7974
8622
  const [focusedField, setFocusedField] = useState20("mode");
7975
8623
  const [copied, setCopied] = useState20(false);
7976
8624
  const service = new UtilsService();
7977
- useInput18((input4, key) => {
8625
+ useInput18((input5, key) => {
7978
8626
  if (key.tab) {
7979
8627
  const fields = mode === "decode" ? ["mode", "token", "process"] : ["mode", "payload", "secret", "process"];
7980
8628
  const currentIndex = fields.indexOf(focusedField);
@@ -7987,7 +8635,7 @@ var JwtView = () => {
7987
8635
  } else {
7988
8636
  handleProcess();
7989
8637
  }
7990
- } else if (input4 === "c" && result.token) {
8638
+ } else if (input5 === "c" && result.token) {
7991
8639
  handleCopy();
7992
8640
  }
7993
8641
  });
@@ -8112,12 +8760,12 @@ var CronView = () => {
8112
8760
  const [focusedField, setFocusedField] = useState21("expression");
8113
8761
  const [copied, setCopied] = useState21(false);
8114
8762
  const service = new UtilsService();
8115
- useInput19((input4, key) => {
8763
+ useInput19((input5, key) => {
8116
8764
  if (key.tab) {
8117
8765
  setFocusedField(focusedField === "expression" ? "parse" : "expression");
8118
8766
  } else if (key.return) {
8119
8767
  handleParse();
8120
- } else if (input4 === "c" && result) {
8768
+ } else if (input5 === "c" && result) {
8121
8769
  handleCopy();
8122
8770
  }
8123
8771
  });
@@ -8218,14 +8866,14 @@ var TimezoneView = () => {
8218
8866
  const [focusedField, setFocusedField] = useState22("time");
8219
8867
  const [copied, setCopied] = useState22(false);
8220
8868
  const service = new UtilsService();
8221
- useInput20((input4, key) => {
8869
+ useInput20((input5, key) => {
8222
8870
  if (key.tab) {
8223
8871
  const fields = ["time", "from", "to", "convert"];
8224
8872
  const currentIndex = fields.indexOf(focusedField);
8225
8873
  setFocusedField(fields[(currentIndex + 1) % fields.length]);
8226
8874
  } else if (key.return) {
8227
8875
  handleConvert();
8228
- } else if (input4 === "c" && result) {
8876
+ } else if (input5 === "c" && result) {
8229
8877
  handleCopy();
8230
8878
  }
8231
8879
  });
@@ -8344,7 +8992,7 @@ var HttpView = () => {
8344
8992
  const [focusedField, setFocusedField] = useState23("url");
8345
8993
  const [copied, setCopied] = useState23(false);
8346
8994
  const service = new UtilsService();
8347
- useInput21((input4, key) => {
8995
+ useInput21((input5, key) => {
8348
8996
  if (loading) return;
8349
8997
  if (key.tab) {
8350
8998
  const fields = ["url", "method", "headers", "body", "send"];
@@ -8358,7 +9006,7 @@ var HttpView = () => {
8358
9006
  setMethod(METHODS[(currentIndex + 1) % METHODS.length]);
8359
9007
  } else if (key.return && focusedField === "send") {
8360
9008
  handleSend();
8361
- } else if (input4 === "c" && response) {
9009
+ } else if (input5 === "c" && response) {
8362
9010
  handleCopy();
8363
9011
  }
8364
9012
  });
@@ -8482,14 +9130,14 @@ var HttpView = () => {
8482
9130
  import React37, { useState as useState24 } from "react";
8483
9131
  import { Box as Box27, Text as Text28, useInput as useInput22 } from "ink";
8484
9132
  import TextInput14 from "ink-text-input";
8485
- import * as fs10 from "fs";
8486
- import * as path6 from "path";
9133
+ import * as fs12 from "fs";
9134
+ import * as path7 from "path";
8487
9135
  var MarkdownView = () => {
8488
9136
  const [filePath, setFilePath] = useState24("");
8489
9137
  const [content, setContent] = useState24("");
8490
9138
  const [error, setError] = useState24("");
8491
9139
  const [focusedField, setFocusedField] = useState24("file");
8492
- useInput22((input4, key) => {
9140
+ useInput22((input5, key) => {
8493
9141
  if (key.tab) {
8494
9142
  setFocusedField(focusedField === "file" ? "preview" : "file");
8495
9143
  } else if (key.return) {
@@ -8503,12 +9151,12 @@ var MarkdownView = () => {
8503
9151
  }
8504
9152
  try {
8505
9153
  setError("");
8506
- const resolvedPath = path6.resolve(filePath);
8507
- if (!fs10.existsSync(resolvedPath)) {
9154
+ const resolvedPath = path7.resolve(filePath);
9155
+ if (!fs12.existsSync(resolvedPath)) {
8508
9156
  setError(`File not found: ${resolvedPath}`);
8509
9157
  return;
8510
9158
  }
8511
- let fileContent = fs10.readFileSync(resolvedPath, "utf-8");
9159
+ let fileContent = fs12.readFileSync(resolvedPath, "utf-8");
8512
9160
  fileContent = fileContent.replace(/```mermaid\n([\s\S]*?)```/g, (match, code) => {
8513
9161
  return `
8514
9162
  \u{1F3A8} **Mermaid Diagram**
@@ -8604,20 +9252,20 @@ var UtilsApp = ({ onExit }) => {
8604
9252
  const [selectedIndex, setSelectedIndex] = useState25(0);
8605
9253
  const [activeView, setActiveView] = useState25(null);
8606
9254
  const { exit } = useApp5();
8607
- useInput23((input4, key) => {
9255
+ useInput23((input5, key) => {
8608
9256
  if (activeView) {
8609
9257
  if (key.escape) {
8610
9258
  setActiveView(null);
8611
9259
  }
8612
9260
  return;
8613
9261
  }
8614
- if (key.upArrow || input4 === "k") {
9262
+ if (key.upArrow || input5 === "k") {
8615
9263
  setSelectedIndex((prev) => prev > 0 ? prev - 1 : MENU_ITEMS2.length - 1);
8616
- } else if (key.downArrow || input4 === "j") {
9264
+ } else if (key.downArrow || input5 === "j") {
8617
9265
  setSelectedIndex((prev) => prev < MENU_ITEMS2.length - 1 ? prev + 1 : 0);
8618
9266
  } else if (key.return) {
8619
9267
  setActiveView(MENU_ITEMS2[selectedIndex].id);
8620
- } else if (input4 === "q" || key.escape) {
9268
+ } else if (input5 === "q" || key.escape) {
8621
9269
  onExit();
8622
9270
  exit();
8623
9271
  }
@@ -8747,7 +9395,7 @@ async function runInteractiveMode() {
8747
9395
 
8748
9396
  // src/commands/utils/index.ts
8749
9397
  function createUtilsCommand() {
8750
- const utilsCommand = new Command34("utils").description("Developer utilities for common tasks").option("-i, --interactive", "Run in interactive mode").addHelpText("after", `
9398
+ const utilsCommand = new Command35("utils").description("Developer utilities for common tasks").option("-i, --interactive", "Run in interactive mode").addHelpText("after", `
8751
9399
  Interactive Mode:
8752
9400
  $ jai1 utils --interactive
8753
9401
  $ jai1 utils -i
@@ -8782,15 +9430,15 @@ Quick Usage:
8782
9430
  }
8783
9431
 
8784
9432
  // src/commands/deps/index.ts
8785
- import { Command as Command36 } from "commander";
9433
+ import { Command as Command37 } from "commander";
8786
9434
 
8787
9435
  // src/commands/deps/upgrade.ts
8788
- import { Command as Command35 } from "commander";
8789
- import { checkbox as checkbox3, confirm as confirm5 } from "@inquirer/prompts";
9436
+ import { Command as Command36 } from "commander";
9437
+ import { checkbox as checkbox3, confirm as confirm6 } from "@inquirer/prompts";
8790
9438
 
8791
9439
  // src/services/deps.service.ts
8792
- import { promises as fs11 } from "fs";
8793
- import path7 from "path";
9440
+ import { promises as fs13 } from "fs";
9441
+ import path8 from "path";
8794
9442
  import { execSync } from "child_process";
8795
9443
  import pLimit2 from "p-limit";
8796
9444
  var DepsService = class {
@@ -8799,9 +9447,9 @@ var DepsService = class {
8799
9447
  * Đọc package.json từ thư mục
8800
9448
  */
8801
9449
  async readPackageJson(cwd) {
8802
- const pkgPath = path7.join(cwd, "package.json");
9450
+ const pkgPath = path8.join(cwd, "package.json");
8803
9451
  try {
8804
- const content = await fs11.readFile(pkgPath, "utf-8");
9452
+ const content = await fs13.readFile(pkgPath, "utf-8");
8805
9453
  return JSON.parse(content);
8806
9454
  } catch (error) {
8807
9455
  if (error.code === "ENOENT") {
@@ -8907,7 +9555,7 @@ var DepsService = class {
8907
9555
  ];
8908
9556
  for (const { file, pm } of lockFiles) {
8909
9557
  try {
8910
- await fs11.access(path7.join(cwd, file));
9558
+ await fs13.access(path8.join(cwd, file));
8911
9559
  return pm;
8912
9560
  } catch {
8913
9561
  }
@@ -8999,7 +9647,7 @@ var colors2 = {
8999
9647
  dim: "\x1B[2m"
9000
9648
  };
9001
9649
  function createDepsUpgradeCommand() {
9002
- return new Command35("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) => {
9650
+ return new Command36("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) => {
9003
9651
  await handleDepsUpgrade(options);
9004
9652
  });
9005
9653
  }
@@ -9091,7 +9739,7 @@ ${colors2.yellow}\u23F8\uFE0F \u0110\xE3 h\u1EE7y${colors2.reset}
9091
9739
  }
9092
9740
  let shouldProceed;
9093
9741
  try {
9094
- shouldProceed = await confirm5({
9742
+ shouldProceed = await confirm6({
9095
9743
  message: `Ti\u1EBFn h\xE0nh upgrade ${selectedPackages.length} packages?`,
9096
9744
  default: true
9097
9745
  });
@@ -9179,20 +9827,20 @@ function displayUpgradeTable(packages) {
9179
9827
 
9180
9828
  // src/commands/deps/index.ts
9181
9829
  function createDepsCommand() {
9182
- const depsCommand = new Command36("deps").description("Qu\u1EA3n l\xFD dependencies trong project");
9830
+ const depsCommand = new Command37("deps").description("Qu\u1EA3n l\xFD dependencies trong project");
9183
9831
  depsCommand.addCommand(createDepsUpgradeCommand());
9184
9832
  return depsCommand;
9185
9833
  }
9186
9834
 
9187
9835
  // src/commands/kit/index.ts
9188
- import { Command as Command40 } from "commander";
9836
+ import { Command as Command41 } from "commander";
9189
9837
 
9190
9838
  // src/commands/kit/list.ts
9191
- import { Command as Command37 } from "commander";
9839
+ import { Command as Command38 } from "commander";
9192
9840
 
9193
9841
  // src/services/starter-kit.service.ts
9194
- import { promises as fs12 } from "fs";
9195
- import { join as join5 } from "path";
9842
+ import { promises as fs14 } from "fs";
9843
+ import { join as join6 } from "path";
9196
9844
  import AdmZip from "adm-zip";
9197
9845
  var StarterKitService = class {
9198
9846
  /**
@@ -9239,23 +9887,23 @@ var StarterKitService = class {
9239
9887
  throw new NetworkError(`Failed to download kit: HTTP ${response.status}`);
9240
9888
  }
9241
9889
  if (onProgress) onProgress(30);
9242
- const tmpDir = join5(process.env.TMPDIR || "/tmp", "jai1-kits");
9243
- await fs12.mkdir(tmpDir, { recursive: true });
9244
- const tmpFile = join5(tmpDir, `${slug}.zip`);
9890
+ const tmpDir = join6(process.env.TMPDIR || "/tmp", "jai1-kits");
9891
+ await fs14.mkdir(tmpDir, { recursive: true });
9892
+ const tmpFile = join6(tmpDir, `${slug}.zip`);
9245
9893
  const buffer = await response.arrayBuffer();
9246
- await fs12.writeFile(tmpFile, Buffer.from(buffer));
9894
+ await fs14.writeFile(tmpFile, Buffer.from(buffer));
9247
9895
  if (onProgress) onProgress(60);
9248
9896
  const zip = new AdmZip(tmpFile);
9249
- await fs12.mkdir(targetDir, { recursive: true });
9897
+ await fs14.mkdir(targetDir, { recursive: true });
9250
9898
  zip.extractAllTo(targetDir, true);
9251
9899
  if (onProgress) onProgress(100);
9252
- await fs12.unlink(tmpFile);
9900
+ await fs14.unlink(tmpFile);
9253
9901
  }
9254
9902
  };
9255
9903
 
9256
9904
  // src/commands/kit/list.ts
9257
9905
  function createKitListCommand() {
9258
- return new Command37("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) => {
9906
+ return new Command38("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) => {
9259
9907
  const configService = new ConfigService();
9260
9908
  const config = await configService.load();
9261
9909
  if (!config) {
@@ -9292,9 +9940,9 @@ function createKitListCommand() {
9292
9940
  }
9293
9941
 
9294
9942
  // src/commands/kit/info.ts
9295
- import { Command as Command38 } from "commander";
9943
+ import { Command as Command39 } from "commander";
9296
9944
  function createKitInfoCommand() {
9297
- return new Command38("info").description("Show detailed information about a starter kit").argument("<slug>", "Starter kit slug").action(async (slug) => {
9945
+ return new Command39("info").description("Show detailed information about a starter kit").argument("<slug>", "Starter kit slug").action(async (slug) => {
9298
9946
  const configService = new ConfigService();
9299
9947
  const config = await configService.load();
9300
9948
  if (!config) {
@@ -9343,10 +9991,10 @@ Post-Init Commands:`);
9343
9991
  }
9344
9992
 
9345
9993
  // src/commands/kit/create.ts
9346
- import { Command as Command39 } from "commander";
9347
- import { promises as fs13 } from "fs";
9348
- import { join as join6 } from "path";
9349
- import { select as select2, input, checkbox as checkbox4 } from "@inquirer/prompts";
9994
+ import { Command as Command40 } from "commander";
9995
+ import { promises as fs15 } from "fs";
9996
+ import { join as join7 } from "path";
9997
+ import { select as select3, input as input2, checkbox as checkbox4 } from "@inquirer/prompts";
9350
9998
  import { execa as execa2 } from "execa";
9351
9999
 
9352
10000
  // src/services/hook-executor.service.ts
@@ -9388,7 +10036,7 @@ var HookExecutor = class {
9388
10036
 
9389
10037
  // src/commands/kit/create.ts
9390
10038
  function createKitCreateCommand() {
9391
- return new Command39("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) => {
10039
+ return new Command40("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) => {
9392
10040
  const configService = new ConfigService();
9393
10041
  const config = await configService.load();
9394
10042
  if (!config) {
@@ -9408,9 +10056,9 @@ function createKitCreateCommand() {
9408
10056
  }
9409
10057
  }
9410
10058
  }
9411
- const targetDir = directory || join6(process.cwd(), options.name || slug);
10059
+ const targetDir = directory || join7(process.cwd(), options.name || slug);
9412
10060
  try {
9413
- await fs13.access(targetDir);
10061
+ await fs15.access(targetDir);
9414
10062
  throw new Error(`Directory already exists: ${targetDir}`);
9415
10063
  } catch (error) {
9416
10064
  if (error.code !== "ENOENT") {
@@ -9444,14 +10092,14 @@ function createKitCreateCommand() {
9444
10092
  console.log("\u{1F4DD} Please provide project details:");
9445
10093
  for (const v of kit.config.variables) {
9446
10094
  if (v.type === "select" && v.options) {
9447
- const answer = await select2({
10095
+ const answer = await select3({
9448
10096
  message: v.prompt,
9449
10097
  choices: v.options.map((opt) => ({ name: opt, value: opt })),
9450
10098
  default: v.default
9451
10099
  });
9452
10100
  variables[v.name] = answer;
9453
10101
  } else {
9454
- const answer = await input({
10102
+ const answer = await input2({
9455
10103
  message: v.prompt,
9456
10104
  default: v.default
9457
10105
  });
@@ -9528,7 +10176,7 @@ function createKitCreateCommand() {
9528
10176
  async function applyVariableSubstitution(dir, variables) {
9529
10177
  const files = await getAllFiles(dir);
9530
10178
  for (const file of files) {
9531
- let content = await fs13.readFile(file, "utf-8");
10179
+ let content = await fs15.readFile(file, "utf-8");
9532
10180
  let modified = false;
9533
10181
  for (const [key, value] of Object.entries(variables)) {
9534
10182
  const regex = new RegExp(`\\{\\{${key}\\}\\}`, "g");
@@ -9538,15 +10186,15 @@ async function applyVariableSubstitution(dir, variables) {
9538
10186
  }
9539
10187
  }
9540
10188
  if (modified) {
9541
- await fs13.writeFile(file, content, "utf-8");
10189
+ await fs15.writeFile(file, content, "utf-8");
9542
10190
  }
9543
10191
  }
9544
10192
  }
9545
10193
  async function getAllFiles(dir) {
9546
10194
  const files = [];
9547
- const entries = await fs13.readdir(dir, { withFileTypes: true });
10195
+ const entries = await fs15.readdir(dir, { withFileTypes: true });
9548
10196
  for (const entry of entries) {
9549
- const fullPath = join6(dir, entry.name);
10197
+ const fullPath = join7(dir, entry.name);
9550
10198
  if (entry.isDirectory()) {
9551
10199
  if (!entry.name.startsWith(".") && entry.name !== "node_modules") {
9552
10200
  files.push(...await getAllFiles(fullPath));
@@ -9560,7 +10208,7 @@ async function getAllFiles(dir) {
9560
10208
 
9561
10209
  // src/commands/kit/index.ts
9562
10210
  function createKitCommand() {
9563
- const cmd = new Command40("kit").description("Manage starter kits for new projects").action(() => {
10211
+ const cmd = new Command41("kit").description("Manage starter kits for new projects").action(() => {
9564
10212
  cmd.help();
9565
10213
  });
9566
10214
  cmd.addCommand(createKitListCommand());
@@ -9570,12 +10218,12 @@ function createKitCommand() {
9570
10218
  }
9571
10219
 
9572
10220
  // src/commands/rules/index.ts
9573
- import { Command as Command47 } from "commander";
10221
+ import { Command as Command48 } from "commander";
9574
10222
 
9575
10223
  // src/commands/rules/list.ts
9576
- import { Command as Command41 } from "commander";
10224
+ import { Command as Command42 } from "commander";
9577
10225
  function createRulesListCommand() {
9578
- return new Command41("list").description("List available rule presets").option("--json", "Output as JSON").action(async (options) => {
10226
+ return new Command42("list").description("List available rule presets").option("--json", "Output as JSON").action(async (options) => {
9579
10227
  const configService = new ConfigService();
9580
10228
  const config = await configService.load();
9581
10229
  if (!config) {
@@ -9630,12 +10278,12 @@ function createRulesListCommand() {
9630
10278
  }
9631
10279
 
9632
10280
  // src/commands/rules/init.ts
9633
- import { Command as Command42 } from "commander";
9634
- import { promises as fs14 } from "fs";
9635
- import { join as join7 } from "path";
9636
- import { select as select3, confirm as confirm6 } from "@inquirer/prompts";
10281
+ import { Command as Command43 } from "commander";
10282
+ import { promises as fs16 } from "fs";
10283
+ import { join as join8 } from "path";
10284
+ import { select as select4, confirm as confirm7 } from "@inquirer/prompts";
9637
10285
  function createRulesInitCommand() {
9638
- return new Command42("init").description("Apply rule preset to project").option("--preset <slug>", "Preset slug to apply").option("--output <format>", "Output format: cursor, agents-md, both (default: cursor)", "cursor").option("-y, --yes", "Skip confirmations").action(async (options) => {
10286
+ return new Command43("init").description("Apply rule preset to project").option("--preset <slug>", "Preset slug to apply").option("--output <format>", "Output format: cursor, agents-md, both (default: cursor)", "cursor").option("-y, --yes", "Skip confirmations").action(async (options) => {
9639
10287
  const configService = new ConfigService();
9640
10288
  const config = await configService.load();
9641
10289
  if (!config) {
@@ -9657,7 +10305,7 @@ function createRulesInitCommand() {
9657
10305
  console.log("No presets available.");
9658
10306
  return;
9659
10307
  }
9660
- presetSlug = await select3({
10308
+ presetSlug = await select4({
9661
10309
  message: "Select a preset:",
9662
10310
  choices: data.presets.map((p) => ({
9663
10311
  name: `${p.name} - ${p.description}`,
@@ -9685,7 +10333,7 @@ function createRulesInitCommand() {
9685
10333
  console.log(` Files: ${Object.keys(bundle.files).length}`);
9686
10334
  let outputFormat = options.output;
9687
10335
  if (!["cursor", "agents-md", "both"].includes(outputFormat)) {
9688
- outputFormat = await select3({
10336
+ outputFormat = await select4({
9689
10337
  message: "Select output format:",
9690
10338
  choices: [
9691
10339
  { name: "Cursor (.cursor/rules/)", value: "cursor" },
@@ -9695,7 +10343,7 @@ function createRulesInitCommand() {
9695
10343
  });
9696
10344
  }
9697
10345
  if (!options.yes) {
9698
- const proceed = await confirm6({
10346
+ const proceed = await confirm7({
9699
10347
  message: `Apply preset '${bundle.preset.name}' to current directory?`,
9700
10348
  default: true
9701
10349
  });
@@ -9717,7 +10365,7 @@ function createRulesInitCommand() {
9717
10365
  appliedAt: (/* @__PURE__ */ new Date()).toISOString(),
9718
10366
  customContext: "09-custom.mdc"
9719
10367
  };
9720
- await fs14.writeFile("jai1-rules.json", JSON.stringify(projectConfig, null, 2));
10368
+ await fs16.writeFile("jai1-rules.json", JSON.stringify(projectConfig, null, 2));
9721
10369
  console.log("\u2713 Created jai1-rules.json");
9722
10370
  console.log("\n\u2705 Preset applied successfully!\n");
9723
10371
  console.log("Next steps:");
@@ -9727,11 +10375,11 @@ function createRulesInitCommand() {
9727
10375
  });
9728
10376
  }
9729
10377
  async function applyCursorFormat(bundle) {
9730
- const rulesDir = join7(process.cwd(), ".cursor", "rules");
9731
- await fs14.mkdir(rulesDir, { recursive: true });
10378
+ const rulesDir = join8(process.cwd(), ".cursor", "rules");
10379
+ await fs16.mkdir(rulesDir, { recursive: true });
9732
10380
  for (const [filename, content] of Object.entries(bundle.files)) {
9733
- const filePath = join7(rulesDir, filename);
9734
- await fs14.writeFile(filePath, content, "utf-8");
10381
+ const filePath = join8(rulesDir, filename);
10382
+ await fs16.writeFile(filePath, content, "utf-8");
9735
10383
  console.log(`\u2713 Created .cursor/rules/${filename}`);
9736
10384
  }
9737
10385
  }
@@ -9758,15 +10406,15 @@ async function applyAgentsMdFormat(bundle) {
9758
10406
  }
9759
10407
  }
9760
10408
  const agentsMd = sections.join("\n");
9761
- await fs14.writeFile("AGENTS.md", agentsMd, "utf-8");
10409
+ await fs16.writeFile("AGENTS.md", agentsMd, "utf-8");
9762
10410
  console.log("\u2713 Created AGENTS.md");
9763
10411
  }
9764
10412
 
9765
10413
  // src/commands/rules/apply.ts
9766
- import { Command as Command43 } from "commander";
9767
- import { promises as fs16 } from "fs";
9768
- import { join as join9 } from "path";
9769
- import { select as select4, confirm as confirm7, checkbox as checkbox5 } from "@inquirer/prompts";
10414
+ import { Command as Command44 } from "commander";
10415
+ import { promises as fs18 } from "fs";
10416
+ import { join as join10 } from "path";
10417
+ import { select as select5, confirm as confirm8, checkbox as checkbox5 } from "@inquirer/prompts";
9770
10418
 
9771
10419
  // src/services/rules-generator.service.ts
9772
10420
  var RulesGeneratorService = class {
@@ -10125,8 +10773,8 @@ Follow all instructions and patterns defined in AGENTS.md above.
10125
10773
  };
10126
10774
 
10127
10775
  // src/services/backup.service.ts
10128
- import { promises as fs15 } from "fs";
10129
- import { join as join8, dirname } from "path";
10776
+ import { promises as fs17 } from "fs";
10777
+ import { join as join9, dirname } from "path";
10130
10778
  var BackupService = class {
10131
10779
  backupDir = ".jai1/backups";
10132
10780
  /**
@@ -10134,7 +10782,7 @@ var BackupService = class {
10134
10782
  */
10135
10783
  async createBackup(ides, presetSlug) {
10136
10784
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
10137
- const backupPath = join8(this.backupDir, timestamp);
10785
+ const backupPath = join9(this.backupDir, timestamp);
10138
10786
  const backedUpFiles = [];
10139
10787
  let hasContent = false;
10140
10788
  for (const ideId of ides) {
@@ -10143,7 +10791,7 @@ var BackupService = class {
10143
10791
  console.warn(`Unknown IDE format: ${ideId}, skipping backup`);
10144
10792
  continue;
10145
10793
  }
10146
- const rulesPath = format.rulesPath === "." ? process.cwd() : join8(process.cwd(), format.rulesPath);
10794
+ const rulesPath = format.rulesPath === "." ? process.cwd() : join9(process.cwd(), format.rulesPath);
10147
10795
  try {
10148
10796
  const exists = await this.pathExists(rulesPath);
10149
10797
  if (!exists) {
@@ -10156,19 +10804,19 @@ var BackupService = class {
10156
10804
  await this.backupSingleFile("GEMINI.md", backupPath, ideId, backedUpFiles);
10157
10805
  hasContent = true;
10158
10806
  } else {
10159
- const stats = await fs15.stat(rulesPath);
10807
+ const stats = await fs17.stat(rulesPath);
10160
10808
  if (stats.isDirectory()) {
10161
- const files = await fs15.readdir(rulesPath);
10809
+ const files = await fs17.readdir(rulesPath);
10162
10810
  for (const file of files) {
10163
10811
  if (file.endsWith(format.fileExtension)) {
10164
- const originalPath = join8(rulesPath, file);
10165
- const relativePath = join8(format.rulesPath, file);
10166
- const destPath = join8(backupPath, ideId, file);
10167
- await fs15.mkdir(dirname(destPath), { recursive: true });
10168
- await fs15.copyFile(originalPath, destPath);
10812
+ const originalPath = join9(rulesPath, file);
10813
+ const relativePath = join9(format.rulesPath, file);
10814
+ const destPath = join9(backupPath, ideId, file);
10815
+ await fs17.mkdir(dirname(destPath), { recursive: true });
10816
+ await fs17.copyFile(originalPath, destPath);
10169
10817
  backedUpFiles.push({
10170
10818
  originalPath: relativePath,
10171
- backupPath: join8(ideId, file),
10819
+ backupPath: join9(ideId, file),
10172
10820
  ide: ideId
10173
10821
  });
10174
10822
  hasContent = true;
@@ -10189,9 +10837,9 @@ var BackupService = class {
10189
10837
  ides,
10190
10838
  files: backedUpFiles
10191
10839
  };
10192
- await fs15.mkdir(backupPath, { recursive: true });
10193
- await fs15.writeFile(
10194
- join8(backupPath, "metadata.json"),
10840
+ await fs17.mkdir(backupPath, { recursive: true });
10841
+ await fs17.writeFile(
10842
+ join9(backupPath, "metadata.json"),
10195
10843
  JSON.stringify(metadata, null, 2),
10196
10844
  "utf-8"
10197
10845
  );
@@ -10201,18 +10849,18 @@ var BackupService = class {
10201
10849
  * Backup a single file (for AGENTS.md, GEMINI.md)
10202
10850
  */
10203
10851
  async backupSingleFile(filename, backupPath, ideId, backedUpFiles) {
10204
- const originalPath = join8(process.cwd(), filename);
10852
+ const originalPath = join9(process.cwd(), filename);
10205
10853
  try {
10206
10854
  const exists = await this.pathExists(originalPath);
10207
10855
  if (!exists) {
10208
10856
  return;
10209
10857
  }
10210
- const destPath = join8(backupPath, ideId, filename);
10211
- await fs15.mkdir(dirname(destPath), { recursive: true });
10212
- await fs15.copyFile(originalPath, destPath);
10858
+ const destPath = join9(backupPath, ideId, filename);
10859
+ await fs17.mkdir(dirname(destPath), { recursive: true });
10860
+ await fs17.copyFile(originalPath, destPath);
10213
10861
  backedUpFiles.push({
10214
10862
  originalPath: filename,
10215
- backupPath: join8(ideId, filename),
10863
+ backupPath: join9(ideId, filename),
10216
10864
  ide: ideId
10217
10865
  });
10218
10866
  } catch (error) {
@@ -10222,16 +10870,16 @@ var BackupService = class {
10222
10870
  * Restore files from a backup
10223
10871
  */
10224
10872
  async restoreBackup(backupPath) {
10225
- const metadataPath = join8(backupPath, "metadata.json");
10226
- const metadataContent = await fs15.readFile(metadataPath, "utf-8");
10873
+ const metadataPath = join9(backupPath, "metadata.json");
10874
+ const metadataContent = await fs17.readFile(metadataPath, "utf-8");
10227
10875
  const metadata = JSON.parse(metadataContent);
10228
10876
  console.log(`
10229
10877
  Restoring backup from ${metadata.timestamp}...`);
10230
10878
  for (const file of metadata.files) {
10231
- const sourcePath = join8(backupPath, file.backupPath);
10232
- const destPath = join8(process.cwd(), file.originalPath);
10233
- await fs15.mkdir(dirname(destPath), { recursive: true });
10234
- await fs15.copyFile(sourcePath, destPath);
10879
+ const sourcePath = join9(backupPath, file.backupPath);
10880
+ const destPath = join9(process.cwd(), file.originalPath);
10881
+ await fs17.mkdir(dirname(destPath), { recursive: true });
10882
+ await fs17.copyFile(sourcePath, destPath);
10235
10883
  console.log(`\u2713 Restored ${file.originalPath}`);
10236
10884
  }
10237
10885
  console.log("\n\u2705 Backup restored successfully!");
@@ -10241,18 +10889,18 @@ Restoring backup from ${metadata.timestamp}...`);
10241
10889
  */
10242
10890
  async listBackups() {
10243
10891
  try {
10244
- const backupDirPath = join8(process.cwd(), this.backupDir);
10892
+ const backupDirPath = join9(process.cwd(), this.backupDir);
10245
10893
  const exists = await this.pathExists(backupDirPath);
10246
10894
  if (!exists) {
10247
10895
  return [];
10248
10896
  }
10249
- const entries = await fs15.readdir(backupDirPath, { withFileTypes: true });
10897
+ const entries = await fs17.readdir(backupDirPath, { withFileTypes: true });
10250
10898
  const backups = [];
10251
10899
  for (const entry of entries) {
10252
10900
  if (entry.isDirectory()) {
10253
- const metadataPath = join8(backupDirPath, entry.name, "metadata.json");
10901
+ const metadataPath = join9(backupDirPath, entry.name, "metadata.json");
10254
10902
  try {
10255
- const metadataContent = await fs15.readFile(metadataPath, "utf-8");
10903
+ const metadataContent = await fs17.readFile(metadataPath, "utf-8");
10256
10904
  const metadata = JSON.parse(metadataContent);
10257
10905
  backups.push(metadata);
10258
10906
  } catch {
@@ -10269,7 +10917,7 @@ Restoring backup from ${metadata.timestamp}...`);
10269
10917
  * Delete a specific backup
10270
10918
  */
10271
10919
  async deleteBackup(timestamp) {
10272
- const backupPath = join8(process.cwd(), this.backupDir, timestamp);
10920
+ const backupPath = join9(process.cwd(), this.backupDir, timestamp);
10273
10921
  await this.deleteDirectory(backupPath);
10274
10922
  }
10275
10923
  /**
@@ -10299,9 +10947,9 @@ Restoring backup from ${metadata.timestamp}...`);
10299
10947
  /**
10300
10948
  * Check if a path exists
10301
10949
  */
10302
- async pathExists(path9) {
10950
+ async pathExists(path10) {
10303
10951
  try {
10304
- await fs15.access(path9);
10952
+ await fs17.access(path10);
10305
10953
  return true;
10306
10954
  } catch {
10307
10955
  return false;
@@ -10310,22 +10958,22 @@ Restoring backup from ${metadata.timestamp}...`);
10310
10958
  /**
10311
10959
  * Recursively delete a directory
10312
10960
  */
10313
- async deleteDirectory(path9) {
10961
+ async deleteDirectory(path10) {
10314
10962
  try {
10315
- const exists = await this.pathExists(path9);
10963
+ const exists = await this.pathExists(path10);
10316
10964
  if (!exists) {
10317
10965
  return;
10318
10966
  }
10319
- const entries = await fs15.readdir(path9, { withFileTypes: true });
10967
+ const entries = await fs17.readdir(path10, { withFileTypes: true });
10320
10968
  for (const entry of entries) {
10321
- const fullPath = join8(path9, entry.name);
10969
+ const fullPath = join9(path10, entry.name);
10322
10970
  if (entry.isDirectory()) {
10323
10971
  await this.deleteDirectory(fullPath);
10324
10972
  } else {
10325
- await fs15.unlink(fullPath);
10973
+ await fs17.unlink(fullPath);
10326
10974
  }
10327
10975
  }
10328
- await fs15.rmdir(path9);
10976
+ await fs17.rmdir(path10);
10329
10977
  } catch (error) {
10330
10978
  }
10331
10979
  }
@@ -10333,20 +10981,20 @@ Restoring backup from ${metadata.timestamp}...`);
10333
10981
  * Get backup directory path
10334
10982
  */
10335
10983
  getBackupDir() {
10336
- return join8(process.cwd(), this.backupDir);
10984
+ return join9(process.cwd(), this.backupDir);
10337
10985
  }
10338
10986
  /**
10339
10987
  * Ensure backup directory exists
10340
10988
  */
10341
10989
  async ensureBackupDir() {
10342
- const backupDirPath = join8(process.cwd(), this.backupDir);
10343
- await fs15.mkdir(backupDirPath, { recursive: true });
10990
+ const backupDirPath = join9(process.cwd(), this.backupDir);
10991
+ await fs17.mkdir(backupDirPath, { recursive: true });
10344
10992
  }
10345
10993
  };
10346
10994
 
10347
10995
  // src/commands/rules/apply.ts
10348
10996
  function createRulesApplyCommand() {
10349
- return new Command43("apply").description("Apply rule preset to project with multi-IDE support").argument("[preset]", "Preset slug to apply (optional)").option("--ides <ides>", "Comma-separated list of IDE formats (cursor,windsurf,antigravity,claude,agentsmd,gemini)").option("--skip-backup", "Skip backup creation").option("-y, --yes", "Skip all confirmations (auto mode)").action(async (presetSlug, options) => {
10997
+ return new Command44("apply").description("Apply rule preset to project with multi-IDE support").argument("[preset]", "Preset slug to apply (optional)").option("--ides <ides>", "Comma-separated list of IDE formats (cursor,windsurf,antigravity,claude,agentsmd,gemini)").option("--skip-backup", "Skip backup creation").option("-y, --yes", "Skip all confirmations (auto mode)").action(async (presetSlug, options) => {
10350
10998
  const configService = new ConfigService();
10351
10999
  const config = await configService.load();
10352
11000
  if (!config) {
@@ -10378,7 +11026,7 @@ function createRulesApplyCommand() {
10378
11026
  console.log("No presets available.");
10379
11027
  return;
10380
11028
  }
10381
- presetSlug = await select4({
11029
+ presetSlug = await select5({
10382
11030
  message: "Select a preset:",
10383
11031
  choices: data.presets.map((p) => ({
10384
11032
  name: `${p.name} - ${p.description}`,
@@ -10486,7 +11134,7 @@ function createRulesApplyCommand() {
10486
11134
  if (backupPath) {
10487
11135
  console.log(` Backup: ${backupPath}`);
10488
11136
  }
10489
- const proceed = await confirm7({
11137
+ const proceed = await confirm8({
10490
11138
  message: "Apply these rules to the current directory?",
10491
11139
  default: true
10492
11140
  });
@@ -10496,21 +11144,21 @@ function createRulesApplyCommand() {
10496
11144
  }
10497
11145
  }
10498
11146
  console.log("\n\u{1F4DD} Applying preset...\n");
10499
- const rulePresetDir = join9(process.cwd(), ".jai1", "rule-preset");
11147
+ const rulePresetDir = join10(process.cwd(), ".jai1", "rule-preset");
10500
11148
  try {
10501
- await fs16.rm(rulePresetDir, { recursive: true, force: true });
11149
+ await fs18.rm(rulePresetDir, { recursive: true, force: true });
10502
11150
  } catch {
10503
11151
  }
10504
- await fs16.mkdir(rulePresetDir, { recursive: true });
10505
- await fs16.writeFile(
10506
- join9(rulePresetDir, "preset.json"),
11152
+ await fs18.mkdir(rulePresetDir, { recursive: true });
11153
+ await fs18.writeFile(
11154
+ join10(rulePresetDir, "preset.json"),
10507
11155
  JSON.stringify(bundle.preset, null, 2),
10508
11156
  "utf-8"
10509
11157
  );
10510
11158
  for (const [filename, content] of Object.entries(bundle.files)) {
10511
- const filePath = join9(rulePresetDir, filename);
10512
- await fs16.mkdir(join9(filePath, ".."), { recursive: true });
10513
- await fs16.writeFile(filePath, content, "utf-8");
11159
+ const filePath = join10(rulePresetDir, filename);
11160
+ await fs18.mkdir(join10(filePath, ".."), { recursive: true });
11161
+ await fs18.writeFile(filePath, content, "utf-8");
10514
11162
  }
10515
11163
  console.log(`\u2713 Saved preset to .jai1/rule-preset/`);
10516
11164
  const allGeneratedFiles = [];
@@ -10518,9 +11166,9 @@ function createRulesApplyCommand() {
10518
11166
  try {
10519
11167
  const files = generatorService.generateForIde(bundle, ideId);
10520
11168
  for (const file of files) {
10521
- const fullPath = join9(process.cwd(), file.path);
10522
- await fs16.mkdir(join9(fullPath, ".."), { recursive: true });
10523
- await fs16.writeFile(fullPath, file.content, "utf-8");
11169
+ const fullPath = join10(process.cwd(), file.path);
11170
+ await fs18.mkdir(join10(fullPath, ".."), { recursive: true });
11171
+ await fs18.writeFile(fullPath, file.content, "utf-8");
10524
11172
  console.log(`\u2713 [${ideId}] ${file.path}`);
10525
11173
  allGeneratedFiles.push({
10526
11174
  ide: ideId,
@@ -10547,8 +11195,8 @@ function createRulesApplyCommand() {
10547
11195
  ] : []
10548
11196
  };
10549
11197
  try {
10550
- const existingConfigPath = join9(process.cwd(), "jai1-rules.json");
10551
- const existingConfigContent = await fs16.readFile(existingConfigPath, "utf-8");
11198
+ const existingConfigPath = join10(process.cwd(), "jai1-rules.json");
11199
+ const existingConfigContent = await fs18.readFile(existingConfigPath, "utf-8");
10552
11200
  const existingConfig = JSON.parse(existingConfigContent);
10553
11201
  if (existingConfig.backups && existingConfig.backups.length > 0) {
10554
11202
  projectConfig.backups = [
@@ -10559,8 +11207,8 @@ function createRulesApplyCommand() {
10559
11207
  }
10560
11208
  } catch {
10561
11209
  }
10562
- await fs16.writeFile(
10563
- join9(process.cwd(), "jai1-rules.json"),
11210
+ await fs18.writeFile(
11211
+ join10(process.cwd(), "jai1-rules.json"),
10564
11212
  JSON.stringify(projectConfig, null, 2),
10565
11213
  "utf-8"
10566
11214
  );
@@ -10591,11 +11239,11 @@ function createRulesApplyCommand() {
10591
11239
  }
10592
11240
 
10593
11241
  // src/commands/rules/restore.ts
10594
- import { Command as Command44 } from "commander";
10595
- import { join as join10 } from "path";
10596
- import { select as select5, confirm as confirm8 } from "@inquirer/prompts";
11242
+ import { Command as Command45 } from "commander";
11243
+ import { join as join11 } from "path";
11244
+ import { select as select6, confirm as confirm9 } from "@inquirer/prompts";
10597
11245
  function createRulesRestoreCommand() {
10598
- return new Command44("restore").description("Restore rules from a backup").option("--latest", "Restore the most recent backup").option("-y, --yes", "Skip confirmation").action(async (options) => {
11246
+ return new Command45("restore").description("Restore rules from a backup").option("--latest", "Restore the most recent backup").option("-y, --yes", "Skip confirmation").action(async (options) => {
10599
11247
  const backupService = new BackupService();
10600
11248
  const backups = await backupService.listBackups();
10601
11249
  if (backups.length === 0) {
@@ -10608,7 +11256,7 @@ function createRulesRestoreCommand() {
10608
11256
  console.log(`\u{1F4E6} Selected latest backup: ${selectedBackup.timestamp}`);
10609
11257
  } else {
10610
11258
  console.log("\u{1F4CB} Available backups:\n");
10611
- const backupTimestamp = await select5({
11259
+ const backupTimestamp = await select6({
10612
11260
  message: "Select a backup to restore:",
10613
11261
  choices: backups.map((backup) => ({
10614
11262
  name: formatBackupInfo(backup),
@@ -10627,7 +11275,7 @@ function createRulesRestoreCommand() {
10627
11275
  console.log(` IDEs: ${selectedBackup.ides.join(", ")}`);
10628
11276
  console.log(` Files: ${selectedBackup.files.length}`);
10629
11277
  if (!options.yes) {
10630
- const proceed = await confirm8({
11278
+ const proceed = await confirm9({
10631
11279
  message: "This will overwrite current rules. Continue?",
10632
11280
  default: false
10633
11281
  });
@@ -10638,7 +11286,7 @@ function createRulesRestoreCommand() {
10638
11286
  }
10639
11287
  console.log("\n\u{1F504} Restoring backup...\n");
10640
11288
  try {
10641
- const backupPath = join10(backupService.getBackupDir(), selectedBackup.timestamp);
11289
+ const backupPath = join11(backupService.getBackupDir(), selectedBackup.timestamp);
10642
11290
  await backupService.restoreBackup(backupPath);
10643
11291
  console.log("\n\u2705 Backup restored successfully!\n");
10644
11292
  console.log("\u{1F4A1} Tip: Your IDE may need to be restarted to pick up the changes.");
@@ -10663,16 +11311,16 @@ function formatTimestamp(timestamp) {
10663
11311
  }
10664
11312
 
10665
11313
  // src/commands/rules/sync.ts
10666
- import { Command as Command45 } from "commander";
10667
- import { promises as fs17 } from "fs";
10668
- import { join as join11 } from "path";
10669
- import { confirm as confirm9 } from "@inquirer/prompts";
11314
+ import { Command as Command46 } from "commander";
11315
+ import { promises as fs19 } from "fs";
11316
+ import { join as join12 } from "path";
11317
+ import { confirm as confirm10 } from "@inquirer/prompts";
10670
11318
  function createRulesSyncCommand() {
10671
- return new Command45("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) => {
10672
- const configPath = join11(process.cwd(), "jai1-rules.json");
11319
+ return new Command46("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) => {
11320
+ const configPath = join12(process.cwd(), "jai1-rules.json");
10673
11321
  let projectConfig;
10674
11322
  try {
10675
- const configContent = await fs17.readFile(configPath, "utf-8");
11323
+ const configContent = await fs19.readFile(configPath, "utf-8");
10676
11324
  projectConfig = JSON.parse(configContent);
10677
11325
  } catch {
10678
11326
  throw new ValidationError(
@@ -10699,7 +11347,7 @@ Detected ${detected.length} active IDE(s):
10699
11347
  console.log(` ${confidence} ${d.name} - ${d.ruleCount} rules`);
10700
11348
  });
10701
11349
  if (!options.yes) {
10702
- const proceed = await confirm9({
11350
+ const proceed = await confirm10({
10703
11351
  message: "\nSync these detected IDEs?",
10704
11352
  default: true
10705
11353
  });
@@ -10752,14 +11400,14 @@ Detected ${detected.length} active IDE(s):
10752
11400
  throw new Error(`Failed to fetch preset: ${presetResponse.statusText}`);
10753
11401
  }
10754
11402
  const bundle = await presetResponse.json();
10755
- const rulePresetDir = join11(process.cwd(), ".jai1", "rule-preset");
11403
+ const rulePresetDir = join12(process.cwd(), ".jai1", "rule-preset");
10756
11404
  const presetExists = await checkPathExists(rulePresetDir);
10757
11405
  if (presetExists) {
10758
- const files = await fs17.readdir(rulePresetDir);
11406
+ const files = await fs19.readdir(rulePresetDir);
10759
11407
  for (const file of files) {
10760
11408
  if (file.endsWith(".mdc")) {
10761
- const filePath = join11(rulePresetDir, file);
10762
- const content = await fs17.readFile(filePath, "utf-8");
11409
+ const filePath = join12(rulePresetDir, file);
11410
+ const content = await fs19.readFile(filePath, "utf-8");
10763
11411
  bundle.files[file] = content;
10764
11412
  }
10765
11413
  }
@@ -10778,9 +11426,9 @@ Detected ${detected.length} active IDE(s):
10778
11426
  }
10779
11427
  const files = generatorService.generateForIde(bundle, ideId);
10780
11428
  for (const file of files) {
10781
- const fullPath = join11(process.cwd(), file.path);
10782
- await fs17.mkdir(join11(fullPath, ".."), { recursive: true });
10783
- await fs17.writeFile(fullPath, file.content, "utf-8");
11429
+ const fullPath = join12(process.cwd(), file.path);
11430
+ await fs19.mkdir(join12(fullPath, ".."), { recursive: true });
11431
+ await fs19.writeFile(fullPath, file.content, "utf-8");
10784
11432
  }
10785
11433
  console.log(`\u2713 ${format.name} - ${files.length} files regenerated`);
10786
11434
  } catch (error) {
@@ -10789,8 +11437,8 @@ Detected ${detected.length} active IDE(s):
10789
11437
  }
10790
11438
  if (JSON.stringify(projectConfig.ides) !== JSON.stringify(idesToSync)) {
10791
11439
  projectConfig.ides = idesToSync;
10792
- await fs17.writeFile(
10793
- join11(process.cwd(), "jai1-rules.json"),
11440
+ await fs19.writeFile(
11441
+ join12(process.cwd(), "jai1-rules.json"),
10794
11442
  JSON.stringify(projectConfig, null, 2),
10795
11443
  "utf-8"
10796
11444
  );
@@ -10805,7 +11453,7 @@ Detected ${detected.length} active IDE(s):
10805
11453
  }
10806
11454
  async function checkPathExists(absolutePath) {
10807
11455
  try {
10808
- await fs17.access(absolutePath);
11456
+ await fs19.access(absolutePath);
10809
11457
  return true;
10810
11458
  } catch {
10811
11459
  return false;
@@ -10813,15 +11461,15 @@ async function checkPathExists(absolutePath) {
10813
11461
  }
10814
11462
 
10815
11463
  // src/commands/rules/info.ts
10816
- import { Command as Command46 } from "commander";
10817
- import { promises as fs18 } from "fs";
10818
- import { join as join12 } from "path";
11464
+ import { Command as Command47 } from "commander";
11465
+ import { promises as fs20 } from "fs";
11466
+ import { join as join13 } from "path";
10819
11467
  function createRulesInfoCommand() {
10820
- return new Command46("info").description("Show current preset information").option("--json", "Output as JSON").action(async (options) => {
10821
- const configPath = join12(process.cwd(), "jai1-rules.json");
11468
+ return new Command47("info").description("Show current preset information").option("--json", "Output as JSON").action(async (options) => {
11469
+ const configPath = join13(process.cwd(), "jai1-rules.json");
10822
11470
  let projectConfig;
10823
11471
  try {
10824
- const configContent = await fs18.readFile(configPath, "utf-8");
11472
+ const configContent = await fs20.readFile(configPath, "utf-8");
10825
11473
  projectConfig = JSON.parse(configContent);
10826
11474
  } catch {
10827
11475
  throw new ValidationError(
@@ -10833,14 +11481,14 @@ function createRulesInfoCommand() {
10833
11481
  return;
10834
11482
  }
10835
11483
  console.log("\u{1F4CB} Current Preset Information\n");
10836
- const rulePresetDir = join12(process.cwd(), ".jai1", "rule-preset");
10837
- const presetJsonPath = join12(rulePresetDir, "preset.json");
11484
+ const rulePresetDir = join13(process.cwd(), ".jai1", "rule-preset");
11485
+ const presetJsonPath = join13(rulePresetDir, "preset.json");
10838
11486
  let presetMetadata = null;
10839
11487
  let presetFiles = [];
10840
11488
  try {
10841
- const presetContent = await fs18.readFile(presetJsonPath, "utf-8");
11489
+ const presetContent = await fs20.readFile(presetJsonPath, "utf-8");
10842
11490
  presetMetadata = JSON.parse(presetContent);
10843
- const files = await fs18.readdir(rulePresetDir);
11491
+ const files = await fs20.readdir(rulePresetDir);
10844
11492
  presetFiles = files.filter((f) => f.endsWith(".mdc"));
10845
11493
  } catch {
10846
11494
  }
@@ -10899,9 +11547,9 @@ Available Backups (${projectConfig.backups.length}):`);
10899
11547
  console.log(' \u2022 "jai1 rules apply" - Apply a different preset (replaces current)');
10900
11548
  });
10901
11549
  }
10902
- async function checkPathExists2(path9) {
11550
+ async function checkPathExists2(path10) {
10903
11551
  try {
10904
- await fs18.access(join12(process.cwd(), path9));
11552
+ await fs20.access(join13(process.cwd(), path10));
10905
11553
  return true;
10906
11554
  } catch {
10907
11555
  return false;
@@ -10923,7 +11571,7 @@ async function checkIdeFilesExist(ideId, format) {
10923
11571
 
10924
11572
  // src/commands/rules/index.ts
10925
11573
  function createRulesCommand() {
10926
- const rulesCommand = new Command47("rules").description("Manage rule presets for AI agents");
11574
+ const rulesCommand = new Command48("rules").description("Manage rule presets for AI agents");
10927
11575
  rulesCommand.addCommand(createRulesListCommand());
10928
11576
  rulesCommand.addCommand(createRulesInitCommand());
10929
11577
  rulesCommand.addCommand(createRulesApplyCommand());
@@ -10934,8 +11582,8 @@ function createRulesCommand() {
10934
11582
  }
10935
11583
 
10936
11584
  // src/commands/upgrade.ts
10937
- import { Command as Command48 } from "commander";
10938
- import { confirm as confirm10 } from "@inquirer/prompts";
11585
+ import { Command as Command49 } from "commander";
11586
+ import { confirm as confirm11 } from "@inquirer/prompts";
10939
11587
  import { execSync as execSync2 } from "child_process";
10940
11588
  var colors3 = {
10941
11589
  yellow: "\x1B[33m",
@@ -10946,7 +11594,7 @@ var colors3 = {
10946
11594
  bold: "\x1B[1m"
10947
11595
  };
10948
11596
  function createUpgradeCommand() {
10949
- return new Command48("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) => {
11597
+ return new Command49("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) => {
10950
11598
  await handleUpgrade(options);
10951
11599
  });
10952
11600
  }
@@ -10990,7 +11638,7 @@ ${colors3.bold}Current version:${colors3.reset} ${currentVersion}`);
10990
11638
  return;
10991
11639
  }
10992
11640
  if (!options.force) {
10993
- const shouldUpdate = await confirm10({
11641
+ const shouldUpdate = await confirm11({
10994
11642
  message: "Update to the latest version now?",
10995
11643
  default: true
10996
11644
  });
@@ -11094,11 +11742,11 @@ function getInstallCommand(packageManager2) {
11094
11742
  }
11095
11743
 
11096
11744
  // src/commands/clean.ts
11097
- import { Command as Command49 } from "commander";
11098
- import { confirm as confirm11, select as select6 } from "@inquirer/prompts";
11099
- import { join as join13 } from "path";
11745
+ import { Command as Command50 } from "commander";
11746
+ import { confirm as confirm12, select as select7 } from "@inquirer/prompts";
11747
+ import { join as join14 } from "path";
11100
11748
  function createCleanCommand() {
11101
- return new Command49("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) => {
11749
+ return new Command50("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) => {
11102
11750
  await handleClean(options);
11103
11751
  });
11104
11752
  }
@@ -11109,7 +11757,7 @@ async function handleClean(options) {
11109
11757
  {
11110
11758
  name: "Backups",
11111
11759
  description: "Component backup files (.jai1_backup/)",
11112
- path: join13(cwd, ".jai1_backup"),
11760
+ path: join14(cwd, ".jai1_backup"),
11113
11761
  check: async () => {
11114
11762
  const backups = await service.listBackups(cwd);
11115
11763
  return { exists: backups.length > 0, count: backups.length };
@@ -11159,7 +11807,7 @@ async function handleClean(options) {
11159
11807
  console.log(` Path: ${target.path}
11160
11808
  `);
11161
11809
  }
11162
- const action = await select6({
11810
+ const action = await select7({
11163
11811
  message: "What do you want to clean?",
11164
11812
  choices: [
11165
11813
  ...availableTargets.map(({ target, info }) => ({
@@ -11193,7 +11841,7 @@ async function cleanTarget(target, skipConfirm) {
11193
11841
  }
11194
11842
  const countStr = info.count ? ` (${info.count} items)` : "";
11195
11843
  if (!skipConfirm) {
11196
- const confirmed = await confirm11({
11844
+ const confirmed = await confirm12({
11197
11845
  message: `Delete ${target.name}${countStr}?`,
11198
11846
  default: false
11199
11847
  });
@@ -11211,7 +11859,7 @@ async function cleanTarget(target, skipConfirm) {
11211
11859
  }
11212
11860
 
11213
11861
  // src/commands/redmine/check.ts
11214
- import { Command as Command50 } from "commander";
11862
+ import { Command as Command51 } from "commander";
11215
11863
 
11216
11864
  // src/services/redmine-config.service.ts
11217
11865
  import { readFile as readFile6 } from "fs/promises";
@@ -11332,8 +11980,8 @@ var RedmineApiClient = class {
11332
11980
  this.retryConfig = config.defaults.retry;
11333
11981
  this.concurrencyLimit = pLimit3(config.defaults.concurrency);
11334
11982
  }
11335
- async request(path9, options = {}) {
11336
- const url = `${this.baseUrl}${path9}`;
11983
+ async request(path10, options = {}) {
11984
+ const url = `${this.baseUrl}${path10}`;
11337
11985
  const headers = {
11338
11986
  "X-Redmine-API-Key": this.apiAccessToken,
11339
11987
  "Content-Type": "application/json",
@@ -11394,8 +12042,8 @@ var RedmineApiClient = class {
11394
12042
  if (include && include.length > 0) {
11395
12043
  params.append("include", include.join(","));
11396
12044
  }
11397
- const path9 = `/issues/${issueId}.json${params.toString() ? `?${params.toString()}` : ""}`;
11398
- return this.request(path9);
12045
+ const path10 = `/issues/${issueId}.json${params.toString() ? `?${params.toString()}` : ""}`;
12046
+ return this.request(path10);
11399
12047
  }
11400
12048
  async getIssues(projectId, options = {}) {
11401
12049
  const params = new URLSearchParams();
@@ -11415,8 +12063,8 @@ var RedmineApiClient = class {
11415
12063
  if (options.updatedSince) {
11416
12064
  params.append("updated_on", `>=${options.updatedSince}`);
11417
12065
  }
11418
- const path9 = `/issues.json?${params.toString()}`;
11419
- return this.request(path9);
12066
+ const path10 = `/issues.json?${params.toString()}`;
12067
+ return this.request(path10);
11420
12068
  }
11421
12069
  async getAllIssues(projectId, options = {}) {
11422
12070
  const pageSize = options.pageSize || 100;
@@ -11518,7 +12166,7 @@ async function checkConnectivity(config) {
11518
12166
 
11519
12167
  // src/commands/redmine/check.ts
11520
12168
  function createRedmineCheckCommand() {
11521
- const cmd = new Command50("check").description("Check Redmine connectivity").option("-c, --config <path>", "Config file path", "redmine.config.yaml").option("--json", "Output as JSON").action(async (options) => {
12169
+ const cmd = new Command51("check").description("Check Redmine connectivity").option("-c, --config <path>", "Config file path", "redmine.config.yaml").option("--json", "Output as JSON").action(async (options) => {
11522
12170
  await handleRedmineCheck(options);
11523
12171
  });
11524
12172
  return cmd;
@@ -11546,7 +12194,7 @@ async function handleRedmineCheck(options) {
11546
12194
  }
11547
12195
 
11548
12196
  // src/commands/redmine/sync-issue.ts
11549
- import { Command as Command51 } from "commander";
12197
+ import { Command as Command52 } from "commander";
11550
12198
 
11551
12199
  // src/sync-issue.ts
11552
12200
  import { resolve as resolve3, relative } from "path";
@@ -11930,7 +12578,7 @@ function extractIssueIdFromUrl(url) {
11930
12578
 
11931
12579
  // src/commands/redmine/sync-issue.ts
11932
12580
  function createSyncIssueCommand() {
11933
- const cmd = new Command51("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) => {
12581
+ const cmd = new Command52("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) => {
11934
12582
  await handleSyncIssue(options);
11935
12583
  });
11936
12584
  return cmd;
@@ -11974,7 +12622,7 @@ async function handleSyncIssue(options) {
11974
12622
  }
11975
12623
 
11976
12624
  // src/commands/redmine/sync-project.ts
11977
- import { Command as Command52 } from "commander";
12625
+ import { Command as Command53 } from "commander";
11978
12626
 
11979
12627
  // src/sync-project.ts
11980
12628
  async function syncProject(config, options = {}) {
@@ -12044,7 +12692,7 @@ async function syncProject(config, options = {}) {
12044
12692
 
12045
12693
  // src/commands/redmine/sync-project.ts
12046
12694
  function createSyncProjectCommand() {
12047
- const cmd = new Command52("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) => {
12695
+ const cmd = new Command53("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) => {
12048
12696
  await handleSyncProject(options);
12049
12697
  });
12050
12698
  return cmd;
@@ -12099,12 +12747,12 @@ async function handleSyncProject(options) {
12099
12747
  }
12100
12748
 
12101
12749
  // src/commands/framework/info.ts
12102
- import { Command as Command53 } from "commander";
12103
- import { promises as fs19 } from "fs";
12104
- import { join as join14 } from "path";
12750
+ import { Command as Command54 } from "commander";
12751
+ import { promises as fs21 } from "fs";
12752
+ import { join as join15 } from "path";
12105
12753
  import { homedir as homedir5 } from "os";
12106
12754
  function createInfoCommand() {
12107
- const cmd = new Command53("info").description("Show jai1-client configuration and status").option("--json", "Output as JSON").option("--verbose", "Show detailed information").action(async (options) => {
12755
+ const cmd = new Command54("info").description("Show jai1-client configuration and status").option("--json", "Output as JSON").option("--verbose", "Show detailed information").action(async (options) => {
12108
12756
  await handleInfo(options);
12109
12757
  });
12110
12758
  return cmd;
@@ -12115,7 +12763,7 @@ async function handleInfo(options) {
12115
12763
  if (!config) {
12116
12764
  throw new ValidationError('Not initialized. Run "jai1 auth" first.');
12117
12765
  }
12118
- const frameworkPath = join14(homedir5(), ".jai1", "framework");
12766
+ const frameworkPath = join15(homedir5(), ".jai1", "framework");
12119
12767
  const projectStatus = await getProjectStatus2();
12120
12768
  const info = {
12121
12769
  configPath: configService.getConfigPath(),
@@ -12150,9 +12798,9 @@ function maskKey3(key) {
12150
12798
  return "****" + key.slice(-4);
12151
12799
  }
12152
12800
  async function getProjectStatus2() {
12153
- const projectJai1 = join14(process.cwd(), ".jai1");
12801
+ const projectJai1 = join15(process.cwd(), ".jai1");
12154
12802
  try {
12155
- await fs19.access(projectJai1);
12803
+ await fs21.access(projectJai1);
12156
12804
  return { exists: true, version: "Synced" };
12157
12805
  } catch {
12158
12806
  return { exists: false };
@@ -12160,8 +12808,8 @@ async function getProjectStatus2() {
12160
12808
  }
12161
12809
 
12162
12810
  // src/commands/self-update.ts
12163
- import { Command as Command54 } from "commander";
12164
- import { confirm as confirm12 } from "@inquirer/prompts";
12811
+ import { Command as Command55 } from "commander";
12812
+ import { confirm as confirm13 } from "@inquirer/prompts";
12165
12813
  import { execSync as execSync3 } from "child_process";
12166
12814
  var colors4 = {
12167
12815
  yellow: "\x1B[33m",
@@ -12172,7 +12820,7 @@ var colors4 = {
12172
12820
  bold: "\x1B[1m"
12173
12821
  };
12174
12822
  function createSelfUpdateCommand() {
12175
- return new Command54("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) => {
12823
+ return new Command55("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) => {
12176
12824
  await handleSelfUpdate(options);
12177
12825
  });
12178
12826
  }
@@ -12216,7 +12864,7 @@ ${colors4.bold}Current version:${colors4.reset} ${currentVersion}`);
12216
12864
  return;
12217
12865
  }
12218
12866
  if (!options.force) {
12219
- const shouldUpdate = await confirm12({
12867
+ const shouldUpdate = await confirm13({
12220
12868
  message: "Update to the latest version now?",
12221
12869
  default: true
12222
12870
  });
@@ -12312,10 +12960,10 @@ function getInstallCommand2(packageManager2) {
12312
12960
  }
12313
12961
 
12314
12962
  // src/commands/clear-backups.ts
12315
- import { Command as Command55 } from "commander";
12316
- import { confirm as confirm13 } from "@inquirer/prompts";
12963
+ import { Command as Command56 } from "commander";
12964
+ import { confirm as confirm14 } from "@inquirer/prompts";
12317
12965
  function createClearBackupsCommand() {
12318
- return new Command55("clear-backups").description("Clear backup files").option("-y, --yes", "Skip confirmation").action(async (options) => {
12966
+ return new Command56("clear-backups").description("Clear backup files").option("-y, --yes", "Skip confirmation").action(async (options) => {
12319
12967
  const service = new ComponentsService();
12320
12968
  const backups = await service.listBackups(process.cwd());
12321
12969
  if (backups.length === 0) {
@@ -12331,7 +12979,7 @@ function createClearBackupsCommand() {
12331
12979
  }
12332
12980
  console.log();
12333
12981
  if (!options.yes) {
12334
- const ok = await confirm13({ message: "Delete all backups?", default: false });
12982
+ const ok = await confirm14({ message: "Delete all backups?", default: false });
12335
12983
  if (!ok) return;
12336
12984
  }
12337
12985
  await service.clearBackups(process.cwd());
@@ -12340,10 +12988,10 @@ function createClearBackupsCommand() {
12340
12988
  }
12341
12989
 
12342
12990
  // src/commands/vscode/index.ts
12343
- import { Command as Command56 } from "commander";
12344
- import { checkbox as checkbox7, confirm as confirm14, select as select7 } from "@inquirer/prompts";
12345
- import fs20 from "fs/promises";
12346
- import path8 from "path";
12991
+ import { Command as Command57 } from "commander";
12992
+ import { checkbox as checkbox7, confirm as confirm15, select as select8 } from "@inquirer/prompts";
12993
+ import fs22 from "fs/promises";
12994
+ import path9 from "path";
12347
12995
  import { existsSync as existsSync3 } from "fs";
12348
12996
  var PERFORMANCE_GROUPS2 = {
12349
12997
  telemetry: {
@@ -12480,7 +13128,7 @@ var PERFORMANCE_GROUPS2 = {
12480
13128
  }
12481
13129
  };
12482
13130
  function createVSCodeCommand() {
12483
- const vscodeCommand = new Command56("vscode").description("Qu\u1EA3n l\xFD c\xE0i \u0111\u1EB7t VSCode cho d\u1EF1 \xE1n hi\u1EC7n t\u1EA1i");
13131
+ const vscodeCommand = new Command57("vscode").description("Qu\u1EA3n l\xFD c\xE0i \u0111\u1EB7t VSCode cho d\u1EF1 \xE1n hi\u1EC7n t\u1EA1i");
12484
13132
  vscodeCommand.action(async () => {
12485
13133
  await interactiveMode2();
12486
13134
  });
@@ -12524,7 +13172,7 @@ async function interactiveMode2() {
12524
13172
  console.log("\u2502 \u2022 Nh\u1EA5n ENTER \u0111\u1EC3 x\xE1c nh\u1EADn v\xE0 \xE1p d\u1EE5ng \u2502");
12525
13173
  console.log("\u2502 \u2022 Nh\u1EA5n Ctrl+C \u0111\u1EC3 h\u1EE7y \u2502");
12526
13174
  console.log("\u2570\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256F\n");
12527
- const action = await select7({
13175
+ const action = await select8({
12528
13176
  message: "B\u1EA1n mu\u1ED1n l\xE0m g\xEC?",
12529
13177
  choices: [
12530
13178
  { name: "\u2705 Enable c\xE1c nh\xF3m t\u1ED1i \u01B0u", value: "enable" },
@@ -12563,8 +13211,8 @@ async function selectGroupsToApply2(action) {
12563
13211
  }
12564
13212
  }
12565
13213
  async function applyGroups2(groupKeys, action) {
12566
- const vscodeDir = path8.join(process.cwd(), ".vscode");
12567
- const settingsPath = path8.join(vscodeDir, "settings.json");
13214
+ const vscodeDir = path9.join(process.cwd(), ".vscode");
13215
+ const settingsPath = path9.join(vscodeDir, "settings.json");
12568
13216
  const invalidGroups = groupKeys.filter((key) => !PERFORMANCE_GROUPS2[key]);
12569
13217
  if (invalidGroups.length > 0) {
12570
13218
  console.log(`
@@ -12573,18 +13221,18 @@ async function applyGroups2(groupKeys, action) {
12573
13221
  return;
12574
13222
  }
12575
13223
  if (!existsSync3(vscodeDir)) {
12576
- await fs20.mkdir(vscodeDir, { recursive: true });
13224
+ await fs22.mkdir(vscodeDir, { recursive: true });
12577
13225
  console.log("\u{1F4C1} \u0110\xE3 t\u1EA1o th\u01B0 m\u1EE5c .vscode/");
12578
13226
  }
12579
13227
  let currentSettings = {};
12580
13228
  if (existsSync3(settingsPath)) {
12581
13229
  try {
12582
- const content = await fs20.readFile(settingsPath, "utf-8");
13230
+ const content = await fs22.readFile(settingsPath, "utf-8");
12583
13231
  currentSettings = JSON.parse(content);
12584
13232
  console.log("\u{1F4C4} \u0110\xE3 \u0111\u1ECDc c\xE0i \u0111\u1EB7t hi\u1EC7n t\u1EA1i t\u1EEB settings.json");
12585
13233
  } catch {
12586
13234
  console.warn("\u26A0\uFE0F Kh\xF4ng th\u1EC3 \u0111\u1ECDc settings.json (c\xF3 th\u1EC3 ch\u1EE9a comments).");
12587
- const confirmOverwrite = await confirm14({
13235
+ const confirmOverwrite = await confirm15({
12588
13236
  message: "Ghi \u0111\xE8 file settings.json hi\u1EC7n t\u1EA1i?",
12589
13237
  default: false
12590
13238
  });
@@ -12619,19 +13267,19 @@ async function applyGroups2(groupKeys, action) {
12619
13267
  }
12620
13268
  }
12621
13269
  }
12622
- await fs20.writeFile(settingsPath, JSON.stringify(newSettings, null, 2));
13270
+ await fs22.writeFile(settingsPath, JSON.stringify(newSettings, null, 2));
12623
13271
  console.log(`
12624
13272
  \u2705 \u0110\xE3 c\u1EADp nh\u1EADt c\xE0i \u0111\u1EB7t VSCode t\u1EA1i: ${settingsPath}`);
12625
13273
  console.log("\u{1F4A1} M\u1EB9o: Kh\u1EDFi \u0111\u1ED9ng l\u1EA1i VSCode \u0111\u1EC3 \xE1p d\u1EE5ng c\xE1c thay \u0111\u1ED5i.");
12626
13274
  }
12627
13275
  async function resetSettings2(groupKeys) {
12628
- const vscodeDir = path8.join(process.cwd(), ".vscode");
12629
- const settingsPath = path8.join(vscodeDir, "settings.json");
13276
+ const vscodeDir = path9.join(process.cwd(), ".vscode");
13277
+ const settingsPath = path9.join(vscodeDir, "settings.json");
12630
13278
  if (!existsSync3(settingsPath)) {
12631
13279
  console.log("\n\u26A0\uFE0F Kh\xF4ng t\xECm th\u1EA5y file settings.json");
12632
13280
  return;
12633
13281
  }
12634
- const confirmReset = await confirm14({
13282
+ const confirmReset = await confirm15({
12635
13283
  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(", ")}?`,
12636
13284
  default: false
12637
13285
  });
@@ -12640,7 +13288,7 @@ async function resetSettings2(groupKeys) {
12640
13288
  return;
12641
13289
  }
12642
13290
  if (groupKeys.length === 0) {
12643
- await fs20.unlink(settingsPath);
13291
+ await fs22.unlink(settingsPath);
12644
13292
  console.log("\n\u2705 \u0110\xE3 x\xF3a file settings.json");
12645
13293
  } else {
12646
13294
  await applyGroups2(groupKeys, "disable");
@@ -12651,9 +13299,9 @@ async function resetSettings2(groupKeys) {
12651
13299
  // src/commands/guide.ts
12652
13300
  import React40 from "react";
12653
13301
  import { render as render6 } from "ink";
12654
- import { Command as Command57 } from "commander";
13302
+ import { Command as Command58 } from "commander";
12655
13303
  function createGuideCommand() {
12656
- const cmd = new Command57("guide").description("Interactive guide center for Agentic Coding").option("--topic <topic>", "Open specific topic (intro, rules, workflows, prompts, skills)").action(async (options) => {
13304
+ const cmd = new Command58("guide").description("Interactive guide center for Agentic Coding").option("--topic <topic>", "Open specific topic (intro, rules, workflows, prompts, skills)").action(async (options) => {
12657
13305
  const { waitUntilExit } = render6(
12658
13306
  React40.createElement(GuideApp, {
12659
13307
  initialTopic: options.topic,
@@ -12670,9 +13318,9 @@ function createGuideCommand() {
12670
13318
  // src/commands/context.ts
12671
13319
  import React41 from "react";
12672
13320
  import { render as render7 } from "ink";
12673
- import { Command as Command58 } from "commander";
13321
+ import { Command as Command59 } from "commander";
12674
13322
  function createContextCommand() {
12675
- const cmd = new Command58("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) => {
13323
+ const cmd = new Command59("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) => {
12676
13324
  let initialIDE;
12677
13325
  if (options.ide) {
12678
13326
  const validIDEs = ["cursor", "windsurf", "antigravity", "jai1"];
@@ -12749,10 +13397,10 @@ async function printStats2() {
12749
13397
  }
12750
13398
 
12751
13399
  // src/commands/migrate-ide.ts
12752
- import { Command as Command59 } from "commander";
12753
- import { checkbox as checkbox8, confirm as confirm15 } from "@inquirer/prompts";
13400
+ import { Command as Command60 } from "commander";
13401
+ import { checkbox as checkbox8, confirm as confirm16 } from "@inquirer/prompts";
12754
13402
  function createMigrateIdeCommand() {
12755
- const cmd = new Command59("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) => {
13403
+ const cmd = new Command60("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) => {
12756
13404
  await runMigrateIde(options);
12757
13405
  });
12758
13406
  return cmd;
@@ -12821,7 +13469,7 @@ async function runMigrateIde(options) {
12821
13469
  if (options.dryRun) {
12822
13470
  console.log("\u{1F50D} DRY RUN - No files will be written\n");
12823
13471
  }
12824
- const confirmed = await confirm15({
13472
+ const confirmed = await confirm16({
12825
13473
  message: "Proceed with migration?",
12826
13474
  default: true
12827
13475
  });
@@ -12858,7 +13506,7 @@ async function runMigrateIde(options) {
12858
13506
  }
12859
13507
 
12860
13508
  // src/cli.ts
12861
- var program = new Command60();
13509
+ var program = new Command61();
12862
13510
  if (process.argv.includes("-v") || process.argv.includes("--version")) {
12863
13511
  console.log(package_default.version);
12864
13512
  if (!process.argv.includes("--skip-update-check")) {
@@ -12880,15 +13528,16 @@ program.addCommand(createOpenAiKeysCommand());
12880
13528
  program.addCommand(createStatsCommand());
12881
13529
  program.addCommand(createTranslateCommand());
12882
13530
  program.addCommand(createImageCommand());
13531
+ program.addCommand(createFeedbackCommand());
12883
13532
  program.addCommand(createUtilsCommand());
12884
13533
  program.addCommand(createDepsCommand());
12885
13534
  program.addCommand(createKitCommand());
12886
13535
  program.addCommand(createRulesCommand());
12887
13536
  program.addCommand(createUpgradeCommand());
12888
13537
  program.addCommand(createCleanCommand());
12889
- var redmineCommand = new Command60("redmine").description("Redmine context sync commands");
13538
+ var redmineCommand = new Command61("redmine").description("Redmine context sync commands");
12890
13539
  redmineCommand.addCommand(createRedmineCheckCommand());
12891
- var syncCommand = new Command60("sync").description("Sync Redmine issues to markdown files");
13540
+ var syncCommand = new Command61("sync").description("Sync Redmine issues to markdown files");
12892
13541
  syncCommand.addCommand(createSyncIssueCommand());
12893
13542
  syncCommand.addCommand(createSyncProjectCommand());
12894
13543
  redmineCommand.addCommand(syncCommand);