@jvittechs/jai1-cli 0.1.85 → 0.1.86

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 Command47 } from "commander";
4
+ import { Command as Command52 } 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.85",
36
+ version: "0.1.86",
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: {
@@ -895,9 +895,9 @@ var UnifiedApplyApp = ({
895
895
  (c) => c.filepath.toLowerCase().includes(query) || c.name.toLowerCase().includes(query) || c.tags && c.tags.some((t) => t.toLowerCase().includes(query))
896
896
  );
897
897
  }, [components, searchQuery]);
898
- useInput((input2, key) => {
898
+ useInput((input3, key) => {
899
899
  if (viewState === "summary") {
900
- if (key.return || input2 === "q" || key.escape) {
900
+ if (key.return || input3 === "q" || key.escape) {
901
901
  onExit();
902
902
  }
903
903
  return;
@@ -911,7 +911,7 @@ var UnifiedApplyApp = ({
911
911
  else setFocusArea("search");
912
912
  return;
913
913
  }
914
- if (key.escape || input2 === "q") {
914
+ if (key.escape || input3 === "q") {
915
915
  onExit();
916
916
  return;
917
917
  }
@@ -926,7 +926,7 @@ var UnifiedApplyApp = ({
926
926
  setCursorIndex((prev) => Math.max(0, prev - 1));
927
927
  } else if (key.downArrow) {
928
928
  setCursorIndex((prev) => Math.min(filteredComponents.length - 1, prev + 1));
929
- } else if (input2 === " ") {
929
+ } else if (input3 === " ") {
930
930
  const current = filteredComponents[cursorIndex];
931
931
  if (current) {
932
932
  setSelectedPaths((prev) => {
@@ -939,13 +939,13 @@ var UnifiedApplyApp = ({
939
939
  return next;
940
940
  });
941
941
  }
942
- } else if (input2 === "a") {
942
+ } else if (input3 === "a") {
943
943
  setSelectedPaths((prev) => {
944
944
  const next = new Set(prev);
945
945
  filteredComponents.forEach((c) => next.add(c.filepath));
946
946
  return next;
947
947
  });
948
- } else if (input2 === "c") {
948
+ } else if (input3 === "c") {
949
949
  setSelectedPaths(/* @__PURE__ */ new Set());
950
950
  }
951
951
  }
@@ -954,7 +954,7 @@ var UnifiedApplyApp = ({
954
954
  setSelectedPackageIndex((prev) => Math.max(0, prev - 1));
955
955
  } else if (key.rightArrow) {
956
956
  setSelectedPackageIndex((prev) => Math.min(tags.length - 1, prev + 1));
957
- } else if (input2 === " " || key.return) {
957
+ } else if (input3 === " " || key.return) {
958
958
  const tag = tags[selectedPackageIndex];
959
959
  if (tag) {
960
960
  const packageComponents = components.filter((c) => c.tags?.includes(tag.tag));
@@ -1332,7 +1332,7 @@ var MainMenuView = ({ ideContexts, onSelect }) => {
1332
1332
  available: ideContexts.some((ctx) => ctx.ide === "jai1")
1333
1333
  }
1334
1334
  ];
1335
- useInput2((input2, key) => {
1335
+ useInput2((input3, key) => {
1336
1336
  if (key.upArrow) {
1337
1337
  setSelectedIndex((prev) => Math.max(0, prev - 1));
1338
1338
  } else if (key.downArrow) {
@@ -1434,13 +1434,13 @@ var IDEOverviewView = ({
1434
1434
  count: ideContext.stats.byType.context
1435
1435
  });
1436
1436
  }
1437
- useInput3((input2, key) => {
1437
+ useInput3((input3, key) => {
1438
1438
  if (key.tab || key.rightArrow) {
1439
1439
  setSelectedTabIndex((prev) => Math.min(tabs.length - 1, prev + 1));
1440
1440
  } else if (key.leftArrow) {
1441
1441
  setSelectedTabIndex((prev) => Math.max(0, prev - 1));
1442
1442
  }
1443
- const num = parseInt(input2, 10);
1443
+ const num = parseInt(input3, 10);
1444
1444
  if (!isNaN(num) && num >= 1 && num <= tabs.length) {
1445
1445
  setSelectedTabIndex(num - 1);
1446
1446
  }
@@ -1502,7 +1502,7 @@ import React7, { useState as useState4 } from "react";
1502
1502
  import { Box as Box5, Text as Text6, useInput as useInput4 } from "ink";
1503
1503
  var ListView = ({ items, contentType, onSelect, onBack }) => {
1504
1504
  const [selectedIndex, setSelectedIndex] = useState4(0);
1505
- useInput4((input2, key) => {
1505
+ useInput4((input3, key) => {
1506
1506
  if (key.upArrow) {
1507
1507
  setSelectedIndex((prev) => Math.max(0, prev - 1));
1508
1508
  } else if (key.downArrow) {
@@ -1553,18 +1553,18 @@ var DetailView = ({ item, scrollPosition: initialScroll, onBack }) => {
1553
1553
  const [scrollPosition, setScrollPosition] = useState5(initialScroll);
1554
1554
  const maxVisibleLines = 25;
1555
1555
  const maxScroll = Math.max(0, item.previewLines.length - maxVisibleLines);
1556
- useInput5((input2, key) => {
1557
- if (key.upArrow || input2 === "k") {
1556
+ useInput5((input3, key) => {
1557
+ if (key.upArrow || input3 === "k") {
1558
1558
  setScrollPosition((prev) => Math.max(0, prev - 1));
1559
- } else if (key.downArrow || input2 === "j") {
1559
+ } else if (key.downArrow || input3 === "j") {
1560
1560
  setScrollPosition((prev) => Math.min(maxScroll, prev + 1));
1561
- } else if (key.pageDown || input2 === "d") {
1561
+ } else if (key.pageDown || input3 === "d") {
1562
1562
  setScrollPosition((prev) => Math.min(maxScroll, prev + 5));
1563
- } else if (key.pageUp || input2 === "u") {
1563
+ } else if (key.pageUp || input3 === "u") {
1564
1564
  setScrollPosition((prev) => Math.max(0, prev - 5));
1565
- } else if (input2 === "g") {
1565
+ } else if (input3 === "g") {
1566
1566
  setScrollPosition(0);
1567
- } else if (input2 === "G") {
1567
+ } else if (input3 === "G") {
1568
1568
  setScrollPosition(maxScroll);
1569
1569
  } else if (key.escape || key.backspace) {
1570
1570
  onBack();
@@ -1960,8 +1960,8 @@ var ContextApp = ({ initialIDE, initialType, onExit }) => {
1960
1960
  setLoading(false);
1961
1961
  });
1962
1962
  }, [initialIDE]);
1963
- useInput6((input2, key) => {
1964
- if (input2 === "q") {
1963
+ useInput6((input3, key) => {
1964
+ if (input3 === "q") {
1965
1965
  onExit();
1966
1966
  return;
1967
1967
  }
@@ -2888,7 +2888,7 @@ var MENU_ITEMS = [
2888
2888
  ];
2889
2889
  var MenuView = ({ onSelect }) => {
2890
2890
  const [selectedIndex, setSelectedIndex] = useState7(0);
2891
- useInput7((input2, key) => {
2891
+ useInput7((input3, key) => {
2892
2892
  if (key.upArrow) {
2893
2893
  setSelectedIndex((prev) => Math.max(0, prev - 1));
2894
2894
  } else if (key.downArrow) {
@@ -3501,7 +3501,7 @@ var AgenticGuideView = ({ onBack }) => {
3501
3501
  const [isTyping, setIsTyping] = useState8(false);
3502
3502
  const [selectedSuggestion, setSelectedSuggestion] = useState8(0);
3503
3503
  const [focusArea, setFocusArea] = useState8("input");
3504
- useInput8((input2, key) => {
3504
+ useInput8((input3, key) => {
3505
3505
  if (key.escape) {
3506
3506
  onBack();
3507
3507
  return;
@@ -3633,7 +3633,7 @@ var GuideApp = ({ initialTopic, onExit }) => {
3633
3633
  setCurrentTopic(TOPIC_MAP[initialTopic]);
3634
3634
  }
3635
3635
  }, [initialTopic]);
3636
- useInput9((input2, key) => {
3636
+ useInput9((input3, key) => {
3637
3637
  if (key.escape || currentTopic !== "menu" && key.backspace) {
3638
3638
  if (currentTopic === "menu") {
3639
3639
  onExit();
@@ -3643,7 +3643,7 @@ var GuideApp = ({ initialTopic, onExit }) => {
3643
3643
  }
3644
3644
  return;
3645
3645
  }
3646
- if (input2 === "q") {
3646
+ if (input3 === "q") {
3647
3647
  onExit();
3648
3648
  return;
3649
3649
  }
@@ -4142,7 +4142,7 @@ var ModelSelector = ({
4142
4142
  const allowedModels = models.filter((m) => m.allowed);
4143
4143
  const currentIndex = allowedModels.findIndex((m) => m.id === currentModel);
4144
4144
  const [selectedIndex, setSelectedIndex] = useState12(Math.max(0, currentIndex));
4145
- useInput10((input2, key) => {
4145
+ useInput10((input3, key) => {
4146
4146
  if (key.escape) {
4147
4147
  onCancel();
4148
4148
  return;
@@ -4268,7 +4268,7 @@ var ChatApp = ({ service, initialModel }) => {
4268
4268
  }
4269
4269
  return false;
4270
4270
  }, [refetch, exit]);
4271
- useInput11((input2, key) => {
4271
+ useInput11((input3, key) => {
4272
4272
  if (showSlashMenu) {
4273
4273
  if (key.upArrow) {
4274
4274
  setSlashMenuIndex((i) => Math.max(0, i - 1));
@@ -4296,7 +4296,7 @@ var ChatApp = ({ service, initialModel }) => {
4296
4296
  }
4297
4297
  return;
4298
4298
  }
4299
- if (currentView === "error" && (key.return || input2 === "r")) {
4299
+ if (currentView === "error" && (key.return || input3 === "r")) {
4300
4300
  setCurrentView("loading");
4301
4301
  refetch();
4302
4302
  return;
@@ -4551,9 +4551,9 @@ var TranslationService = class {
4551
4551
  /**
4552
4552
  * Detect input type
4553
4553
  */
4554
- async detectInputType(input2) {
4554
+ async detectInputType(input3) {
4555
4555
  try {
4556
- const stat = await fs7.stat(input2);
4556
+ const stat = await fs7.stat(input3);
4557
4557
  if (stat.isDirectory()) return "folder";
4558
4558
  if (stat.isFile()) return "file";
4559
4559
  } catch {
@@ -4785,7 +4785,7 @@ Return ONLY the translated content, no explanations.`;
4785
4785
  };
4786
4786
 
4787
4787
  // src/commands/translate.ts
4788
- async function handleTranslate(input2, options) {
4788
+ async function handleTranslate(input3, options) {
4789
4789
  const configService = new ConfigService();
4790
4790
  const config = await configService.load();
4791
4791
  if (!config) {
@@ -4793,16 +4793,16 @@ async function handleTranslate(input2, options) {
4793
4793
  }
4794
4794
  const llmService = new LlmProxyService(config);
4795
4795
  const translationService = new TranslationService(llmService, options, options.model);
4796
- const inputType = await translationService.detectInputType(input2);
4796
+ const inputType = await translationService.detectInputType(input3);
4797
4797
  switch (inputType) {
4798
4798
  case "text":
4799
- await handleTextTranslation(translationService, input2, options);
4799
+ await handleTextTranslation(translationService, input3, options);
4800
4800
  break;
4801
4801
  case "file":
4802
- await handleFileTranslation(translationService, input2, options);
4802
+ await handleFileTranslation(translationService, input3, options);
4803
4803
  break;
4804
4804
  case "folder":
4805
- await handleFolderTranslation(translationService, input2, options);
4805
+ await handleFolderTranslation(translationService, input3, options);
4806
4806
  break;
4807
4807
  }
4808
4808
  }
@@ -4879,8 +4879,8 @@ async function handleFolderTranslation(service, folderPath, options) {
4879
4879
  }
4880
4880
  }
4881
4881
  function createTranslateCommand() {
4882
- const cmd = new Command14("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 (input2, options) => {
4883
- await handleTranslate(input2, options);
4882
+ const cmd = new Command14("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 (input3, options) => {
4883
+ await handleTranslate(input3, options);
4884
4884
  });
4885
4885
  return cmd;
4886
4886
  }
@@ -4940,12 +4940,12 @@ var UtilsService = class {
4940
4940
  /**
4941
4941
  * Hash text or file using specified algorithm
4942
4942
  */
4943
- async hash(input2, algorithm) {
4943
+ async hash(input3, algorithm) {
4944
4944
  if (algorithm === "bcrypt") {
4945
4945
  throw new Error("Use hashBcrypt for bcrypt algorithm");
4946
4946
  }
4947
4947
  const hash = crypto.createHash(algorithm);
4948
- hash.update(input2);
4948
+ hash.update(input3);
4949
4949
  return hash.digest("hex");
4950
4950
  }
4951
4951
  /**
@@ -4958,14 +4958,14 @@ var UtilsService = class {
4958
4958
  /**
4959
4959
  * Hash using bcrypt
4960
4960
  */
4961
- async hashBcrypt(input2, rounds = 10) {
4962
- return bcrypt.hash(input2, rounds);
4961
+ async hashBcrypt(input3, rounds = 10) {
4962
+ return bcrypt.hash(input3, rounds);
4963
4963
  }
4964
4964
  /**
4965
4965
  * Base64 encode
4966
4966
  */
4967
- base64Encode(input2, urlSafe = false) {
4968
- const buffer = typeof input2 === "string" ? Buffer.from(input2, "utf-8") : input2;
4967
+ base64Encode(input3, urlSafe = false) {
4968
+ const buffer = typeof input3 === "string" ? Buffer.from(input3, "utf-8") : input3;
4969
4969
  let encoded = buffer.toString("base64");
4970
4970
  if (urlSafe) {
4971
4971
  encoded = encoded.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
@@ -4975,8 +4975,8 @@ var UtilsService = class {
4975
4975
  /**
4976
4976
  * Base64 decode
4977
4977
  */
4978
- base64Decode(input2) {
4979
- let normalized = input2.replace(/-/g, "+").replace(/_/g, "/");
4978
+ base64Decode(input3) {
4979
+ let normalized = input3.replace(/-/g, "+").replace(/_/g, "/");
4980
4980
  while (normalized.length % 4) {
4981
4981
  normalized += "=";
4982
4982
  }
@@ -5105,14 +5105,14 @@ var UtilsService = class {
5105
5105
  /**
5106
5106
  * URL encode
5107
5107
  */
5108
- urlEncode(input2, full = false) {
5109
- return full ? encodeURI(input2) : encodeURIComponent(input2);
5108
+ urlEncode(input3, full = false) {
5109
+ return full ? encodeURI(input3) : encodeURIComponent(input3);
5110
5110
  }
5111
5111
  /**
5112
5112
  * URL decode
5113
5113
  */
5114
- urlDecode(input2, full = false) {
5115
- return full ? decodeURI(input2) : decodeURIComponent(input2);
5114
+ urlDecode(input3, full = false) {
5115
+ return full ? decodeURI(input3) : decodeURIComponent(input3);
5116
5116
  }
5117
5117
  /**
5118
5118
  * Format bytes to human-readable size
@@ -5222,7 +5222,7 @@ Examples:
5222
5222
 
5223
5223
  // src/commands/utils/hash.ts
5224
5224
  import { Command as Command17 } from "commander";
5225
- async function handleHashGeneration(input2, options) {
5225
+ async function handleHashGeneration(input3, options) {
5226
5226
  const service = new UtilsService();
5227
5227
  try {
5228
5228
  let hash;
@@ -5233,14 +5233,14 @@ async function handleHashGeneration(input2, options) {
5233
5233
  }
5234
5234
  hash = await service.hashFile(options.file, options.algorithm);
5235
5235
  } else {
5236
- if (!input2) {
5236
+ if (!input3) {
5237
5237
  console.error("\u274C Please provide input text or use --file option");
5238
5238
  process.exit(1);
5239
5239
  }
5240
5240
  if (options.algorithm === "bcrypt") {
5241
- hash = await service.hashBcrypt(input2, options.rounds);
5241
+ hash = await service.hashBcrypt(input3, options.rounds);
5242
5242
  } else {
5243
- hash = await service.hash(input2, options.algorithm);
5243
+ hash = await service.hash(input3, options.algorithm);
5244
5244
  }
5245
5245
  }
5246
5246
  console.log("\u{1F512} Hash Result:");
@@ -5273,8 +5273,8 @@ Examples:
5273
5273
  $ jai1 utils hash "password" --algorithm bcrypt --rounds 12
5274
5274
  $ jai1 utils hash --file ./myfile.txt
5275
5275
  $ jai1 utils hash --file ./image.png --algorithm sha512
5276
- `).action(async (input2, options) => {
5277
- await handleHashGeneration(input2, {
5276
+ `).action(async (input3, options) => {
5277
+ await handleHashGeneration(input3, {
5278
5278
  ...options,
5279
5279
  rounds: parseInt(options.rounds, 10)
5280
5280
  });
@@ -5285,7 +5285,7 @@ Examples:
5285
5285
  // src/commands/utils/base64-encode.ts
5286
5286
  import { Command as Command18 } from "commander";
5287
5287
  import { readFile as readFile2 } from "fs/promises";
5288
- async function handleBase64Encode(input2, options) {
5288
+ async function handleBase64Encode(input3, options) {
5289
5289
  const service = new UtilsService();
5290
5290
  try {
5291
5291
  let encoded;
@@ -5293,11 +5293,11 @@ async function handleBase64Encode(input2, options) {
5293
5293
  const content = await readFile2(options.file);
5294
5294
  encoded = service.base64Encode(content, options.urlSafe);
5295
5295
  } else {
5296
- if (!input2) {
5296
+ if (!input3) {
5297
5297
  console.error("\u274C Please provide input text or use --file option");
5298
5298
  process.exit(1);
5299
5299
  }
5300
- encoded = service.base64Encode(input2, options.urlSafe);
5300
+ encoded = service.base64Encode(input3, options.urlSafe);
5301
5301
  }
5302
5302
  console.log("\u{1F4DD} Base64 Encoded:");
5303
5303
  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");
@@ -5322,8 +5322,8 @@ Examples:
5322
5322
  $ jai1 utils base64-encode "hello world" --url-safe
5323
5323
  $ jai1 utils base64-encode --file ./document.txt
5324
5324
  $ jai1 utils base64-encode --file ./image.png
5325
- `).action(async (input2, options) => {
5326
- await handleBase64Encode(input2, options);
5325
+ `).action(async (input3, options) => {
5326
+ await handleBase64Encode(input3, options);
5327
5327
  });
5328
5328
  return cmd;
5329
5329
  }
@@ -5331,18 +5331,18 @@ Examples:
5331
5331
  // src/commands/utils/base64-decode.ts
5332
5332
  import { Command as Command19 } from "commander";
5333
5333
  import { readFile as readFile3, writeFile } from "fs/promises";
5334
- async function handleBase64Decode(input2, options) {
5334
+ async function handleBase64Decode(input3, options) {
5335
5335
  const service = new UtilsService();
5336
5336
  try {
5337
5337
  let encodedInput;
5338
5338
  if (options.file) {
5339
5339
  encodedInput = await readFile3(options.file, "utf-8");
5340
5340
  } else {
5341
- if (!input2) {
5341
+ if (!input3) {
5342
5342
  console.error("\u274C Please provide Base64 input or use --file option");
5343
5343
  process.exit(1);
5344
5344
  }
5345
- encodedInput = input2;
5345
+ encodedInput = input3;
5346
5346
  }
5347
5347
  const decoded = service.base64Decode(encodedInput.trim());
5348
5348
  if (options.output) {
@@ -5367,8 +5367,8 @@ Examples:
5367
5367
  $ jai1 utils base64-decode --file ./encoded.txt
5368
5368
  $ jai1 utils base64-decode "aGVsbG8=" --output ./decoded.txt
5369
5369
  $ jai1 utils base64-decode --file ./encoded.txt --output ./image.png
5370
- `).action(async (input2, options) => {
5371
- await handleBase64Decode(input2, options);
5370
+ `).action(async (input3, options) => {
5371
+ await handleBase64Decode(input3, options);
5372
5372
  });
5373
5373
  return cmd;
5374
5374
  }
@@ -5519,10 +5519,10 @@ Examples:
5519
5519
 
5520
5520
  // src/commands/utils/unix-time.ts
5521
5521
  import { Command as Command22 } from "commander";
5522
- async function handleUnixTime(input2, options) {
5522
+ async function handleUnixTime(input3, options) {
5523
5523
  const service = new UtilsService();
5524
5524
  try {
5525
- if (!input2) {
5525
+ if (!input3) {
5526
5526
  const now = /* @__PURE__ */ new Date();
5527
5527
  const timestamp = service.dateToUnix(now, options.ms);
5528
5528
  console.log("\u{1F552} Current Unix Timestamp:");
@@ -5532,8 +5532,8 @@ async function handleUnixTime(input2, options) {
5532
5532
  console.log(` ISO: ${now.toISOString()}`);
5533
5533
  console.log(` Local: ${now.toLocaleString()}`);
5534
5534
  console.log();
5535
- } else if (/^\d+$/.test(input2)) {
5536
- const timestamp = parseInt(input2, 10);
5535
+ } else if (/^\d+$/.test(input3)) {
5536
+ const timestamp = parseInt(input3, 10);
5537
5537
  const date = service.unixToDate(timestamp, options.ms);
5538
5538
  console.log("\u{1F552} Unix Timestamp to Date:");
5539
5539
  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");
@@ -5546,7 +5546,7 @@ async function handleUnixTime(input2, options) {
5546
5546
  }
5547
5547
  console.log();
5548
5548
  } else {
5549
- const date = new Date(input2);
5549
+ const date = new Date(input3);
5550
5550
  if (isNaN(date.getTime())) {
5551
5551
  console.error("\u274C Invalid date format");
5552
5552
  process.exit(1);
@@ -5554,7 +5554,7 @@ async function handleUnixTime(input2, options) {
5554
5554
  const timestamp = service.dateToUnix(date, options.ms);
5555
5555
  console.log("\u{1F552} Date to Unix Timestamp:");
5556
5556
  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");
5557
- console.log(` Input: ${input2}`);
5557
+ console.log(` Input: ${input3}`);
5558
5558
  console.log(` Parsed: ${date.toISOString()}`);
5559
5559
  console.log();
5560
5560
  console.log(` ${timestamp}${options.ms ? " (ms)" : ""}`);
@@ -5574,8 +5574,8 @@ Examples:
5574
5574
  $ jai1 utils unix-time "2024-01-15 10:30:00"
5575
5575
  $ jai1 utils unix-time "2024-01-15" --format local
5576
5576
  $ jai1 utils unix-time --ms
5577
- `).action(async (input2, options) => {
5578
- await handleUnixTime(input2, options);
5577
+ `).action(async (input3, options) => {
5578
+ await handleUnixTime(input3, options);
5579
5579
  });
5580
5580
  return cmd;
5581
5581
  }
@@ -5632,10 +5632,10 @@ Examples:
5632
5632
 
5633
5633
  // src/commands/utils/url-encode.ts
5634
5634
  import { Command as Command24 } from "commander";
5635
- async function handleUrlEncode(input2, options) {
5635
+ async function handleUrlEncode(input3, options) {
5636
5636
  const service = new UtilsService();
5637
5637
  try {
5638
- const encoded = service.urlEncode(input2, options.full);
5638
+ const encoded = service.urlEncode(input3, options.full);
5639
5639
  console.log("\u{1F517} URL Encoded:");
5640
5640
  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");
5641
5641
  if (options.full) {
@@ -5658,18 +5658,18 @@ Examples:
5658
5658
  $ jai1 utils url-encode "hello world & test"
5659
5659
  $ jai1 utils url-encode "name=John Doe&age=30"
5660
5660
  $ jai1 utils url-encode "https://example.com/path with spaces" --full
5661
- `).showHelpAfterError("(add --help for additional examples)").action(async (input2, options) => {
5662
- await handleUrlEncode(input2, options);
5661
+ `).showHelpAfterError("(add --help for additional examples)").action(async (input3, options) => {
5662
+ await handleUrlEncode(input3, options);
5663
5663
  });
5664
5664
  return cmd;
5665
5665
  }
5666
5666
 
5667
5667
  // src/commands/utils/url-decode.ts
5668
5668
  import { Command as Command25 } from "commander";
5669
- async function handleUrlDecode(input2, options) {
5669
+ async function handleUrlDecode(input3, options) {
5670
5670
  const service = new UtilsService();
5671
5671
  try {
5672
- const decoded = service.urlDecode(input2, options.full);
5672
+ const decoded = service.urlDecode(input3, options.full);
5673
5673
  console.log("\u{1F517} URL Decoded:");
5674
5674
  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");
5675
5675
  if (options.full) {
@@ -5692,8 +5692,8 @@ Examples:
5692
5692
  $ jai1 utils url-decode "hello%20world%20%26%20test"
5693
5693
  $ jai1 utils url-decode "name%3DJohn%20Doe%26age%3D30"
5694
5694
  $ jai1 utils url-decode "https://example.com/path%20with%20spaces" --full
5695
- `).showHelpAfterError("(add --help for additional examples)").action(async (input2, options) => {
5696
- await handleUrlDecode(input2, options);
5695
+ `).showHelpAfterError("(add --help for additional examples)").action(async (input3, options) => {
5696
+ await handleUrlDecode(input3, options);
5697
5697
  });
5698
5698
  return cmd;
5699
5699
  }
@@ -5829,14 +5829,14 @@ var PasswordView = () => {
5829
5829
  React27.useEffect(() => {
5830
5830
  handleGenerate();
5831
5831
  }, []);
5832
- useInput12((input2, key) => {
5832
+ useInput12((input3, key) => {
5833
5833
  if (key.tab) {
5834
5834
  if (focusedField === "length") setFocusedField("count");
5835
5835
  else if (focusedField === "count") setFocusedField("generate");
5836
5836
  else setFocusedField("length");
5837
5837
  } else if (key.return) {
5838
5838
  handleGenerate();
5839
- } else if (input2 === "c" && passwords.length > 0) {
5839
+ } else if (input3 === "c" && passwords.length > 0) {
5840
5840
  handleCopy(0);
5841
5841
  }
5842
5842
  });
@@ -5919,7 +5919,7 @@ var UuidView = () => {
5919
5919
  React28.useEffect(() => {
5920
5920
  handleGenerate();
5921
5921
  }, []);
5922
- useInput13((input2, key) => {
5922
+ useInput13((input3, key) => {
5923
5923
  if (key.tab) {
5924
5924
  const fields = ["count", "uppercase", "hyphens", "generate"];
5925
5925
  const currentIndex = fields.indexOf(focusedField);
@@ -5932,7 +5932,7 @@ var UuidView = () => {
5932
5932
  } else {
5933
5933
  handleGenerate();
5934
5934
  }
5935
- } else if (input2 === "c" && uuids.length > 0) {
5935
+ } else if (input3 === "c" && uuids.length > 0) {
5936
5936
  handleCopy(0);
5937
5937
  }
5938
5938
  });
@@ -6007,7 +6007,7 @@ var HashView = () => {
6007
6007
  React29.useEffect(() => {
6008
6008
  handleGenerate();
6009
6009
  }, []);
6010
- useInput14((input2, key) => {
6010
+ useInput14((input3, key) => {
6011
6011
  if (key.tab) {
6012
6012
  const fields = ["text", "algorithm", "generate"];
6013
6013
  const currentIndex = fields.indexOf(focusedField);
@@ -6020,7 +6020,7 @@ var HashView = () => {
6020
6020
  } else if (key.rightArrow && focusedField === "algorithm") {
6021
6021
  const currentIndex = ALGORITHMS.indexOf(algorithm);
6022
6022
  setAlgorithm(ALGORITHMS[(currentIndex + 1) % ALGORITHMS.length]);
6023
- } else if (input2 === "c" && hash) {
6023
+ } else if (input3 === "c" && hash) {
6024
6024
  handleCopy();
6025
6025
  }
6026
6026
  });
@@ -6086,7 +6086,7 @@ import React30, { useState as useState17 } from "react";
6086
6086
  import { Box as Box20, Text as Text21, useInput as useInput15 } from "ink";
6087
6087
  import TextInput7 from "ink-text-input";
6088
6088
  var Base64View = () => {
6089
- const [input2, setInput] = useState17("");
6089
+ const [input3, setInput] = useState17("");
6090
6090
  const [mode, setMode] = useState17("encode");
6091
6091
  const [urlSafe, setUrlSafe] = useState17(false);
6092
6092
  const [result, setResult] = useState17("");
@@ -6094,7 +6094,7 @@ var Base64View = () => {
6094
6094
  const [focusedField, setFocusedField] = useState17("input");
6095
6095
  const [copied, setCopied] = useState17(false);
6096
6096
  const service = new UtilsService();
6097
- useInput15((input3, key) => {
6097
+ useInput15((input4, key) => {
6098
6098
  if (key.tab) {
6099
6099
  const fields = ["input", "mode", "urlsafe", "convert"];
6100
6100
  const currentIndex = fields.indexOf(focusedField);
@@ -6109,22 +6109,22 @@ var Base64View = () => {
6109
6109
  } else {
6110
6110
  handleConvert();
6111
6111
  }
6112
- } else if (input3 === "c" && result) {
6112
+ } else if (input4 === "c" && result) {
6113
6113
  handleCopy();
6114
6114
  }
6115
6115
  });
6116
6116
  const handleConvert = () => {
6117
- if (!input2) {
6117
+ if (!input3) {
6118
6118
  setError("Input cannot be empty");
6119
6119
  return;
6120
6120
  }
6121
6121
  try {
6122
6122
  setError("");
6123
6123
  if (mode === "encode") {
6124
- const encoded = service.base64Encode(input2, urlSafe);
6124
+ const encoded = service.base64Encode(input3, urlSafe);
6125
6125
  setResult(encoded);
6126
6126
  } else {
6127
- const decoded = service.base64Decode(input2);
6127
+ const decoded = service.base64Decode(input3);
6128
6128
  setResult(decoded.toString("utf-8"));
6129
6129
  }
6130
6130
  setCopied(false);
@@ -6153,7 +6153,7 @@ var Base64View = () => {
6153
6153
  marginBottom: 1
6154
6154
  },
6155
6155
  /* @__PURE__ */ React30.createElement(Text21, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
6156
- /* @__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: input2, onChange: setInput, placeholder: "Enter text..." }) : /* @__PURE__ */ React30.createElement(Text21, { dimColor: !input2 }, input2 || "(empty)"))),
6156
+ /* @__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: input3, onChange: setInput, placeholder: "Enter text..." }) : /* @__PURE__ */ React30.createElement(Text21, { dimColor: !input3 }, input3 || "(empty)"))),
6157
6157
  /* @__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)")),
6158
6158
  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 _)")),
6159
6159
  /* @__PURE__ */ React30.createElement(Box20, { marginTop: 1 }, /* @__PURE__ */ React30.createElement(
@@ -6198,14 +6198,14 @@ import React31, { useState as useState18 } from "react";
6198
6198
  import { Box as Box21, Text as Text22, useInput as useInput16 } from "ink";
6199
6199
  import TextInput8 from "ink-text-input";
6200
6200
  var UrlView = () => {
6201
- const [input2, setInput] = useState18("");
6201
+ const [input3, setInput] = useState18("");
6202
6202
  const [mode, setMode] = useState18("encode");
6203
6203
  const [fullUrl, setFullUrl] = useState18(false);
6204
6204
  const [result, setResult] = useState18("");
6205
6205
  const [focusedField, setFocusedField] = useState18("input");
6206
6206
  const [copied, setCopied] = useState18(false);
6207
6207
  const service = new UtilsService();
6208
- useInput16((input3, key) => {
6208
+ useInput16((input4, key) => {
6209
6209
  if (key.tab) {
6210
6210
  const fields = ["input", "mode", "full", "convert"];
6211
6211
  const currentIndex = fields.indexOf(focusedField);
@@ -6219,17 +6219,17 @@ var UrlView = () => {
6219
6219
  } else {
6220
6220
  handleConvert();
6221
6221
  }
6222
- } else if (input3 === "c" && result) {
6222
+ } else if (input4 === "c" && result) {
6223
6223
  handleCopy();
6224
6224
  }
6225
6225
  });
6226
6226
  const handleConvert = () => {
6227
- if (!input2) return;
6227
+ if (!input3) return;
6228
6228
  if (mode === "encode") {
6229
- const encoded = fullUrl ? service.urlEncode(input2, true) : service.urlEncode(input2, false);
6229
+ const encoded = fullUrl ? service.urlEncode(input3, true) : service.urlEncode(input3, false);
6230
6230
  setResult(encoded);
6231
6231
  } else {
6232
- const decoded = fullUrl ? service.urlDecode(input2, true) : service.urlDecode(input2, false);
6232
+ const decoded = fullUrl ? service.urlDecode(input3, true) : service.urlDecode(input3, false);
6233
6233
  setResult(decoded);
6234
6234
  }
6235
6235
  setCopied(false);
@@ -6254,7 +6254,7 @@ var UrlView = () => {
6254
6254
  marginBottom: 1
6255
6255
  },
6256
6256
  /* @__PURE__ */ React31.createElement(Text22, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
6257
- /* @__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: input2, onChange: setInput, placeholder: "Enter text or URL..." }) : /* @__PURE__ */ React31.createElement(Text22, { dimColor: !input2 }, input2 || "(empty)"))),
6257
+ /* @__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: input3, onChange: setInput, placeholder: "Enter text or URL..." }) : /* @__PURE__ */ React31.createElement(Text22, { dimColor: !input3 }, input3 || "(empty)"))),
6258
6258
  /* @__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)")),
6259
6259
  /* @__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)")),
6260
6260
  /* @__PURE__ */ React31.createElement(Box21, { marginTop: 1 }, /* @__PURE__ */ React31.createElement(
@@ -6288,7 +6288,7 @@ import React32, { useState as useState19 } from "react";
6288
6288
  import { Box as Box22, Text as Text23, useInput as useInput17 } from "ink";
6289
6289
  import TextInput9 from "ink-text-input";
6290
6290
  var UnixTimeView = () => {
6291
- const [input2, setInput] = useState19("");
6291
+ const [input3, setInput] = useState19("");
6292
6292
  const [mode, setMode] = useState19("now");
6293
6293
  const [format, setFormat] = useState19("iso");
6294
6294
  const [useMs, setUseMs] = useState19(false);
@@ -6297,7 +6297,7 @@ var UnixTimeView = () => {
6297
6297
  const [focusedField, setFocusedField] = useState19("mode");
6298
6298
  const [copied, setCopied] = useState19(false);
6299
6299
  const service = new UtilsService();
6300
- useInput17((input3, key) => {
6300
+ useInput17((input4, key) => {
6301
6301
  if (key.tab) {
6302
6302
  const fields = mode === "now" ? ["mode", "ms", "convert"] : mode === "to-human" ? ["mode", "input", "format", "convert"] : ["mode", "input", "convert"];
6303
6303
  const currentIndex = fields.indexOf(focusedField);
@@ -6318,7 +6318,7 @@ var UnixTimeView = () => {
6318
6318
  } else {
6319
6319
  handleConvert();
6320
6320
  }
6321
- } else if (input3 === "c" && result) {
6321
+ } else if (input4 === "c" && result) {
6322
6322
  handleCopy();
6323
6323
  }
6324
6324
  });
@@ -6329,18 +6329,18 @@ var UnixTimeView = () => {
6329
6329
  const timestamp = service.unixTimeCurrent(useMs);
6330
6330
  setResult(timestamp.toString());
6331
6331
  } else if (mode === "to-human") {
6332
- if (!input2) {
6332
+ if (!input3) {
6333
6333
  setError("Please enter a timestamp");
6334
6334
  return;
6335
6335
  }
6336
- const human = service.unixTimeToHuman(parseInt(input2, 10), format);
6336
+ const human = service.unixTimeToHuman(parseInt(input3, 10), format);
6337
6337
  setResult(human);
6338
6338
  } else {
6339
- if (!input2) {
6339
+ if (!input3) {
6340
6340
  setError("Please enter a date string");
6341
6341
  return;
6342
6342
  }
6343
- const timestamp = service.unixTimeFromString(input2);
6343
+ const timestamp = service.unixTimeFromString(input3);
6344
6344
  setResult(timestamp.toString());
6345
6345
  }
6346
6346
  setCopied(false);
@@ -6373,11 +6373,11 @@ var UnixTimeView = () => {
6373
6373
  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(
6374
6374
  TextInput9,
6375
6375
  {
6376
- value: input2,
6376
+ value: input3,
6377
6377
  onChange: setInput,
6378
6378
  placeholder: mode === "to-human" ? "1702550400" : "2024-01-15 10:30:00"
6379
6379
  }
6380
- ) : /* @__PURE__ */ React32.createElement(Text23, { dimColor: !input2 }, input2 || "(empty)"))),
6380
+ ) : /* @__PURE__ */ React32.createElement(Text23, { dimColor: !input3 }, input3 || "(empty)"))),
6381
6381
  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)")),
6382
6382
  mode === "now" && /* @__PURE__ */ React32.createElement(Box22, { marginBottom: 1 }, /* @__PURE__ */ React32.createElement(Text23, { color: focusedField === "ms" ? "green" : void 0 }, focusedField === "ms" ? "\u25B6 " : " ", "[", useMs ? "\u2713" : " ", "] Milliseconds")),
6383
6383
  /* @__PURE__ */ React32.createElement(Box22, { marginTop: 1 }, /* @__PURE__ */ React32.createElement(
@@ -6431,7 +6431,7 @@ var JwtView = () => {
6431
6431
  const [focusedField, setFocusedField] = useState20("mode");
6432
6432
  const [copied, setCopied] = useState20(false);
6433
6433
  const service = new UtilsService();
6434
- useInput18((input2, key) => {
6434
+ useInput18((input3, key) => {
6435
6435
  if (key.tab) {
6436
6436
  const fields = mode === "decode" ? ["mode", "token", "process"] : ["mode", "payload", "secret", "process"];
6437
6437
  const currentIndex = fields.indexOf(focusedField);
@@ -6444,7 +6444,7 @@ var JwtView = () => {
6444
6444
  } else {
6445
6445
  handleProcess();
6446
6446
  }
6447
- } else if (input2 === "c" && result.token) {
6447
+ } else if (input3 === "c" && result.token) {
6448
6448
  handleCopy();
6449
6449
  }
6450
6450
  });
@@ -6569,12 +6569,12 @@ var CronView = () => {
6569
6569
  const [focusedField, setFocusedField] = useState21("expression");
6570
6570
  const [copied, setCopied] = useState21(false);
6571
6571
  const service = new UtilsService();
6572
- useInput19((input2, key) => {
6572
+ useInput19((input3, key) => {
6573
6573
  if (key.tab) {
6574
6574
  setFocusedField(focusedField === "expression" ? "parse" : "expression");
6575
6575
  } else if (key.return) {
6576
6576
  handleParse();
6577
- } else if (input2 === "c" && result) {
6577
+ } else if (input3 === "c" && result) {
6578
6578
  handleCopy();
6579
6579
  }
6580
6580
  });
@@ -6675,14 +6675,14 @@ var TimezoneView = () => {
6675
6675
  const [focusedField, setFocusedField] = useState22("time");
6676
6676
  const [copied, setCopied] = useState22(false);
6677
6677
  const service = new UtilsService();
6678
- useInput20((input2, key) => {
6678
+ useInput20((input3, key) => {
6679
6679
  if (key.tab) {
6680
6680
  const fields = ["time", "from", "to", "convert"];
6681
6681
  const currentIndex = fields.indexOf(focusedField);
6682
6682
  setFocusedField(fields[(currentIndex + 1) % fields.length]);
6683
6683
  } else if (key.return) {
6684
6684
  handleConvert();
6685
- } else if (input2 === "c" && result) {
6685
+ } else if (input3 === "c" && result) {
6686
6686
  handleCopy();
6687
6687
  }
6688
6688
  });
@@ -6801,7 +6801,7 @@ var HttpView = () => {
6801
6801
  const [focusedField, setFocusedField] = useState23("url");
6802
6802
  const [copied, setCopied] = useState23(false);
6803
6803
  const service = new UtilsService();
6804
- useInput21((input2, key) => {
6804
+ useInput21((input3, key) => {
6805
6805
  if (loading) return;
6806
6806
  if (key.tab) {
6807
6807
  const fields = ["url", "method", "headers", "body", "send"];
@@ -6815,7 +6815,7 @@ var HttpView = () => {
6815
6815
  setMethod(METHODS[(currentIndex + 1) % METHODS.length]);
6816
6816
  } else if (key.return && focusedField === "send") {
6817
6817
  handleSend();
6818
- } else if (input2 === "c" && response) {
6818
+ } else if (input3 === "c" && response) {
6819
6819
  handleCopy();
6820
6820
  }
6821
6821
  });
@@ -6946,7 +6946,7 @@ var MarkdownView = () => {
6946
6946
  const [content, setContent] = useState24("");
6947
6947
  const [error, setError] = useState24("");
6948
6948
  const [focusedField, setFocusedField] = useState24("file");
6949
- useInput22((input2, key) => {
6949
+ useInput22((input3, key) => {
6950
6950
  if (key.tab) {
6951
6951
  setFocusedField(focusedField === "file" ? "preview" : "file");
6952
6952
  } else if (key.return) {
@@ -7061,20 +7061,20 @@ var UtilsApp = ({ onExit }) => {
7061
7061
  const [selectedIndex, setSelectedIndex] = useState25(0);
7062
7062
  const [activeView, setActiveView] = useState25(null);
7063
7063
  const { exit } = useApp5();
7064
- useInput23((input2, key) => {
7064
+ useInput23((input3, key) => {
7065
7065
  if (activeView) {
7066
7066
  if (key.escape) {
7067
7067
  setActiveView(null);
7068
7068
  }
7069
7069
  return;
7070
7070
  }
7071
- if (key.upArrow || input2 === "k") {
7071
+ if (key.upArrow || input3 === "k") {
7072
7072
  setSelectedIndex((prev) => prev > 0 ? prev - 1 : MENU_ITEMS2.length - 1);
7073
- } else if (key.downArrow || input2 === "j") {
7073
+ } else if (key.downArrow || input3 === "j") {
7074
7074
  setSelectedIndex((prev) => prev < MENU_ITEMS2.length - 1 ? prev + 1 : 0);
7075
7075
  } else if (key.return) {
7076
7076
  setActiveView(MENU_ITEMS2[selectedIndex].id);
7077
- } else if (input2 === "q" || key.escape) {
7077
+ } else if (input3 === "q" || key.escape) {
7078
7078
  onExit();
7079
7079
  exit();
7080
7080
  }
@@ -8026,9 +8026,353 @@ function createKitCommand() {
8026
8026
  return cmd;
8027
8027
  }
8028
8028
 
8029
- // src/commands/upgrade.ts
8029
+ // src/commands/rules/index.ts
8030
+ import { Command as Command39 } from "commander";
8031
+
8032
+ // src/commands/rules/list.ts
8030
8033
  import { Command as Command35 } from "commander";
8031
- import { confirm as confirm5 } from "@inquirer/prompts";
8034
+ function createRulesListCommand() {
8035
+ return new Command35("list").description("List available rule presets").option("--json", "Output as JSON").action(async (options) => {
8036
+ const configService = new ConfigService();
8037
+ const config = await configService.load();
8038
+ if (!config) {
8039
+ throw new ValidationError('Not initialized. Run "jai1 auth" first.');
8040
+ }
8041
+ console.log("\u{1F4CB} Fetching available rule presets...\n");
8042
+ try {
8043
+ const response = await fetch(`${config.apiUrl}/api/rules/presets`, {
8044
+ headers: {
8045
+ "JAI1-Access-Key": config.accessKey
8046
+ }
8047
+ });
8048
+ if (!response.ok) {
8049
+ throw new Error(`Failed to fetch presets: ${response.statusText}`);
8050
+ }
8051
+ const data = await response.json();
8052
+ if (options.json) {
8053
+ console.log(JSON.stringify(data, null, 2));
8054
+ return;
8055
+ }
8056
+ if (data.total === 0) {
8057
+ console.log("No presets available.");
8058
+ return;
8059
+ }
8060
+ console.log(`Found ${data.total} preset${data.total > 1 ? "s" : ""}:
8061
+ `);
8062
+ for (const preset of data.presets) {
8063
+ console.log(`\u{1F4E6} ${preset.slug}`);
8064
+ console.log(` Name: ${preset.name}`);
8065
+ console.log(` Description: ${preset.description}`);
8066
+ console.log(` Version: ${preset.version}`);
8067
+ const stackParts = [];
8068
+ if (preset.stack.frontend) stackParts.push(preset.stack.frontend);
8069
+ if (preset.stack.backend) stackParts.push(preset.stack.backend);
8070
+ if (preset.stack.css) stackParts.push(preset.stack.css);
8071
+ if (preset.stack.database) stackParts.push(preset.stack.database);
8072
+ if (stackParts.length > 0) {
8073
+ console.log(` Stack: ${stackParts.join(" + ")}`);
8074
+ }
8075
+ console.log(` Tags: ${preset.tags.join(", ")}`);
8076
+ console.log(` Downloads: ${preset.downloads}`);
8077
+ console.log("");
8078
+ }
8079
+ console.log(`
8080
+ \u2139\uFE0F Use 'jai1 rules init --preset=<slug>' to apply a preset`);
8081
+ } catch (error) {
8082
+ throw new Error(
8083
+ `Failed to list presets: ${error instanceof Error ? error.message : String(error)}`
8084
+ );
8085
+ }
8086
+ });
8087
+ }
8088
+
8089
+ // src/commands/rules/init.ts
8090
+ import { Command as Command36 } from "commander";
8091
+ import { promises as fs12 } from "fs";
8092
+ import { join as join6 } from "path";
8093
+ import { select as select3, confirm as confirm5 } from "@inquirer/prompts";
8094
+ function createRulesInitCommand() {
8095
+ return new Command36("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) => {
8096
+ const configService = new ConfigService();
8097
+ const config = await configService.load();
8098
+ if (!config) {
8099
+ throw new ValidationError('Not initialized. Run "jai1 auth" first.');
8100
+ }
8101
+ let presetSlug = options.preset;
8102
+ if (!presetSlug) {
8103
+ console.log("\u{1F4CB} Fetching available presets...\n");
8104
+ const response = await fetch(`${config.apiUrl}/api/rules/presets`, {
8105
+ headers: {
8106
+ "JAI1-Access-Key": config.accessKey
8107
+ }
8108
+ });
8109
+ if (!response.ok) {
8110
+ throw new Error(`Failed to fetch presets: ${response.statusText}`);
8111
+ }
8112
+ const data = await response.json();
8113
+ if (data.total === 0) {
8114
+ console.log("No presets available.");
8115
+ return;
8116
+ }
8117
+ presetSlug = await select3({
8118
+ message: "Select a preset:",
8119
+ choices: data.presets.map((p) => ({
8120
+ name: `${p.name} - ${p.description}`,
8121
+ value: p.slug,
8122
+ description: `v${p.version} | ${p.tags.join(", ")}`
8123
+ }))
8124
+ });
8125
+ }
8126
+ console.log(`
8127
+ \u{1F4E6} Fetching preset: ${presetSlug}...
8128
+ `);
8129
+ const presetResponse = await fetch(`${config.apiUrl}/api/rules/presets/${presetSlug}`, {
8130
+ headers: {
8131
+ "JAI1-Access-Key": config.accessKey
8132
+ }
8133
+ });
8134
+ if (!presetResponse.ok) {
8135
+ if (presetResponse.status === 404) {
8136
+ throw new Error(`Preset '${presetSlug}' not found`);
8137
+ }
8138
+ throw new Error(`Failed to fetch preset: ${presetResponse.statusText}`);
8139
+ }
8140
+ const bundle = await presetResponse.json();
8141
+ console.log(`\u2713 Preset: ${bundle.preset.name} v${bundle.preset.version}`);
8142
+ console.log(` Files: ${Object.keys(bundle.files).length}`);
8143
+ let outputFormat = options.output;
8144
+ if (!["cursor", "agents-md", "both"].includes(outputFormat)) {
8145
+ outputFormat = await select3({
8146
+ message: "Select output format:",
8147
+ choices: [
8148
+ { name: "Cursor (.cursor/rules/)", value: "cursor" },
8149
+ { name: "AGENTS.md (single file)", value: "agents-md" },
8150
+ { name: "Both", value: "both" }
8151
+ ]
8152
+ });
8153
+ }
8154
+ if (!options.yes) {
8155
+ const proceed = await confirm5({
8156
+ message: `Apply preset '${bundle.preset.name}' to current directory?`,
8157
+ default: true
8158
+ });
8159
+ if (!proceed) {
8160
+ console.log("Cancelled.");
8161
+ return;
8162
+ }
8163
+ }
8164
+ console.log("\n\u{1F4DD} Applying preset...\n");
8165
+ if (outputFormat === "cursor" || outputFormat === "both") {
8166
+ await applyCursorFormat(bundle);
8167
+ }
8168
+ if (outputFormat === "agents-md" || outputFormat === "both") {
8169
+ await applyAgentsMdFormat(bundle);
8170
+ }
8171
+ const projectConfig = {
8172
+ preset: bundle.preset.slug,
8173
+ version: bundle.preset.version,
8174
+ appliedAt: (/* @__PURE__ */ new Date()).toISOString(),
8175
+ customContext: "09-custom.mdc"
8176
+ };
8177
+ await fs12.writeFile("jai1-rules.json", JSON.stringify(projectConfig, null, 2));
8178
+ console.log("\u2713 Created jai1-rules.json");
8179
+ console.log("\n\u2705 Preset applied successfully!\n");
8180
+ console.log("Next steps:");
8181
+ console.log(" 1. Edit 09-custom.mdc to add project-specific rules");
8182
+ console.log(" 2. Commit the rules to git");
8183
+ console.log(' 3. Use "jai1 rules sync" to regenerate outputs after editing\n');
8184
+ });
8185
+ }
8186
+ async function applyCursorFormat(bundle) {
8187
+ const rulesDir = join6(process.cwd(), ".cursor", "rules");
8188
+ await fs12.mkdir(rulesDir, { recursive: true });
8189
+ for (const [filename, content] of Object.entries(bundle.files)) {
8190
+ const filePath = join6(rulesDir, filename);
8191
+ await fs12.writeFile(filePath, content, "utf-8");
8192
+ console.log(`\u2713 Created .cursor/rules/${filename}`);
8193
+ }
8194
+ }
8195
+ async function applyAgentsMdFormat(bundle) {
8196
+ const sections = [];
8197
+ sections.push("# AGENTS.md\n");
8198
+ sections.push(`<!-- Generated by jai1 rules - Preset: ${bundle.preset.slug} v${bundle.preset.version} -->
8199
+ `);
8200
+ const fileOrder = [
8201
+ "01-project.mdc",
8202
+ "02-standards.mdc",
8203
+ "03-frontend.mdc",
8204
+ "04-backend.mdc",
8205
+ "05-testing.mdc",
8206
+ "06-workflow.mdc",
8207
+ "09-custom.mdc"
8208
+ ];
8209
+ for (const filename of fileOrder) {
8210
+ if (bundle.files[filename]) {
8211
+ const content = bundle.files[filename];
8212
+ const withoutFrontmatter = content.replace(/^---\n[\s\S]*?\n---\n/, "");
8213
+ sections.push(withoutFrontmatter.trim());
8214
+ sections.push("\n");
8215
+ }
8216
+ }
8217
+ const agentsMd = sections.join("\n");
8218
+ await fs12.writeFile("AGENTS.md", agentsMd, "utf-8");
8219
+ console.log("\u2713 Created AGENTS.md");
8220
+ }
8221
+
8222
+ // src/commands/rules/sync.ts
8223
+ import { Command as Command37 } from "commander";
8224
+ import { promises as fs13 } from "fs";
8225
+ import { join as join7 } from "path";
8226
+ function createRulesSyncCommand() {
8227
+ return new Command37("sync").description("Regenerate rule outputs after editing custom context").action(async () => {
8228
+ const configPath = join7(process.cwd(), "jai1-rules.json");
8229
+ let projectConfig;
8230
+ try {
8231
+ const configContent = await fs13.readFile(configPath, "utf-8");
8232
+ projectConfig = JSON.parse(configContent);
8233
+ } catch {
8234
+ throw new ValidationError(
8235
+ 'No jai1-rules.json found. Run "jai1 rules init" first.'
8236
+ );
8237
+ }
8238
+ console.log("\u{1F504} Syncing rules...\n");
8239
+ console.log(`Preset: ${projectConfig.preset} v${projectConfig.version}`);
8240
+ const hasCursorRules = await checkPathExists(".cursor/rules");
8241
+ const hasAgentsMd = await checkPathExists("AGENTS.md");
8242
+ if (!hasCursorRules && !hasAgentsMd) {
8243
+ throw new ValidationError(
8244
+ 'No rule outputs found. Run "jai1 rules init" first.'
8245
+ );
8246
+ }
8247
+ if (hasCursorRules) {
8248
+ await syncCursorFormat(projectConfig);
8249
+ }
8250
+ if (hasAgentsMd) {
8251
+ await syncAgentsMdFormat(projectConfig);
8252
+ }
8253
+ console.log("\n\u2705 Rules synced successfully!\n");
8254
+ });
8255
+ }
8256
+ async function checkPathExists(path8) {
8257
+ try {
8258
+ await fs13.access(join7(process.cwd(), path8));
8259
+ return true;
8260
+ } catch {
8261
+ return false;
8262
+ }
8263
+ }
8264
+ async function syncCursorFormat(config) {
8265
+ const customPath = join7(process.cwd(), ".cursor", "rules", config.customContext);
8266
+ try {
8267
+ await fs13.access(customPath);
8268
+ console.log(`\u2713 Custom context found: ${config.customContext}`);
8269
+ } catch {
8270
+ console.log(`\u26A0\uFE0F Warning: ${config.customContext} not found in .cursor/rules/`);
8271
+ }
8272
+ console.log("\u2713 Cursor rules (.cursor/rules/) - no changes needed");
8273
+ console.log(" (Files are already in place, edit them directly)");
8274
+ }
8275
+ async function syncAgentsMdFormat(config) {
8276
+ const rulesDir = join7(process.cwd(), ".cursor", "rules");
8277
+ try {
8278
+ await fs13.access(rulesDir);
8279
+ } catch {
8280
+ console.log("\u26A0\uFE0F Warning: .cursor/rules/ not found, cannot regenerate AGENTS.md");
8281
+ return;
8282
+ }
8283
+ const sections = [];
8284
+ sections.push("# AGENTS.md\n");
8285
+ sections.push(`<!-- Generated by jai1 rules - Preset: ${config.preset} v${config.version} -->
8286
+ `);
8287
+ sections.push(`<!-- Last synced: ${(/* @__PURE__ */ new Date()).toISOString()} -->
8288
+ `);
8289
+ const fileOrder = [
8290
+ "01-project.mdc",
8291
+ "02-standards.mdc",
8292
+ "03-frontend.mdc",
8293
+ "04-backend.mdc",
8294
+ "05-testing.mdc",
8295
+ "06-workflow.mdc",
8296
+ "09-custom.mdc"
8297
+ ];
8298
+ for (const filename of fileOrder) {
8299
+ const filePath = join7(rulesDir, filename);
8300
+ try {
8301
+ const content = await fs13.readFile(filePath, "utf-8");
8302
+ const withoutFrontmatter = content.replace(/^---\n[\s\S]*?\n---\n/, "");
8303
+ sections.push(withoutFrontmatter.trim());
8304
+ sections.push("\n");
8305
+ } catch {
8306
+ continue;
8307
+ }
8308
+ }
8309
+ const agentsMd = sections.join("\n");
8310
+ await fs13.writeFile("AGENTS.md", agentsMd, "utf-8");
8311
+ console.log("\u2713 Regenerated AGENTS.md");
8312
+ }
8313
+
8314
+ // src/commands/rules/info.ts
8315
+ import { Command as Command38 } from "commander";
8316
+ import { promises as fs14 } from "fs";
8317
+ import { join as join8 } from "path";
8318
+ function createRulesInfoCommand() {
8319
+ return new Command38("info").description("Show current preset information").option("--json", "Output as JSON").action(async (options) => {
8320
+ const configPath = join8(process.cwd(), "jai1-rules.json");
8321
+ let projectConfig;
8322
+ try {
8323
+ const configContent = await fs14.readFile(configPath, "utf-8");
8324
+ projectConfig = JSON.parse(configContent);
8325
+ } catch {
8326
+ throw new ValidationError(
8327
+ 'No jai1-rules.json found. Run "jai1 rules init" first.'
8328
+ );
8329
+ }
8330
+ if (options.json) {
8331
+ console.log(JSON.stringify(projectConfig, null, 2));
8332
+ return;
8333
+ }
8334
+ console.log("\u{1F4CB} Current Preset Information\n");
8335
+ console.log(`Preset: ${projectConfig.preset}`);
8336
+ console.log(`Version: ${projectConfig.version}`);
8337
+ console.log(`Applied at: ${new Date(projectConfig.appliedAt).toLocaleString()}`);
8338
+ console.log(`Custom rules: ${projectConfig.customContext}`);
8339
+ console.log("\nOutput files:");
8340
+ const cursorRulesExists = await checkPathExists2(".cursor/rules");
8341
+ const agentsMdExists = await checkPathExists2("AGENTS.md");
8342
+ if (cursorRulesExists) {
8343
+ console.log(" \u2713 .cursor/rules/");
8344
+ }
8345
+ if (agentsMdExists) {
8346
+ console.log(" \u2713 AGENTS.md");
8347
+ }
8348
+ if (!cursorRulesExists && !agentsMdExists) {
8349
+ console.log(" (none found)");
8350
+ }
8351
+ console.log('\n\u2139\uFE0F Use "jai1 rules sync" to regenerate outputs after editing');
8352
+ });
8353
+ }
8354
+ async function checkPathExists2(path8) {
8355
+ try {
8356
+ await fs14.access(join8(process.cwd(), path8));
8357
+ return true;
8358
+ } catch {
8359
+ return false;
8360
+ }
8361
+ }
8362
+
8363
+ // src/commands/rules/index.ts
8364
+ function createRulesCommand() {
8365
+ const rulesCommand = new Command39("rules").description("Manage rule presets for AI agents");
8366
+ rulesCommand.addCommand(createRulesListCommand());
8367
+ rulesCommand.addCommand(createRulesInitCommand());
8368
+ rulesCommand.addCommand(createRulesSyncCommand());
8369
+ rulesCommand.addCommand(createRulesInfoCommand());
8370
+ return rulesCommand;
8371
+ }
8372
+
8373
+ // src/commands/upgrade.ts
8374
+ import { Command as Command40 } from "commander";
8375
+ import { confirm as confirm6 } from "@inquirer/prompts";
8032
8376
  import { execSync as execSync2 } from "child_process";
8033
8377
  var colors3 = {
8034
8378
  yellow: "\x1B[33m",
@@ -8039,7 +8383,7 @@ var colors3 = {
8039
8383
  bold: "\x1B[1m"
8040
8384
  };
8041
8385
  function createUpgradeCommand() {
8042
- return new Command35("upgrade").description("Upgrade jai1-client to the latest version").option("--check", "Only check for updates without installing").option("--force", "Force upgrade without confirmation").action(async (options) => {
8386
+ return new Command40("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) => {
8043
8387
  await handleUpgrade(options);
8044
8388
  });
8045
8389
  }
@@ -8083,7 +8427,7 @@ ${colors3.bold}Current version:${colors3.reset} ${currentVersion}`);
8083
8427
  return;
8084
8428
  }
8085
8429
  if (!options.force) {
8086
- const shouldUpdate = await confirm5({
8430
+ const shouldUpdate = await confirm6({
8087
8431
  message: "Update to the latest version now?",
8088
8432
  default: true
8089
8433
  });
@@ -8187,11 +8531,11 @@ function getInstallCommand(packageManager2) {
8187
8531
  }
8188
8532
 
8189
8533
  // src/commands/clean.ts
8190
- import { Command as Command36 } from "commander";
8191
- import { confirm as confirm6, select as select3 } from "@inquirer/prompts";
8192
- import { join as join6 } from "path";
8534
+ import { Command as Command41 } from "commander";
8535
+ import { confirm as confirm7, select as select4 } from "@inquirer/prompts";
8536
+ import { join as join9 } from "path";
8193
8537
  function createCleanCommand() {
8194
- return new Command36("clean").description("Clean up backups, cache, and temporary files").option("-y, --yes", "Skip confirmation").option("--backups", "Clean only backup files").option("--all", "Clean all (backups + cache)").action(async (options) => {
8538
+ return new Command41("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) => {
8195
8539
  await handleClean(options);
8196
8540
  });
8197
8541
  }
@@ -8202,7 +8546,7 @@ async function handleClean(options) {
8202
8546
  {
8203
8547
  name: "Backups",
8204
8548
  description: "Component backup files (.jai1_backup/)",
8205
- path: join6(cwd, ".jai1_backup"),
8549
+ path: join9(cwd, ".jai1_backup"),
8206
8550
  check: async () => {
8207
8551
  const backups = await service.listBackups(cwd);
8208
8552
  return { exists: backups.length > 0, count: backups.length };
@@ -8252,7 +8596,7 @@ async function handleClean(options) {
8252
8596
  console.log(` Path: ${target.path}
8253
8597
  `);
8254
8598
  }
8255
- const action = await select3({
8599
+ const action = await select4({
8256
8600
  message: "What do you want to clean?",
8257
8601
  choices: [
8258
8602
  ...availableTargets.map(({ target, info }) => ({
@@ -8286,7 +8630,7 @@ async function cleanTarget(target, skipConfirm) {
8286
8630
  }
8287
8631
  const countStr = info.count ? ` (${info.count} items)` : "";
8288
8632
  if (!skipConfirm) {
8289
- const confirmed = await confirm6({
8633
+ const confirmed = await confirm7({
8290
8634
  message: `Delete ${target.name}${countStr}?`,
8291
8635
  default: false
8292
8636
  });
@@ -8304,7 +8648,7 @@ async function cleanTarget(target, skipConfirm) {
8304
8648
  }
8305
8649
 
8306
8650
  // src/commands/redmine/check.ts
8307
- import { Command as Command37 } from "commander";
8651
+ import { Command as Command42 } from "commander";
8308
8652
 
8309
8653
  // src/services/redmine-config.service.ts
8310
8654
  import { readFile as readFile6 } from "fs/promises";
@@ -8611,7 +8955,7 @@ async function checkConnectivity(config) {
8611
8955
 
8612
8956
  // src/commands/redmine/check.ts
8613
8957
  function createRedmineCheckCommand() {
8614
- const cmd = new Command37("check").description("Check Redmine connectivity").option("-c, --config <path>", "Config file path", "redmine.config.yaml").option("--json", "Output as JSON").action(async (options) => {
8958
+ const cmd = new Command42("check").description("Check Redmine connectivity").option("-c, --config <path>", "Config file path", "redmine.config.yaml").option("--json", "Output as JSON").action(async (options) => {
8615
8959
  await handleRedmineCheck(options);
8616
8960
  });
8617
8961
  return cmd;
@@ -8639,7 +8983,7 @@ async function handleRedmineCheck(options) {
8639
8983
  }
8640
8984
 
8641
8985
  // src/commands/redmine/sync-issue.ts
8642
- import { Command as Command38 } from "commander";
8986
+ import { Command as Command43 } from "commander";
8643
8987
 
8644
8988
  // src/sync-issue.ts
8645
8989
  import { resolve as resolve3, relative } from "path";
@@ -9015,7 +9359,7 @@ function extractIssueIdFromUrl(url) {
9015
9359
 
9016
9360
  // src/commands/redmine/sync-issue.ts
9017
9361
  function createSyncIssueCommand() {
9018
- const cmd = new Command38("issue").description("Sync a single issue").option("-i, --id <number>", "Issue ID").option("-u, --url <url>", "Issue URL").option("--dry-run", "Preview without making changes").option("-c, --config <path>", "Config file path").option("-o, --output-dir <path>", "Output directory").option("--json", "Output as JSON").action(async (options) => {
9362
+ const cmd = new Command43("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) => {
9019
9363
  await handleSyncIssue(options);
9020
9364
  });
9021
9365
  return cmd;
@@ -9059,7 +9403,7 @@ async function handleSyncIssue(options) {
9059
9403
  }
9060
9404
 
9061
9405
  // src/commands/redmine/sync-project.ts
9062
- import { Command as Command39 } from "commander";
9406
+ import { Command as Command44 } from "commander";
9063
9407
 
9064
9408
  // src/sync-project.ts
9065
9409
  async function syncProject(config, options = {}) {
@@ -9129,7 +9473,7 @@ async function syncProject(config, options = {}) {
9129
9473
 
9130
9474
  // src/commands/redmine/sync-project.ts
9131
9475
  function createSyncProjectCommand() {
9132
- const cmd = new Command39("project").description("Sync all issues in a project").option("-s, --status <status>", "Filter by status (default: *)", "*").option("--updated-since <date>", "Only sync issues updated since YYYY-MM-DD").option("--concurrency <number>", "Number of concurrent requests").option("--page-size <number>", "Page size for API requests").option("--dry-run", "Preview without making changes").option("-c, --config <path>", "Config file path").option("-o, --output-dir <path>", "Output directory").option("--json", "Output as JSON").action(async (options) => {
9476
+ const cmd = new Command44("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) => {
9133
9477
  await handleSyncProject(options);
9134
9478
  });
9135
9479
  return cmd;
@@ -9184,12 +9528,12 @@ async function handleSyncProject(options) {
9184
9528
  }
9185
9529
 
9186
9530
  // src/commands/framework/info.ts
9187
- import { Command as Command40 } from "commander";
9188
- import { promises as fs12 } from "fs";
9189
- import { join as join7 } from "path";
9531
+ import { Command as Command45 } from "commander";
9532
+ import { promises as fs15 } from "fs";
9533
+ import { join as join10 } from "path";
9190
9534
  import { homedir as homedir5 } from "os";
9191
9535
  function createInfoCommand() {
9192
- const cmd = new Command40("info").description("Show jai1-client configuration and status").option("--json", "Output as JSON").option("--verbose", "Show detailed information").action(async (options) => {
9536
+ const cmd = new Command45("info").description("Show jai1-client configuration and status").option("--json", "Output as JSON").option("--verbose", "Show detailed information").action(async (options) => {
9193
9537
  await handleInfo(options);
9194
9538
  });
9195
9539
  return cmd;
@@ -9200,7 +9544,7 @@ async function handleInfo(options) {
9200
9544
  if (!config) {
9201
9545
  throw new ValidationError('Not initialized. Run "jai1 auth" first.');
9202
9546
  }
9203
- const frameworkPath = join7(homedir5(), ".jai1", "framework");
9547
+ const frameworkPath = join10(homedir5(), ".jai1", "framework");
9204
9548
  const projectStatus = await getProjectStatus2();
9205
9549
  const info = {
9206
9550
  configPath: configService.getConfigPath(),
@@ -9235,9 +9579,9 @@ function maskKey3(key) {
9235
9579
  return "****" + key.slice(-4);
9236
9580
  }
9237
9581
  async function getProjectStatus2() {
9238
- const projectJai1 = join7(process.cwd(), ".jai1");
9582
+ const projectJai1 = join10(process.cwd(), ".jai1");
9239
9583
  try {
9240
- await fs12.access(projectJai1);
9584
+ await fs15.access(projectJai1);
9241
9585
  return { exists: true, version: "Synced" };
9242
9586
  } catch {
9243
9587
  return { exists: false };
@@ -9245,8 +9589,8 @@ async function getProjectStatus2() {
9245
9589
  }
9246
9590
 
9247
9591
  // src/commands/self-update.ts
9248
- import { Command as Command41 } from "commander";
9249
- import { confirm as confirm7 } from "@inquirer/prompts";
9592
+ import { Command as Command46 } from "commander";
9593
+ import { confirm as confirm8 } from "@inquirer/prompts";
9250
9594
  import { execSync as execSync3 } from "child_process";
9251
9595
  var colors4 = {
9252
9596
  yellow: "\x1B[33m",
@@ -9257,7 +9601,7 @@ var colors4 = {
9257
9601
  bold: "\x1B[1m"
9258
9602
  };
9259
9603
  function createSelfUpdateCommand() {
9260
- return new Command41("self-update").description("Update jai1-client to the latest version").option("--check", "Only check for updates without installing").option("--force", "Force update without confirmation").action(async (options) => {
9604
+ return new Command46("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) => {
9261
9605
  await handleSelfUpdate(options);
9262
9606
  });
9263
9607
  }
@@ -9301,7 +9645,7 @@ ${colors4.bold}Current version:${colors4.reset} ${currentVersion}`);
9301
9645
  return;
9302
9646
  }
9303
9647
  if (!options.force) {
9304
- const shouldUpdate = await confirm7({
9648
+ const shouldUpdate = await confirm8({
9305
9649
  message: "Update to the latest version now?",
9306
9650
  default: true
9307
9651
  });
@@ -9397,10 +9741,10 @@ function getInstallCommand2(packageManager2) {
9397
9741
  }
9398
9742
 
9399
9743
  // src/commands/clear-backups.ts
9400
- import { Command as Command42 } from "commander";
9401
- import { confirm as confirm8 } from "@inquirer/prompts";
9744
+ import { Command as Command47 } from "commander";
9745
+ import { confirm as confirm9 } from "@inquirer/prompts";
9402
9746
  function createClearBackupsCommand() {
9403
- return new Command42("clear-backups").description("Clear backup files").option("-y, --yes", "Skip confirmation").action(async (options) => {
9747
+ return new Command47("clear-backups").description("Clear backup files").option("-y, --yes", "Skip confirmation").action(async (options) => {
9404
9748
  const service = new ComponentsService();
9405
9749
  const backups = await service.listBackups(process.cwd());
9406
9750
  if (backups.length === 0) {
@@ -9416,7 +9760,7 @@ function createClearBackupsCommand() {
9416
9760
  }
9417
9761
  console.log();
9418
9762
  if (!options.yes) {
9419
- const ok = await confirm8({ message: "Delete all backups?", default: false });
9763
+ const ok = await confirm9({ message: "Delete all backups?", default: false });
9420
9764
  if (!ok) return;
9421
9765
  }
9422
9766
  await service.clearBackups(process.cwd());
@@ -9425,9 +9769,9 @@ function createClearBackupsCommand() {
9425
9769
  }
9426
9770
 
9427
9771
  // src/commands/vscode/index.ts
9428
- import { Command as Command43 } from "commander";
9429
- import { checkbox as checkbox5, confirm as confirm9, select as select4 } from "@inquirer/prompts";
9430
- import fs13 from "fs/promises";
9772
+ import { Command as Command48 } from "commander";
9773
+ import { checkbox as checkbox5, confirm as confirm10, select as select5 } from "@inquirer/prompts";
9774
+ import fs16 from "fs/promises";
9431
9775
  import path7 from "path";
9432
9776
  import { existsSync as existsSync3 } from "fs";
9433
9777
  var PERFORMANCE_GROUPS2 = {
@@ -9565,7 +9909,7 @@ var PERFORMANCE_GROUPS2 = {
9565
9909
  }
9566
9910
  };
9567
9911
  function createVSCodeCommand() {
9568
- const vscodeCommand = new Command43("vscode").description("Qu\u1EA3n l\xFD c\xE0i \u0111\u1EB7t VSCode cho d\u1EF1 \xE1n hi\u1EC7n t\u1EA1i");
9912
+ const vscodeCommand = new Command48("vscode").description("Qu\u1EA3n l\xFD c\xE0i \u0111\u1EB7t VSCode cho d\u1EF1 \xE1n hi\u1EC7n t\u1EA1i");
9569
9913
  vscodeCommand.action(async () => {
9570
9914
  await interactiveMode2();
9571
9915
  });
@@ -9609,7 +9953,7 @@ async function interactiveMode2() {
9609
9953
  console.log("\u2502 \u2022 Nh\u1EA5n ENTER \u0111\u1EC3 x\xE1c nh\u1EADn v\xE0 \xE1p d\u1EE5ng \u2502");
9610
9954
  console.log("\u2502 \u2022 Nh\u1EA5n Ctrl+C \u0111\u1EC3 h\u1EE7y \u2502");
9611
9955
  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");
9612
- const action = await select4({
9956
+ const action = await select5({
9613
9957
  message: "B\u1EA1n mu\u1ED1n l\xE0m g\xEC?",
9614
9958
  choices: [
9615
9959
  { name: "\u2705 Enable c\xE1c nh\xF3m t\u1ED1i \u01B0u", value: "enable" },
@@ -9658,18 +10002,18 @@ async function applyGroups2(groupKeys, action) {
9658
10002
  return;
9659
10003
  }
9660
10004
  if (!existsSync3(vscodeDir)) {
9661
- await fs13.mkdir(vscodeDir, { recursive: true });
10005
+ await fs16.mkdir(vscodeDir, { recursive: true });
9662
10006
  console.log("\u{1F4C1} \u0110\xE3 t\u1EA1o th\u01B0 m\u1EE5c .vscode/");
9663
10007
  }
9664
10008
  let currentSettings = {};
9665
10009
  if (existsSync3(settingsPath)) {
9666
10010
  try {
9667
- const content = await fs13.readFile(settingsPath, "utf-8");
10011
+ const content = await fs16.readFile(settingsPath, "utf-8");
9668
10012
  currentSettings = JSON.parse(content);
9669
10013
  console.log("\u{1F4C4} \u0110\xE3 \u0111\u1ECDc c\xE0i \u0111\u1EB7t hi\u1EC7n t\u1EA1i t\u1EEB settings.json");
9670
10014
  } catch {
9671
10015
  console.warn("\u26A0\uFE0F Kh\xF4ng th\u1EC3 \u0111\u1ECDc settings.json (c\xF3 th\u1EC3 ch\u1EE9a comments).");
9672
- const confirmOverwrite = await confirm9({
10016
+ const confirmOverwrite = await confirm10({
9673
10017
  message: "Ghi \u0111\xE8 file settings.json hi\u1EC7n t\u1EA1i?",
9674
10018
  default: false
9675
10019
  });
@@ -9704,7 +10048,7 @@ async function applyGroups2(groupKeys, action) {
9704
10048
  }
9705
10049
  }
9706
10050
  }
9707
- await fs13.writeFile(settingsPath, JSON.stringify(newSettings, null, 2));
10051
+ await fs16.writeFile(settingsPath, JSON.stringify(newSettings, null, 2));
9708
10052
  console.log(`
9709
10053
  \u2705 \u0110\xE3 c\u1EADp nh\u1EADt c\xE0i \u0111\u1EB7t VSCode t\u1EA1i: ${settingsPath}`);
9710
10054
  console.log("\u{1F4A1} M\u1EB9o: Kh\u1EDFi \u0111\u1ED9ng l\u1EA1i VSCode \u0111\u1EC3 \xE1p d\u1EE5ng c\xE1c thay \u0111\u1ED5i.");
@@ -9716,7 +10060,7 @@ async function resetSettings2(groupKeys) {
9716
10060
  console.log("\n\u26A0\uFE0F Kh\xF4ng t\xECm th\u1EA5y file settings.json");
9717
10061
  return;
9718
10062
  }
9719
- const confirmReset = await confirm9({
10063
+ const confirmReset = await confirm10({
9720
10064
  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(", ")}?`,
9721
10065
  default: false
9722
10066
  });
@@ -9725,7 +10069,7 @@ async function resetSettings2(groupKeys) {
9725
10069
  return;
9726
10070
  }
9727
10071
  if (groupKeys.length === 0) {
9728
- await fs13.unlink(settingsPath);
10072
+ await fs16.unlink(settingsPath);
9729
10073
  console.log("\n\u2705 \u0110\xE3 x\xF3a file settings.json");
9730
10074
  } else {
9731
10075
  await applyGroups2(groupKeys, "disable");
@@ -9736,9 +10080,9 @@ async function resetSettings2(groupKeys) {
9736
10080
  // src/commands/guide.ts
9737
10081
  import React40 from "react";
9738
10082
  import { render as render6 } from "ink";
9739
- import { Command as Command44 } from "commander";
10083
+ import { Command as Command49 } from "commander";
9740
10084
  function createGuideCommand() {
9741
- const cmd = new Command44("guide").description("Interactive guide center for Agentic Coding").option("--topic <topic>", "Open specific topic (intro, rules, workflows, prompts, skills)").action(async (options) => {
10085
+ const cmd = new Command49("guide").description("Interactive guide center for Agentic Coding").option("--topic <topic>", "Open specific topic (intro, rules, workflows, prompts, skills)").action(async (options) => {
9742
10086
  const { waitUntilExit } = render6(
9743
10087
  React40.createElement(GuideApp, {
9744
10088
  initialTopic: options.topic,
@@ -9755,9 +10099,9 @@ function createGuideCommand() {
9755
10099
  // src/commands/context.ts
9756
10100
  import React41 from "react";
9757
10101
  import { render as render7 } from "ink";
9758
- import { Command as Command45 } from "commander";
10102
+ import { Command as Command50 } from "commander";
9759
10103
  function createContextCommand() {
9760
- const cmd = new Command45("context").description("Kh\xE1m ph\xE1 v\xE0 qu\u1EA3n l\xFD context d\u1EF1 \xE1n cho c\xE1c IDE").option("--ide <ide>", "M\u1EDF tr\u1EF1c ti\u1EBFp IDE c\u1EE5 th\u1EC3 (cursor, windsurf, antigravity, jai1)").option("--type <type>", "Hi\u1EC3n th\u1ECB lo\u1EA1i context c\u1EE5 th\u1EC3 (rules, workflows, skills, agents, prompts)").option("--stats", "Hi\u1EC3n th\u1ECB th\u1ED1ng k\xEA context (non-interactive)").action(async (options) => {
10104
+ const cmd = new Command50("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) => {
9761
10105
  let initialIDE;
9762
10106
  if (options.ide) {
9763
10107
  const validIDEs = ["cursor", "windsurf", "antigravity", "jai1"];
@@ -9834,10 +10178,10 @@ async function printStats2() {
9834
10178
  }
9835
10179
 
9836
10180
  // src/commands/migrate-ide.ts
9837
- import { Command as Command46 } from "commander";
9838
- import { checkbox as checkbox6, confirm as confirm10 } from "@inquirer/prompts";
10181
+ import { Command as Command51 } from "commander";
10182
+ import { checkbox as checkbox6, confirm as confirm11 } from "@inquirer/prompts";
9839
10183
  function createMigrateIdeCommand() {
9840
- const cmd = new Command46("migrate-ide").description("Migrate .jai1 rules v\xE0 workflows sang IDEs (Cursor, Windsurf, Claude Code, etc.)").option("--ide <ides...>", "Target IDEs (cursor, windsurf, antigravity, claudecode, opencode)").option("--type <types...>", "Content types (rules, workflows, commands)").option("--dry-run", "Preview changes without writing files").action(async (options) => {
10184
+ const cmd = new Command51("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) => {
9841
10185
  await runMigrateIde(options);
9842
10186
  });
9843
10187
  return cmd;
@@ -9906,7 +10250,7 @@ async function runMigrateIde(options) {
9906
10250
  if (options.dryRun) {
9907
10251
  console.log("\u{1F50D} DRY RUN - No files will be written\n");
9908
10252
  }
9909
- const confirmed = await confirm10({
10253
+ const confirmed = await confirm11({
9910
10254
  message: "Proceed with migration?",
9911
10255
  default: true
9912
10256
  });
@@ -9943,7 +10287,7 @@ async function runMigrateIde(options) {
9943
10287
  }
9944
10288
 
9945
10289
  // src/cli.ts
9946
- var program = new Command47();
10290
+ var program = new Command52();
9947
10291
  if (process.argv.includes("-v") || process.argv.includes("--version")) {
9948
10292
  console.log(package_default.version);
9949
10293
  if (!process.argv.includes("--skip-update-check")) {
@@ -9967,11 +10311,12 @@ program.addCommand(createTranslateCommand());
9967
10311
  program.addCommand(createUtilsCommand());
9968
10312
  program.addCommand(createDepsCommand());
9969
10313
  program.addCommand(createKitCommand());
10314
+ program.addCommand(createRulesCommand());
9970
10315
  program.addCommand(createUpgradeCommand());
9971
10316
  program.addCommand(createCleanCommand());
9972
- var redmineCommand = new Command47("redmine").description("Redmine context sync commands");
10317
+ var redmineCommand = new Command52("redmine").description("Redmine context sync commands");
9973
10318
  redmineCommand.addCommand(createRedmineCheckCommand());
9974
- var syncCommand = new Command47("sync").description("Sync Redmine issues to markdown files");
10319
+ var syncCommand = new Command52("sync").description("Sync Redmine issues to markdown files");
9975
10320
  syncCommand.addCommand(createSyncIssueCommand());
9976
10321
  syncCommand.addCommand(createSyncProjectCommand());
9977
10322
  redmineCommand.addCommand(syncCommand);
@@ -10014,6 +10359,12 @@ program.on("command:*", (operands) => {
10014
10359
  console.error(" deps Manage project dependencies");
10015
10360
  console.error(" utils Developer tools (password, uuid, hash, jwt, etc.)");
10016
10361
  console.error("");
10362
+ console.error(" \u{1F4CB} Rule Presets");
10363
+ console.error(" rules list List available rule presets");
10364
+ console.error(" rules init Apply preset to project");
10365
+ console.error(" rules sync Regenerate outputs after editing");
10366
+ console.error(" rules info Show current preset information");
10367
+ console.error("");
10017
10368
  console.error(" \u{1F527} Maintenance");
10018
10369
  console.error(" upgrade Upgrade jai1-client to latest version");
10019
10370
  console.error(" clean Clean up backups and cache");