@jvittechs/jai1-cli 0.1.78 → 0.1.80

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 Command41 } from "commander";
4
+ import { Command as Command45 } 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.78",
36
+ version: "0.1.80",
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: {
@@ -85,6 +85,7 @@ var package_default = {
85
85
  clipboardy: "^4.0.0",
86
86
  commander: "^12.1.0",
87
87
  cronstrue: "^2.50.0",
88
+ execa: "^9.6.1",
88
89
  "gray-matter": "^4.0.3",
89
90
  ink: "^5.0.1",
90
91
  "ink-spinner": "^5.0.0",
@@ -894,9 +895,9 @@ var UnifiedApplyApp = ({
894
895
  (c) => c.filepath.toLowerCase().includes(query) || c.name.toLowerCase().includes(query) || c.tags && c.tags.some((t) => t.toLowerCase().includes(query))
895
896
  );
896
897
  }, [components, searchQuery]);
897
- useInput((input, key) => {
898
+ useInput((input2, key) => {
898
899
  if (viewState === "summary") {
899
- if (key.return || input === "q" || key.escape) {
900
+ if (key.return || input2 === "q" || key.escape) {
900
901
  onExit();
901
902
  }
902
903
  return;
@@ -910,7 +911,7 @@ var UnifiedApplyApp = ({
910
911
  else setFocusArea("search");
911
912
  return;
912
913
  }
913
- if (key.escape || input === "q") {
914
+ if (key.escape || input2 === "q") {
914
915
  onExit();
915
916
  return;
916
917
  }
@@ -925,7 +926,7 @@ var UnifiedApplyApp = ({
925
926
  setCursorIndex((prev) => Math.max(0, prev - 1));
926
927
  } else if (key.downArrow) {
927
928
  setCursorIndex((prev) => Math.min(filteredComponents.length - 1, prev + 1));
928
- } else if (input === " ") {
929
+ } else if (input2 === " ") {
929
930
  const current = filteredComponents[cursorIndex];
930
931
  if (current) {
931
932
  setSelectedPaths((prev) => {
@@ -938,13 +939,13 @@ var UnifiedApplyApp = ({
938
939
  return next;
939
940
  });
940
941
  }
941
- } else if (input === "a") {
942
+ } else if (input2 === "a") {
942
943
  setSelectedPaths((prev) => {
943
944
  const next = new Set(prev);
944
945
  filteredComponents.forEach((c) => next.add(c.filepath));
945
946
  return next;
946
947
  });
947
- } else if (input === "c") {
948
+ } else if (input2 === "c") {
948
949
  setSelectedPaths(/* @__PURE__ */ new Set());
949
950
  }
950
951
  }
@@ -953,7 +954,7 @@ var UnifiedApplyApp = ({
953
954
  setSelectedPackageIndex((prev) => Math.max(0, prev - 1));
954
955
  } else if (key.rightArrow) {
955
956
  setSelectedPackageIndex((prev) => Math.min(tags.length - 1, prev + 1));
956
- } else if (input === " " || key.return) {
957
+ } else if (input2 === " " || key.return) {
957
958
  const tag = tags[selectedPackageIndex];
958
959
  if (tag) {
959
960
  const packageComponents = components.filter((c) => c.tags?.includes(tag.tag));
@@ -1331,7 +1332,7 @@ var MainMenuView = ({ ideContexts, onSelect }) => {
1331
1332
  available: ideContexts.some((ctx) => ctx.ide === "jai1")
1332
1333
  }
1333
1334
  ];
1334
- useInput2((input, key) => {
1335
+ useInput2((input2, key) => {
1335
1336
  if (key.upArrow) {
1336
1337
  setSelectedIndex((prev) => Math.max(0, prev - 1));
1337
1338
  } else if (key.downArrow) {
@@ -1433,13 +1434,13 @@ var IDEOverviewView = ({
1433
1434
  count: ideContext.stats.byType.context
1434
1435
  });
1435
1436
  }
1436
- useInput3((input, key) => {
1437
+ useInput3((input2, key) => {
1437
1438
  if (key.tab || key.rightArrow) {
1438
1439
  setSelectedTabIndex((prev) => Math.min(tabs.length - 1, prev + 1));
1439
1440
  } else if (key.leftArrow) {
1440
1441
  setSelectedTabIndex((prev) => Math.max(0, prev - 1));
1441
1442
  }
1442
- const num = parseInt(input, 10);
1443
+ const num = parseInt(input2, 10);
1443
1444
  if (!isNaN(num) && num >= 1 && num <= tabs.length) {
1444
1445
  setSelectedTabIndex(num - 1);
1445
1446
  }
@@ -1501,7 +1502,7 @@ import React7, { useState as useState4 } from "react";
1501
1502
  import { Box as Box5, Text as Text6, useInput as useInput4 } from "ink";
1502
1503
  var ListView = ({ items, contentType, onSelect, onBack }) => {
1503
1504
  const [selectedIndex, setSelectedIndex] = useState4(0);
1504
- useInput4((input, key) => {
1505
+ useInput4((input2, key) => {
1505
1506
  if (key.upArrow) {
1506
1507
  setSelectedIndex((prev) => Math.max(0, prev - 1));
1507
1508
  } else if (key.downArrow) {
@@ -1552,18 +1553,18 @@ var DetailView = ({ item, scrollPosition: initialScroll, onBack }) => {
1552
1553
  const [scrollPosition, setScrollPosition] = useState5(initialScroll);
1553
1554
  const maxVisibleLines = 25;
1554
1555
  const maxScroll = Math.max(0, item.previewLines.length - maxVisibleLines);
1555
- useInput5((input, key) => {
1556
- if (key.upArrow || input === "k") {
1556
+ useInput5((input2, key) => {
1557
+ if (key.upArrow || input2 === "k") {
1557
1558
  setScrollPosition((prev) => Math.max(0, prev - 1));
1558
- } else if (key.downArrow || input === "j") {
1559
+ } else if (key.downArrow || input2 === "j") {
1559
1560
  setScrollPosition((prev) => Math.min(maxScroll, prev + 1));
1560
- } else if (key.pageDown || input === "d") {
1561
+ } else if (key.pageDown || input2 === "d") {
1561
1562
  setScrollPosition((prev) => Math.min(maxScroll, prev + 5));
1562
- } else if (key.pageUp || input === "u") {
1563
+ } else if (key.pageUp || input2 === "u") {
1563
1564
  setScrollPosition((prev) => Math.max(0, prev - 5));
1564
- } else if (input === "g") {
1565
+ } else if (input2 === "g") {
1565
1566
  setScrollPosition(0);
1566
- } else if (input === "G") {
1567
+ } else if (input2 === "G") {
1567
1568
  setScrollPosition(maxScroll);
1568
1569
  } else if (key.escape || key.backspace) {
1569
1570
  onBack();
@@ -1959,8 +1960,8 @@ var ContextApp = ({ initialIDE, initialType, onExit }) => {
1959
1960
  setLoading(false);
1960
1961
  });
1961
1962
  }, [initialIDE]);
1962
- useInput6((input, key) => {
1963
- if (input === "q") {
1963
+ useInput6((input2, key) => {
1964
+ if (input2 === "q") {
1964
1965
  onExit();
1965
1966
  return;
1966
1967
  }
@@ -2887,7 +2888,7 @@ var MENU_ITEMS = [
2887
2888
  ];
2888
2889
  var MenuView = ({ onSelect }) => {
2889
2890
  const [selectedIndex, setSelectedIndex] = useState7(0);
2890
- useInput7((input, key) => {
2891
+ useInput7((input2, key) => {
2891
2892
  if (key.upArrow) {
2892
2893
  setSelectedIndex((prev) => Math.max(0, prev - 1));
2893
2894
  } else if (key.downArrow) {
@@ -3500,7 +3501,7 @@ var AgenticGuideView = ({ onBack }) => {
3500
3501
  const [isTyping, setIsTyping] = useState8(false);
3501
3502
  const [selectedSuggestion, setSelectedSuggestion] = useState8(0);
3502
3503
  const [focusArea, setFocusArea] = useState8("input");
3503
- useInput8((input, key) => {
3504
+ useInput8((input2, key) => {
3504
3505
  if (key.escape) {
3505
3506
  onBack();
3506
3507
  return;
@@ -3632,7 +3633,7 @@ var GuideApp = ({ initialTopic, onExit }) => {
3632
3633
  setCurrentTopic(TOPIC_MAP[initialTopic]);
3633
3634
  }
3634
3635
  }, [initialTopic]);
3635
- useInput9((input, key) => {
3636
+ useInput9((input2, key) => {
3636
3637
  if (key.escape || currentTopic !== "menu" && key.backspace) {
3637
3638
  if (currentTopic === "menu") {
3638
3639
  onExit();
@@ -3642,7 +3643,7 @@ var GuideApp = ({ initialTopic, onExit }) => {
3642
3643
  }
3643
3644
  return;
3644
3645
  }
3645
- if (input === "q") {
3646
+ if (input2 === "q") {
3646
3647
  onExit();
3647
3648
  return;
3648
3649
  }
@@ -4141,7 +4142,7 @@ var ModelSelector = ({
4141
4142
  const allowedModels = models.filter((m) => m.allowed);
4142
4143
  const currentIndex = allowedModels.findIndex((m) => m.id === currentModel);
4143
4144
  const [selectedIndex, setSelectedIndex] = useState12(Math.max(0, currentIndex));
4144
- useInput10((input, key) => {
4145
+ useInput10((input2, key) => {
4145
4146
  if (key.escape) {
4146
4147
  onCancel();
4147
4148
  return;
@@ -4267,7 +4268,7 @@ var ChatApp = ({ service, initialModel }) => {
4267
4268
  }
4268
4269
  return false;
4269
4270
  }, [refetch, exit]);
4270
- useInput11((input, key) => {
4271
+ useInput11((input2, key) => {
4271
4272
  if (showSlashMenu) {
4272
4273
  if (key.upArrow) {
4273
4274
  setSlashMenuIndex((i) => Math.max(0, i - 1));
@@ -4295,7 +4296,7 @@ var ChatApp = ({ service, initialModel }) => {
4295
4296
  }
4296
4297
  return;
4297
4298
  }
4298
- if (currentView === "error" && (key.return || input === "r")) {
4299
+ if (currentView === "error" && (key.return || input2 === "r")) {
4299
4300
  setCurrentView("loading");
4300
4301
  refetch();
4301
4302
  return;
@@ -4550,9 +4551,9 @@ var TranslationService = class {
4550
4551
  /**
4551
4552
  * Detect input type
4552
4553
  */
4553
- async detectInputType(input) {
4554
+ async detectInputType(input2) {
4554
4555
  try {
4555
- const stat = await fs7.stat(input);
4556
+ const stat = await fs7.stat(input2);
4556
4557
  if (stat.isDirectory()) return "folder";
4557
4558
  if (stat.isFile()) return "file";
4558
4559
  } catch {
@@ -4784,7 +4785,7 @@ Return ONLY the translated content, no explanations.`;
4784
4785
  };
4785
4786
 
4786
4787
  // src/commands/translate.ts
4787
- async function handleTranslate(input, options) {
4788
+ async function handleTranslate(input2, options) {
4788
4789
  const configService = new ConfigService();
4789
4790
  const config = await configService.load();
4790
4791
  if (!config) {
@@ -4792,16 +4793,16 @@ async function handleTranslate(input, options) {
4792
4793
  }
4793
4794
  const llmService = new LlmProxyService(config);
4794
4795
  const translationService = new TranslationService(llmService, options, options.model);
4795
- const inputType = await translationService.detectInputType(input);
4796
+ const inputType = await translationService.detectInputType(input2);
4796
4797
  switch (inputType) {
4797
4798
  case "text":
4798
- await handleTextTranslation(translationService, input, options);
4799
+ await handleTextTranslation(translationService, input2, options);
4799
4800
  break;
4800
4801
  case "file":
4801
- await handleFileTranslation(translationService, input, options);
4802
+ await handleFileTranslation(translationService, input2, options);
4802
4803
  break;
4803
4804
  case "folder":
4804
- await handleFolderTranslation(translationService, input, options);
4805
+ await handleFolderTranslation(translationService, input2, options);
4805
4806
  break;
4806
4807
  }
4807
4808
  }
@@ -4878,8 +4879,8 @@ async function handleFolderTranslation(service, folderPath, options) {
4878
4879
  }
4879
4880
  }
4880
4881
  function createTranslateCommand() {
4881
- 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 (input, options) => {
4882
- await handleTranslate(input, 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 (input2, options) => {
4883
+ await handleTranslate(input2, options);
4883
4884
  });
4884
4885
  return cmd;
4885
4886
  }
@@ -4939,12 +4940,12 @@ var UtilsService = class {
4939
4940
  /**
4940
4941
  * Hash text or file using specified algorithm
4941
4942
  */
4942
- async hash(input, algorithm) {
4943
+ async hash(input2, algorithm) {
4943
4944
  if (algorithm === "bcrypt") {
4944
4945
  throw new Error("Use hashBcrypt for bcrypt algorithm");
4945
4946
  }
4946
4947
  const hash = crypto.createHash(algorithm);
4947
- hash.update(input);
4948
+ hash.update(input2);
4948
4949
  return hash.digest("hex");
4949
4950
  }
4950
4951
  /**
@@ -4957,14 +4958,14 @@ var UtilsService = class {
4957
4958
  /**
4958
4959
  * Hash using bcrypt
4959
4960
  */
4960
- async hashBcrypt(input, rounds = 10) {
4961
- return bcrypt.hash(input, rounds);
4961
+ async hashBcrypt(input2, rounds = 10) {
4962
+ return bcrypt.hash(input2, rounds);
4962
4963
  }
4963
4964
  /**
4964
4965
  * Base64 encode
4965
4966
  */
4966
- base64Encode(input, urlSafe = false) {
4967
- const buffer = typeof input === "string" ? Buffer.from(input, "utf-8") : input;
4967
+ base64Encode(input2, urlSafe = false) {
4968
+ const buffer = typeof input2 === "string" ? Buffer.from(input2, "utf-8") : input2;
4968
4969
  let encoded = buffer.toString("base64");
4969
4970
  if (urlSafe) {
4970
4971
  encoded = encoded.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
@@ -4974,8 +4975,8 @@ var UtilsService = class {
4974
4975
  /**
4975
4976
  * Base64 decode
4976
4977
  */
4977
- base64Decode(input) {
4978
- let normalized = input.replace(/-/g, "+").replace(/_/g, "/");
4978
+ base64Decode(input2) {
4979
+ let normalized = input2.replace(/-/g, "+").replace(/_/g, "/");
4979
4980
  while (normalized.length % 4) {
4980
4981
  normalized += "=";
4981
4982
  }
@@ -5104,14 +5105,14 @@ var UtilsService = class {
5104
5105
  /**
5105
5106
  * URL encode
5106
5107
  */
5107
- urlEncode(input, full = false) {
5108
- return full ? encodeURI(input) : encodeURIComponent(input);
5108
+ urlEncode(input2, full = false) {
5109
+ return full ? encodeURI(input2) : encodeURIComponent(input2);
5109
5110
  }
5110
5111
  /**
5111
5112
  * URL decode
5112
5113
  */
5113
- urlDecode(input, full = false) {
5114
- return full ? decodeURI(input) : decodeURIComponent(input);
5114
+ urlDecode(input2, full = false) {
5115
+ return full ? decodeURI(input2) : decodeURIComponent(input2);
5115
5116
  }
5116
5117
  /**
5117
5118
  * Format bytes to human-readable size
@@ -5221,7 +5222,7 @@ Examples:
5221
5222
 
5222
5223
  // src/commands/utils/hash.ts
5223
5224
  import { Command as Command17 } from "commander";
5224
- async function handleHashGeneration(input, options) {
5225
+ async function handleHashGeneration(input2, options) {
5225
5226
  const service = new UtilsService();
5226
5227
  try {
5227
5228
  let hash;
@@ -5232,14 +5233,14 @@ async function handleHashGeneration(input, options) {
5232
5233
  }
5233
5234
  hash = await service.hashFile(options.file, options.algorithm);
5234
5235
  } else {
5235
- if (!input) {
5236
+ if (!input2) {
5236
5237
  console.error("\u274C Please provide input text or use --file option");
5237
5238
  process.exit(1);
5238
5239
  }
5239
5240
  if (options.algorithm === "bcrypt") {
5240
- hash = await service.hashBcrypt(input, options.rounds);
5241
+ hash = await service.hashBcrypt(input2, options.rounds);
5241
5242
  } else {
5242
- hash = await service.hash(input, options.algorithm);
5243
+ hash = await service.hash(input2, options.algorithm);
5243
5244
  }
5244
5245
  }
5245
5246
  console.log("\u{1F512} Hash Result:");
@@ -5272,8 +5273,8 @@ Examples:
5272
5273
  $ jai1 utils hash "password" --algorithm bcrypt --rounds 12
5273
5274
  $ jai1 utils hash --file ./myfile.txt
5274
5275
  $ jai1 utils hash --file ./image.png --algorithm sha512
5275
- `).action(async (input, options) => {
5276
- await handleHashGeneration(input, {
5276
+ `).action(async (input2, options) => {
5277
+ await handleHashGeneration(input2, {
5277
5278
  ...options,
5278
5279
  rounds: parseInt(options.rounds, 10)
5279
5280
  });
@@ -5284,7 +5285,7 @@ Examples:
5284
5285
  // src/commands/utils/base64-encode.ts
5285
5286
  import { Command as Command18 } from "commander";
5286
5287
  import { readFile as readFile2 } from "fs/promises";
5287
- async function handleBase64Encode(input, options) {
5288
+ async function handleBase64Encode(input2, options) {
5288
5289
  const service = new UtilsService();
5289
5290
  try {
5290
5291
  let encoded;
@@ -5292,11 +5293,11 @@ async function handleBase64Encode(input, options) {
5292
5293
  const content = await readFile2(options.file);
5293
5294
  encoded = service.base64Encode(content, options.urlSafe);
5294
5295
  } else {
5295
- if (!input) {
5296
+ if (!input2) {
5296
5297
  console.error("\u274C Please provide input text or use --file option");
5297
5298
  process.exit(1);
5298
5299
  }
5299
- encoded = service.base64Encode(input, options.urlSafe);
5300
+ encoded = service.base64Encode(input2, options.urlSafe);
5300
5301
  }
5301
5302
  console.log("\u{1F4DD} Base64 Encoded:");
5302
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");
@@ -5321,8 +5322,8 @@ Examples:
5321
5322
  $ jai1 utils base64-encode "hello world" --url-safe
5322
5323
  $ jai1 utils base64-encode --file ./document.txt
5323
5324
  $ jai1 utils base64-encode --file ./image.png
5324
- `).action(async (input, options) => {
5325
- await handleBase64Encode(input, options);
5325
+ `).action(async (input2, options) => {
5326
+ await handleBase64Encode(input2, options);
5326
5327
  });
5327
5328
  return cmd;
5328
5329
  }
@@ -5330,18 +5331,18 @@ Examples:
5330
5331
  // src/commands/utils/base64-decode.ts
5331
5332
  import { Command as Command19 } from "commander";
5332
5333
  import { readFile as readFile3, writeFile } from "fs/promises";
5333
- async function handleBase64Decode(input, options) {
5334
+ async function handleBase64Decode(input2, options) {
5334
5335
  const service = new UtilsService();
5335
5336
  try {
5336
5337
  let encodedInput;
5337
5338
  if (options.file) {
5338
5339
  encodedInput = await readFile3(options.file, "utf-8");
5339
5340
  } else {
5340
- if (!input) {
5341
+ if (!input2) {
5341
5342
  console.error("\u274C Please provide Base64 input or use --file option");
5342
5343
  process.exit(1);
5343
5344
  }
5344
- encodedInput = input;
5345
+ encodedInput = input2;
5345
5346
  }
5346
5347
  const decoded = service.base64Decode(encodedInput.trim());
5347
5348
  if (options.output) {
@@ -5366,8 +5367,8 @@ Examples:
5366
5367
  $ jai1 utils base64-decode --file ./encoded.txt
5367
5368
  $ jai1 utils base64-decode "aGVsbG8=" --output ./decoded.txt
5368
5369
  $ jai1 utils base64-decode --file ./encoded.txt --output ./image.png
5369
- `).action(async (input, options) => {
5370
- await handleBase64Decode(input, options);
5370
+ `).action(async (input2, options) => {
5371
+ await handleBase64Decode(input2, options);
5371
5372
  });
5372
5373
  return cmd;
5373
5374
  }
@@ -5518,10 +5519,10 @@ Examples:
5518
5519
 
5519
5520
  // src/commands/utils/unix-time.ts
5520
5521
  import { Command as Command22 } from "commander";
5521
- async function handleUnixTime(input, options) {
5522
+ async function handleUnixTime(input2, options) {
5522
5523
  const service = new UtilsService();
5523
5524
  try {
5524
- if (!input) {
5525
+ if (!input2) {
5525
5526
  const now = /* @__PURE__ */ new Date();
5526
5527
  const timestamp = service.dateToUnix(now, options.ms);
5527
5528
  console.log("\u{1F552} Current Unix Timestamp:");
@@ -5531,8 +5532,8 @@ async function handleUnixTime(input, options) {
5531
5532
  console.log(` ISO: ${now.toISOString()}`);
5532
5533
  console.log(` Local: ${now.toLocaleString()}`);
5533
5534
  console.log();
5534
- } else if (/^\d+$/.test(input)) {
5535
- const timestamp = parseInt(input, 10);
5535
+ } else if (/^\d+$/.test(input2)) {
5536
+ const timestamp = parseInt(input2, 10);
5536
5537
  const date = service.unixToDate(timestamp, options.ms);
5537
5538
  console.log("\u{1F552} Unix Timestamp to Date:");
5538
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");
@@ -5545,7 +5546,7 @@ async function handleUnixTime(input, options) {
5545
5546
  }
5546
5547
  console.log();
5547
5548
  } else {
5548
- const date = new Date(input);
5549
+ const date = new Date(input2);
5549
5550
  if (isNaN(date.getTime())) {
5550
5551
  console.error("\u274C Invalid date format");
5551
5552
  process.exit(1);
@@ -5553,7 +5554,7 @@ async function handleUnixTime(input, options) {
5553
5554
  const timestamp = service.dateToUnix(date, options.ms);
5554
5555
  console.log("\u{1F552} Date to Unix Timestamp:");
5555
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");
5556
- console.log(` Input: ${input}`);
5557
+ console.log(` Input: ${input2}`);
5557
5558
  console.log(` Parsed: ${date.toISOString()}`);
5558
5559
  console.log();
5559
5560
  console.log(` ${timestamp}${options.ms ? " (ms)" : ""}`);
@@ -5573,8 +5574,8 @@ Examples:
5573
5574
  $ jai1 utils unix-time "2024-01-15 10:30:00"
5574
5575
  $ jai1 utils unix-time "2024-01-15" --format local
5575
5576
  $ jai1 utils unix-time --ms
5576
- `).action(async (input, options) => {
5577
- await handleUnixTime(input, options);
5577
+ `).action(async (input2, options) => {
5578
+ await handleUnixTime(input2, options);
5578
5579
  });
5579
5580
  return cmd;
5580
5581
  }
@@ -5631,10 +5632,10 @@ Examples:
5631
5632
 
5632
5633
  // src/commands/utils/url-encode.ts
5633
5634
  import { Command as Command24 } from "commander";
5634
- async function handleUrlEncode(input, options) {
5635
+ async function handleUrlEncode(input2, options) {
5635
5636
  const service = new UtilsService();
5636
5637
  try {
5637
- const encoded = service.urlEncode(input, options.full);
5638
+ const encoded = service.urlEncode(input2, options.full);
5638
5639
  console.log("\u{1F517} URL Encoded:");
5639
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");
5640
5641
  if (options.full) {
@@ -5657,18 +5658,18 @@ Examples:
5657
5658
  $ jai1 utils url-encode "hello world & test"
5658
5659
  $ jai1 utils url-encode "name=John Doe&age=30"
5659
5660
  $ jai1 utils url-encode "https://example.com/path with spaces" --full
5660
- `).showHelpAfterError("(add --help for additional examples)").action(async (input, options) => {
5661
- await handleUrlEncode(input, options);
5661
+ `).showHelpAfterError("(add --help for additional examples)").action(async (input2, options) => {
5662
+ await handleUrlEncode(input2, options);
5662
5663
  });
5663
5664
  return cmd;
5664
5665
  }
5665
5666
 
5666
5667
  // src/commands/utils/url-decode.ts
5667
5668
  import { Command as Command25 } from "commander";
5668
- async function handleUrlDecode(input, options) {
5669
+ async function handleUrlDecode(input2, options) {
5669
5670
  const service = new UtilsService();
5670
5671
  try {
5671
- const decoded = service.urlDecode(input, options.full);
5672
+ const decoded = service.urlDecode(input2, options.full);
5672
5673
  console.log("\u{1F517} URL Decoded:");
5673
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");
5674
5675
  if (options.full) {
@@ -5691,8 +5692,8 @@ Examples:
5691
5692
  $ jai1 utils url-decode "hello%20world%20%26%20test"
5692
5693
  $ jai1 utils url-decode "name%3DJohn%20Doe%26age%3D30"
5693
5694
  $ jai1 utils url-decode "https://example.com/path%20with%20spaces" --full
5694
- `).showHelpAfterError("(add --help for additional examples)").action(async (input, options) => {
5695
- await handleUrlDecode(input, options);
5695
+ `).showHelpAfterError("(add --help for additional examples)").action(async (input2, options) => {
5696
+ await handleUrlDecode(input2, options);
5696
5697
  });
5697
5698
  return cmd;
5698
5699
  }
@@ -5828,14 +5829,14 @@ var PasswordView = () => {
5828
5829
  React27.useEffect(() => {
5829
5830
  handleGenerate();
5830
5831
  }, []);
5831
- useInput12((input, key) => {
5832
+ useInput12((input2, key) => {
5832
5833
  if (key.tab) {
5833
5834
  if (focusedField === "length") setFocusedField("count");
5834
5835
  else if (focusedField === "count") setFocusedField("generate");
5835
5836
  else setFocusedField("length");
5836
5837
  } else if (key.return) {
5837
5838
  handleGenerate();
5838
- } else if (input === "c" && passwords.length > 0) {
5839
+ } else if (input2 === "c" && passwords.length > 0) {
5839
5840
  handleCopy(0);
5840
5841
  }
5841
5842
  });
@@ -5918,7 +5919,7 @@ var UuidView = () => {
5918
5919
  React28.useEffect(() => {
5919
5920
  handleGenerate();
5920
5921
  }, []);
5921
- useInput13((input, key) => {
5922
+ useInput13((input2, key) => {
5922
5923
  if (key.tab) {
5923
5924
  const fields = ["count", "uppercase", "hyphens", "generate"];
5924
5925
  const currentIndex = fields.indexOf(focusedField);
@@ -5931,7 +5932,7 @@ var UuidView = () => {
5931
5932
  } else {
5932
5933
  handleGenerate();
5933
5934
  }
5934
- } else if (input === "c" && uuids.length > 0) {
5935
+ } else if (input2 === "c" && uuids.length > 0) {
5935
5936
  handleCopy(0);
5936
5937
  }
5937
5938
  });
@@ -6006,7 +6007,7 @@ var HashView = () => {
6006
6007
  React29.useEffect(() => {
6007
6008
  handleGenerate();
6008
6009
  }, []);
6009
- useInput14((input, key) => {
6010
+ useInput14((input2, key) => {
6010
6011
  if (key.tab) {
6011
6012
  const fields = ["text", "algorithm", "generate"];
6012
6013
  const currentIndex = fields.indexOf(focusedField);
@@ -6019,7 +6020,7 @@ var HashView = () => {
6019
6020
  } else if (key.rightArrow && focusedField === "algorithm") {
6020
6021
  const currentIndex = ALGORITHMS.indexOf(algorithm);
6021
6022
  setAlgorithm(ALGORITHMS[(currentIndex + 1) % ALGORITHMS.length]);
6022
- } else if (input === "c" && hash) {
6023
+ } else if (input2 === "c" && hash) {
6023
6024
  handleCopy();
6024
6025
  }
6025
6026
  });
@@ -6085,7 +6086,7 @@ import React30, { useState as useState17 } from "react";
6085
6086
  import { Box as Box20, Text as Text21, useInput as useInput15 } from "ink";
6086
6087
  import TextInput7 from "ink-text-input";
6087
6088
  var Base64View = () => {
6088
- const [input, setInput] = useState17("");
6089
+ const [input2, setInput] = useState17("");
6089
6090
  const [mode, setMode] = useState17("encode");
6090
6091
  const [urlSafe, setUrlSafe] = useState17(false);
6091
6092
  const [result, setResult] = useState17("");
@@ -6093,7 +6094,7 @@ var Base64View = () => {
6093
6094
  const [focusedField, setFocusedField] = useState17("input");
6094
6095
  const [copied, setCopied] = useState17(false);
6095
6096
  const service = new UtilsService();
6096
- useInput15((input2, key) => {
6097
+ useInput15((input3, key) => {
6097
6098
  if (key.tab) {
6098
6099
  const fields = ["input", "mode", "urlsafe", "convert"];
6099
6100
  const currentIndex = fields.indexOf(focusedField);
@@ -6108,22 +6109,22 @@ var Base64View = () => {
6108
6109
  } else {
6109
6110
  handleConvert();
6110
6111
  }
6111
- } else if (input2 === "c" && result) {
6112
+ } else if (input3 === "c" && result) {
6112
6113
  handleCopy();
6113
6114
  }
6114
6115
  });
6115
6116
  const handleConvert = () => {
6116
- if (!input) {
6117
+ if (!input2) {
6117
6118
  setError("Input cannot be empty");
6118
6119
  return;
6119
6120
  }
6120
6121
  try {
6121
6122
  setError("");
6122
6123
  if (mode === "encode") {
6123
- const encoded = service.base64Encode(input, urlSafe);
6124
+ const encoded = service.base64Encode(input2, urlSafe);
6124
6125
  setResult(encoded);
6125
6126
  } else {
6126
- const decoded = service.base64Decode(input);
6127
+ const decoded = service.base64Decode(input2);
6127
6128
  setResult(decoded.toString("utf-8"));
6128
6129
  }
6129
6130
  setCopied(false);
@@ -6152,7 +6153,7 @@ var Base64View = () => {
6152
6153
  marginBottom: 1
6153
6154
  },
6154
6155
  /* @__PURE__ */ React30.createElement(Text21, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
6155
- /* @__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: input, onChange: setInput, placeholder: "Enter text..." }) : /* @__PURE__ */ React30.createElement(Text21, { dimColor: !input }, input || "(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: input2, onChange: setInput, placeholder: "Enter text..." }) : /* @__PURE__ */ React30.createElement(Text21, { dimColor: !input2 }, input2 || "(empty)"))),
6156
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)")),
6157
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 _)")),
6158
6159
  /* @__PURE__ */ React30.createElement(Box20, { marginTop: 1 }, /* @__PURE__ */ React30.createElement(
@@ -6197,14 +6198,14 @@ import React31, { useState as useState18 } from "react";
6197
6198
  import { Box as Box21, Text as Text22, useInput as useInput16 } from "ink";
6198
6199
  import TextInput8 from "ink-text-input";
6199
6200
  var UrlView = () => {
6200
- const [input, setInput] = useState18("");
6201
+ const [input2, setInput] = useState18("");
6201
6202
  const [mode, setMode] = useState18("encode");
6202
6203
  const [fullUrl, setFullUrl] = useState18(false);
6203
6204
  const [result, setResult] = useState18("");
6204
6205
  const [focusedField, setFocusedField] = useState18("input");
6205
6206
  const [copied, setCopied] = useState18(false);
6206
6207
  const service = new UtilsService();
6207
- useInput16((input2, key) => {
6208
+ useInput16((input3, key) => {
6208
6209
  if (key.tab) {
6209
6210
  const fields = ["input", "mode", "full", "convert"];
6210
6211
  const currentIndex = fields.indexOf(focusedField);
@@ -6218,17 +6219,17 @@ var UrlView = () => {
6218
6219
  } else {
6219
6220
  handleConvert();
6220
6221
  }
6221
- } else if (input2 === "c" && result) {
6222
+ } else if (input3 === "c" && result) {
6222
6223
  handleCopy();
6223
6224
  }
6224
6225
  });
6225
6226
  const handleConvert = () => {
6226
- if (!input) return;
6227
+ if (!input2) return;
6227
6228
  if (mode === "encode") {
6228
- const encoded = fullUrl ? service.urlEncode(input, true) : service.urlEncode(input, false);
6229
+ const encoded = fullUrl ? service.urlEncode(input2, true) : service.urlEncode(input2, false);
6229
6230
  setResult(encoded);
6230
6231
  } else {
6231
- const decoded = fullUrl ? service.urlDecode(input, true) : service.urlDecode(input, false);
6232
+ const decoded = fullUrl ? service.urlDecode(input2, true) : service.urlDecode(input2, false);
6232
6233
  setResult(decoded);
6233
6234
  }
6234
6235
  setCopied(false);
@@ -6253,7 +6254,7 @@ var UrlView = () => {
6253
6254
  marginBottom: 1
6254
6255
  },
6255
6256
  /* @__PURE__ */ React31.createElement(Text22, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
6256
- /* @__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: input, onChange: setInput, placeholder: "Enter text or URL..." }) : /* @__PURE__ */ React31.createElement(Text22, { dimColor: !input }, input || "(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: input2, onChange: setInput, placeholder: "Enter text or URL..." }) : /* @__PURE__ */ React31.createElement(Text22, { dimColor: !input2 }, input2 || "(empty)"))),
6257
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)")),
6258
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)")),
6259
6260
  /* @__PURE__ */ React31.createElement(Box21, { marginTop: 1 }, /* @__PURE__ */ React31.createElement(
@@ -6287,7 +6288,7 @@ import React32, { useState as useState19 } from "react";
6287
6288
  import { Box as Box22, Text as Text23, useInput as useInput17 } from "ink";
6288
6289
  import TextInput9 from "ink-text-input";
6289
6290
  var UnixTimeView = () => {
6290
- const [input, setInput] = useState19("");
6291
+ const [input2, setInput] = useState19("");
6291
6292
  const [mode, setMode] = useState19("now");
6292
6293
  const [format, setFormat] = useState19("iso");
6293
6294
  const [useMs, setUseMs] = useState19(false);
@@ -6296,7 +6297,7 @@ var UnixTimeView = () => {
6296
6297
  const [focusedField, setFocusedField] = useState19("mode");
6297
6298
  const [copied, setCopied] = useState19(false);
6298
6299
  const service = new UtilsService();
6299
- useInput17((input2, key) => {
6300
+ useInput17((input3, key) => {
6300
6301
  if (key.tab) {
6301
6302
  const fields = mode === "now" ? ["mode", "ms", "convert"] : mode === "to-human" ? ["mode", "input", "format", "convert"] : ["mode", "input", "convert"];
6302
6303
  const currentIndex = fields.indexOf(focusedField);
@@ -6317,7 +6318,7 @@ var UnixTimeView = () => {
6317
6318
  } else {
6318
6319
  handleConvert();
6319
6320
  }
6320
- } else if (input2 === "c" && result) {
6321
+ } else if (input3 === "c" && result) {
6321
6322
  handleCopy();
6322
6323
  }
6323
6324
  });
@@ -6328,18 +6329,18 @@ var UnixTimeView = () => {
6328
6329
  const timestamp = service.unixTimeCurrent(useMs);
6329
6330
  setResult(timestamp.toString());
6330
6331
  } else if (mode === "to-human") {
6331
- if (!input) {
6332
+ if (!input2) {
6332
6333
  setError("Please enter a timestamp");
6333
6334
  return;
6334
6335
  }
6335
- const human = service.unixTimeToHuman(parseInt(input, 10), format);
6336
+ const human = service.unixTimeToHuman(parseInt(input2, 10), format);
6336
6337
  setResult(human);
6337
6338
  } else {
6338
- if (!input) {
6339
+ if (!input2) {
6339
6340
  setError("Please enter a date string");
6340
6341
  return;
6341
6342
  }
6342
- const timestamp = service.unixTimeFromString(input);
6343
+ const timestamp = service.unixTimeFromString(input2);
6343
6344
  setResult(timestamp.toString());
6344
6345
  }
6345
6346
  setCopied(false);
@@ -6372,11 +6373,11 @@ var UnixTimeView = () => {
6372
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(
6373
6374
  TextInput9,
6374
6375
  {
6375
- value: input,
6376
+ value: input2,
6376
6377
  onChange: setInput,
6377
6378
  placeholder: mode === "to-human" ? "1702550400" : "2024-01-15 10:30:00"
6378
6379
  }
6379
- ) : /* @__PURE__ */ React32.createElement(Text23, { dimColor: !input }, input || "(empty)"))),
6380
+ ) : /* @__PURE__ */ React32.createElement(Text23, { dimColor: !input2 }, input2 || "(empty)"))),
6380
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)")),
6381
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")),
6382
6383
  /* @__PURE__ */ React32.createElement(Box22, { marginTop: 1 }, /* @__PURE__ */ React32.createElement(
@@ -6430,7 +6431,7 @@ var JwtView = () => {
6430
6431
  const [focusedField, setFocusedField] = useState20("mode");
6431
6432
  const [copied, setCopied] = useState20(false);
6432
6433
  const service = new UtilsService();
6433
- useInput18((input, key) => {
6434
+ useInput18((input2, key) => {
6434
6435
  if (key.tab) {
6435
6436
  const fields = mode === "decode" ? ["mode", "token", "process"] : ["mode", "payload", "secret", "process"];
6436
6437
  const currentIndex = fields.indexOf(focusedField);
@@ -6443,7 +6444,7 @@ var JwtView = () => {
6443
6444
  } else {
6444
6445
  handleProcess();
6445
6446
  }
6446
- } else if (input === "c" && result.token) {
6447
+ } else if (input2 === "c" && result.token) {
6447
6448
  handleCopy();
6448
6449
  }
6449
6450
  });
@@ -6568,12 +6569,12 @@ var CronView = () => {
6568
6569
  const [focusedField, setFocusedField] = useState21("expression");
6569
6570
  const [copied, setCopied] = useState21(false);
6570
6571
  const service = new UtilsService();
6571
- useInput19((input, key) => {
6572
+ useInput19((input2, key) => {
6572
6573
  if (key.tab) {
6573
6574
  setFocusedField(focusedField === "expression" ? "parse" : "expression");
6574
6575
  } else if (key.return) {
6575
6576
  handleParse();
6576
- } else if (input === "c" && result) {
6577
+ } else if (input2 === "c" && result) {
6577
6578
  handleCopy();
6578
6579
  }
6579
6580
  });
@@ -6674,14 +6675,14 @@ var TimezoneView = () => {
6674
6675
  const [focusedField, setFocusedField] = useState22("time");
6675
6676
  const [copied, setCopied] = useState22(false);
6676
6677
  const service = new UtilsService();
6677
- useInput20((input, key) => {
6678
+ useInput20((input2, key) => {
6678
6679
  if (key.tab) {
6679
6680
  const fields = ["time", "from", "to", "convert"];
6680
6681
  const currentIndex = fields.indexOf(focusedField);
6681
6682
  setFocusedField(fields[(currentIndex + 1) % fields.length]);
6682
6683
  } else if (key.return) {
6683
6684
  handleConvert();
6684
- } else if (input === "c" && result) {
6685
+ } else if (input2 === "c" && result) {
6685
6686
  handleCopy();
6686
6687
  }
6687
6688
  });
@@ -6800,7 +6801,7 @@ var HttpView = () => {
6800
6801
  const [focusedField, setFocusedField] = useState23("url");
6801
6802
  const [copied, setCopied] = useState23(false);
6802
6803
  const service = new UtilsService();
6803
- useInput21((input, key) => {
6804
+ useInput21((input2, key) => {
6804
6805
  if (loading) return;
6805
6806
  if (key.tab) {
6806
6807
  const fields = ["url", "method", "headers", "body", "send"];
@@ -6814,7 +6815,7 @@ var HttpView = () => {
6814
6815
  setMethod(METHODS[(currentIndex + 1) % METHODS.length]);
6815
6816
  } else if (key.return && focusedField === "send") {
6816
6817
  handleSend();
6817
- } else if (input === "c" && response) {
6818
+ } else if (input2 === "c" && response) {
6818
6819
  handleCopy();
6819
6820
  }
6820
6821
  });
@@ -6945,7 +6946,7 @@ var MarkdownView = () => {
6945
6946
  const [content, setContent] = useState24("");
6946
6947
  const [error, setError] = useState24("");
6947
6948
  const [focusedField, setFocusedField] = useState24("file");
6948
- useInput22((input, key) => {
6949
+ useInput22((input2, key) => {
6949
6950
  if (key.tab) {
6950
6951
  setFocusedField(focusedField === "file" ? "preview" : "file");
6951
6952
  } else if (key.return) {
@@ -7060,20 +7061,20 @@ var UtilsApp = ({ onExit }) => {
7060
7061
  const [selectedIndex, setSelectedIndex] = useState25(0);
7061
7062
  const [activeView, setActiveView] = useState25(null);
7062
7063
  const { exit } = useApp5();
7063
- useInput23((input, key) => {
7064
+ useInput23((input2, key) => {
7064
7065
  if (activeView) {
7065
7066
  if (key.escape) {
7066
7067
  setActiveView(null);
7067
7068
  }
7068
7069
  return;
7069
7070
  }
7070
- if (key.upArrow || input === "k") {
7071
+ if (key.upArrow || input2 === "k") {
7071
7072
  setSelectedIndex((prev) => prev > 0 ? prev - 1 : MENU_ITEMS2.length - 1);
7072
- } else if (key.downArrow || input === "j") {
7073
+ } else if (key.downArrow || input2 === "j") {
7073
7074
  setSelectedIndex((prev) => prev < MENU_ITEMS2.length - 1 ? prev + 1 : 0);
7074
7075
  } else if (key.return) {
7075
7076
  setActiveView(MENU_ITEMS2[selectedIndex].id);
7076
- } else if (input === "q" || key.escape) {
7077
+ } else if (input2 === "q" || key.escape) {
7077
7078
  onExit();
7078
7079
  exit();
7079
7080
  }
@@ -7237,8 +7238,398 @@ Quick Usage:
7237
7238
  return utilsCommand;
7238
7239
  }
7239
7240
 
7240
- // src/commands/upgrade.ts
7241
+ // src/commands/kit/index.ts
7242
+ import { Command as Command32 } from "commander";
7243
+
7244
+ // src/commands/kit/list.ts
7241
7245
  import { Command as Command29 } from "commander";
7246
+
7247
+ // src/services/starter-kit.service.ts
7248
+ import { promises as fs9 } from "fs";
7249
+ import { join as join4 } from "path";
7250
+ import AdmZip from "adm-zip";
7251
+ var StarterKitService = class {
7252
+ /**
7253
+ * List available starter kits
7254
+ */
7255
+ async list(config, options) {
7256
+ const params = new URLSearchParams();
7257
+ if (options?.category) params.set("category", options.category);
7258
+ if (options?.search) params.set("search", options.search);
7259
+ const url = `${config.apiUrl}/api/starter-kits${params.toString() ? "?" + params : ""}`;
7260
+ const response = await fetch(url, {
7261
+ headers: { "JAI1-Access-Key": config.accessKey }
7262
+ });
7263
+ if (!response.ok) {
7264
+ throw new NetworkError(`Failed to list starter kits: HTTP ${response.status}`);
7265
+ }
7266
+ const data = await response.json();
7267
+ return data.kits;
7268
+ }
7269
+ /**
7270
+ * Get single starter kit with full config
7271
+ */
7272
+ async get(config, slug) {
7273
+ const response = await fetch(`${config.apiUrl}/api/starter-kits/${slug}`, {
7274
+ headers: { "JAI1-Access-Key": config.accessKey }
7275
+ });
7276
+ if (!response.ok) {
7277
+ if (response.status === 404) {
7278
+ throw new Error(`Starter kit not found: ${slug}`);
7279
+ }
7280
+ throw new NetworkError(`Failed to get starter kit: HTTP ${response.status}`);
7281
+ }
7282
+ return await response.json();
7283
+ }
7284
+ /**
7285
+ * Download and extract starter kit
7286
+ */
7287
+ async downloadAndExtract(config, slug, targetDir, onProgress) {
7288
+ if (onProgress) onProgress(10);
7289
+ const response = await fetch(`${config.apiUrl}/api/starter-kits/${slug}/download`, {
7290
+ headers: { "JAI1-Access-Key": config.accessKey }
7291
+ });
7292
+ if (!response.ok) {
7293
+ throw new NetworkError(`Failed to get download URL: HTTP ${response.status}`);
7294
+ }
7295
+ const data = await response.json();
7296
+ if (onProgress) onProgress(30);
7297
+ const downloadResponse = await fetch(data.downloadUrl);
7298
+ if (!downloadResponse.ok) {
7299
+ throw new NetworkError(`Failed to download kit: HTTP ${downloadResponse.status}`);
7300
+ }
7301
+ if (onProgress) onProgress(60);
7302
+ const tmpDir = join4(process.env.TMPDIR || "/tmp", "jai1-kits");
7303
+ await fs9.mkdir(tmpDir, { recursive: true });
7304
+ const tmpFile = join4(tmpDir, `${slug}.zip`);
7305
+ const buffer = await downloadResponse.arrayBuffer();
7306
+ await fs9.writeFile(tmpFile, Buffer.from(buffer));
7307
+ if (onProgress) onProgress(80);
7308
+ const zip = new AdmZip(tmpFile);
7309
+ await fs9.mkdir(targetDir, { recursive: true });
7310
+ zip.extractAllTo(targetDir, true);
7311
+ if (onProgress) onProgress(100);
7312
+ await fs9.unlink(tmpFile);
7313
+ }
7314
+ };
7315
+
7316
+ // src/commands/kit/list.ts
7317
+ function createKitListCommand() {
7318
+ return new Command29("list").description("List available starter kits").option("-c, --category <category>", "Filter by category (backend, frontend, fullstack)").option("-s, --search <term>", "Search kits by name or description").action(async (options) => {
7319
+ const configService = new ConfigService();
7320
+ const config = await configService.load();
7321
+ if (!config) {
7322
+ throw new ValidationError('Not initialized. Run "jai1 auth" first.');
7323
+ }
7324
+ const kitService = new StarterKitService();
7325
+ const kits = await kitService.list(config, {
7326
+ category: options.category,
7327
+ search: options.search
7328
+ });
7329
+ if (kits.length === 0) {
7330
+ console.log("No starter kits found.");
7331
+ return;
7332
+ }
7333
+ const byCategory = {};
7334
+ for (const kit of kits) {
7335
+ if (!byCategory[kit.category]) {
7336
+ byCategory[kit.category] = [];
7337
+ }
7338
+ byCategory[kit.category].push(kit);
7339
+ }
7340
+ console.log("\u{1F4E6} Available Starter Kits:\n");
7341
+ for (const [category, categoryKits] of Object.entries(byCategory)) {
7342
+ console.log(`${category.charAt(0).toUpperCase() + category.slice(1)}:`);
7343
+ for (const kit of categoryKits) {
7344
+ const tags = kit.tags.length > 0 ? ` [${kit.tags.join(", ")}]` : "";
7345
+ console.log(
7346
+ ` ${kit.slug.padEnd(20)} ${kit.description.slice(0, 50).padEnd(52)} v${kit.version}${tags}`
7347
+ );
7348
+ }
7349
+ console.log();
7350
+ }
7351
+ });
7352
+ }
7353
+
7354
+ // src/commands/kit/info.ts
7355
+ import { Command as Command30 } from "commander";
7356
+ function createKitInfoCommand() {
7357
+ return new Command30("info").description("Show detailed information about a starter kit").argument("<slug>", "Starter kit slug").action(async (slug) => {
7358
+ const configService = new ConfigService();
7359
+ const config = await configService.load();
7360
+ if (!config) {
7361
+ throw new ValidationError('Not initialized. Run "jai1 auth" first.');
7362
+ }
7363
+ const kitService = new StarterKitService();
7364
+ const kit = await kitService.get(config, slug);
7365
+ console.log(`\u{1F4E6} ${kit.name}
7366
+ `);
7367
+ console.log(`Description: ${kit.description}`);
7368
+ console.log(`Category: ${kit.category}`);
7369
+ console.log(`Version: ${kit.version}`);
7370
+ console.log(`Downloads: ${kit.downloads}`);
7371
+ if (kit.tags.length > 0) {
7372
+ console.log(`Tags: ${kit.tags.join(", ")}`);
7373
+ }
7374
+ if (kit.config.requiredTools && kit.config.requiredTools.length > 0) {
7375
+ console.log(`
7376
+ Required Tools:`);
7377
+ kit.config.requiredTools.forEach((tool) => {
7378
+ console.log(` - ${tool}`);
7379
+ });
7380
+ }
7381
+ if (kit.config.framework?.apply && kit.config.framework.components.length > 0) {
7382
+ console.log(`
7383
+ Included Framework Components:`);
7384
+ kit.config.framework.components.forEach((comp) => {
7385
+ console.log(` - ${comp}`);
7386
+ });
7387
+ }
7388
+ if (kit.config.variables && kit.config.variables.length > 0) {
7389
+ console.log(`
7390
+ Variables (prompted during creation):`);
7391
+ kit.config.variables.forEach((v) => {
7392
+ console.log(` - ${v.name}: ${v.prompt}${v.default ? ` (default: ${v.default})` : ""}`);
7393
+ });
7394
+ }
7395
+ if (kit.config.hooks?.postInit && kit.config.hooks.postInit.length > 0) {
7396
+ console.log(`
7397
+ Post-Init Commands:`);
7398
+ kit.config.hooks.postInit.forEach((cmd) => {
7399
+ console.log(` - ${cmd}`);
7400
+ });
7401
+ }
7402
+ });
7403
+ }
7404
+
7405
+ // src/commands/kit/create.ts
7406
+ import { Command as Command31 } from "commander";
7407
+ import { promises as fs10 } from "fs";
7408
+ import { join as join5 } from "path";
7409
+ import { select as select2, input, checkbox as checkbox3 } from "@inquirer/prompts";
7410
+ import { execa as execa2 } from "execa";
7411
+
7412
+ // src/services/hook-executor.service.ts
7413
+ import { execa } from "execa";
7414
+ var HookExecutor = class {
7415
+ constructor(cwd, variables) {
7416
+ this.cwd = cwd;
7417
+ this.variables = variables;
7418
+ }
7419
+ /**
7420
+ * Run hooks sequentially
7421
+ */
7422
+ async run(hooks) {
7423
+ for (const hook of hooks) {
7424
+ const cmd = this.replaceVariables(hook);
7425
+ console.log(` $ ${cmd}`);
7426
+ try {
7427
+ await execa(cmd, {
7428
+ cwd: this.cwd,
7429
+ shell: true,
7430
+ stdio: "inherit"
7431
+ });
7432
+ } catch (error) {
7433
+ throw new Error(`Hook failed: ${cmd}`);
7434
+ }
7435
+ }
7436
+ }
7437
+ /**
7438
+ * Replace variables in command
7439
+ */
7440
+ replaceVariables(cmd) {
7441
+ let result = cmd;
7442
+ for (const [key, value] of Object.entries(this.variables)) {
7443
+ result = result.replace(new RegExp(`\\{\\{${key}\\}\\}`, "g"), value);
7444
+ }
7445
+ return result;
7446
+ }
7447
+ };
7448
+
7449
+ // src/commands/kit/create.ts
7450
+ function createKitCreateCommand() {
7451
+ return new Command31("create").description("Create a new project from a starter kit").argument("<slug>", "Starter kit slug").argument("[directory]", "Project directory (default: ./<slug>)").option("-y, --yes", "Auto mode - use defaults, no prompts").option("--name <name>", "Project name").option("--skip-install", "Skip dependency installation").option("--skip-git", "Skip git initialization").option("--skip-framework", "Skip framework apply").option("--skip-ide", "Skip IDE sync").action(async (slug, directory, options) => {
7452
+ const configService = new ConfigService();
7453
+ const config = await configService.load();
7454
+ if (!config) {
7455
+ throw new ValidationError('Not initialized. Run "jai1 auth" first.');
7456
+ }
7457
+ const isAutoMode = options.yes === true;
7458
+ const kitService = new StarterKitService();
7459
+ console.log(`\u{1F4E6} Fetching starter kit: ${slug}...`);
7460
+ const kit = await kitService.get(config, slug);
7461
+ if (kit.config.requiredTools && kit.config.requiredTools.length > 0) {
7462
+ console.log("\u{1F50D} Checking required tools...");
7463
+ for (const tool of kit.config.requiredTools) {
7464
+ try {
7465
+ await execa2("which", [tool]);
7466
+ } catch {
7467
+ console.warn(`\u26A0\uFE0F Warning: Required tool '${tool}' not found`);
7468
+ }
7469
+ }
7470
+ }
7471
+ const targetDir = directory || join5(process.cwd(), options.name || slug);
7472
+ try {
7473
+ await fs10.access(targetDir);
7474
+ throw new Error(`Directory already exists: ${targetDir}`);
7475
+ } catch (error) {
7476
+ if (error.code !== "ENOENT") {
7477
+ throw error;
7478
+ }
7479
+ }
7480
+ if (kit.config.hooks?.preInit && kit.config.hooks.preInit.length > 0) {
7481
+ console.log("\u{1F527} Running pre-init hooks...");
7482
+ const hookExecutor = new HookExecutor(process.cwd(), {});
7483
+ await hookExecutor.run(kit.config.hooks.preInit);
7484
+ }
7485
+ console.log("\u{1F4E5} Downloading template...");
7486
+ await kitService.downloadAndExtract(config, slug, targetDir, (percent) => {
7487
+ if (percent === 100) {
7488
+ console.log(" \u2713 Downloaded and extracted");
7489
+ }
7490
+ });
7491
+ if (kit.config.hooks?.postExtract && kit.config.hooks.postExtract.length > 0) {
7492
+ console.log("\u{1F4C4} Setting up environment...");
7493
+ const hookExecutor = new HookExecutor(targetDir, {});
7494
+ await hookExecutor.run(kit.config.hooks.postExtract);
7495
+ }
7496
+ const variables = {};
7497
+ if (kit.config.variables && kit.config.variables.length > 0) {
7498
+ if (isAutoMode) {
7499
+ console.log("\u{1F4DD} Using default values (auto mode)");
7500
+ for (const v of kit.config.variables) {
7501
+ variables[v.name] = options.name && v.name === "PROJECT_NAME" ? options.name : v.default || "";
7502
+ }
7503
+ } else {
7504
+ console.log("\u{1F4DD} Please provide project details:");
7505
+ for (const v of kit.config.variables) {
7506
+ if (v.type === "select" && v.options) {
7507
+ const answer = await select2({
7508
+ message: v.prompt,
7509
+ choices: v.options.map((opt) => ({ name: opt, value: opt })),
7510
+ default: v.default
7511
+ });
7512
+ variables[v.name] = answer;
7513
+ } else {
7514
+ const answer = await input({
7515
+ message: v.prompt,
7516
+ default: v.default
7517
+ });
7518
+ variables[v.name] = answer;
7519
+ }
7520
+ }
7521
+ }
7522
+ }
7523
+ if (Object.keys(variables).length > 0) {
7524
+ await applyVariableSubstitution(targetDir, variables);
7525
+ }
7526
+ if (!options.skipFramework && kit.config.framework?.apply) {
7527
+ console.log("\u{1F916} Applying jai1 framework...");
7528
+ const componentsService = new ComponentsService(targetDir);
7529
+ for (const filepath of kit.config.framework.components) {
7530
+ console.log(` \u{1F4E5} Installing ${filepath}...`);
7531
+ await componentsService.install(config, filepath);
7532
+ }
7533
+ console.log(" \u2713 Framework components applied");
7534
+ }
7535
+ if (!options.skipGit && kit.config.git?.init) {
7536
+ console.log("\u{1F527} Initializing git repository...");
7537
+ await execa2("git", ["init"], { cwd: targetDir });
7538
+ await execa2("git", ["add", "."], { cwd: targetDir });
7539
+ const commitMsg = kit.config.git.initialCommit || "Initial commit";
7540
+ await execa2("git", ["commit", "-m", commitMsg], { cwd: targetDir });
7541
+ console.log(" \u2713 Git initialized");
7542
+ }
7543
+ if (!options.skipInstall && kit.config.hooks?.postInit) {
7544
+ console.log("\u{1F527} Running setup...");
7545
+ const hookExecutor = new HookExecutor(targetDir, variables);
7546
+ await hookExecutor.run(kit.config.hooks.postInit);
7547
+ }
7548
+ if (!options.skipIde) {
7549
+ const ideChoices = [
7550
+ { name: "Cursor", value: "cursor" },
7551
+ { name: "Windsurf", value: "windsurf" },
7552
+ { name: "VSCode", value: "vscode" },
7553
+ { name: "Claude Code", value: "claude-code" },
7554
+ { name: "Antigravity", value: "antigravity" }
7555
+ ];
7556
+ let selectedIdes = [];
7557
+ if (isAutoMode) {
7558
+ selectedIdes = kit.config.ide?.defaultTargets || [];
7559
+ if (selectedIdes.length > 0) {
7560
+ console.log(`\u{1F5A5}\uFE0F Syncing to IDEs: ${selectedIdes.join(", ")}`);
7561
+ }
7562
+ } else {
7563
+ const defaultTargets = kit.config.ide?.defaultTargets || [];
7564
+ const answer = await checkbox3({
7565
+ message: "Ch\u1ECDn IDE \u0111\u1EC3 sync framework:",
7566
+ choices: ideChoices.map((c) => ({
7567
+ ...c,
7568
+ checked: defaultTargets.includes(c.value)
7569
+ }))
7570
+ });
7571
+ selectedIdes = answer;
7572
+ }
7573
+ if (selectedIdes.length > 0) {
7574
+ await execa2("jai1", ["ide", "sync", ...selectedIdes], {
7575
+ cwd: targetDir,
7576
+ stdio: "inherit"
7577
+ });
7578
+ }
7579
+ }
7580
+ console.log("\n\u2705 Project created successfully!");
7581
+ console.log(`\u{1F4C1} Location: ${targetDir}`);
7582
+ console.log("\n\u{1F4A1} Next steps:");
7583
+ console.log(` cd ${targetDir}`);
7584
+ console.log(" jai1 apply # Add more framework components");
7585
+ });
7586
+ }
7587
+ async function applyVariableSubstitution(dir, variables) {
7588
+ const files = await getAllFiles(dir);
7589
+ for (const file of files) {
7590
+ let content = await fs10.readFile(file, "utf-8");
7591
+ let modified = false;
7592
+ for (const [key, value] of Object.entries(variables)) {
7593
+ const regex = new RegExp(`\\{\\{${key}\\}\\}`, "g");
7594
+ if (regex.test(content)) {
7595
+ content = content.replace(regex, value);
7596
+ modified = true;
7597
+ }
7598
+ }
7599
+ if (modified) {
7600
+ await fs10.writeFile(file, content, "utf-8");
7601
+ }
7602
+ }
7603
+ }
7604
+ async function getAllFiles(dir) {
7605
+ const files = [];
7606
+ const entries = await fs10.readdir(dir, { withFileTypes: true });
7607
+ for (const entry of entries) {
7608
+ const fullPath = join5(dir, entry.name);
7609
+ if (entry.isDirectory()) {
7610
+ if (!entry.name.startsWith(".") && entry.name !== "node_modules") {
7611
+ files.push(...await getAllFiles(fullPath));
7612
+ }
7613
+ } else {
7614
+ files.push(fullPath);
7615
+ }
7616
+ }
7617
+ return files;
7618
+ }
7619
+
7620
+ // src/commands/kit/index.ts
7621
+ function createKitCommand() {
7622
+ const cmd = new Command32("kit").description("Manage starter kits for new projects").action(() => {
7623
+ cmd.help();
7624
+ });
7625
+ cmd.addCommand(createKitListCommand());
7626
+ cmd.addCommand(createKitInfoCommand());
7627
+ cmd.addCommand(createKitCreateCommand());
7628
+ return cmd;
7629
+ }
7630
+
7631
+ // src/commands/upgrade.ts
7632
+ import { Command as Command33 } from "commander";
7242
7633
  import { confirm as confirm4 } from "@inquirer/prompts";
7243
7634
  import { execSync } from "child_process";
7244
7635
  var colors2 = {
@@ -7250,7 +7641,7 @@ var colors2 = {
7250
7641
  bold: "\x1B[1m"
7251
7642
  };
7252
7643
  function createUpgradeCommand() {
7253
- return new Command29("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) => {
7644
+ return new Command33("upgrade").description("Upgrade jai1-client to the latest version").option("--check", "Only check for updates without installing").option("--force", "Force upgrade without confirmation").action(async (options) => {
7254
7645
  await handleUpgrade(options);
7255
7646
  });
7256
7647
  }
@@ -7398,11 +7789,11 @@ function getInstallCommand(packageManager2) {
7398
7789
  }
7399
7790
 
7400
7791
  // src/commands/clean.ts
7401
- import { Command as Command30 } from "commander";
7402
- import { confirm as confirm5, select as select2 } from "@inquirer/prompts";
7403
- import { join as join4 } from "path";
7792
+ import { Command as Command34 } from "commander";
7793
+ import { confirm as confirm5, select as select3 } from "@inquirer/prompts";
7794
+ import { join as join6 } from "path";
7404
7795
  function createCleanCommand() {
7405
- return new Command30("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) => {
7796
+ return new Command34("clean").description("Clean up backups, cache, and temporary files").option("-y, --yes", "Skip confirmation").option("--backups", "Clean only backup files").option("--all", "Clean all (backups + cache)").action(async (options) => {
7406
7797
  await handleClean(options);
7407
7798
  });
7408
7799
  }
@@ -7413,7 +7804,7 @@ async function handleClean(options) {
7413
7804
  {
7414
7805
  name: "Backups",
7415
7806
  description: "Component backup files (.jai1_backup/)",
7416
- path: join4(cwd, ".jai1_backup"),
7807
+ path: join6(cwd, ".jai1_backup"),
7417
7808
  check: async () => {
7418
7809
  const backups = await service.listBackups(cwd);
7419
7810
  return { exists: backups.length > 0, count: backups.length };
@@ -7463,7 +7854,7 @@ async function handleClean(options) {
7463
7854
  console.log(` Path: ${target.path}
7464
7855
  `);
7465
7856
  }
7466
- const action = await select2({
7857
+ const action = await select3({
7467
7858
  message: "What do you want to clean?",
7468
7859
  choices: [
7469
7860
  ...availableTargets.map(({ target, info }) => ({
@@ -7515,7 +7906,7 @@ async function cleanTarget(target, skipConfirm) {
7515
7906
  }
7516
7907
 
7517
7908
  // src/commands/redmine/check.ts
7518
- import { Command as Command31 } from "commander";
7909
+ import { Command as Command35 } from "commander";
7519
7910
 
7520
7911
  // src/services/redmine-config.service.ts
7521
7912
  import { readFile as readFile6 } from "fs/promises";
@@ -7822,7 +8213,7 @@ async function checkConnectivity(config) {
7822
8213
 
7823
8214
  // src/commands/redmine/check.ts
7824
8215
  function createRedmineCheckCommand() {
7825
- const cmd = new Command31("check").description("Check Redmine connectivity").option("-c, --config <path>", "Config file path", "redmine.config.yaml").option("--json", "Output as JSON").action(async (options) => {
8216
+ const cmd = new Command35("check").description("Check Redmine connectivity").option("-c, --config <path>", "Config file path", "redmine.config.yaml").option("--json", "Output as JSON").action(async (options) => {
7826
8217
  await handleRedmineCheck(options);
7827
8218
  });
7828
8219
  return cmd;
@@ -7850,7 +8241,7 @@ async function handleRedmineCheck(options) {
7850
8241
  }
7851
8242
 
7852
8243
  // src/commands/redmine/sync-issue.ts
7853
- import { Command as Command32 } from "commander";
8244
+ import { Command as Command36 } from "commander";
7854
8245
 
7855
8246
  // src/sync-issue.ts
7856
8247
  import { resolve as resolve3, relative } from "path";
@@ -8226,7 +8617,7 @@ function extractIssueIdFromUrl(url) {
8226
8617
 
8227
8618
  // src/commands/redmine/sync-issue.ts
8228
8619
  function createSyncIssueCommand() {
8229
- const cmd = new Command32("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) => {
8620
+ const cmd = new Command36("issue").description("Sync a single issue").option("-i, --id <number>", "Issue ID").option("-u, --url <url>", "Issue URL").option("--dry-run", "Preview without making changes").option("-c, --config <path>", "Config file path").option("-o, --output-dir <path>", "Output directory").option("--json", "Output as JSON").action(async (options) => {
8230
8621
  await handleSyncIssue(options);
8231
8622
  });
8232
8623
  return cmd;
@@ -8270,7 +8661,7 @@ async function handleSyncIssue(options) {
8270
8661
  }
8271
8662
 
8272
8663
  // src/commands/redmine/sync-project.ts
8273
- import { Command as Command33 } from "commander";
8664
+ import { Command as Command37 } from "commander";
8274
8665
 
8275
8666
  // src/sync-project.ts
8276
8667
  async function syncProject(config, options = {}) {
@@ -8340,7 +8731,7 @@ async function syncProject(config, options = {}) {
8340
8731
 
8341
8732
  // src/commands/redmine/sync-project.ts
8342
8733
  function createSyncProjectCommand() {
8343
- const cmd = new Command33("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) => {
8734
+ const cmd = new Command37("project").description("Sync all issues in a project").option("-s, --status <status>", "Filter by status (default: *)", "*").option("--updated-since <date>", "Only sync issues updated since YYYY-MM-DD").option("--concurrency <number>", "Number of concurrent requests").option("--page-size <number>", "Page size for API requests").option("--dry-run", "Preview without making changes").option("-c, --config <path>", "Config file path").option("-o, --output-dir <path>", "Output directory").option("--json", "Output as JSON").action(async (options) => {
8344
8735
  await handleSyncProject(options);
8345
8736
  });
8346
8737
  return cmd;
@@ -8395,12 +8786,12 @@ async function handleSyncProject(options) {
8395
8786
  }
8396
8787
 
8397
8788
  // src/commands/framework/info.ts
8398
- import { Command as Command34 } from "commander";
8399
- import { promises as fs9 } from "fs";
8400
- import { join as join5 } from "path";
8789
+ import { Command as Command38 } from "commander";
8790
+ import { promises as fs11 } from "fs";
8791
+ import { join as join7 } from "path";
8401
8792
  import { homedir as homedir5 } from "os";
8402
8793
  function createInfoCommand() {
8403
- const cmd = new Command34("info").description("Show jai1-client configuration and status").option("--json", "Output as JSON").option("--verbose", "Show detailed information").action(async (options) => {
8794
+ const cmd = new Command38("info").description("Show jai1-client configuration and status").option("--json", "Output as JSON").option("--verbose", "Show detailed information").action(async (options) => {
8404
8795
  await handleInfo(options);
8405
8796
  });
8406
8797
  return cmd;
@@ -8411,7 +8802,7 @@ async function handleInfo(options) {
8411
8802
  if (!config) {
8412
8803
  throw new ValidationError('Not initialized. Run "jai1 auth" first.');
8413
8804
  }
8414
- const frameworkPath = join5(homedir5(), ".jai1", "framework");
8805
+ const frameworkPath = join7(homedir5(), ".jai1", "framework");
8415
8806
  const projectStatus = await getProjectStatus2();
8416
8807
  const info = {
8417
8808
  configPath: configService.getConfigPath(),
@@ -8446,9 +8837,9 @@ function maskKey3(key) {
8446
8837
  return "****" + key.slice(-4);
8447
8838
  }
8448
8839
  async function getProjectStatus2() {
8449
- const projectJai1 = join5(process.cwd(), ".jai1");
8840
+ const projectJai1 = join7(process.cwd(), ".jai1");
8450
8841
  try {
8451
- await fs9.access(projectJai1);
8842
+ await fs11.access(projectJai1);
8452
8843
  return { exists: true, version: "Synced" };
8453
8844
  } catch {
8454
8845
  return { exists: false };
@@ -8456,7 +8847,7 @@ async function getProjectStatus2() {
8456
8847
  }
8457
8848
 
8458
8849
  // src/commands/self-update.ts
8459
- import { Command as Command35 } from "commander";
8850
+ import { Command as Command39 } from "commander";
8460
8851
  import { confirm as confirm6 } from "@inquirer/prompts";
8461
8852
  import { execSync as execSync2 } from "child_process";
8462
8853
  var colors3 = {
@@ -8468,7 +8859,7 @@ var colors3 = {
8468
8859
  bold: "\x1B[1m"
8469
8860
  };
8470
8861
  function createSelfUpdateCommand() {
8471
- return new Command35("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) => {
8862
+ return new Command39("self-update").description("Update jai1-client to the latest version").option("--check", "Only check for updates without installing").option("--force", "Force update without confirmation").action(async (options) => {
8472
8863
  await handleSelfUpdate(options);
8473
8864
  });
8474
8865
  }
@@ -8608,10 +8999,10 @@ function getInstallCommand2(packageManager2) {
8608
8999
  }
8609
9000
 
8610
9001
  // src/commands/clear-backups.ts
8611
- import { Command as Command36 } from "commander";
9002
+ import { Command as Command40 } from "commander";
8612
9003
  import { confirm as confirm7 } from "@inquirer/prompts";
8613
9004
  function createClearBackupsCommand() {
8614
- return new Command36("clear-backups").description("Clear backup files").option("-y, --yes", "Skip confirmation").action(async (options) => {
9005
+ return new Command40("clear-backups").description("Clear backup files").option("-y, --yes", "Skip confirmation").action(async (options) => {
8615
9006
  const service = new ComponentsService();
8616
9007
  const backups = await service.listBackups(process.cwd());
8617
9008
  if (backups.length === 0) {
@@ -8636,9 +9027,9 @@ function createClearBackupsCommand() {
8636
9027
  }
8637
9028
 
8638
9029
  // src/commands/vscode/index.ts
8639
- import { Command as Command37 } from "commander";
8640
- import { checkbox as checkbox3, confirm as confirm8, select as select3 } from "@inquirer/prompts";
8641
- import fs10 from "fs/promises";
9030
+ import { Command as Command41 } from "commander";
9031
+ import { checkbox as checkbox4, confirm as confirm8, select as select4 } from "@inquirer/prompts";
9032
+ import fs12 from "fs/promises";
8642
9033
  import path6 from "path";
8643
9034
  import { existsSync as existsSync3 } from "fs";
8644
9035
  var PERFORMANCE_GROUPS2 = {
@@ -8776,7 +9167,7 @@ var PERFORMANCE_GROUPS2 = {
8776
9167
  }
8777
9168
  };
8778
9169
  function createVSCodeCommand() {
8779
- const vscodeCommand = new Command37("vscode").description("Qu\u1EA3n l\xFD c\xE0i \u0111\u1EB7t VSCode cho d\u1EF1 \xE1n hi\u1EC7n t\u1EA1i");
9170
+ const vscodeCommand = new Command41("vscode").description("Qu\u1EA3n l\xFD c\xE0i \u0111\u1EB7t VSCode cho d\u1EF1 \xE1n hi\u1EC7n t\u1EA1i");
8780
9171
  vscodeCommand.action(async () => {
8781
9172
  await interactiveMode2();
8782
9173
  });
@@ -8820,7 +9211,7 @@ async function interactiveMode2() {
8820
9211
  console.log("\u2502 \u2022 Nh\u1EA5n ENTER \u0111\u1EC3 x\xE1c nh\u1EADn v\xE0 \xE1p d\u1EE5ng \u2502");
8821
9212
  console.log("\u2502 \u2022 Nh\u1EA5n Ctrl+C \u0111\u1EC3 h\u1EE7y \u2502");
8822
9213
  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");
8823
- const action = await select3({
9214
+ const action = await select4({
8824
9215
  message: "B\u1EA1n mu\u1ED1n l\xE0m g\xEC?",
8825
9216
  choices: [
8826
9217
  { name: "\u2705 Enable c\xE1c nh\xF3m t\u1ED1i \u01B0u", value: "enable" },
@@ -8844,7 +9235,7 @@ async function selectGroupsToApply2(action) {
8844
9235
  value: key
8845
9236
  }));
8846
9237
  try {
8847
- const selectedGroups = await checkbox3({
9238
+ const selectedGroups = await checkbox4({
8848
9239
  message: `Ch\u1ECDn c\xE1c nh\xF3m \u0111\u1EC3 ${action === "enable" ? "enable" : "disable"} (SPACE \u0111\u1EC3 ch\u1ECDn, ENTER \u0111\u1EC3 x\xE1c nh\u1EADn):`,
8849
9240
  choices
8850
9241
  });
@@ -8869,13 +9260,13 @@ async function applyGroups2(groupKeys, action) {
8869
9260
  return;
8870
9261
  }
8871
9262
  if (!existsSync3(vscodeDir)) {
8872
- await fs10.mkdir(vscodeDir, { recursive: true });
9263
+ await fs12.mkdir(vscodeDir, { recursive: true });
8873
9264
  console.log("\u{1F4C1} \u0110\xE3 t\u1EA1o th\u01B0 m\u1EE5c .vscode/");
8874
9265
  }
8875
9266
  let currentSettings = {};
8876
9267
  if (existsSync3(settingsPath)) {
8877
9268
  try {
8878
- const content = await fs10.readFile(settingsPath, "utf-8");
9269
+ const content = await fs12.readFile(settingsPath, "utf-8");
8879
9270
  currentSettings = JSON.parse(content);
8880
9271
  console.log("\u{1F4C4} \u0110\xE3 \u0111\u1ECDc c\xE0i \u0111\u1EB7t hi\u1EC7n t\u1EA1i t\u1EEB settings.json");
8881
9272
  } catch {
@@ -8915,7 +9306,7 @@ async function applyGroups2(groupKeys, action) {
8915
9306
  }
8916
9307
  }
8917
9308
  }
8918
- await fs10.writeFile(settingsPath, JSON.stringify(newSettings, null, 2));
9309
+ await fs12.writeFile(settingsPath, JSON.stringify(newSettings, null, 2));
8919
9310
  console.log(`
8920
9311
  \u2705 \u0110\xE3 c\u1EADp nh\u1EADt c\xE0i \u0111\u1EB7t VSCode t\u1EA1i: ${settingsPath}`);
8921
9312
  console.log("\u{1F4A1} M\u1EB9o: Kh\u1EDFi \u0111\u1ED9ng l\u1EA1i VSCode \u0111\u1EC3 \xE1p d\u1EE5ng c\xE1c thay \u0111\u1ED5i.");
@@ -8936,7 +9327,7 @@ async function resetSettings2(groupKeys) {
8936
9327
  return;
8937
9328
  }
8938
9329
  if (groupKeys.length === 0) {
8939
- await fs10.unlink(settingsPath);
9330
+ await fs12.unlink(settingsPath);
8940
9331
  console.log("\n\u2705 \u0110\xE3 x\xF3a file settings.json");
8941
9332
  } else {
8942
9333
  await applyGroups2(groupKeys, "disable");
@@ -8947,9 +9338,9 @@ async function resetSettings2(groupKeys) {
8947
9338
  // src/commands/guide.ts
8948
9339
  import React40 from "react";
8949
9340
  import { render as render6 } from "ink";
8950
- import { Command as Command38 } from "commander";
9341
+ import { Command as Command42 } from "commander";
8951
9342
  function createGuideCommand() {
8952
- const cmd = new Command38("guide").description("Interactive guide center for Agentic Coding").option("--topic <topic>", "Open specific topic (intro, rules, workflows, prompts, skills)").action(async (options) => {
9343
+ const cmd = new Command42("guide").description("Interactive guide center for Agentic Coding").option("--topic <topic>", "Open specific topic (intro, rules, workflows, prompts, skills)").action(async (options) => {
8953
9344
  const { waitUntilExit } = render6(
8954
9345
  React40.createElement(GuideApp, {
8955
9346
  initialTopic: options.topic,
@@ -8966,9 +9357,9 @@ function createGuideCommand() {
8966
9357
  // src/commands/context.ts
8967
9358
  import React41 from "react";
8968
9359
  import { render as render7 } from "ink";
8969
- import { Command as Command39 } from "commander";
9360
+ import { Command as Command43 } from "commander";
8970
9361
  function createContextCommand() {
8971
- const cmd = new Command39("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) => {
9362
+ const cmd = new Command43("context").description("Kh\xE1m ph\xE1 v\xE0 qu\u1EA3n l\xFD context d\u1EF1 \xE1n cho c\xE1c IDE").option("--ide <ide>", "M\u1EDF tr\u1EF1c ti\u1EBFp IDE c\u1EE5 th\u1EC3 (cursor, windsurf, antigravity, jai1)").option("--type <type>", "Hi\u1EC3n th\u1ECB lo\u1EA1i context c\u1EE5 th\u1EC3 (rules, workflows, skills, agents, prompts)").option("--stats", "Hi\u1EC3n th\u1ECB th\u1ED1ng k\xEA context (non-interactive)").action(async (options) => {
8972
9363
  let initialIDE;
8973
9364
  if (options.ide) {
8974
9365
  const validIDEs = ["cursor", "windsurf", "antigravity", "jai1"];
@@ -9045,10 +9436,10 @@ async function printStats2() {
9045
9436
  }
9046
9437
 
9047
9438
  // src/commands/migrate-ide.ts
9048
- import { Command as Command40 } from "commander";
9049
- import { checkbox as checkbox4, confirm as confirm9 } from "@inquirer/prompts";
9439
+ import { Command as Command44 } from "commander";
9440
+ import { checkbox as checkbox5, confirm as confirm9 } from "@inquirer/prompts";
9050
9441
  function createMigrateIdeCommand() {
9051
- const cmd = new Command40("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) => {
9442
+ const cmd = new Command44("migrate-ide").description("Migrate .jai1 rules v\xE0 workflows sang IDEs (Cursor, Windsurf, Claude Code, etc.)").option("--ide <ides...>", "Target IDEs (cursor, windsurf, antigravity, claudecode, opencode)").option("--type <types...>", "Content types (rules, workflows, commands)").option("--dry-run", "Preview changes without writing files").action(async (options) => {
9052
9443
  await runMigrateIde(options);
9053
9444
  });
9054
9445
  return cmd;
@@ -9076,7 +9467,7 @@ async function runMigrateIde(options) {
9076
9467
  value: ide
9077
9468
  };
9078
9469
  });
9079
- selectedIdes = await checkbox4({
9470
+ selectedIdes = await checkbox5({
9080
9471
  message: "Ch\u1ECDn IDE(s) \u0111\u1EC3 migrate (SPACE \u0111\u1EC3 ch\u1ECDn, ENTER \u0111\u1EC3 x\xE1c nh\u1EADn):",
9081
9472
  choices: ideChoices
9082
9473
  });
@@ -9095,7 +9486,7 @@ async function runMigrateIde(options) {
9095
9486
  { name: `Workflows (${content.workflows.length} files)`, value: "workflows" },
9096
9487
  { name: `Commands (${content.commands.length} files)`, value: "commands" }
9097
9488
  ];
9098
- selectedTypes = await checkbox4({
9489
+ selectedTypes = await checkbox5({
9099
9490
  message: "Ch\u1ECDn content types \u0111\u1EC3 migrate:",
9100
9491
  choices: typeChoices
9101
9492
  });
@@ -9154,7 +9545,7 @@ async function runMigrateIde(options) {
9154
9545
  }
9155
9546
 
9156
9547
  // src/cli.ts
9157
- var program = new Command41();
9548
+ var program = new Command45();
9158
9549
  if (process.argv.includes("-v") || process.argv.includes("--version")) {
9159
9550
  console.log(package_default.version);
9160
9551
  if (!process.argv.includes("--skip-update-check")) {
@@ -9176,11 +9567,12 @@ program.addCommand(createOpenAiKeysCommand());
9176
9567
  program.addCommand(createStatsCommand());
9177
9568
  program.addCommand(createTranslateCommand());
9178
9569
  program.addCommand(createUtilsCommand());
9570
+ program.addCommand(createKitCommand());
9179
9571
  program.addCommand(createUpgradeCommand());
9180
9572
  program.addCommand(createCleanCommand());
9181
- var redmineCommand = new Command41("redmine").description("Redmine context sync commands");
9573
+ var redmineCommand = new Command45("redmine").description("Redmine context sync commands");
9182
9574
  redmineCommand.addCommand(createRedmineCheckCommand());
9183
- var syncCommand = new Command41("sync").description("Sync Redmine issues to markdown files");
9575
+ var syncCommand = new Command45("sync").description("Sync Redmine issues to markdown files");
9184
9576
  syncCommand.addCommand(createSyncIssueCommand());
9185
9577
  syncCommand.addCommand(createSyncProjectCommand());
9186
9578
  redmineCommand.addCommand(syncCommand);