@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 +529 -178
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
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
|
|
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.
|
|
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((
|
|
898
|
+
useInput((input3, key) => {
|
|
899
899
|
if (viewState === "summary") {
|
|
900
|
-
if (key.return ||
|
|
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 ||
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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((
|
|
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((
|
|
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(
|
|
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((
|
|
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((
|
|
1557
|
-
if (key.upArrow ||
|
|
1556
|
+
useInput5((input3, key) => {
|
|
1557
|
+
if (key.upArrow || input3 === "k") {
|
|
1558
1558
|
setScrollPosition((prev) => Math.max(0, prev - 1));
|
|
1559
|
-
} else if (key.downArrow ||
|
|
1559
|
+
} else if (key.downArrow || input3 === "j") {
|
|
1560
1560
|
setScrollPosition((prev) => Math.min(maxScroll, prev + 1));
|
|
1561
|
-
} else if (key.pageDown ||
|
|
1561
|
+
} else if (key.pageDown || input3 === "d") {
|
|
1562
1562
|
setScrollPosition((prev) => Math.min(maxScroll, prev + 5));
|
|
1563
|
-
} else if (key.pageUp ||
|
|
1563
|
+
} else if (key.pageUp || input3 === "u") {
|
|
1564
1564
|
setScrollPosition((prev) => Math.max(0, prev - 5));
|
|
1565
|
-
} else if (
|
|
1565
|
+
} else if (input3 === "g") {
|
|
1566
1566
|
setScrollPosition(0);
|
|
1567
|
-
} else if (
|
|
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((
|
|
1964
|
-
if (
|
|
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((
|
|
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((
|
|
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((
|
|
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 (
|
|
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((
|
|
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((
|
|
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 ||
|
|
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(
|
|
4554
|
+
async detectInputType(input3) {
|
|
4555
4555
|
try {
|
|
4556
|
-
const stat = await fs7.stat(
|
|
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(
|
|
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(
|
|
4796
|
+
const inputType = await translationService.detectInputType(input3);
|
|
4797
4797
|
switch (inputType) {
|
|
4798
4798
|
case "text":
|
|
4799
|
-
await handleTextTranslation(translationService,
|
|
4799
|
+
await handleTextTranslation(translationService, input3, options);
|
|
4800
4800
|
break;
|
|
4801
4801
|
case "file":
|
|
4802
|
-
await handleFileTranslation(translationService,
|
|
4802
|
+
await handleFileTranslation(translationService, input3, options);
|
|
4803
4803
|
break;
|
|
4804
4804
|
case "folder":
|
|
4805
|
-
await handleFolderTranslation(translationService,
|
|
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 (
|
|
4883
|
-
await handleTranslate(
|
|
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(
|
|
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(
|
|
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(
|
|
4962
|
-
return bcrypt.hash(
|
|
4961
|
+
async hashBcrypt(input3, rounds = 10) {
|
|
4962
|
+
return bcrypt.hash(input3, rounds);
|
|
4963
4963
|
}
|
|
4964
4964
|
/**
|
|
4965
4965
|
* Base64 encode
|
|
4966
4966
|
*/
|
|
4967
|
-
base64Encode(
|
|
4968
|
-
const buffer = typeof
|
|
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(
|
|
4979
|
-
let normalized =
|
|
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(
|
|
5109
|
-
return full ? encodeURI(
|
|
5108
|
+
urlEncode(input3, full = false) {
|
|
5109
|
+
return full ? encodeURI(input3) : encodeURIComponent(input3);
|
|
5110
5110
|
}
|
|
5111
5111
|
/**
|
|
5112
5112
|
* URL decode
|
|
5113
5113
|
*/
|
|
5114
|
-
urlDecode(
|
|
5115
|
-
return full ? decodeURI(
|
|
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(
|
|
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 (!
|
|
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(
|
|
5241
|
+
hash = await service.hashBcrypt(input3, options.rounds);
|
|
5242
5242
|
} else {
|
|
5243
|
-
hash = await service.hash(
|
|
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 (
|
|
5277
|
-
await handleHashGeneration(
|
|
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(
|
|
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 (!
|
|
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(
|
|
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 (
|
|
5326
|
-
await handleBase64Encode(
|
|
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(
|
|
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 (!
|
|
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 =
|
|
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 (
|
|
5371
|
-
await handleBase64Decode(
|
|
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(
|
|
5522
|
+
async function handleUnixTime(input3, options) {
|
|
5523
5523
|
const service = new UtilsService();
|
|
5524
5524
|
try {
|
|
5525
|
-
if (!
|
|
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(
|
|
5536
|
-
const timestamp = parseInt(
|
|
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(
|
|
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: ${
|
|
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 (
|
|
5578
|
-
await handleUnixTime(
|
|
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(
|
|
5635
|
+
async function handleUrlEncode(input3, options) {
|
|
5636
5636
|
const service = new UtilsService();
|
|
5637
5637
|
try {
|
|
5638
|
-
const encoded = service.urlEncode(
|
|
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 (
|
|
5662
|
-
await handleUrlEncode(
|
|
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(
|
|
5669
|
+
async function handleUrlDecode(input3, options) {
|
|
5670
5670
|
const service = new UtilsService();
|
|
5671
5671
|
try {
|
|
5672
|
-
const decoded = service.urlDecode(
|
|
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 (
|
|
5696
|
-
await handleUrlDecode(
|
|
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((
|
|
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 (
|
|
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((
|
|
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 (
|
|
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((
|
|
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 (
|
|
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 [
|
|
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((
|
|
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 (
|
|
6112
|
+
} else if (input4 === "c" && result) {
|
|
6113
6113
|
handleCopy();
|
|
6114
6114
|
}
|
|
6115
6115
|
});
|
|
6116
6116
|
const handleConvert = () => {
|
|
6117
|
-
if (!
|
|
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(
|
|
6124
|
+
const encoded = service.base64Encode(input3, urlSafe);
|
|
6125
6125
|
setResult(encoded);
|
|
6126
6126
|
} else {
|
|
6127
|
-
const decoded = service.base64Decode(
|
|
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:
|
|
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 [
|
|
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((
|
|
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 (
|
|
6222
|
+
} else if (input4 === "c" && result) {
|
|
6223
6223
|
handleCopy();
|
|
6224
6224
|
}
|
|
6225
6225
|
});
|
|
6226
6226
|
const handleConvert = () => {
|
|
6227
|
-
if (!
|
|
6227
|
+
if (!input3) return;
|
|
6228
6228
|
if (mode === "encode") {
|
|
6229
|
-
const encoded = fullUrl ? service.urlEncode(
|
|
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(
|
|
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:
|
|
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 [
|
|
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((
|
|
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 (
|
|
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 (!
|
|
6332
|
+
if (!input3) {
|
|
6333
6333
|
setError("Please enter a timestamp");
|
|
6334
6334
|
return;
|
|
6335
6335
|
}
|
|
6336
|
-
const human = service.unixTimeToHuman(parseInt(
|
|
6336
|
+
const human = service.unixTimeToHuman(parseInt(input3, 10), format);
|
|
6337
6337
|
setResult(human);
|
|
6338
6338
|
} else {
|
|
6339
|
-
if (!
|
|
6339
|
+
if (!input3) {
|
|
6340
6340
|
setError("Please enter a date string");
|
|
6341
6341
|
return;
|
|
6342
6342
|
}
|
|
6343
|
-
const timestamp = service.unixTimeFromString(
|
|
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:
|
|
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: !
|
|
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((
|
|
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 (
|
|
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((
|
|
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 (
|
|
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((
|
|
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 (
|
|
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((
|
|
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 (
|
|
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((
|
|
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((
|
|
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 ||
|
|
7071
|
+
if (key.upArrow || input3 === "k") {
|
|
7072
7072
|
setSelectedIndex((prev) => prev > 0 ? prev - 1 : MENU_ITEMS2.length - 1);
|
|
7073
|
-
} else if (key.downArrow ||
|
|
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 (
|
|
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/
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
8191
|
-
import { confirm as
|
|
8192
|
-
import { join as
|
|
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
|
|
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:
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
9188
|
-
import { promises as
|
|
9189
|
-
import { join as
|
|
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
|
|
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 =
|
|
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 =
|
|
9582
|
+
const projectJai1 = join10(process.cwd(), ".jai1");
|
|
9239
9583
|
try {
|
|
9240
|
-
await
|
|
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
|
|
9249
|
-
import { confirm as
|
|
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
|
|
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
|
|
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
|
|
9401
|
-
import { confirm as
|
|
9744
|
+
import { Command as Command47 } from "commander";
|
|
9745
|
+
import { confirm as confirm9 } from "@inquirer/prompts";
|
|
9402
9746
|
function createClearBackupsCommand() {
|
|
9403
|
-
return new
|
|
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
|
|
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
|
|
9429
|
-
import { checkbox as checkbox5, confirm as
|
|
9430
|
-
import
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
10083
|
+
import { Command as Command49 } from "commander";
|
|
9740
10084
|
function createGuideCommand() {
|
|
9741
|
-
const cmd = new
|
|
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
|
|
10102
|
+
import { Command as Command50 } from "commander";
|
|
9759
10103
|
function createContextCommand() {
|
|
9760
|
-
const cmd = new
|
|
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
|
|
9838
|
-
import { checkbox as checkbox6, confirm as
|
|
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
|
|
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
|
|
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
|
|
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
|
|
10317
|
+
var redmineCommand = new Command52("redmine").description("Redmine context sync commands");
|
|
9973
10318
|
redmineCommand.addCommand(createRedmineCheckCommand());
|
|
9974
|
-
var syncCommand = new
|
|
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");
|