@jvittechs/jai1-cli 1.0.4 → 1.0.6
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 +1160 -773
- 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 Command62 } 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: "1.0.
|
|
36
|
+
version: "1.0.6",
|
|
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: {
|
|
@@ -1419,7 +1419,6 @@ var UnifiedApplyApp = ({
|
|
|
1419
1419
|
const [cursorIndex, setCursorIndex] = useState(0);
|
|
1420
1420
|
const [focusArea, setFocusArea] = useState("packages");
|
|
1421
1421
|
const [selectedPackageIndex, setSelectedPackageIndex] = useState(0);
|
|
1422
|
-
const [activePackageFilter, setActivePackageFilter] = useState(null);
|
|
1423
1422
|
const [installProgress, setInstallProgress] = useState([]);
|
|
1424
1423
|
const [installStats, setInstallStats] = useState({ total: 0, completed: 0, added: 0, updated: 0, failed: 0 });
|
|
1425
1424
|
const [availableIdes, setAvailableIdes] = useState([]);
|
|
@@ -1439,9 +1438,7 @@ var UnifiedApplyApp = ({
|
|
|
1439
1438
|
setComponents(comps);
|
|
1440
1439
|
setTags(tagList);
|
|
1441
1440
|
setInstalledPaths(new Set(Object.keys(installed)));
|
|
1442
|
-
|
|
1443
|
-
setActivePackageFilter(tagList[0].tag);
|
|
1444
|
-
}
|
|
1441
|
+
setSelectedPackageIndex(0);
|
|
1445
1442
|
setLoading(false);
|
|
1446
1443
|
} catch (err) {
|
|
1447
1444
|
setError(err instanceof Error ? err.message : "Failed to load");
|
|
@@ -1451,18 +1448,27 @@ var UnifiedApplyApp = ({
|
|
|
1451
1448
|
loadData();
|
|
1452
1449
|
setAvailableIdes(getMigrationIDEs());
|
|
1453
1450
|
}, []);
|
|
1451
|
+
const packageOptions = useMemo(() => {
|
|
1452
|
+
const allCount = components.length;
|
|
1453
|
+
return [
|
|
1454
|
+
{ tag: "All", count: allCount },
|
|
1455
|
+
...tags
|
|
1456
|
+
];
|
|
1457
|
+
}, [tags, components]);
|
|
1454
1458
|
const filteredComponents = useMemo(() => {
|
|
1455
|
-
|
|
1456
|
-
|
|
1459
|
+
let filtered = components;
|
|
1460
|
+
const selectedPackage2 = packageOptions[selectedPackageIndex];
|
|
1461
|
+
if (selectedPackage2 && selectedPackage2.tag !== "All") {
|
|
1462
|
+
filtered = filtered.filter((c) => c.tags?.includes(selectedPackage2.tag));
|
|
1457
1463
|
}
|
|
1458
1464
|
if (searchQuery.trim()) {
|
|
1459
1465
|
const query = searchQuery.toLowerCase();
|
|
1460
|
-
|
|
1466
|
+
filtered = filtered.filter(
|
|
1461
1467
|
(c) => c.filepath.toLowerCase().includes(query) || c.tags?.some((t) => t.toLowerCase().includes(query))
|
|
1462
1468
|
);
|
|
1463
1469
|
}
|
|
1464
|
-
return
|
|
1465
|
-
}, [components,
|
|
1470
|
+
return filtered;
|
|
1471
|
+
}, [components, packageOptions, selectedPackageIndex, searchQuery]);
|
|
1466
1472
|
useInput((input5, key) => {
|
|
1467
1473
|
if (viewState === "done") {
|
|
1468
1474
|
if (key.return || input5 === "q" && key.ctrl || key.escape) {
|
|
@@ -1517,14 +1523,18 @@ var UnifiedApplyApp = ({
|
|
|
1517
1523
|
}
|
|
1518
1524
|
if (key.tab) {
|
|
1519
1525
|
if (focusArea === "packages") {
|
|
1520
|
-
setFocusArea("components");
|
|
1521
|
-
} else if (focusArea === "components") {
|
|
1522
1526
|
setFocusArea("search");
|
|
1523
|
-
|
|
1527
|
+
} else if (focusArea === "search") {
|
|
1528
|
+
setFocusArea("packages");
|
|
1524
1529
|
} else {
|
|
1525
1530
|
setFocusArea("packages");
|
|
1526
|
-
|
|
1527
|
-
|
|
1531
|
+
}
|
|
1532
|
+
return;
|
|
1533
|
+
}
|
|
1534
|
+
if (key.downArrow && (focusArea === "packages" || focusArea === "search")) {
|
|
1535
|
+
if (filteredComponents.length > 0) {
|
|
1536
|
+
setFocusArea("components");
|
|
1537
|
+
setCursorIndex(0);
|
|
1528
1538
|
}
|
|
1529
1539
|
return;
|
|
1530
1540
|
}
|
|
@@ -1553,6 +1563,10 @@ var UnifiedApplyApp = ({
|
|
|
1553
1563
|
}
|
|
1554
1564
|
if (focusArea === "components") {
|
|
1555
1565
|
if (key.upArrow) {
|
|
1566
|
+
if (cursorIndex === 0) {
|
|
1567
|
+
setFocusArea("packages");
|
|
1568
|
+
return;
|
|
1569
|
+
}
|
|
1556
1570
|
setCursorIndex((prev) => Math.max(0, prev - 1));
|
|
1557
1571
|
} else if (key.downArrow) {
|
|
1558
1572
|
setCursorIndex((prev) => Math.min(filteredComponents.length - 1, prev + 1));
|
|
@@ -1573,29 +1587,17 @@ var UnifiedApplyApp = ({
|
|
|
1573
1587
|
}
|
|
1574
1588
|
if (focusArea === "packages") {
|
|
1575
1589
|
if (key.leftArrow) {
|
|
1576
|
-
setSelectedPackageIndex((prev) =>
|
|
1577
|
-
|
|
1578
|
-
const tag = tags[newIndex];
|
|
1579
|
-
if (tag) setActivePackageFilter(tag.tag);
|
|
1580
|
-
return newIndex;
|
|
1581
|
-
});
|
|
1590
|
+
setSelectedPackageIndex((prev) => Math.max(0, prev - 1));
|
|
1591
|
+
setCursorIndex(0);
|
|
1582
1592
|
} else if (key.rightArrow) {
|
|
1583
|
-
setSelectedPackageIndex((prev) =>
|
|
1584
|
-
|
|
1585
|
-
const tag = tags[newIndex];
|
|
1586
|
-
if (tag) setActivePackageFilter(tag.tag);
|
|
1587
|
-
return newIndex;
|
|
1588
|
-
});
|
|
1593
|
+
setSelectedPackageIndex((prev) => Math.min(packageOptions.length - 1, prev + 1));
|
|
1594
|
+
setCursorIndex(0);
|
|
1589
1595
|
} else if (input5 === " " || key.return) {
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
packageComponents.forEach((c) => next.add(c.filepath));
|
|
1596
|
-
return next;
|
|
1597
|
-
});
|
|
1598
|
-
}
|
|
1596
|
+
setSelectedPaths((prev) => {
|
|
1597
|
+
const next = new Set(prev);
|
|
1598
|
+
filteredComponents.forEach((c) => next.add(c.filepath));
|
|
1599
|
+
return next;
|
|
1600
|
+
});
|
|
1599
1601
|
}
|
|
1600
1602
|
}
|
|
1601
1603
|
});
|
|
@@ -1708,33 +1710,35 @@ var UnifiedApplyApp = ({
|
|
|
1708
1710
|
}
|
|
1709
1711
|
const visibleComponents = filteredComponents.slice(0, 12);
|
|
1710
1712
|
const hasMore = filteredComponents.length > 12;
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
placeholder: "Type to filter..."
|
|
1717
|
-
}
|
|
1718
|
-
) : /* @__PURE__ */ React3.createElement(Text3, null, searchQuery || /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, "Press Tab to search"))), /* @__PURE__ */ React3.createElement(Box2, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React3.createElement(Text3, { bold: true, dimColor: true }, "Quick Apply (Packages):"), /* @__PURE__ */ React3.createElement(Box2, { marginTop: 1, flexWrap: "wrap" }, tags.map((tag, i) => {
|
|
1719
|
-
const isSelected = focusArea === "packages" && i === selectedPackageIndex;
|
|
1720
|
-
return /* @__PURE__ */ React3.createElement(Box2, { key: tag.tag, marginRight: 1 }, /* @__PURE__ */ React3.createElement(
|
|
1713
|
+
const selectedPackage = packageOptions[selectedPackageIndex];
|
|
1714
|
+
return /* @__PURE__ */ React3.createElement(Box2, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React3.createElement(Box2, { marginBottom: 1 }, /* @__PURE__ */ React3.createElement(Text3, { bold: true, color: "cyan" }, "\u{1F4E6} Jai1 Apply"), selectedPaths.size > 0 && /* @__PURE__ */ React3.createElement(Text3, { color: "green" }, " [", selectedPaths.size, " selected]")), /* @__PURE__ */ React3.createElement(Box2, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React3.createElement(Box2, null, /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, "\u{1F4C1} "), packageOptions.map((pkg, i) => {
|
|
1715
|
+
const isActive = i === selectedPackageIndex;
|
|
1716
|
+
const isFocused = focusArea === "packages" && isActive;
|
|
1717
|
+
return /* @__PURE__ */ React3.createElement(Box2, { key: pkg.tag, marginRight: 1 }, /* @__PURE__ */ React3.createElement(
|
|
1721
1718
|
Text3,
|
|
1722
1719
|
{
|
|
1723
|
-
backgroundColor:
|
|
1724
|
-
color:
|
|
1720
|
+
backgroundColor: isFocused ? "cyan" : isActive ? "gray" : void 0,
|
|
1721
|
+
color: isFocused ? "black" : isActive ? "white" : "gray"
|
|
1725
1722
|
},
|
|
1726
1723
|
"[",
|
|
1727
|
-
|
|
1724
|
+
pkg.tag,
|
|
1728
1725
|
":",
|
|
1729
|
-
|
|
1726
|
+
pkg.count,
|
|
1730
1727
|
"]"
|
|
1731
1728
|
));
|
|
1732
|
-
})),
|
|
1729
|
+
})), /* @__PURE__ */ React3.createElement(Box2, { marginTop: 1 }, /* @__PURE__ */ React3.createElement(Text3, { color: focusArea === "search" ? "cyan" : "gray" }, "\u{1F50D} "), focusArea === "search" ? /* @__PURE__ */ React3.createElement(
|
|
1730
|
+
TextInput,
|
|
1731
|
+
{
|
|
1732
|
+
value: searchQuery,
|
|
1733
|
+
onChange: setSearchQuery,
|
|
1734
|
+
placeholder: "Type to filter..."
|
|
1735
|
+
}
|
|
1736
|
+
) : /* @__PURE__ */ React3.createElement(Text3, null, searchQuery || /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, "Tab to search")))), /* @__PURE__ */ React3.createElement(Box2, { flexDirection: "column", borderStyle: "round", borderColor: focusArea === "components" ? "cyan" : "gray", padding: 1 }, /* @__PURE__ */ React3.createElement(Box2, { marginBottom: 1 }, /* @__PURE__ */ React3.createElement(Text3, { bold: true }, "Components "), selectedPackage && selectedPackage.tag !== "All" && /* @__PURE__ */ React3.createElement(Text3, { color: "cyan" }, "[", selectedPackage.tag, "] "), searchQuery && /* @__PURE__ */ React3.createElement(Text3, { color: "yellow" }, '"', searchQuery, '" '), /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, "(", filteredComponents.length, " shown", hasMore ? `, \u2193 for more` : "", ")")), visibleComponents.map((comp, i) => {
|
|
1733
1737
|
const isCursor = i === cursorIndex && focusArea === "components";
|
|
1734
1738
|
const isChecked = selectedPaths.has(comp.filepath);
|
|
1735
1739
|
const isInstalled = installedPaths.has(comp.filepath);
|
|
1736
|
-
return /* @__PURE__ */ React3.createElement(Box2, { key: comp.filepath }, /* @__PURE__ */ React3.createElement(Text3, { color: isCursor ? "cyan" : "white" }, isCursor ? "\u276F " : " ", isChecked ? "[\u2713]" : "[ ]", " ", comp.filepath), /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, " ", isInstalled ? "\u2713
|
|
1737
|
-
}), filteredComponents.length === 0 && /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, "No components match your
|
|
1740
|
+
return /* @__PURE__ */ React3.createElement(Box2, { key: comp.filepath }, /* @__PURE__ */ React3.createElement(Text3, { color: isCursor ? "cyan" : "white" }, isCursor ? "\u276F " : " ", isChecked ? "[\u2713]" : "[ ]", " ", comp.filepath), /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, " ", isInstalled ? "\u2713" : "\u25CB"));
|
|
1741
|
+
}), filteredComponents.length === 0 && /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, "No components match your filter")), selectedPaths.size > 0 && /* @__PURE__ */ React3.createElement(Box2, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React3.createElement(Text3, { bold: true }, "Selected: ", selectedPaths.size, " components"), /* @__PURE__ */ React3.createElement(Box2, { flexDirection: "column", marginLeft: 2 }, Array.from(selectedPaths).slice(0, 3).map((fp) => /* @__PURE__ */ React3.createElement(Text3, { key: fp, dimColor: true }, "\u{1F4CC} ", fp)), selectedPaths.size > 3 && /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, " ... +", selectedPaths.size - 3, " more"))), /* @__PURE__ */ React3.createElement(Box2, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 1 }, /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, focusArea === "packages" && "[\u2190\u2192] Package \xB7 [\u2193] List \xB7 [\u2423] Select all", focusArea === "search" && "Type to filter \xB7 [\u2193] List", focusArea === "components" && "[\u2191\u2193] Navigate \xB7 [\u2423] Toggle", " \xB7 [Tab] Switch \xB7 [A] All \xB7 [C] Clear \xB7 [Enter] Apply")));
|
|
1738
1742
|
};
|
|
1739
1743
|
|
|
1740
1744
|
// src/commands/apply.ts
|
|
@@ -1816,12 +1820,394 @@ async function nonInteractiveApply(config, items, options) {
|
|
|
1816
1820
|
\u{1F4A1} Next step: Run "jai1 ide sync" to sync content to your IDE(s)`);
|
|
1817
1821
|
}
|
|
1818
1822
|
|
|
1819
|
-
// src/commands/
|
|
1823
|
+
// src/commands/apply-new.ts
|
|
1824
|
+
import React6 from "react";
|
|
1825
|
+
import { render as render2 } from "ink";
|
|
1820
1826
|
import { Command as Command4 } from "commander";
|
|
1827
|
+
|
|
1828
|
+
// src/ui/apply/TwoPaneApplyApp.tsx
|
|
1829
|
+
import React5, { useState as useState2, useEffect as useEffect2, useMemo as useMemo2 } from "react";
|
|
1830
|
+
import { Box as Box3, Text as Text4, useInput as useInput2, useApp as useApp2 } from "ink";
|
|
1831
|
+
import Spinner2 from "ink-spinner";
|
|
1832
|
+
import TextInput2 from "ink-text-input";
|
|
1833
|
+
var TwoPaneApplyApp = ({
|
|
1834
|
+
config,
|
|
1835
|
+
force = false,
|
|
1836
|
+
onExit
|
|
1837
|
+
}) => {
|
|
1838
|
+
const { exit } = useApp2();
|
|
1839
|
+
const [viewState, setViewState] = useState2("browse");
|
|
1840
|
+
const [components, setComponents] = useState2([]);
|
|
1841
|
+
const [tags, setTags] = useState2([]);
|
|
1842
|
+
const [installedPaths, setInstalledPaths] = useState2(/* @__PURE__ */ new Set());
|
|
1843
|
+
const [loading, setLoading] = useState2(true);
|
|
1844
|
+
const [error, setError] = useState2(null);
|
|
1845
|
+
const [activePane, setActivePane] = useState2("packages");
|
|
1846
|
+
const [searchQuery, setSearchQuery] = useState2("");
|
|
1847
|
+
const [isSearchFocused, setIsSearchFocused] = useState2(false);
|
|
1848
|
+
const [selectedPaths, setSelectedPaths] = useState2(/* @__PURE__ */ new Set());
|
|
1849
|
+
const [packageCursorIndex, setPackageCursorIndex] = useState2(0);
|
|
1850
|
+
const [componentCursorIndex, setComponentCursorIndex] = useState2(0);
|
|
1851
|
+
const [installProgress, setInstallProgress] = useState2([]);
|
|
1852
|
+
const [installStats, setInstallStats] = useState2({ total: 0, completed: 0, added: 0, updated: 0, failed: 0 });
|
|
1853
|
+
const [availableIdes, setAvailableIdes] = useState2([]);
|
|
1854
|
+
const [selectedIdes, setSelectedIdes] = useState2(/* @__PURE__ */ new Set());
|
|
1855
|
+
const [ideCursorIndex, setIdeCursorIndex] = useState2(0);
|
|
1856
|
+
const [syncProgress, setSyncProgress] = useState2([]);
|
|
1857
|
+
const [syncStats, setSyncStats] = useState2({ total: 0, completed: 0, created: 0, updated: 0, skipped: 0, errors: 0 });
|
|
1858
|
+
const service = new ComponentsService();
|
|
1859
|
+
const packageOptions = useMemo2(() => {
|
|
1860
|
+
return [
|
|
1861
|
+
{ tag: "All", count: components.length },
|
|
1862
|
+
...tags
|
|
1863
|
+
];
|
|
1864
|
+
}, [tags, components]);
|
|
1865
|
+
useEffect2(() => {
|
|
1866
|
+
const loadData = async () => {
|
|
1867
|
+
try {
|
|
1868
|
+
const [comps, tagList, installed] = await Promise.all([
|
|
1869
|
+
service.list(config),
|
|
1870
|
+
service.listTags(config),
|
|
1871
|
+
service.getInstalled()
|
|
1872
|
+
]);
|
|
1873
|
+
setComponents(comps);
|
|
1874
|
+
setTags(tagList);
|
|
1875
|
+
setInstalledPaths(new Set(Object.keys(installed)));
|
|
1876
|
+
setLoading(false);
|
|
1877
|
+
} catch (err) {
|
|
1878
|
+
setError(err instanceof Error ? err.message : "Failed to load");
|
|
1879
|
+
setLoading(false);
|
|
1880
|
+
}
|
|
1881
|
+
};
|
|
1882
|
+
loadData();
|
|
1883
|
+
setAvailableIdes(getMigrationIDEs());
|
|
1884
|
+
}, []);
|
|
1885
|
+
const filteredComponents = useMemo2(() => {
|
|
1886
|
+
let filtered = components;
|
|
1887
|
+
const selectedPackage2 = packageOptions[packageCursorIndex];
|
|
1888
|
+
if (selectedPackage2 && selectedPackage2.tag !== "All") {
|
|
1889
|
+
filtered = filtered.filter((c) => c.tags?.includes(selectedPackage2.tag));
|
|
1890
|
+
}
|
|
1891
|
+
if (searchQuery.trim()) {
|
|
1892
|
+
const query = searchQuery.toLowerCase();
|
|
1893
|
+
filtered = filtered.filter(
|
|
1894
|
+
(c) => c.filepath.toLowerCase().includes(query) || c.tags?.some((t) => t.toLowerCase().includes(query))
|
|
1895
|
+
);
|
|
1896
|
+
}
|
|
1897
|
+
return filtered;
|
|
1898
|
+
}, [components, packageOptions, packageCursorIndex, searchQuery]);
|
|
1899
|
+
useEffect2(() => {
|
|
1900
|
+
setComponentCursorIndex(0);
|
|
1901
|
+
}, [packageCursorIndex, searchQuery]);
|
|
1902
|
+
useInput2((input5, key) => {
|
|
1903
|
+
if (viewState === "done") {
|
|
1904
|
+
if (key.return || input5 === "q" && key.ctrl || key.escape) {
|
|
1905
|
+
onExit();
|
|
1906
|
+
}
|
|
1907
|
+
return;
|
|
1908
|
+
}
|
|
1909
|
+
if (viewState === "summary") {
|
|
1910
|
+
if (key.return) {
|
|
1911
|
+
setViewState("ide-sync");
|
|
1912
|
+
} else if (input5 === "s" || input5 === "q" && key.ctrl || key.escape) {
|
|
1913
|
+
onExit();
|
|
1914
|
+
}
|
|
1915
|
+
return;
|
|
1916
|
+
}
|
|
1917
|
+
if (viewState === "ide-sync") {
|
|
1918
|
+
if (key.upArrow) {
|
|
1919
|
+
setIdeCursorIndex((prev) => Math.max(0, prev - 1));
|
|
1920
|
+
} else if (key.downArrow) {
|
|
1921
|
+
setIdeCursorIndex((prev) => Math.min(availableIdes.length - 1, prev + 1));
|
|
1922
|
+
} else if (input5 === " ") {
|
|
1923
|
+
const ide = availableIdes[ideCursorIndex];
|
|
1924
|
+
if (ide) {
|
|
1925
|
+
setSelectedIdes((prev) => {
|
|
1926
|
+
const next = new Set(prev);
|
|
1927
|
+
if (next.has(ide)) next.delete(ide);
|
|
1928
|
+
else next.add(ide);
|
|
1929
|
+
return next;
|
|
1930
|
+
});
|
|
1931
|
+
}
|
|
1932
|
+
} else if (input5 === "a") {
|
|
1933
|
+
setSelectedIdes(new Set(availableIdes));
|
|
1934
|
+
} else if (input5 === "c") {
|
|
1935
|
+
setSelectedIdes(/* @__PURE__ */ new Set());
|
|
1936
|
+
} else if (key.return && selectedIdes.size > 0) {
|
|
1937
|
+
handleIdeSync();
|
|
1938
|
+
} else if (input5 === "s" || input5 === "q" && key.ctrl || key.escape) {
|
|
1939
|
+
onExit();
|
|
1940
|
+
}
|
|
1941
|
+
return;
|
|
1942
|
+
}
|
|
1943
|
+
if (viewState === "syncing" || viewState === "installing") {
|
|
1944
|
+
return;
|
|
1945
|
+
}
|
|
1946
|
+
if (key.escape || input5 === "q" && key.ctrl) {
|
|
1947
|
+
onExit();
|
|
1948
|
+
return;
|
|
1949
|
+
}
|
|
1950
|
+
if (input5 === "/") {
|
|
1951
|
+
setIsSearchFocused(true);
|
|
1952
|
+
setActivePane("components");
|
|
1953
|
+
return;
|
|
1954
|
+
}
|
|
1955
|
+
if (key.leftArrow && activePane === "components") {
|
|
1956
|
+
setActivePane("packages");
|
|
1957
|
+
return;
|
|
1958
|
+
}
|
|
1959
|
+
if (key.rightArrow && activePane === "packages") {
|
|
1960
|
+
setActivePane("components");
|
|
1961
|
+
return;
|
|
1962
|
+
}
|
|
1963
|
+
if (key.tab) {
|
|
1964
|
+
setActivePane(activePane === "packages" ? "components" : "packages");
|
|
1965
|
+
return;
|
|
1966
|
+
}
|
|
1967
|
+
if (key.return && selectedPaths.size > 0) {
|
|
1968
|
+
handleApply();
|
|
1969
|
+
return;
|
|
1970
|
+
}
|
|
1971
|
+
if (input5 === "a") {
|
|
1972
|
+
setSelectedPaths((prev) => {
|
|
1973
|
+
const next = new Set(prev);
|
|
1974
|
+
filteredComponents.forEach((c) => next.add(c.filepath));
|
|
1975
|
+
return next;
|
|
1976
|
+
});
|
|
1977
|
+
return;
|
|
1978
|
+
}
|
|
1979
|
+
if (input5 === "c") {
|
|
1980
|
+
setSelectedPaths(/* @__PURE__ */ new Set());
|
|
1981
|
+
return;
|
|
1982
|
+
}
|
|
1983
|
+
if (activePane === "packages") {
|
|
1984
|
+
if (key.upArrow) {
|
|
1985
|
+
setPackageCursorIndex((prev) => Math.max(0, prev - 1));
|
|
1986
|
+
} else if (key.downArrow) {
|
|
1987
|
+
setPackageCursorIndex((prev) => Math.min(packageOptions.length - 1, prev + 1));
|
|
1988
|
+
} else if (input5 === " ") {
|
|
1989
|
+
setSelectedPaths((prev) => {
|
|
1990
|
+
const next = new Set(prev);
|
|
1991
|
+
filteredComponents.forEach((c) => next.add(c.filepath));
|
|
1992
|
+
return next;
|
|
1993
|
+
});
|
|
1994
|
+
}
|
|
1995
|
+
}
|
|
1996
|
+
if (activePane === "components") {
|
|
1997
|
+
if (key.upArrow) {
|
|
1998
|
+
setComponentCursorIndex((prev) => Math.max(0, prev - 1));
|
|
1999
|
+
} else if (key.downArrow) {
|
|
2000
|
+
setComponentCursorIndex((prev) => Math.min(filteredComponents.length - 1, prev + 1));
|
|
2001
|
+
} else if (input5 === " ") {
|
|
2002
|
+
const current = filteredComponents[componentCursorIndex];
|
|
2003
|
+
if (current) {
|
|
2004
|
+
setSelectedPaths((prev) => {
|
|
2005
|
+
const next = new Set(prev);
|
|
2006
|
+
if (next.has(current.filepath)) next.delete(current.filepath);
|
|
2007
|
+
else next.add(current.filepath);
|
|
2008
|
+
return next;
|
|
2009
|
+
});
|
|
2010
|
+
}
|
|
2011
|
+
}
|
|
2012
|
+
}
|
|
2013
|
+
}, { isActive: !isSearchFocused });
|
|
2014
|
+
useInput2((input5, key) => {
|
|
2015
|
+
if (key.escape) {
|
|
2016
|
+
setIsSearchFocused(false);
|
|
2017
|
+
return;
|
|
2018
|
+
}
|
|
2019
|
+
if (key.return) {
|
|
2020
|
+
setIsSearchFocused(false);
|
|
2021
|
+
return;
|
|
2022
|
+
}
|
|
2023
|
+
if (key.downArrow && filteredComponents.length > 0) {
|
|
2024
|
+
setIsSearchFocused(false);
|
|
2025
|
+
setComponentCursorIndex(0);
|
|
2026
|
+
return;
|
|
2027
|
+
}
|
|
2028
|
+
}, { isActive: isSearchFocused });
|
|
2029
|
+
const handleApply = async () => {
|
|
2030
|
+
setViewState("installing");
|
|
2031
|
+
const targetDir = process.cwd() + "/.jai1";
|
|
2032
|
+
const pathsToInstall = Array.from(selectedPaths);
|
|
2033
|
+
const resolvedPaths = await service.resolveWithDependencies(config, pathsToInstall);
|
|
2034
|
+
const installed = await service.getInstalled();
|
|
2035
|
+
const initialProgress = resolvedPaths.map((fp) => ({
|
|
2036
|
+
filepath: fp,
|
|
2037
|
+
status: "pending"
|
|
2038
|
+
}));
|
|
2039
|
+
setInstallProgress(initialProgress);
|
|
2040
|
+
setInstallStats({ total: resolvedPaths.length, completed: 0, added: 0, updated: 0, failed: 0 });
|
|
2041
|
+
let added = 0, updated = 0, failed = 0;
|
|
2042
|
+
for (let i = 0; i < resolvedPaths.length; i++) {
|
|
2043
|
+
const fp = resolvedPaths[i];
|
|
2044
|
+
setInstallProgress((prev) => prev.map(
|
|
2045
|
+
(p) => p.filepath === fp ? { ...p, status: "downloading" } : p
|
|
2046
|
+
));
|
|
2047
|
+
try {
|
|
2048
|
+
const info = installed[fp];
|
|
2049
|
+
if (info && !force && info.modified) {
|
|
2050
|
+
setInstallProgress((prev) => prev.map(
|
|
2051
|
+
(p) => p.filepath === fp ? { ...p, status: "error", error: "Modified locally" } : p
|
|
2052
|
+
));
|
|
2053
|
+
failed++;
|
|
2054
|
+
} else {
|
|
2055
|
+
await service.install(config, fp, targetDir);
|
|
2056
|
+
setInstallProgress((prev) => prev.map(
|
|
2057
|
+
(p) => p.filepath === fp ? { ...p, status: "success" } : p
|
|
2058
|
+
));
|
|
2059
|
+
if (info) updated++;
|
|
2060
|
+
else added++;
|
|
2061
|
+
}
|
|
2062
|
+
} catch (err) {
|
|
2063
|
+
setInstallProgress((prev) => prev.map(
|
|
2064
|
+
(p) => p.filepath === fp ? { ...p, status: "error", error: err instanceof Error ? err.message : "Error" } : p
|
|
2065
|
+
));
|
|
2066
|
+
failed++;
|
|
2067
|
+
}
|
|
2068
|
+
setInstallStats({ total: resolvedPaths.length, completed: i + 1, added, updated, failed });
|
|
2069
|
+
}
|
|
2070
|
+
setViewState("summary");
|
|
2071
|
+
};
|
|
2072
|
+
const handleIdeSync = async () => {
|
|
2073
|
+
setViewState("syncing");
|
|
2074
|
+
const migrateService = new MigrateIdeService();
|
|
2075
|
+
const content = await migrateService.scanJai1Content();
|
|
2076
|
+
if (content.totalCount === 0) {
|
|
2077
|
+
setSyncStats({ total: 0, completed: 0, created: 0, updated: 0, skipped: 0, errors: 0 });
|
|
2078
|
+
setViewState("done");
|
|
2079
|
+
return;
|
|
2080
|
+
}
|
|
2081
|
+
const selectedIdeList = Array.from(selectedIdes);
|
|
2082
|
+
const contentTypes = ["rules", "workflows"];
|
|
2083
|
+
const totalItems = contentTypes.reduce((sum, type) => {
|
|
2084
|
+
return sum + (type === "rules" ? content.rules.length : type === "workflows" ? content.workflows.length : content.commands.length);
|
|
2085
|
+
}, 0);
|
|
2086
|
+
const totalFiles = totalItems * selectedIdeList.length;
|
|
2087
|
+
setSyncStats({ total: totalFiles, completed: 0, created: 0, updated: 0, skipped: 0, errors: 0 });
|
|
2088
|
+
let created = 0, updated = 0, skipped = 0, errors = 0;
|
|
2089
|
+
let completed = 0;
|
|
2090
|
+
await migrateService.migrate(
|
|
2091
|
+
selectedIdeList,
|
|
2092
|
+
contentTypes,
|
|
2093
|
+
content,
|
|
2094
|
+
(result) => {
|
|
2095
|
+
completed++;
|
|
2096
|
+
if (result.status === "created") created++;
|
|
2097
|
+
else if (result.status === "updated") updated++;
|
|
2098
|
+
else if (result.status === "skipped") skipped++;
|
|
2099
|
+
else if (result.status === "error") errors++;
|
|
2100
|
+
setSyncProgress((prev) => [...prev.slice(-7), {
|
|
2101
|
+
targetPath: result.targetPath || result.source.relativePath,
|
|
2102
|
+
status: result.status === "error" ? "error" : "success",
|
|
2103
|
+
error: result.error
|
|
2104
|
+
}]);
|
|
2105
|
+
setSyncStats({ total: totalFiles, completed, created, updated, skipped, errors });
|
|
2106
|
+
}
|
|
2107
|
+
);
|
|
2108
|
+
setViewState("done");
|
|
2109
|
+
};
|
|
2110
|
+
if (loading) {
|
|
2111
|
+
return /* @__PURE__ */ React5.createElement(Box3, { padding: 1 }, /* @__PURE__ */ React5.createElement(Text4, { color: "cyan" }, /* @__PURE__ */ React5.createElement(Spinner2, { type: "dots" }), " Loading components..."));
|
|
2112
|
+
}
|
|
2113
|
+
if (error) {
|
|
2114
|
+
return /* @__PURE__ */ React5.createElement(Box3, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React5.createElement(Text4, { color: "red" }, "\u274C Error: ", error), /* @__PURE__ */ React5.createElement(Text4, { dimColor: true }, "Press Ctrl+Q to exit"));
|
|
2115
|
+
}
|
|
2116
|
+
if (viewState === "installing") {
|
|
2117
|
+
return /* @__PURE__ */ React5.createElement(Box3, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React5.createElement(Box3, { marginBottom: 1 }, /* @__PURE__ */ React5.createElement(Text4, { bold: true, color: "cyan" }, "\u{1F4E6} Installing Components")), /* @__PURE__ */ React5.createElement(Box3, { marginBottom: 1 }, /* @__PURE__ */ React5.createElement(ProgressBar, { current: installStats.completed, total: installStats.total, width: 50 })), /* @__PURE__ */ React5.createElement(Box3, { flexDirection: "column", borderStyle: "round", borderColor: "gray", padding: 1, height: 10 }, installProgress.slice(-8).map((item) => /* @__PURE__ */ React5.createElement(Box3, { key: item.filepath }, /* @__PURE__ */ React5.createElement(StatusIcon, { status: item.status === "success" ? "success" : item.status === "error" ? "error" : item.status === "downloading" ? "loading" : "pending" }), /* @__PURE__ */ React5.createElement(Text4, null, " ", item.filepath), item.error && /* @__PURE__ */ React5.createElement(Text4, { color: "red", dimColor: true }, " (", item.error, ")")))), /* @__PURE__ */ React5.createElement(Box3, { marginTop: 1 }, /* @__PURE__ */ React5.createElement(Text4, null, "\u{1F4CA} ", /* @__PURE__ */ React5.createElement(Text4, { color: "green" }, installStats.added, " added"), " \xB7 ", /* @__PURE__ */ React5.createElement(Text4, { color: "cyan" }, installStats.updated, " updated"), " \xB7 ", /* @__PURE__ */ React5.createElement(Text4, { color: "red" }, installStats.failed, " failed"))));
|
|
2118
|
+
}
|
|
2119
|
+
if (viewState === "summary") {
|
|
2120
|
+
return /* @__PURE__ */ React5.createElement(Box3, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React5.createElement(Box3, { marginBottom: 1 }, /* @__PURE__ */ React5.createElement(Text4, { bold: true, color: "green" }, "\u2705 Installation Complete!")), /* @__PURE__ */ React5.createElement(Box3, { flexDirection: "column", borderStyle: "round", borderColor: "gray", padding: 1 }, /* @__PURE__ */ React5.createElement(Text4, null, installStats.total, " components processed:"), /* @__PURE__ */ React5.createElement(Text4, null, " \u2514\u2500 ", /* @__PURE__ */ React5.createElement(Text4, { color: "green" }, installStats.added), " added"), /* @__PURE__ */ React5.createElement(Text4, null, " \u2514\u2500 ", /* @__PURE__ */ React5.createElement(Text4, { color: "cyan" }, installStats.updated), " updated"), installStats.failed > 0 && /* @__PURE__ */ React5.createElement(Text4, null, " \u2514\u2500 ", /* @__PURE__ */ React5.createElement(Text4, { color: "red" }, installStats.failed), " failed")), /* @__PURE__ */ React5.createElement(Box3, { marginTop: 1 }, /* @__PURE__ */ React5.createElement(Text4, null, "\u{1F4C1} Location: ", /* @__PURE__ */ React5.createElement(Text4, { color: "cyan" }, process.cwd(), "/.jai1"))), /* @__PURE__ */ React5.createElement(Box3, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React5.createElement(Text4, { bold: true, color: "yellow" }, "\u{1F4E6} Sync to IDE(s)?"), /* @__PURE__ */ React5.createElement(Text4, { dimColor: true }, "Sync rules and workflows to your IDE directories")), /* @__PURE__ */ React5.createElement(Box3, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 1 }, /* @__PURE__ */ React5.createElement(Text4, { dimColor: true }, "[Enter] Select IDEs \xB7 [S/Esc] Skip")));
|
|
2121
|
+
}
|
|
2122
|
+
if (viewState === "ide-sync") {
|
|
2123
|
+
return /* @__PURE__ */ React5.createElement(Box3, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React5.createElement(Box3, { marginBottom: 1 }, /* @__PURE__ */ React5.createElement(Text4, { bold: true, color: "cyan" }, "\u{1F504} Select IDE(s)")), /* @__PURE__ */ React5.createElement(Box3, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", padding: 1 }, availableIdes.map((ide, i) => {
|
|
2124
|
+
const ideConfig = IDE_MIGRATION_CONFIGS[ide];
|
|
2125
|
+
const isCursor = i === ideCursorIndex;
|
|
2126
|
+
const isChecked = selectedIdes.has(ide);
|
|
2127
|
+
return /* @__PURE__ */ React5.createElement(Box3, { key: ide }, /* @__PURE__ */ React5.createElement(Text4, { color: isCursor ? "cyan" : "white" }, isCursor ? "\u276F " : " ", isChecked ? "[\u2713]" : "[ ]", " ", ideConfig.icon, " ", ideConfig.name));
|
|
2128
|
+
})), selectedIdes.size > 0 && /* @__PURE__ */ React5.createElement(Box3, { marginTop: 1 }, /* @__PURE__ */ React5.createElement(Text4, null, "Selected: ", /* @__PURE__ */ React5.createElement(Text4, { color: "green" }, selectedIdes.size), " IDE(s)")), /* @__PURE__ */ React5.createElement(Box3, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 1 }, /* @__PURE__ */ React5.createElement(Text4, { dimColor: true }, "[\u2191\u2193] Navigate \xB7 [\u2423] Toggle \xB7 [A] All \xB7 [Enter] Sync \xB7 [S] Skip")));
|
|
2129
|
+
}
|
|
2130
|
+
if (viewState === "syncing") {
|
|
2131
|
+
return /* @__PURE__ */ React5.createElement(Box3, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React5.createElement(Box3, { marginBottom: 1 }, /* @__PURE__ */ React5.createElement(Text4, { bold: true, color: "cyan" }, "\u{1F504} Syncing to IDE(s)")), /* @__PURE__ */ React5.createElement(Box3, { marginBottom: 1 }, /* @__PURE__ */ React5.createElement(ProgressBar, { current: syncStats.completed, total: syncStats.total, width: 50 })), /* @__PURE__ */ React5.createElement(Box3, { flexDirection: "column", borderStyle: "round", borderColor: "gray", padding: 1, height: 10 }, syncProgress.slice(-8).map((item, idx) => /* @__PURE__ */ React5.createElement(Box3, { key: `${item.targetPath}-${idx}` }, /* @__PURE__ */ React5.createElement(StatusIcon, { status: item.status === "success" ? "success" : item.status === "error" ? "error" : "pending" }), /* @__PURE__ */ React5.createElement(Text4, null, " ", item.targetPath), item.error && /* @__PURE__ */ React5.createElement(Text4, { color: "red", dimColor: true }, " (", item.error, ")")))), /* @__PURE__ */ React5.createElement(Box3, { marginTop: 1 }, /* @__PURE__ */ React5.createElement(Text4, null, "\u{1F4CA} ", /* @__PURE__ */ React5.createElement(Text4, { color: "green" }, syncStats.created, " created"), " \xB7 ", /* @__PURE__ */ React5.createElement(Text4, { color: "cyan" }, syncStats.updated, " updated"), syncStats.skipped > 0 && /* @__PURE__ */ React5.createElement(React5.Fragment, null, " \xB7 ", /* @__PURE__ */ React5.createElement(Text4, { color: "yellow" }, syncStats.skipped, " skipped")), syncStats.errors > 0 && /* @__PURE__ */ React5.createElement(React5.Fragment, null, " \xB7 ", /* @__PURE__ */ React5.createElement(Text4, { color: "red" }, syncStats.errors, " errors")))));
|
|
2132
|
+
}
|
|
2133
|
+
if (viewState === "done") {
|
|
2134
|
+
return /* @__PURE__ */ React5.createElement(Box3, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React5.createElement(Box3, { marginBottom: 1 }, /* @__PURE__ */ React5.createElement(Text4, { bold: true, color: "green" }, "\u{1F389} All Done!")), /* @__PURE__ */ React5.createElement(Box3, { flexDirection: "column", borderStyle: "round", borderColor: "gray", padding: 1 }, /* @__PURE__ */ React5.createElement(Text4, { bold: true }, "\u{1F4E6} Components:"), /* @__PURE__ */ React5.createElement(Text4, null, " \u2514\u2500 ", /* @__PURE__ */ React5.createElement(Text4, { color: "green" }, installStats.added), " added, ", /* @__PURE__ */ React5.createElement(Text4, { color: "cyan" }, installStats.updated), " updated"), syncStats.total > 0 && /* @__PURE__ */ React5.createElement(React5.Fragment, null, /* @__PURE__ */ React5.createElement(Text4, null, " "), /* @__PURE__ */ React5.createElement(Text4, { bold: true }, "\u{1F504} IDE Sync:"), /* @__PURE__ */ React5.createElement(Text4, null, " \u2514\u2500 ", /* @__PURE__ */ React5.createElement(Text4, { color: "green" }, syncStats.created), " created, ", /* @__PURE__ */ React5.createElement(Text4, { color: "cyan" }, syncStats.updated), " updated"), /* @__PURE__ */ React5.createElement(Text4, null, " \u2514\u2500 ", Array.from(selectedIdes).map((ide) => IDE_MIGRATION_CONFIGS[ide].name).join(", ")))), /* @__PURE__ */ React5.createElement(Box3, { marginTop: 1 }, /* @__PURE__ */ React5.createElement(Text4, { dimColor: true }, "Press Enter to exit")));
|
|
2135
|
+
}
|
|
2136
|
+
const selectedPackage = packageOptions[packageCursorIndex];
|
|
2137
|
+
const visibleComponents = filteredComponents.slice(0, 10);
|
|
2138
|
+
const hasMore = filteredComponents.length > 10;
|
|
2139
|
+
return /* @__PURE__ */ React5.createElement(Box3, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React5.createElement(Box3, { marginBottom: 1 }, /* @__PURE__ */ React5.createElement(Text4, { bold: true, color: "cyan" }, "\u{1F4E6} Jai1 Apply"), selectedPaths.size > 0 && /* @__PURE__ */ React5.createElement(Text4, { color: "green" }, " [", selectedPaths.size, " selected]")), /* @__PURE__ */ React5.createElement(Box3, null, /* @__PURE__ */ React5.createElement(
|
|
2140
|
+
Box3,
|
|
2141
|
+
{
|
|
2142
|
+
flexDirection: "column",
|
|
2143
|
+
borderStyle: "round",
|
|
2144
|
+
borderColor: activePane === "packages" ? "cyan" : "gray",
|
|
2145
|
+
width: 22,
|
|
2146
|
+
padding: 1
|
|
2147
|
+
},
|
|
2148
|
+
/* @__PURE__ */ React5.createElement(Text4, { bold: true, dimColor: true }, "PACKAGES"),
|
|
2149
|
+
/* @__PURE__ */ React5.createElement(Box3, { flexDirection: "column", marginTop: 1 }, packageOptions.map((pkg, i) => {
|
|
2150
|
+
const isCursor = i === packageCursorIndex;
|
|
2151
|
+
const isActive = activePane === "packages";
|
|
2152
|
+
return /* @__PURE__ */ React5.createElement(Box3, { key: pkg.tag }, /* @__PURE__ */ React5.createElement(Text4, { color: isCursor && isActive ? "cyan" : isCursor ? "white" : "gray" }, isCursor && isActive ? "\u276F " : isCursor ? "\u203A " : " ", pkg.tag, " ", /* @__PURE__ */ React5.createElement(Text4, { dimColor: true }, "(", pkg.count, ")")));
|
|
2153
|
+
}))
|
|
2154
|
+
), /* @__PURE__ */ React5.createElement(
|
|
2155
|
+
Box3,
|
|
2156
|
+
{
|
|
2157
|
+
flexDirection: "column",
|
|
2158
|
+
borderStyle: "round",
|
|
2159
|
+
borderColor: activePane === "components" ? "cyan" : "gray",
|
|
2160
|
+
flexGrow: 1,
|
|
2161
|
+
marginLeft: 1,
|
|
2162
|
+
padding: 1
|
|
2163
|
+
},
|
|
2164
|
+
/* @__PURE__ */ React5.createElement(Box3, { marginBottom: 1 }, /* @__PURE__ */ React5.createElement(Text4, { color: isSearchFocused ? "cyan" : "gray" }, "\u{1F50D} "), isSearchFocused ? /* @__PURE__ */ React5.createElement(
|
|
2165
|
+
TextInput2,
|
|
2166
|
+
{
|
|
2167
|
+
value: searchQuery,
|
|
2168
|
+
onChange: setSearchQuery,
|
|
2169
|
+
placeholder: "Type to filter...",
|
|
2170
|
+
focus: true
|
|
2171
|
+
}
|
|
2172
|
+
) : /* @__PURE__ */ React5.createElement(Text4, null, searchQuery || /* @__PURE__ */ React5.createElement(Text4, { dimColor: true }, "/ to search"))),
|
|
2173
|
+
/* @__PURE__ */ React5.createElement(Box3, { marginBottom: 1 }, /* @__PURE__ */ React5.createElement(Text4, { bold: true }, "COMPONENTS "), selectedPackage && selectedPackage.tag !== "All" && /* @__PURE__ */ React5.createElement(Text4, { color: "cyan" }, "[", selectedPackage.tag, "] "), searchQuery && /* @__PURE__ */ React5.createElement(Text4, { color: "yellow" }, '"', searchQuery, '" '), /* @__PURE__ */ React5.createElement(Text4, { dimColor: true }, "(", filteredComponents.length, hasMore ? "+" : "", ")")),
|
|
2174
|
+
/* @__PURE__ */ React5.createElement(Box3, { flexDirection: "column" }, visibleComponents.map((comp, i) => {
|
|
2175
|
+
const isCursor = i === componentCursorIndex && activePane === "components";
|
|
2176
|
+
const isChecked = selectedPaths.has(comp.filepath);
|
|
2177
|
+
const isInstalled = installedPaths.has(comp.filepath);
|
|
2178
|
+
return /* @__PURE__ */ React5.createElement(Box3, { key: comp.filepath }, /* @__PURE__ */ React5.createElement(Text4, { color: isCursor ? "cyan" : "white" }, isCursor ? "\u276F " : " ", isChecked ? "[\u2713]" : "[ ]", " ", comp.filepath), /* @__PURE__ */ React5.createElement(Text4, { dimColor: true }, " ", isInstalled ? "\u2713" : "\u25CB"));
|
|
2179
|
+
}), filteredComponents.length === 0 && /* @__PURE__ */ React5.createElement(Text4, { dimColor: true }, " No components match"), hasMore && /* @__PURE__ */ React5.createElement(Text4, { dimColor: true }, " ... +", filteredComponents.length - 10, " more"))
|
|
2180
|
+
)), selectedPaths.size > 0 && /* @__PURE__ */ React5.createElement(Box3, { marginTop: 1 }, /* @__PURE__ */ React5.createElement(Text4, { dimColor: true }, "\u{1F4CC} ", Array.from(selectedPaths).slice(0, 2).join(", "), selectedPaths.size > 2 && ` +${selectedPaths.size - 2} more`)), /* @__PURE__ */ React5.createElement(Box3, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 1 }, /* @__PURE__ */ React5.createElement(Text4, { dimColor: true }, activePane === "packages" && "[\u2191\u2193] Select \xB7 [\u2192/Tab] Components \xB7 [\u2423] Select all", activePane === "components" && !isSearchFocused && "[\u2191\u2193] Navigate \xB7 [\u2190/Tab] Packages \xB7 [\u2423] Toggle \xB7 [/] Search", isSearchFocused && "Type to filter \xB7 [Enter/Esc] Done", !isSearchFocused && " \xB7 [A] All \xB7 [C] Clear \xB7 [Enter] Apply")));
|
|
2181
|
+
};
|
|
2182
|
+
|
|
2183
|
+
// src/commands/apply-new.ts
|
|
2184
|
+
function createApplyNewCommand() {
|
|
2185
|
+
const cmd = new Command4("apply-new").description("Apply components (Two-Pane UI - experimental)").option("--force", "Force overwrite even if modified locally").action(async (options) => {
|
|
2186
|
+
const configService = new ConfigService();
|
|
2187
|
+
const config = await configService.load();
|
|
2188
|
+
if (!config) {
|
|
2189
|
+
throw new ValidationError('Not initialized. Run "jai1 auth" first.');
|
|
2190
|
+
}
|
|
2191
|
+
const { waitUntilExit } = render2(
|
|
2192
|
+
React6.createElement(TwoPaneApplyApp, {
|
|
2193
|
+
config,
|
|
2194
|
+
force: options.force,
|
|
2195
|
+
onExit: () => {
|
|
2196
|
+
process.exit(0);
|
|
2197
|
+
}
|
|
2198
|
+
})
|
|
2199
|
+
);
|
|
2200
|
+
await waitUntilExit();
|
|
2201
|
+
});
|
|
2202
|
+
return cmd;
|
|
2203
|
+
}
|
|
2204
|
+
|
|
2205
|
+
// src/commands/update.ts
|
|
2206
|
+
import { Command as Command5 } from "commander";
|
|
1821
2207
|
import { confirm } from "@inquirer/prompts";
|
|
1822
2208
|
import chalk3 from "chalk";
|
|
1823
2209
|
function createUpdateCommand() {
|
|
1824
|
-
return new
|
|
2210
|
+
return new Command5("update").description("Update installed components to latest versions").option("--force", "Force update even if files are modified locally").action(async (options) => {
|
|
1825
2211
|
await handleUpdate(options);
|
|
1826
2212
|
});
|
|
1827
2213
|
}
|
|
@@ -1931,11 +2317,11 @@ async function handleUpdate(options) {
|
|
|
1931
2317
|
}
|
|
1932
2318
|
|
|
1933
2319
|
// src/commands/framework/check.ts
|
|
1934
|
-
import { Command as
|
|
2320
|
+
import { Command as Command6 } from "commander";
|
|
1935
2321
|
import chalk4 from "chalk";
|
|
1936
2322
|
import Table from "cli-table3";
|
|
1937
2323
|
function createCheckCommand() {
|
|
1938
|
-
const cmd = new
|
|
2324
|
+
const cmd = new Command6("check").description("Ki\u1EC3m tra c\u1EADp nh\u1EADt framework").option("--json", "Output as JSON").action(async (options) => {
|
|
1939
2325
|
await handleCheck(options);
|
|
1940
2326
|
});
|
|
1941
2327
|
return cmd;
|
|
@@ -2046,23 +2432,23 @@ async function handleCheck(options) {
|
|
|
2046
2432
|
}
|
|
2047
2433
|
|
|
2048
2434
|
// src/commands/ide/index.ts
|
|
2049
|
-
import { Command as
|
|
2435
|
+
import { Command as Command11 } from "commander";
|
|
2050
2436
|
import chalk5 from "chalk";
|
|
2051
2437
|
|
|
2052
2438
|
// src/commands/ide/context.ts
|
|
2053
|
-
import
|
|
2054
|
-
import { render as
|
|
2055
|
-
import { Command as
|
|
2439
|
+
import React12 from "react";
|
|
2440
|
+
import { render as render3 } from "ink";
|
|
2441
|
+
import { Command as Command7 } from "commander";
|
|
2056
2442
|
|
|
2057
2443
|
// src/ui/context/ContextApp.tsx
|
|
2058
|
-
import
|
|
2059
|
-
import { Box as
|
|
2444
|
+
import React11, { useState as useState7, useEffect as useEffect3 } from "react";
|
|
2445
|
+
import { Box as Box8, Text as Text9, useInput as useInput7, useApp as useApp3 } from "ink";
|
|
2060
2446
|
|
|
2061
2447
|
// src/ui/context/views/MainMenuView.tsx
|
|
2062
|
-
import
|
|
2063
|
-
import { Box as
|
|
2448
|
+
import React7, { useState as useState3 } from "react";
|
|
2449
|
+
import { Box as Box4, Text as Text5, useInput as useInput3 } from "ink";
|
|
2064
2450
|
var MainMenuView = ({ ideContexts, onSelect }) => {
|
|
2065
|
-
const [selectedIndex, setSelectedIndex] =
|
|
2451
|
+
const [selectedIndex, setSelectedIndex] = useState3(0);
|
|
2066
2452
|
const menuItems = [
|
|
2067
2453
|
{
|
|
2068
2454
|
ide: "cursor",
|
|
@@ -2093,7 +2479,7 @@ var MainMenuView = ({ ideContexts, onSelect }) => {
|
|
|
2093
2479
|
available: ideContexts.some((ctx) => ctx.ide === "jai1")
|
|
2094
2480
|
}
|
|
2095
2481
|
];
|
|
2096
|
-
|
|
2482
|
+
useInput3((input5, key) => {
|
|
2097
2483
|
if (key.upArrow) {
|
|
2098
2484
|
setSelectedIndex((prev) => Math.max(0, prev - 1));
|
|
2099
2485
|
} else if (key.downArrow) {
|
|
@@ -2119,8 +2505,8 @@ var MainMenuView = ({ ideContexts, onSelect }) => {
|
|
|
2119
2505
|
if (ctx.stats.byType.prompts) parts.push(`${ctx.stats.byType.prompts} prompts`);
|
|
2120
2506
|
return parts.join(", ") || `${item.itemCount} items`;
|
|
2121
2507
|
};
|
|
2122
|
-
return /* @__PURE__ */
|
|
2123
|
-
|
|
2508
|
+
return /* @__PURE__ */ React7.createElement(Box4, { flexDirection: "column" }, /* @__PURE__ */ React7.createElement(
|
|
2509
|
+
Box4,
|
|
2124
2510
|
{
|
|
2125
2511
|
flexDirection: "column",
|
|
2126
2512
|
borderStyle: "round",
|
|
@@ -2128,24 +2514,24 @@ var MainMenuView = ({ ideContexts, onSelect }) => {
|
|
|
2128
2514
|
padding: 1,
|
|
2129
2515
|
marginBottom: 1
|
|
2130
2516
|
},
|
|
2131
|
-
/* @__PURE__ */
|
|
2132
|
-
/* @__PURE__ */
|
|
2133
|
-
), /* @__PURE__ */
|
|
2517
|
+
/* @__PURE__ */ React7.createElement(Text5, null, "Ch\xE0o m\u1EEBng \u0111\u1EBFn v\u1EDBi ", /* @__PURE__ */ React7.createElement(Text5, { bold: true, color: "cyan" }, "Jai1 Context"), "!"),
|
|
2518
|
+
/* @__PURE__ */ React7.createElement(Text5, { dimColor: true }, "Kh\xE1m ph\xE1 v\xE0 qu\u1EA3n l\xFD context cho c\xE1c IDE h\u1ED7 tr\u1EE3 Agentic Coding.")
|
|
2519
|
+
), /* @__PURE__ */ React7.createElement(Box4, { flexDirection: "column", borderStyle: "round", borderColor: "gray", padding: 1 }, /* @__PURE__ */ React7.createElement(Text5, { bold: true, marginBottom: 1 }, "Ch\u1ECDn IDE \u0111\u1EC3 kh\xE1m ph\xE1:"), menuItems.map((item, index) => {
|
|
2134
2520
|
const isSelected = index === selectedIndex;
|
|
2135
2521
|
const dimmed = !item.available;
|
|
2136
|
-
return /* @__PURE__ */
|
|
2137
|
-
})), ideContexts.length === 0 && /* @__PURE__ */
|
|
2522
|
+
return /* @__PURE__ */ React7.createElement(Box4, { key: item.ide, marginY: 0 }, /* @__PURE__ */ React7.createElement(Text5, { color: isSelected ? "cyan" : dimmed ? "gray" : "white", dimColor: dimmed }, isSelected ? "\u276F " : " ", item.icon, " ", item.title), item.available && /* @__PURE__ */ React7.createElement(Text5, { dimColor: true }, " - ", formatSummary(item)), !item.available && /* @__PURE__ */ React7.createElement(Text5, { dimColor: true }, " - Kh\xF4ng c\xF3 context"));
|
|
2523
|
+
})), ideContexts.length === 0 && /* @__PURE__ */ React7.createElement(Box4, { marginTop: 1, borderStyle: "round", borderColor: "yellow", padding: 1 }, /* @__PURE__ */ React7.createElement(Text5, { color: "yellow" }, "\u26A0\uFE0F Kh\xF4ng t\xECm th\u1EA5y context n\xE0o"), /* @__PURE__ */ React7.createElement(Text5, { dimColor: true }, "H\xE3y ch\u1EA1y "), /* @__PURE__ */ React7.createElement(Text5, { color: "cyan" }, "jai1 apply"), /* @__PURE__ */ React7.createElement(Text5, { dimColor: true }, " \u0111\u1EC3 c\xE0i \u0111\u1EB7t context cho IDE c\u1EE7a b\u1EA1n.")));
|
|
2138
2524
|
};
|
|
2139
2525
|
|
|
2140
2526
|
// src/ui/context/views/IDEOverviewView.tsx
|
|
2141
|
-
import
|
|
2142
|
-
import { Box as
|
|
2527
|
+
import React8, { useState as useState4 } from "react";
|
|
2528
|
+
import { Box as Box5, Text as Text6, useInput as useInput4 } from "ink";
|
|
2143
2529
|
var IDEOverviewView = ({
|
|
2144
2530
|
ideContext,
|
|
2145
2531
|
onSelectType,
|
|
2146
2532
|
onBack
|
|
2147
2533
|
}) => {
|
|
2148
|
-
const [selectedTabIndex, setSelectedTabIndex] =
|
|
2534
|
+
const [selectedTabIndex, setSelectedTabIndex] = useState4(0);
|
|
2149
2535
|
const tabs = [];
|
|
2150
2536
|
if (ideContext.stats.byType.rules) {
|
|
2151
2537
|
tabs.push({
|
|
@@ -2195,7 +2581,7 @@ var IDEOverviewView = ({
|
|
|
2195
2581
|
count: ideContext.stats.byType.context
|
|
2196
2582
|
});
|
|
2197
2583
|
}
|
|
2198
|
-
|
|
2584
|
+
useInput4((input5, key) => {
|
|
2199
2585
|
if (key.tab || key.rightArrow) {
|
|
2200
2586
|
setSelectedTabIndex((prev) => Math.min(tabs.length - 1, prev + 1));
|
|
2201
2587
|
} else if (key.leftArrow) {
|
|
@@ -2226,8 +2612,8 @@ var IDEOverviewView = ({
|
|
|
2226
2612
|
day: "2-digit"
|
|
2227
2613
|
});
|
|
2228
2614
|
};
|
|
2229
|
-
return /* @__PURE__ */
|
|
2230
|
-
|
|
2615
|
+
return /* @__PURE__ */ React8.createElement(Box5, { flexDirection: "column" }, /* @__PURE__ */ React8.createElement(Box5, { marginBottom: 1 }, /* @__PURE__ */ React8.createElement(Text6, { bold: true, color: "cyan" }, ideContext.config.icon, " ", ideContext.config.name)), /* @__PURE__ */ React8.createElement(
|
|
2616
|
+
Box5,
|
|
2231
2617
|
{
|
|
2232
2618
|
flexDirection: "column",
|
|
2233
2619
|
borderStyle: "round",
|
|
@@ -2235,12 +2621,12 @@ var IDEOverviewView = ({
|
|
|
2235
2621
|
padding: 1,
|
|
2236
2622
|
marginBottom: 1
|
|
2237
2623
|
},
|
|
2238
|
-
/* @__PURE__ */
|
|
2239
|
-
/* @__PURE__ */
|
|
2240
|
-
), /* @__PURE__ */
|
|
2624
|
+
/* @__PURE__ */ React8.createElement(Text6, { bold: true }, "\u{1F4CA} T\u1ED5ng quan"),
|
|
2625
|
+
/* @__PURE__ */ React8.createElement(Box5, { marginTop: 1 }, /* @__PURE__ */ React8.createElement(Text6, null, "\u{1F4C1} T\u1ED5ng: ", /* @__PURE__ */ React8.createElement(Text6, { bold: true, color: "cyan" }, ideContext.stats.totalItems, " items")), /* @__PURE__ */ React8.createElement(Text6, { dimColor: true }, " \xB7 "), /* @__PURE__ */ React8.createElement(Text6, null, "\u{1F4BE} K\xEDch th\u01B0\u1EDBc: ", /* @__PURE__ */ React8.createElement(Text6, { bold: true }, formatSize(ideContext.stats.totalSize))), ideContext.stats.lastModified && /* @__PURE__ */ React8.createElement(React8.Fragment, null, /* @__PURE__ */ React8.createElement(Text6, { dimColor: true }, " \xB7 "), /* @__PURE__ */ React8.createElement(Text6, null, "\u{1F550} C\u1EADp nh\u1EADt: ", /* @__PURE__ */ React8.createElement(Text6, { bold: true }, formatDate(ideContext.stats.lastModified)))))
|
|
2626
|
+
), /* @__PURE__ */ React8.createElement(Box5, { flexDirection: "column", borderStyle: "round", borderColor: "gray", padding: 1 }, /* @__PURE__ */ React8.createElement(Box5, { marginBottom: 1 }, tabs.map((tab, index) => {
|
|
2241
2627
|
const isSelected = index === selectedTabIndex;
|
|
2242
|
-
return /* @__PURE__ */
|
|
2243
|
-
|
|
2628
|
+
return /* @__PURE__ */ React8.createElement(Box5, { key: tab.type, marginRight: 1 }, /* @__PURE__ */ React8.createElement(
|
|
2629
|
+
Text6,
|
|
2244
2630
|
{
|
|
2245
2631
|
color: isSelected ? "cyan" : "gray",
|
|
2246
2632
|
bold: isSelected,
|
|
@@ -2255,15 +2641,15 @@ var IDEOverviewView = ({
|
|
|
2255
2641
|
")",
|
|
2256
2642
|
" "
|
|
2257
2643
|
));
|
|
2258
|
-
})), currentTab && currentItems.length > 0 && /* @__PURE__ */
|
|
2644
|
+
})), currentTab && currentItems.length > 0 && /* @__PURE__ */ React8.createElement(Box5, { flexDirection: "column" }, /* @__PURE__ */ React8.createElement(Text6, { dimColor: true }, "Preview (nh\u1EA5n Enter \u0111\u1EC3 xem chi ti\u1EBFt):"), /* @__PURE__ */ React8.createElement(Box5, { flexDirection: "column", marginTop: 1 }, currentItems.slice(0, 5).map((item) => /* @__PURE__ */ React8.createElement(Box5, { key: item.id, marginY: 0 }, /* @__PURE__ */ React8.createElement(Text6, null, "\u2022 ", item.name), item.description && /* @__PURE__ */ React8.createElement(Text6, { dimColor: true }, " - ", item.description))), currentItems.length > 5 && /* @__PURE__ */ React8.createElement(Text6, { dimColor: true }, "... v\xE0 ", currentItems.length - 5, " items kh\xE1c"))), currentTab && currentItems.length === 0 && /* @__PURE__ */ React8.createElement(Text6, { dimColor: true }, "Kh\xF4ng c\xF3 items n\xE0o trong ", currentTab.label)));
|
|
2259
2645
|
};
|
|
2260
2646
|
|
|
2261
2647
|
// src/ui/context/views/ListView.tsx
|
|
2262
|
-
import
|
|
2263
|
-
import { Box as
|
|
2648
|
+
import React9, { useState as useState5 } from "react";
|
|
2649
|
+
import { Box as Box6, Text as Text7, useInput as useInput5 } from "ink";
|
|
2264
2650
|
var ListView = ({ items, contentType, onSelect, onBack }) => {
|
|
2265
|
-
const [selectedIndex, setSelectedIndex] =
|
|
2266
|
-
|
|
2651
|
+
const [selectedIndex, setSelectedIndex] = useState5(0);
|
|
2652
|
+
useInput5((input5, key) => {
|
|
2267
2653
|
if (key.upArrow) {
|
|
2268
2654
|
setSelectedIndex((prev) => Math.max(0, prev - 1));
|
|
2269
2655
|
} else if (key.downArrow) {
|
|
@@ -2299,22 +2685,22 @@ var ListView = ({ items, contentType, onSelect, onBack }) => {
|
|
|
2299
2685
|
return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
|
|
2300
2686
|
};
|
|
2301
2687
|
if (items.length === 0) {
|
|
2302
|
-
return /* @__PURE__ */
|
|
2688
|
+
return /* @__PURE__ */ React9.createElement(Box6, { flexDirection: "column" }, /* @__PURE__ */ React9.createElement(Box6, { marginBottom: 1 }, /* @__PURE__ */ React9.createElement(Text7, { bold: true, color: "cyan" }, getTypeLabel())), /* @__PURE__ */ React9.createElement(Box6, { borderStyle: "round", borderColor: "gray", padding: 1 }, /* @__PURE__ */ React9.createElement(Text7, { dimColor: true }, "Kh\xF4ng c\xF3 items n\xE0o")));
|
|
2303
2689
|
}
|
|
2304
|
-
return /* @__PURE__ */
|
|
2690
|
+
return /* @__PURE__ */ React9.createElement(Box6, { flexDirection: "column" }, /* @__PURE__ */ React9.createElement(Box6, { marginBottom: 1 }, /* @__PURE__ */ React9.createElement(Text7, { bold: true, color: "cyan" }, getTypeLabel()), /* @__PURE__ */ React9.createElement(Text7, { dimColor: true }, " - ", items.length, " items")), /* @__PURE__ */ React9.createElement(Box6, { flexDirection: "column", borderStyle: "round", borderColor: "gray", padding: 1 }, items.map((item, index) => {
|
|
2305
2691
|
const isSelected = index === selectedIndex;
|
|
2306
|
-
return /* @__PURE__ */
|
|
2692
|
+
return /* @__PURE__ */ React9.createElement(Box6, { key: item.id, flexDirection: "column", marginY: 0 }, /* @__PURE__ */ React9.createElement(Box6, null, /* @__PURE__ */ React9.createElement(Text7, { color: isSelected ? "cyan" : "white" }, isSelected ? "\u276F " : " ", item.name), /* @__PURE__ */ React9.createElement(Text7, { dimColor: true }, " (", formatSize(item.fileSize), ")")), isSelected && /* @__PURE__ */ React9.createElement(Box6, { marginLeft: 3, flexDirection: "column" }, item.description && /* @__PURE__ */ React9.createElement(Text7, { dimColor: true }, "\u{1F4DD} ", item.description), contentType === "rules" && /* @__PURE__ */ React9.createElement(React9.Fragment, null, item.alwaysApply && /* @__PURE__ */ React9.createElement(Text7, { dimColor: true }, "\u2705 Always active"), item.globs && item.globs.length > 0 && /* @__PURE__ */ React9.createElement(Text7, { dimColor: true }, "\u{1F3AF} Globs: ", item.globs.join(", "))), contentType === "skills" && /* @__PURE__ */ React9.createElement(Box6, null, item.hasScripts && /* @__PURE__ */ React9.createElement(Text7, { dimColor: true }, "\u{1F4E6} scripts/ "), item.hasReferences && /* @__PURE__ */ React9.createElement(Text7, { dimColor: true }, "\u{1F4DA} references/ "), item.hasAssets && /* @__PURE__ */ React9.createElement(Text7, { dimColor: true }, "\u{1F3A8} assets/ ")), contentType === "agents" && item.model && /* @__PURE__ */ React9.createElement(Text7, { dimColor: true }, "\u{1F527} Model: ", item.model), /* @__PURE__ */ React9.createElement(Text7, { dimColor: true }, "\u{1F4C1} ", item.relativePath)));
|
|
2307
2693
|
})));
|
|
2308
2694
|
};
|
|
2309
2695
|
|
|
2310
2696
|
// src/ui/context/views/DetailView.tsx
|
|
2311
|
-
import
|
|
2312
|
-
import { Box as
|
|
2697
|
+
import React10, { useState as useState6 } from "react";
|
|
2698
|
+
import { Box as Box7, Text as Text8, useInput as useInput6 } from "ink";
|
|
2313
2699
|
var DetailView = ({ item, scrollPosition: initialScroll, onBack }) => {
|
|
2314
|
-
const [scrollPosition, setScrollPosition] =
|
|
2700
|
+
const [scrollPosition, setScrollPosition] = useState6(initialScroll);
|
|
2315
2701
|
const maxVisibleLines = 25;
|
|
2316
2702
|
const maxScroll = Math.max(0, item.previewLines.length - maxVisibleLines);
|
|
2317
|
-
|
|
2703
|
+
useInput6((input5, key) => {
|
|
2318
2704
|
if (key.upArrow || input5 === "k") {
|
|
2319
2705
|
setScrollPosition((prev) => Math.max(0, prev - 1));
|
|
2320
2706
|
} else if (key.downArrow || input5 === "j") {
|
|
@@ -2352,10 +2738,10 @@ var DetailView = ({ item, scrollPosition: initialScroll, onBack }) => {
|
|
|
2352
2738
|
const hasMoreAbove = scrollPosition > 0;
|
|
2353
2739
|
const hasMoreBelow = scrollPosition + maxVisibleLines < item.previewLines.length;
|
|
2354
2740
|
const scrollPercentage = item.previewLines.length <= maxVisibleLines ? 100 : Math.round(scrollPosition / maxScroll * 100);
|
|
2355
|
-
return /* @__PURE__ */
|
|
2741
|
+
return /* @__PURE__ */ React10.createElement(Box7, { flexDirection: "column" }, /* @__PURE__ */ React10.createElement(Box7, { flexDirection: "column", marginBottom: 1 }, /* @__PURE__ */ React10.createElement(Text8, { bold: true, color: "cyan" }, item.name), /* @__PURE__ */ React10.createElement(Box7, null, /* @__PURE__ */ React10.createElement(Text8, { dimColor: true }, item.relativePath, " \u2022 ", formatSize(item.fileSize)), item.description && /* @__PURE__ */ React10.createElement(Text8, { dimColor: true }, " \u2022 ", item.description)), /* @__PURE__ */ React10.createElement(Box7, null, item.type === "rules" && item.globs && item.globs.length > 0 && /* @__PURE__ */ React10.createElement(Text8, { dimColor: true }, "globs: ", item.globs.join(", ")), item.type === "agents" && item.model && /* @__PURE__ */ React10.createElement(Text8, { dimColor: true }, "model: ", item.model), item.type === "skills" && /* @__PURE__ */ React10.createElement(Text8, { dimColor: true }, item.hasScripts && "\u{1F4E6} scripts ", item.hasReferences && "\u{1F4DA} refs ", item.hasAssets && "\u{1F3A8} assets"))), /* @__PURE__ */ React10.createElement(Box7, { flexDirection: "column", borderStyle: "round", borderColor: "gray", padding: 1 }, /* @__PURE__ */ React10.createElement(Box7, { justifyContent: "space-between" }, /* @__PURE__ */ React10.createElement(Text8, { bold: true }, "\u{1F441}\uFE0F Preview"), item.previewLines.length > maxVisibleLines && /* @__PURE__ */ React10.createElement(Text8, { dimColor: true }, "[", scrollPosition + 1, "-", Math.min(scrollPosition + maxVisibleLines, item.previewLines.length), "/", item.lineCount, "] ", scrollPercentage, "%")), hasMoreAbove && /* @__PURE__ */ React10.createElement(Box7, { justifyContent: "center" }, /* @__PURE__ */ React10.createElement(Text8, { dimColor: true }, "\u25B2 \u25B2 \u25B2 (", scrollPosition, " d\xF2ng \u1EDF tr\xEAn) \u25B2 \u25B2 \u25B2")), /* @__PURE__ */ React10.createElement(Box7, { flexDirection: "column", marginTop: 1 }, visibleLines.map((line, index) => {
|
|
2356
2742
|
const lineNumber = scrollPosition + index + 1;
|
|
2357
|
-
return /* @__PURE__ */
|
|
2358
|
-
})), hasMoreBelow && /* @__PURE__ */
|
|
2743
|
+
return /* @__PURE__ */ React10.createElement(Box7, { key: index }, /* @__PURE__ */ React10.createElement(Text8, { dimColor: true }, lineNumber.toString().padStart(3, " "), "\u2502 "), /* @__PURE__ */ React10.createElement(Text8, null, line));
|
|
2744
|
+
})), hasMoreBelow && /* @__PURE__ */ React10.createElement(Box7, { justifyContent: "center", marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text8, { dimColor: true }, "\u25BC \u25BC \u25BC (", item.lineCount - scrollPosition - visibleLines.length, " d\xF2ng \u1EDF d\u01B0\u1EDBi) \u25BC \u25BC \u25BC")), item.previewLines.length === 0 && /* @__PURE__ */ React10.createElement(Text8, { dimColor: true }, "Kh\xF4ng c\xF3 n\u1ED9i dung \u0111\u1EC3 hi\u1EC3n th\u1ECB")));
|
|
2359
2745
|
};
|
|
2360
2746
|
|
|
2361
2747
|
// src/services/context-scanner.service.ts
|
|
@@ -2708,15 +3094,15 @@ var ContextScannerService = class {
|
|
|
2708
3094
|
|
|
2709
3095
|
// src/ui/context/ContextApp.tsx
|
|
2710
3096
|
var ContextApp = ({ initialIDE, initialType, onExit }) => {
|
|
2711
|
-
const { exit } =
|
|
2712
|
-
const [screen, setScreen] =
|
|
2713
|
-
const [selectedIDE, setSelectedIDE] =
|
|
2714
|
-
const [selectedType, setSelectedType] =
|
|
2715
|
-
const [selectedItem, setSelectedItem] =
|
|
2716
|
-
const [ideContexts, setIdeContexts] =
|
|
2717
|
-
const [loading, setLoading] =
|
|
2718
|
-
const [scrollPosition, setScrollPosition] =
|
|
2719
|
-
|
|
3097
|
+
const { exit } = useApp3();
|
|
3098
|
+
const [screen, setScreen] = useState7("menu");
|
|
3099
|
+
const [selectedIDE, setSelectedIDE] = useState7(initialIDE || null);
|
|
3100
|
+
const [selectedType, setSelectedType] = useState7(initialType || null);
|
|
3101
|
+
const [selectedItem, setSelectedItem] = useState7(null);
|
|
3102
|
+
const [ideContexts, setIdeContexts] = useState7([]);
|
|
3103
|
+
const [loading, setLoading] = useState7(true);
|
|
3104
|
+
const [scrollPosition, setScrollPosition] = useState7(0);
|
|
3105
|
+
useEffect3(() => {
|
|
2720
3106
|
const scanner = new ContextScannerService();
|
|
2721
3107
|
scanner.scanAll().then((result) => {
|
|
2722
3108
|
setIdeContexts(result.ides);
|
|
@@ -2729,7 +3115,7 @@ var ContextApp = ({ initialIDE, initialType, onExit }) => {
|
|
|
2729
3115
|
setLoading(false);
|
|
2730
3116
|
});
|
|
2731
3117
|
}, [initialIDE]);
|
|
2732
|
-
|
|
3118
|
+
useInput7((input5, key) => {
|
|
2733
3119
|
if (input5 === "q") {
|
|
2734
3120
|
onExit();
|
|
2735
3121
|
return;
|
|
@@ -2771,13 +3157,13 @@ var ContextApp = ({ initialIDE, initialType, onExit }) => {
|
|
|
2771
3157
|
const currentItems = currentIDEContext?.items?.filter((item) => item.type === selectedType) ?? [];
|
|
2772
3158
|
const renderContent = () => {
|
|
2773
3159
|
if (loading) {
|
|
2774
|
-
return /* @__PURE__ */
|
|
3160
|
+
return /* @__PURE__ */ React11.createElement(Box8, { padding: 1 }, /* @__PURE__ */ React11.createElement(Text9, null, "\u0110ang qu\xE9t context..."));
|
|
2775
3161
|
}
|
|
2776
3162
|
switch (screen) {
|
|
2777
3163
|
case "menu":
|
|
2778
|
-
return /* @__PURE__ */
|
|
3164
|
+
return /* @__PURE__ */ React11.createElement(MainMenuView, { ideContexts, onSelect: handleSelectIDE });
|
|
2779
3165
|
case "overview":
|
|
2780
|
-
return currentIDEContext ? /* @__PURE__ */
|
|
3166
|
+
return currentIDEContext ? /* @__PURE__ */ React11.createElement(
|
|
2781
3167
|
IDEOverviewView,
|
|
2782
3168
|
{
|
|
2783
3169
|
ideContext: currentIDEContext,
|
|
@@ -2786,7 +3172,7 @@ var ContextApp = ({ initialIDE, initialType, onExit }) => {
|
|
|
2786
3172
|
}
|
|
2787
3173
|
) : null;
|
|
2788
3174
|
case "list":
|
|
2789
|
-
return /* @__PURE__ */
|
|
3175
|
+
return /* @__PURE__ */ React11.createElement(
|
|
2790
3176
|
ListView,
|
|
2791
3177
|
{
|
|
2792
3178
|
items: currentItems,
|
|
@@ -2796,7 +3182,7 @@ var ContextApp = ({ initialIDE, initialType, onExit }) => {
|
|
|
2796
3182
|
}
|
|
2797
3183
|
);
|
|
2798
3184
|
case "detail":
|
|
2799
|
-
return selectedItem ? /* @__PURE__ */
|
|
3185
|
+
return selectedItem ? /* @__PURE__ */ React11.createElement(
|
|
2800
3186
|
DetailView,
|
|
2801
3187
|
{
|
|
2802
3188
|
item: selectedItem,
|
|
@@ -2805,7 +3191,7 @@ var ContextApp = ({ initialIDE, initialType, onExit }) => {
|
|
|
2805
3191
|
}
|
|
2806
3192
|
) : null;
|
|
2807
3193
|
default:
|
|
2808
|
-
return /* @__PURE__ */
|
|
3194
|
+
return /* @__PURE__ */ React11.createElement(MainMenuView, { ideContexts, onSelect: handleSelectIDE });
|
|
2809
3195
|
}
|
|
2810
3196
|
};
|
|
2811
3197
|
const getFooterHints = () => {
|
|
@@ -2822,12 +3208,12 @@ var ContextApp = ({ initialIDE, initialType, onExit }) => {
|
|
|
2822
3208
|
return "[q] Tho\xE1t";
|
|
2823
3209
|
}
|
|
2824
3210
|
};
|
|
2825
|
-
return /* @__PURE__ */
|
|
3211
|
+
return /* @__PURE__ */ React11.createElement(Box8, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React11.createElement(Box8, { marginBottom: 1 }, /* @__PURE__ */ React11.createElement(Text9, { bold: true, color: "cyan" }, "\u{1F4CB} Jai1 Context"), /* @__PURE__ */ React11.createElement(Text9, { dimColor: true }, " - Kh\xE1m ph\xE1 context d\u1EF1 \xE1n")), renderContent(), /* @__PURE__ */ React11.createElement(Box8, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 1 }, /* @__PURE__ */ React11.createElement(Text9, { dimColor: true }, getFooterHints())));
|
|
2826
3212
|
};
|
|
2827
3213
|
|
|
2828
3214
|
// src/commands/ide/context.ts
|
|
2829
3215
|
function createContextSubcommand() {
|
|
2830
|
-
const cmd = new
|
|
3216
|
+
const cmd = new Command7("context").description("Browse and explore IDE context (rules, workflows, skills)").option("--target <ide>", "Open specific IDE context (cursor, windsurf, antigravity, jai1)").option("--type <type>", "Show specific content type (rules, workflows, skills, agents, prompts)").option("--stats", "Show context statistics (non-interactive)").action(async (options) => {
|
|
2831
3217
|
let initialIDE;
|
|
2832
3218
|
if (options.target) {
|
|
2833
3219
|
const validIDEs = ["cursor", "windsurf", "antigravity", "jai1"];
|
|
@@ -2852,8 +3238,8 @@ function createContextSubcommand() {
|
|
|
2852
3238
|
await printStats();
|
|
2853
3239
|
return;
|
|
2854
3240
|
}
|
|
2855
|
-
const { waitUntilExit } =
|
|
2856
|
-
|
|
3241
|
+
const { waitUntilExit } = render3(
|
|
3242
|
+
React12.createElement(ContextApp, {
|
|
2857
3243
|
initialIDE,
|
|
2858
3244
|
initialType,
|
|
2859
3245
|
onExit: () => {
|
|
@@ -2904,7 +3290,7 @@ async function printStats() {
|
|
|
2904
3290
|
}
|
|
2905
3291
|
|
|
2906
3292
|
// src/commands/ide/setup.ts
|
|
2907
|
-
import { Command as
|
|
3293
|
+
import { Command as Command8 } from "commander";
|
|
2908
3294
|
import { checkbox, confirm as confirm2, select } from "@inquirer/prompts";
|
|
2909
3295
|
import fs6 from "fs/promises";
|
|
2910
3296
|
import path3 from "path";
|
|
@@ -3063,7 +3449,7 @@ var PERFORMANCE_GROUPS = {
|
|
|
3063
3449
|
}
|
|
3064
3450
|
};
|
|
3065
3451
|
function createSetupSubcommand() {
|
|
3066
|
-
const setupCommand = new
|
|
3452
|
+
const setupCommand = new Command8("setup").description("Configure IDE settings and optimizations");
|
|
3067
3453
|
setupCommand.action(async () => {
|
|
3068
3454
|
await interactiveMode();
|
|
3069
3455
|
});
|
|
@@ -3234,10 +3620,10 @@ async function resetSettings(groupKeys) {
|
|
|
3234
3620
|
}
|
|
3235
3621
|
|
|
3236
3622
|
// src/commands/ide/sync.ts
|
|
3237
|
-
import { Command as
|
|
3623
|
+
import { Command as Command9 } from "commander";
|
|
3238
3624
|
import { checkbox as checkbox2, confirm as confirm3 } from "@inquirer/prompts";
|
|
3239
3625
|
function createSyncSubcommand() {
|
|
3240
|
-
const cmd = new
|
|
3626
|
+
const cmd = new Command9("sync").description("Sync .jai1 content to IDE directories (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) => {
|
|
3241
3627
|
await runSync(options);
|
|
3242
3628
|
});
|
|
3243
3629
|
return cmd;
|
|
@@ -3349,7 +3735,7 @@ async function runSync(options) {
|
|
|
3349
3735
|
}
|
|
3350
3736
|
|
|
3351
3737
|
// src/commands/ide/status.ts
|
|
3352
|
-
import { Command as
|
|
3738
|
+
import { Command as Command10 } from "commander";
|
|
3353
3739
|
|
|
3354
3740
|
// src/services/ide-detection.service.ts
|
|
3355
3741
|
import { promises as fs7 } from "fs";
|
|
@@ -3683,7 +4069,7 @@ var IdeDetectionService = class {
|
|
|
3683
4069
|
|
|
3684
4070
|
// src/commands/ide/status.ts
|
|
3685
4071
|
function createStatusSubcommand() {
|
|
3686
|
-
const cmd = new
|
|
4072
|
+
const cmd = new Command10("status").description("Show detected IDEs and their configuration status").option("--json", "Output as JSON").option("--suggestions", "Show IDE suggestions based on project structure").action(async (options) => {
|
|
3687
4073
|
await runStatus(options);
|
|
3688
4074
|
});
|
|
3689
4075
|
return cmd;
|
|
@@ -3801,7 +4187,7 @@ function showIdeHelp() {
|
|
|
3801
4187
|
console.log(chalk5.dim('Ch\u1EA1y "jai1 ide <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt'));
|
|
3802
4188
|
}
|
|
3803
4189
|
function createIdeCommand() {
|
|
3804
|
-
const ideCommand = new
|
|
4190
|
+
const ideCommand = new Command11("ide").description("IDE integration and configuration commands").action(() => {
|
|
3805
4191
|
showIdeHelp();
|
|
3806
4192
|
});
|
|
3807
4193
|
ideCommand.addCommand(createContextSubcommand());
|
|
@@ -3812,17 +4198,17 @@ function createIdeCommand() {
|
|
|
3812
4198
|
}
|
|
3813
4199
|
|
|
3814
4200
|
// src/commands/guide.ts
|
|
3815
|
-
import
|
|
3816
|
-
import { render as
|
|
3817
|
-
import { Command as
|
|
4201
|
+
import React25 from "react";
|
|
4202
|
+
import { render as render4 } from "ink";
|
|
4203
|
+
import { Command as Command12 } from "commander";
|
|
3818
4204
|
|
|
3819
4205
|
// src/ui/guide/GuideApp.tsx
|
|
3820
|
-
import
|
|
3821
|
-
import { Box as
|
|
4206
|
+
import React24, { useState as useState10, useEffect as useEffect5, useCallback as useCallback2 } from "react";
|
|
4207
|
+
import { Box as Box20, Text as Text20, useInput as useInput9, useApp as useApp4 } from "ink";
|
|
3822
4208
|
|
|
3823
4209
|
// src/ui/guide/components/Layout.tsx
|
|
3824
|
-
import
|
|
3825
|
-
import { Box as
|
|
4210
|
+
import React15 from "react";
|
|
4211
|
+
import { Box as Box11, useStdout } from "ink";
|
|
3826
4212
|
|
|
3827
4213
|
// src/ui/guide/utils/theme.ts
|
|
3828
4214
|
var colors2 = {
|
|
@@ -3923,25 +4309,25 @@ var layout = {
|
|
|
3923
4309
|
};
|
|
3924
4310
|
|
|
3925
4311
|
// src/ui/guide/components/Header.tsx
|
|
3926
|
-
import
|
|
3927
|
-
import { Box as
|
|
4312
|
+
import React13 from "react";
|
|
4313
|
+
import { Box as Box9, Text as Text10 } from "ink";
|
|
3928
4314
|
var Header = ({ showSearch = true }) => {
|
|
3929
|
-
return /* @__PURE__ */
|
|
3930
|
-
|
|
4315
|
+
return /* @__PURE__ */ React13.createElement(
|
|
4316
|
+
Box9,
|
|
3931
4317
|
{
|
|
3932
4318
|
borderStyle: borders.header.style,
|
|
3933
4319
|
borderColor: borders.header.color,
|
|
3934
4320
|
paddingX: 1,
|
|
3935
4321
|
justifyContent: "space-between"
|
|
3936
4322
|
},
|
|
3937
|
-
/* @__PURE__ */
|
|
3938
|
-
/* @__PURE__ */
|
|
4323
|
+
/* @__PURE__ */ React13.createElement(Box9, null, /* @__PURE__ */ React13.createElement(Text10, { bold: true, color: colors2.header.title }, "\u{1F393} Jai1 Guide"), /* @__PURE__ */ React13.createElement(Text10, { dimColor: true }, " - Trung t\xE2m h\u01B0\u1EDBng d\u1EABn Agentic Coding")),
|
|
4324
|
+
/* @__PURE__ */ React13.createElement(Box9, null, showSearch && /* @__PURE__ */ React13.createElement(Text10, { dimColor: true }, /* @__PURE__ */ React13.createElement(Text10, { color: colors2.footer.key }, "[/]"), " Search", " "), /* @__PURE__ */ React13.createElement(Text10, { dimColor: true }, /* @__PURE__ */ React13.createElement(Text10, { color: colors2.footer.key }, "[q]"), " Quit"))
|
|
3939
4325
|
);
|
|
3940
4326
|
};
|
|
3941
4327
|
|
|
3942
4328
|
// src/ui/guide/components/Footer.tsx
|
|
3943
|
-
import
|
|
3944
|
-
import { Box as
|
|
4329
|
+
import React14 from "react";
|
|
4330
|
+
import { Box as Box10, Text as Text11 } from "ink";
|
|
3945
4331
|
var Footer = ({ focusArea, isSearchOpen = false }) => {
|
|
3946
4332
|
const getShortcuts = () => {
|
|
3947
4333
|
if (isSearchOpen) {
|
|
@@ -3969,15 +4355,15 @@ var Footer = ({ focusArea, isSearchOpen = false }) => {
|
|
|
3969
4355
|
];
|
|
3970
4356
|
};
|
|
3971
4357
|
const shortcuts = getShortcuts();
|
|
3972
|
-
return /* @__PURE__ */
|
|
3973
|
-
|
|
4358
|
+
return /* @__PURE__ */ React14.createElement(
|
|
4359
|
+
Box10,
|
|
3974
4360
|
{
|
|
3975
4361
|
borderStyle: "single",
|
|
3976
4362
|
borderColor: colors2.muted,
|
|
3977
4363
|
paddingX: 1,
|
|
3978
4364
|
justifyContent: "center"
|
|
3979
4365
|
},
|
|
3980
|
-
/* @__PURE__ */
|
|
4366
|
+
/* @__PURE__ */ React14.createElement(Box10, null, shortcuts.map((shortcut, index) => /* @__PURE__ */ React14.createElement(React14.Fragment, { key: shortcut.key }, index > 0 && /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, " \xB7 "), /* @__PURE__ */ React14.createElement(Text11, { color: colors2.footer.key }, "[", shortcut.key, "]"), /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, " ", shortcut.action))))
|
|
3981
4367
|
);
|
|
3982
4368
|
};
|
|
3983
4369
|
|
|
@@ -3995,8 +4381,8 @@ var Layout = ({
|
|
|
3995
4381
|
const sidebarWidth = Math.min(layout.sidebarWidth, Math.floor(terminalWidth * 0.3));
|
|
3996
4382
|
const contentWidth = terminalWidth - sidebarWidth - 4;
|
|
3997
4383
|
const mainHeight = Math.max(10, terminalHeight - 6);
|
|
3998
|
-
return /* @__PURE__ */
|
|
3999
|
-
|
|
4384
|
+
return /* @__PURE__ */ React15.createElement(Box11, { flexDirection: "column", width: terminalWidth }, /* @__PURE__ */ React15.createElement(Header, { showSearch: !isSearchOpen }), /* @__PURE__ */ React15.createElement(Box11, { height: mainHeight }, /* @__PURE__ */ React15.createElement(
|
|
4385
|
+
Box11,
|
|
4000
4386
|
{
|
|
4001
4387
|
flexDirection: "column",
|
|
4002
4388
|
width: sidebarWidth,
|
|
@@ -4005,8 +4391,8 @@ var Layout = ({
|
|
|
4005
4391
|
paddingX: 1
|
|
4006
4392
|
},
|
|
4007
4393
|
sidebar
|
|
4008
|
-
), /* @__PURE__ */
|
|
4009
|
-
|
|
4394
|
+
), /* @__PURE__ */ React15.createElement(
|
|
4395
|
+
Box11,
|
|
4010
4396
|
{
|
|
4011
4397
|
flexDirection: "column",
|
|
4012
4398
|
flexGrow: 1,
|
|
@@ -4016,8 +4402,8 @@ var Layout = ({
|
|
|
4016
4402
|
marginLeft: -1
|
|
4017
4403
|
},
|
|
4018
4404
|
content
|
|
4019
|
-
)), /* @__PURE__ */
|
|
4020
|
-
|
|
4405
|
+
)), /* @__PURE__ */ React15.createElement(Footer, { focusArea, isSearchOpen }), isSearchOpen && searchOverlay && /* @__PURE__ */ React15.createElement(
|
|
4406
|
+
Box11,
|
|
4021
4407
|
{
|
|
4022
4408
|
position: "absolute",
|
|
4023
4409
|
marginTop: 3,
|
|
@@ -4033,12 +4419,12 @@ var Layout = ({
|
|
|
4033
4419
|
};
|
|
4034
4420
|
|
|
4035
4421
|
// src/ui/guide/components/Sidebar/index.tsx
|
|
4036
|
-
import
|
|
4037
|
-
import { Box as
|
|
4422
|
+
import React18 from "react";
|
|
4423
|
+
import { Box as Box14 } from "ink";
|
|
4038
4424
|
|
|
4039
4425
|
// src/ui/guide/components/Sidebar/MainMenu.tsx
|
|
4040
|
-
import
|
|
4041
|
-
import { Box as
|
|
4426
|
+
import React16 from "react";
|
|
4427
|
+
import { Box as Box12, Text as Text13 } from "ink";
|
|
4042
4428
|
var MENU_ITEMS = [
|
|
4043
4429
|
{ id: "intro", icon: icons.menu.intro, title: "Gi\u1EDBi thi\u1EC7u" },
|
|
4044
4430
|
{ id: "rules", icon: icons.menu.rules, title: "IDE Rules" },
|
|
@@ -4052,11 +4438,11 @@ var MainMenu = ({
|
|
|
4052
4438
|
onSelect,
|
|
4053
4439
|
isFocused
|
|
4054
4440
|
}) => {
|
|
4055
|
-
return /* @__PURE__ */
|
|
4441
|
+
return /* @__PURE__ */ React16.createElement(Box12, { flexDirection: "column" }, /* @__PURE__ */ React16.createElement(Box12, { marginBottom: 1 }, /* @__PURE__ */ React16.createElement(Text13, { bold: true, color: colors2.sidebar.heading }, "\u{1F4DA} MENU")), MENU_ITEMS.map((item, index) => {
|
|
4056
4442
|
const isSelected = isFocused && index === selectedIndex;
|
|
4057
4443
|
const isActive = item.id === currentTopic;
|
|
4058
|
-
return /* @__PURE__ */
|
|
4059
|
-
|
|
4444
|
+
return /* @__PURE__ */ React16.createElement(Box12, { key: item.id }, /* @__PURE__ */ React16.createElement(Text13, { color: isSelected ? colors2.sidebar.selected : void 0 }, isSelected ? icons.ui.selected : icons.ui.unselected), /* @__PURE__ */ React16.createElement(
|
|
4445
|
+
Text13,
|
|
4060
4446
|
{
|
|
4061
4447
|
color: isActive ? colors2.sidebar.active : isSelected ? colors2.sidebar.selected : void 0,
|
|
4062
4448
|
bold: isActive
|
|
@@ -4065,13 +4451,13 @@ var MainMenu = ({
|
|
|
4065
4451
|
item.icon,
|
|
4066
4452
|
" ",
|
|
4067
4453
|
item.title
|
|
4068
|
-
), item.badge && /* @__PURE__ */
|
|
4454
|
+
), item.badge && /* @__PURE__ */ React16.createElement(Text13, { color: "yellow", dimColor: true }, " ", "[", item.badge, "]"), isActive && /* @__PURE__ */ React16.createElement(Text13, { color: colors2.sidebar.active }, " \u25C0"));
|
|
4069
4455
|
}));
|
|
4070
4456
|
};
|
|
4071
4457
|
|
|
4072
4458
|
// src/ui/guide/components/Sidebar/TableOfContents.tsx
|
|
4073
|
-
import
|
|
4074
|
-
import { Box as
|
|
4459
|
+
import React17 from "react";
|
|
4460
|
+
import { Box as Box13, Text as Text14 } from "ink";
|
|
4075
4461
|
var TableOfContents = ({
|
|
4076
4462
|
toc,
|
|
4077
4463
|
selectedIndex,
|
|
@@ -4089,15 +4475,15 @@ var TableOfContents = ({
|
|
|
4089
4475
|
Math.min(selectedIndex - Math.floor(maxVisible / 2), sections.length - maxVisible)
|
|
4090
4476
|
);
|
|
4091
4477
|
const visibleSections = sections.slice(startIndex, startIndex + maxVisible);
|
|
4092
|
-
return /* @__PURE__ */
|
|
4478
|
+
return /* @__PURE__ */ React17.createElement(Box13, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React17.createElement(Box13, { marginBottom: 1 }, /* @__PURE__ */ React17.createElement(Text14, { dimColor: true }, "\u2500".repeat(18))), /* @__PURE__ */ React17.createElement(Box13, { marginBottom: 1 }, /* @__PURE__ */ React17.createElement(Text14, { bold: true, color: colors2.sidebar.heading }, "\u{1F4D1} ", topicTitle || "Contents")), startIndex > 0 && /* @__PURE__ */ React17.createElement(Box13, { justifyContent: "center" }, /* @__PURE__ */ React17.createElement(Text14, { dimColor: true }, icons.ui.scrollUp)), visibleSections.map((entry, visibleIndex) => {
|
|
4093
4479
|
const actualIndex = startIndex + visibleIndex;
|
|
4094
4480
|
const isSelected = isFocused && actualIndex === selectedIndex;
|
|
4095
4481
|
const isActive = entry.id === activeSection;
|
|
4096
4482
|
const indent = " ".repeat(entry.level - 2);
|
|
4097
4483
|
const maxLength = 14;
|
|
4098
4484
|
const displayText = entry.text.length > maxLength ? entry.text.substring(0, maxLength - 1) + "\u2026" : entry.text;
|
|
4099
|
-
return /* @__PURE__ */
|
|
4100
|
-
|
|
4485
|
+
return /* @__PURE__ */ React17.createElement(Box13, { key: entry.id }, /* @__PURE__ */ React17.createElement(Text14, { color: isSelected ? colors2.sidebar.selected : void 0 }, isSelected ? icons.ui.selected : icons.ui.unselected), /* @__PURE__ */ React17.createElement(
|
|
4486
|
+
Text14,
|
|
4101
4487
|
{
|
|
4102
4488
|
color: isActive ? colors2.sidebar.active : isSelected ? colors2.sidebar.selected : colors2.muted
|
|
4103
4489
|
},
|
|
@@ -4105,8 +4491,8 @@ var TableOfContents = ({
|
|
|
4105
4491
|
icons.ui.bullet,
|
|
4106
4492
|
" ",
|
|
4107
4493
|
displayText
|
|
4108
|
-
), isActive && /* @__PURE__ */
|
|
4109
|
-
}), startIndex + maxVisible < sections.length && /* @__PURE__ */
|
|
4494
|
+
), isActive && /* @__PURE__ */ React17.createElement(Text14, { color: colors2.sidebar.active }, " \u25C0"));
|
|
4495
|
+
}), startIndex + maxVisible < sections.length && /* @__PURE__ */ React17.createElement(Box13, { justifyContent: "center" }, /* @__PURE__ */ React17.createElement(Text14, { dimColor: true }, icons.ui.scrollDown)));
|
|
4110
4496
|
};
|
|
4111
4497
|
|
|
4112
4498
|
// src/ui/guide/components/Sidebar/index.tsx
|
|
@@ -4121,7 +4507,7 @@ var Sidebar = ({
|
|
|
4121
4507
|
onSelectTopic,
|
|
4122
4508
|
onSelectSection
|
|
4123
4509
|
}) => {
|
|
4124
|
-
return /* @__PURE__ */
|
|
4510
|
+
return /* @__PURE__ */ React18.createElement(Box14, { flexDirection: "column", height: "100%" }, /* @__PURE__ */ React18.createElement(
|
|
4125
4511
|
MainMenu,
|
|
4126
4512
|
{
|
|
4127
4513
|
selectedIndex: menuIndex,
|
|
@@ -4129,7 +4515,7 @@ var Sidebar = ({
|
|
|
4129
4515
|
onSelect: onSelectTopic,
|
|
4130
4516
|
isFocused: isFocused && mode === "menu"
|
|
4131
4517
|
}
|
|
4132
|
-
), currentTopic && toc.length > 0 && /* @__PURE__ */
|
|
4518
|
+
), currentTopic && toc.length > 0 && /* @__PURE__ */ React18.createElement(
|
|
4133
4519
|
TableOfContents,
|
|
4134
4520
|
{
|
|
4135
4521
|
toc,
|
|
@@ -4141,18 +4527,18 @@ var Sidebar = ({
|
|
|
4141
4527
|
};
|
|
4142
4528
|
|
|
4143
4529
|
// src/ui/guide/components/Content/ContentPane.tsx
|
|
4144
|
-
import
|
|
4145
|
-
import { Box as
|
|
4530
|
+
import React22 from "react";
|
|
4531
|
+
import { Box as Box18, Text as Text18 } from "ink";
|
|
4146
4532
|
|
|
4147
4533
|
// src/ui/guide/components/Content/Breadcrumb.tsx
|
|
4148
|
-
import
|
|
4149
|
-
import { Box as
|
|
4534
|
+
import React19 from "react";
|
|
4535
|
+
import { Box as Box15, Text as Text15 } from "ink";
|
|
4150
4536
|
var Breadcrumb = ({ items }) => {
|
|
4151
4537
|
if (items.length === 0) {
|
|
4152
4538
|
return null;
|
|
4153
4539
|
}
|
|
4154
|
-
return /* @__PURE__ */
|
|
4155
|
-
|
|
4540
|
+
return /* @__PURE__ */ React19.createElement(Box15, { marginBottom: 1 }, /* @__PURE__ */ React19.createElement(Text15, { dimColor: true }, "\u250C\u2500 "), items.map((item, index) => /* @__PURE__ */ React19.createElement(React19.Fragment, { key: index }, index > 0 && /* @__PURE__ */ React19.createElement(Text15, { color: colors2.muted }, " ", ">", " "), /* @__PURE__ */ React19.createElement(
|
|
4541
|
+
Text15,
|
|
4156
4542
|
{
|
|
4157
4543
|
color: index === items.length - 1 ? colors2.secondary : colors2.muted,
|
|
4158
4544
|
bold: index === items.length - 1
|
|
@@ -4162,14 +4548,14 @@ var Breadcrumb = ({ items }) => {
|
|
|
4162
4548
|
};
|
|
4163
4549
|
|
|
4164
4550
|
// src/ui/guide/components/Content/MarkdownRenderer.tsx
|
|
4165
|
-
import
|
|
4166
|
-
import { Box as
|
|
4551
|
+
import React20 from "react";
|
|
4552
|
+
import { Box as Box16, Text as Text16 } from "ink";
|
|
4167
4553
|
var SectionRenderer = ({ section }) => {
|
|
4168
4554
|
switch (section.type) {
|
|
4169
4555
|
case "heading":
|
|
4170
4556
|
if (section.level === 1) {
|
|
4171
|
-
return /* @__PURE__ */
|
|
4172
|
-
|
|
4557
|
+
return /* @__PURE__ */ React20.createElement(
|
|
4558
|
+
Box16,
|
|
4173
4559
|
{
|
|
4174
4560
|
flexDirection: "column",
|
|
4175
4561
|
marginBottom: 1,
|
|
@@ -4177,18 +4563,18 @@ var SectionRenderer = ({ section }) => {
|
|
|
4177
4563
|
borderColor: borders.header.color,
|
|
4178
4564
|
paddingX: 1
|
|
4179
4565
|
},
|
|
4180
|
-
/* @__PURE__ */
|
|
4566
|
+
/* @__PURE__ */ React20.createElement(Text16, { bold: true, color: colors2.content.heading }, section.content)
|
|
4181
4567
|
);
|
|
4182
4568
|
} else if (section.level === 2) {
|
|
4183
|
-
return /* @__PURE__ */
|
|
4569
|
+
return /* @__PURE__ */ React20.createElement(Box16, { marginTop: 1, marginBottom: 1 }, /* @__PURE__ */ React20.createElement(Text16, { bold: true, color: colors2.content.subheading }, "## ", section.content));
|
|
4184
4570
|
} else {
|
|
4185
|
-
return /* @__PURE__ */
|
|
4571
|
+
return /* @__PURE__ */ React20.createElement(Box16, { marginTop: 1 }, /* @__PURE__ */ React20.createElement(Text16, { bold: true }, "### ", section.content));
|
|
4186
4572
|
}
|
|
4187
4573
|
case "paragraph":
|
|
4188
|
-
return /* @__PURE__ */
|
|
4574
|
+
return /* @__PURE__ */ React20.createElement(Box16, { marginBottom: 1, flexDirection: "column" }, section.content.split("\n").map((line, i) => /* @__PURE__ */ React20.createElement(Text16, { key: i }, line)));
|
|
4189
4575
|
case "code":
|
|
4190
|
-
return /* @__PURE__ */
|
|
4191
|
-
|
|
4576
|
+
return /* @__PURE__ */ React20.createElement(
|
|
4577
|
+
Box16,
|
|
4192
4578
|
{
|
|
4193
4579
|
flexDirection: "column",
|
|
4194
4580
|
marginY: 1,
|
|
@@ -4196,37 +4582,37 @@ var SectionRenderer = ({ section }) => {
|
|
|
4196
4582
|
borderColor: borders.code.color,
|
|
4197
4583
|
paddingX: 1
|
|
4198
4584
|
},
|
|
4199
|
-
section.language && /* @__PURE__ */
|
|
4200
|
-
section.content.split("\n").map((line, i) => /* @__PURE__ */
|
|
4585
|
+
section.language && /* @__PURE__ */ React20.createElement(Text16, { dimColor: true }, "[", section.language, "]"),
|
|
4586
|
+
section.content.split("\n").map((line, i) => /* @__PURE__ */ React20.createElement(Text16, { key: i, color: colors2.content.code }, line))
|
|
4201
4587
|
);
|
|
4202
4588
|
case "tip":
|
|
4203
|
-
return /* @__PURE__ */
|
|
4204
|
-
|
|
4589
|
+
return /* @__PURE__ */ React20.createElement(
|
|
4590
|
+
Box16,
|
|
4205
4591
|
{
|
|
4206
4592
|
marginY: 1,
|
|
4207
4593
|
borderStyle: borders.tip.style,
|
|
4208
4594
|
borderColor: borders.tip.color,
|
|
4209
4595
|
paddingX: 1
|
|
4210
4596
|
},
|
|
4211
|
-
/* @__PURE__ */
|
|
4597
|
+
/* @__PURE__ */ React20.createElement(Text16, { color: colors2.success }, icons.ui.tip, " ", /* @__PURE__ */ React20.createElement(Text16, { bold: true }, "Tip:"), " ", section.content)
|
|
4212
4598
|
);
|
|
4213
4599
|
case "warning":
|
|
4214
|
-
return /* @__PURE__ */
|
|
4215
|
-
|
|
4600
|
+
return /* @__PURE__ */ React20.createElement(
|
|
4601
|
+
Box16,
|
|
4216
4602
|
{
|
|
4217
4603
|
marginY: 1,
|
|
4218
4604
|
borderStyle: borders.warning.style,
|
|
4219
4605
|
borderColor: borders.warning.color,
|
|
4220
4606
|
paddingX: 1
|
|
4221
4607
|
},
|
|
4222
|
-
/* @__PURE__ */
|
|
4608
|
+
/* @__PURE__ */ React20.createElement(Text16, { color: colors2.warning }, icons.ui.warning, " ", /* @__PURE__ */ React20.createElement(Text16, { bold: true }, "Warning:"), " ", section.content)
|
|
4223
4609
|
);
|
|
4224
4610
|
case "blockquote":
|
|
4225
|
-
return /* @__PURE__ */
|
|
4611
|
+
return /* @__PURE__ */ React20.createElement(Box16, { marginY: 1, paddingLeft: 1 }, /* @__PURE__ */ React20.createElement(Text16, { color: colors2.muted }, "\u2502 "), /* @__PURE__ */ React20.createElement(Text16, { italic: true, color: colors2.content.blockquote }, section.content));
|
|
4226
4612
|
case "list":
|
|
4227
|
-
return /* @__PURE__ */
|
|
4613
|
+
return /* @__PURE__ */ React20.createElement(Box16, { flexDirection: "column", marginY: 1 }, (section.items || []).map((item, i) => /* @__PURE__ */ React20.createElement(Box16, { key: i }, /* @__PURE__ */ React20.createElement(Text16, null, " ", icons.ui.bullet, " ", item))));
|
|
4228
4614
|
default:
|
|
4229
|
-
return /* @__PURE__ */
|
|
4615
|
+
return /* @__PURE__ */ React20.createElement(Box16, { marginBottom: 1 }, /* @__PURE__ */ React20.createElement(Text16, null, section.content));
|
|
4230
4616
|
}
|
|
4231
4617
|
};
|
|
4232
4618
|
var MarkdownRenderer = ({
|
|
@@ -4240,18 +4626,18 @@ var MarkdownRenderer = ({
|
|
|
4240
4626
|
);
|
|
4241
4627
|
const hasMore = scrollPosition + maxLines < sections.length;
|
|
4242
4628
|
const hasPrevious = scrollPosition > 0;
|
|
4243
|
-
return /* @__PURE__ */
|
|
4629
|
+
return /* @__PURE__ */ React20.createElement(Box16, { flexDirection: "column" }, hasPrevious && /* @__PURE__ */ React20.createElement(Box16, { justifyContent: "center" }, /* @__PURE__ */ React20.createElement(Text16, { dimColor: true }, icons.ui.scrollUp, " Scroll up for more")), visibleSections.map((section, index) => /* @__PURE__ */ React20.createElement(
|
|
4244
4630
|
SectionRenderer,
|
|
4245
4631
|
{
|
|
4246
4632
|
key: `${section.type}-${scrollPosition + index}`,
|
|
4247
4633
|
section
|
|
4248
4634
|
}
|
|
4249
|
-
)), hasMore && /* @__PURE__ */
|
|
4635
|
+
)), hasMore && /* @__PURE__ */ React20.createElement(Box16, { justifyContent: "center", marginTop: 1 }, /* @__PURE__ */ React20.createElement(Text16, { dimColor: true }, icons.ui.scrollDown, " Scroll down for more (", sections.length - scrollPosition - maxLines, " more)")));
|
|
4250
4636
|
};
|
|
4251
4637
|
|
|
4252
4638
|
// src/ui/guide/components/Content/ScrollIndicator.tsx
|
|
4253
|
-
import
|
|
4254
|
-
import { Box as
|
|
4639
|
+
import React21 from "react";
|
|
4640
|
+
import { Box as Box17, Text as Text17 } from "ink";
|
|
4255
4641
|
var ScrollIndicator = ({
|
|
4256
4642
|
current,
|
|
4257
4643
|
total,
|
|
@@ -4264,7 +4650,7 @@ var ScrollIndicator = ({
|
|
|
4264
4650
|
const barWidth = 10;
|
|
4265
4651
|
const filledWidth = Math.round(percentage / 100 * barWidth);
|
|
4266
4652
|
const emptyWidth = barWidth - filledWidth;
|
|
4267
|
-
return /* @__PURE__ */
|
|
4653
|
+
return /* @__PURE__ */ React21.createElement(Box17, { justifyContent: "flex-end" }, /* @__PURE__ */ React21.createElement(Text17, { dimColor: true }, showPercentage && `${percentage}% `, /* @__PURE__ */ React21.createElement(Text17, { color: colors2.secondary }, "\u2588".repeat(filledWidth)), /* @__PURE__ */ React21.createElement(Text17, { color: colors2.muted }, "\u2591".repeat(emptyWidth)), " ", current + 1, "/", total));
|
|
4268
4654
|
};
|
|
4269
4655
|
|
|
4270
4656
|
// src/ui/guide/components/Content/ContentPane.tsx
|
|
@@ -4277,14 +4663,14 @@ var ContentPane = ({
|
|
|
4277
4663
|
isFocused
|
|
4278
4664
|
}) => {
|
|
4279
4665
|
const maxVisibleSections = layout.maxVisibleContentLines;
|
|
4280
|
-
return /* @__PURE__ */
|
|
4666
|
+
return /* @__PURE__ */ React22.createElement(Box18, { flexDirection: "column", height: "100%" }, /* @__PURE__ */ React22.createElement(Breadcrumb, { items: breadcrumb }), /* @__PURE__ */ React22.createElement(Box18, { flexDirection: "column", flexGrow: 1 }, /* @__PURE__ */ React22.createElement(
|
|
4281
4667
|
MarkdownRenderer,
|
|
4282
4668
|
{
|
|
4283
4669
|
sections,
|
|
4284
4670
|
scrollPosition,
|
|
4285
4671
|
maxLines: maxVisibleSections
|
|
4286
4672
|
}
|
|
4287
|
-
)), sections.length > maxVisibleSections && /* @__PURE__ */
|
|
4673
|
+
)), sections.length > maxVisibleSections && /* @__PURE__ */ React22.createElement(
|
|
4288
4674
|
ScrollIndicator,
|
|
4289
4675
|
{
|
|
4290
4676
|
current: scrollPosition,
|
|
@@ -4293,8 +4679,8 @@ var ContentPane = ({
|
|
|
4293
4679
|
));
|
|
4294
4680
|
};
|
|
4295
4681
|
var WelcomePane = () => {
|
|
4296
|
-
return /* @__PURE__ */
|
|
4297
|
-
|
|
4682
|
+
return /* @__PURE__ */ React22.createElement(Box18, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React22.createElement(
|
|
4683
|
+
Box18,
|
|
4298
4684
|
{
|
|
4299
4685
|
flexDirection: "column",
|
|
4300
4686
|
borderStyle: "round",
|
|
@@ -4302,20 +4688,20 @@ var WelcomePane = () => {
|
|
|
4302
4688
|
padding: 1,
|
|
4303
4689
|
marginBottom: 1
|
|
4304
4690
|
},
|
|
4305
|
-
/* @__PURE__ */
|
|
4306
|
-
/* @__PURE__ */
|
|
4307
|
-
/* @__PURE__ */
|
|
4308
|
-
/* @__PURE__ */
|
|
4309
|
-
), /* @__PURE__ */
|
|
4691
|
+
/* @__PURE__ */ React22.createElement(Text18, { bold: true, color: colors2.primary }, "Ch\xE0o m\u1EEBng \u0111\u1EBFn v\u1EDBi Jai1 Guide!"),
|
|
4692
|
+
/* @__PURE__ */ React22.createElement(Text18, null),
|
|
4693
|
+
/* @__PURE__ */ React22.createElement(Text18, null, "\u0110\xE2y l\xE0 trung t\xE2m h\u01B0\u1EDBng d\u1EABn gi\xFAp b\u1EA1n l\xE0m ch\u1EE7", " ", /* @__PURE__ */ React22.createElement(Text18, { bold: true, color: colors2.secondary }, "Agentic Coding"), " -"),
|
|
4694
|
+
/* @__PURE__ */ React22.createElement(Text18, null, "ph\u01B0\u01A1ng ph\xE1p ph\xE1t tri\u1EC3n ph\u1EA7n m\u1EC1m v\u1EDBi s\u1EF1 h\u1ED7 tr\u1EE3 c\u1EE7a AI.")
|
|
4695
|
+
), /* @__PURE__ */ React22.createElement(Box18, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React22.createElement(Text18, { bold: true, color: colors2.secondary }, "B\u1EAFt \u0111\u1EA7u:"), /* @__PURE__ */ React22.createElement(Text18, null), /* @__PURE__ */ React22.createElement(Text18, null, " \u2190 Ch\u1ECDn m\u1ED9t ch\u1EE7 \u0111\u1EC1 t\u1EEB menu b\xEAn tr\xE1i"), /* @__PURE__ */ React22.createElement(Text18, null), /* @__PURE__ */ React22.createElement(Text18, { dimColor: true }, " ho\u1EB7c nh\u1EA5n ", /* @__PURE__ */ React22.createElement(Text18, { color: colors2.footer.key }, "/"), " \u0111\u1EC3 t\xECm ki\u1EBFm")), /* @__PURE__ */ React22.createElement(Box18, { flexDirection: "column", marginTop: 2 }, /* @__PURE__ */ React22.createElement(Text18, { bold: true, color: colors2.secondary }, "G\u1EE3i \xFD \u0111\u1ECDc:"), /* @__PURE__ */ React22.createElement(Text18, null), /* @__PURE__ */ React22.createElement(Text18, null, " 1. ", /* @__PURE__ */ React22.createElement(Text18, { color: colors2.primary }, "Gi\u1EDBi thi\u1EC7u"), " - Hi\u1EC3u v\u1EC1 Agentic Coding"), /* @__PURE__ */ React22.createElement(Text18, null, " 2. ", /* @__PURE__ */ React22.createElement(Text18, { color: colors2.primary }, "IDE Rules"), " - N\u1EC1n t\u1EA3ng quan tr\u1ECDng nh\u1EA5t"), /* @__PURE__ */ React22.createElement(Text18, null, " 3. ", /* @__PURE__ */ React22.createElement(Text18, { color: colors2.primary }, "Workflows"), " - Quy tr\xECnh l\xE0m vi\u1EC7c")));
|
|
4310
4696
|
};
|
|
4311
4697
|
|
|
4312
4698
|
// src/ui/guide/components/Search/SearchOverlay.tsx
|
|
4313
|
-
import
|
|
4314
|
-
import { Box as
|
|
4315
|
-
import
|
|
4699
|
+
import React23, { useState as useState9, useCallback } from "react";
|
|
4700
|
+
import { Box as Box19, Text as Text19, useInput as useInput8 } from "ink";
|
|
4701
|
+
import TextInput3 from "ink-text-input";
|
|
4316
4702
|
|
|
4317
4703
|
// src/ui/guide/hooks/useContent.ts
|
|
4318
|
-
import { useState as
|
|
4704
|
+
import { useState as useState8, useEffect as useEffect4, useMemo as useMemo3 } from "react";
|
|
4319
4705
|
import matter3 from "gray-matter";
|
|
4320
4706
|
|
|
4321
4707
|
// src/ui/guide/utils/markdown.ts
|
|
@@ -5013,10 +5399,10 @@ AI ch\u1EA1y li\u1EC1n m\u1EA1ch, kh\xF4ng d\u1EEBng h\u1ECFi user tr\u1EEB khi
|
|
|
5013
5399
|
|
|
5014
5400
|
// src/ui/guide/hooks/useContent.ts
|
|
5015
5401
|
function useContent(topic) {
|
|
5016
|
-
const [content, setContent] =
|
|
5017
|
-
const [loading, setLoading] =
|
|
5018
|
-
const [error, setError] =
|
|
5019
|
-
|
|
5402
|
+
const [content, setContent] = useState8(null);
|
|
5403
|
+
const [loading, setLoading] = useState8(false);
|
|
5404
|
+
const [error, setError] = useState8(null);
|
|
5405
|
+
useEffect4(() => {
|
|
5020
5406
|
if (!topic) {
|
|
5021
5407
|
setContent(null);
|
|
5022
5408
|
return;
|
|
@@ -5053,7 +5439,7 @@ function useContent(topic) {
|
|
|
5053
5439
|
return { content, loading, error };
|
|
5054
5440
|
}
|
|
5055
5441
|
function useSearch(query) {
|
|
5056
|
-
return
|
|
5442
|
+
return useMemo3(() => {
|
|
5057
5443
|
if (!query || query.length < 2) {
|
|
5058
5444
|
return { results: [] };
|
|
5059
5445
|
}
|
|
@@ -5092,8 +5478,8 @@ var SearchOverlay = ({
|
|
|
5092
5478
|
onClose,
|
|
5093
5479
|
onSelectResult
|
|
5094
5480
|
}) => {
|
|
5095
|
-
const [query, setQuery] =
|
|
5096
|
-
const [selectedIndex, setSelectedIndex] =
|
|
5481
|
+
const [query, setQuery] = useState9("");
|
|
5482
|
+
const [selectedIndex, setSelectedIndex] = useState9(0);
|
|
5097
5483
|
const { results } = useSearch(query);
|
|
5098
5484
|
const flatResults = results.flatMap(
|
|
5099
5485
|
(r) => r.matches.map((m) => ({
|
|
@@ -5103,7 +5489,7 @@ var SearchOverlay = ({
|
|
|
5103
5489
|
context: m.context
|
|
5104
5490
|
}))
|
|
5105
5491
|
);
|
|
5106
|
-
|
|
5492
|
+
useInput8((input5, key) => {
|
|
5107
5493
|
if (key.escape) {
|
|
5108
5494
|
onClose();
|
|
5109
5495
|
return;
|
|
@@ -5129,8 +5515,8 @@ var SearchOverlay = ({
|
|
|
5129
5515
|
setQuery(value);
|
|
5130
5516
|
setSelectedIndex(0);
|
|
5131
5517
|
}, []);
|
|
5132
|
-
return /* @__PURE__ */
|
|
5133
|
-
|
|
5518
|
+
return /* @__PURE__ */ React23.createElement(
|
|
5519
|
+
Box19,
|
|
5134
5520
|
{
|
|
5135
5521
|
flexDirection: "column",
|
|
5136
5522
|
borderStyle: borders.search.style,
|
|
@@ -5138,18 +5524,18 @@ var SearchOverlay = ({
|
|
|
5138
5524
|
padding: 1,
|
|
5139
5525
|
width: 60
|
|
5140
5526
|
},
|
|
5141
|
-
/* @__PURE__ */
|
|
5142
|
-
/* @__PURE__ */
|
|
5143
|
-
|
|
5527
|
+
/* @__PURE__ */ React23.createElement(Box19, { marginBottom: 1 }, /* @__PURE__ */ React23.createElement(Text19, { bold: true, color: colors2.search.border }, icons.ui.search, " Search"), /* @__PURE__ */ React23.createElement(Box19, { flexGrow: 1 }), /* @__PURE__ */ React23.createElement(Text19, { dimColor: true }, "[Esc] Close")),
|
|
5528
|
+
/* @__PURE__ */ React23.createElement(
|
|
5529
|
+
Box19,
|
|
5144
5530
|
{
|
|
5145
5531
|
borderStyle: "single",
|
|
5146
5532
|
borderColor: colors2.secondary,
|
|
5147
5533
|
paddingX: 1,
|
|
5148
5534
|
marginBottom: 1
|
|
5149
5535
|
},
|
|
5150
|
-
/* @__PURE__ */
|
|
5151
|
-
/* @__PURE__ */
|
|
5152
|
-
|
|
5536
|
+
/* @__PURE__ */ React23.createElement(Text19, { color: colors2.secondary }, "\u276F "),
|
|
5537
|
+
/* @__PURE__ */ React23.createElement(
|
|
5538
|
+
TextInput3,
|
|
5153
5539
|
{
|
|
5154
5540
|
value: query,
|
|
5155
5541
|
onChange: handleQueryChange,
|
|
@@ -5158,11 +5544,11 @@ var SearchOverlay = ({
|
|
|
5158
5544
|
}
|
|
5159
5545
|
)
|
|
5160
5546
|
),
|
|
5161
|
-
/* @__PURE__ */
|
|
5547
|
+
/* @__PURE__ */ React23.createElement(Box19, { flexDirection: "column", maxHeight: 10 }, query.length < 2 ? /* @__PURE__ */ React23.createElement(Text19, { dimColor: true }, "Type at least 2 characters to search...") : flatResults.length === 0 ? /* @__PURE__ */ React23.createElement(Text19, { dimColor: true }, 'No results found for "', query, '"') : /* @__PURE__ */ React23.createElement(React23.Fragment, null, /* @__PURE__ */ React23.createElement(Text19, { dimColor: true, marginBottom: 1 }, "Found ", flatResults.length, " result(s):"), flatResults.slice(0, 5).map((result, index) => {
|
|
5162
5548
|
const isSelected = index === selectedIndex;
|
|
5163
5549
|
const matchText = result.match.length > 45 ? result.match.substring(0, 42) + "..." : result.match;
|
|
5164
|
-
return /* @__PURE__ */
|
|
5165
|
-
|
|
5550
|
+
return /* @__PURE__ */ React23.createElement(Box19, { key: `${result.topic}-${index}`, flexDirection: "column" }, /* @__PURE__ */ React23.createElement(Box19, null, /* @__PURE__ */ React23.createElement(
|
|
5551
|
+
Text19,
|
|
5166
5552
|
{
|
|
5167
5553
|
color: isSelected ? colors2.search.selected : void 0,
|
|
5168
5554
|
backgroundColor: isSelected ? colors2.search.selected : void 0,
|
|
@@ -5172,31 +5558,31 @@ var SearchOverlay = ({
|
|
|
5172
5558
|
" [",
|
|
5173
5559
|
result.title,
|
|
5174
5560
|
"]"
|
|
5175
|
-
)), /* @__PURE__ */
|
|
5176
|
-
|
|
5561
|
+
)), /* @__PURE__ */ React23.createElement(Box19, { marginLeft: 2 }, /* @__PURE__ */ React23.createElement(
|
|
5562
|
+
Text19,
|
|
5177
5563
|
{
|
|
5178
5564
|
color: isSelected ? colors2.search.match : colors2.muted,
|
|
5179
5565
|
dimColor: !isSelected
|
|
5180
5566
|
},
|
|
5181
5567
|
matchText
|
|
5182
5568
|
)));
|
|
5183
|
-
}), flatResults.length > 5 && /* @__PURE__ */
|
|
5184
|
-
/* @__PURE__ */
|
|
5569
|
+
}), flatResults.length > 5 && /* @__PURE__ */ React23.createElement(Text19, { dimColor: true, marginTop: 1 }, "... and ", flatResults.length - 5, " more results"))),
|
|
5570
|
+
/* @__PURE__ */ React23.createElement(Box19, { marginTop: 1, borderTop: true, borderColor: colors2.muted, paddingTop: 1 }, /* @__PURE__ */ React23.createElement(Text19, { dimColor: true }, "[\u2191\u2193] Navigate \xB7 [Enter] Go to \xB7 [Esc] Close"))
|
|
5185
5571
|
);
|
|
5186
5572
|
};
|
|
5187
5573
|
|
|
5188
5574
|
// src/ui/guide/GuideApp.tsx
|
|
5189
5575
|
var GuideApp = ({ initialTopic, onExit }) => {
|
|
5190
|
-
const { exit } =
|
|
5191
|
-
const [currentTopic, setCurrentTopic] =
|
|
5192
|
-
const [focusArea, setFocusArea] =
|
|
5193
|
-
const [sidebarMode, setSidebarMode] =
|
|
5194
|
-
const [menuIndex, setMenuIndex] =
|
|
5195
|
-
const [tocIndex, setTocIndex] =
|
|
5196
|
-
const [scrollPosition, setScrollPosition] =
|
|
5197
|
-
const [isSearchOpen, setIsSearchOpen] =
|
|
5576
|
+
const { exit } = useApp4();
|
|
5577
|
+
const [currentTopic, setCurrentTopic] = useState10(null);
|
|
5578
|
+
const [focusArea, setFocusArea] = useState10("sidebar");
|
|
5579
|
+
const [sidebarMode, setSidebarMode] = useState10("menu");
|
|
5580
|
+
const [menuIndex, setMenuIndex] = useState10(0);
|
|
5581
|
+
const [tocIndex, setTocIndex] = useState10(0);
|
|
5582
|
+
const [scrollPosition, setScrollPosition] = useState10(0);
|
|
5583
|
+
const [isSearchOpen, setIsSearchOpen] = useState10(false);
|
|
5198
5584
|
const { content, loading, error } = useContent(currentTopic);
|
|
5199
|
-
|
|
5585
|
+
useEffect5(() => {
|
|
5200
5586
|
if (initialTopic) {
|
|
5201
5587
|
const validTopics = ["intro", "rules", "workflows", "prompts", "skills"];
|
|
5202
5588
|
if (validTopics.includes(initialTopic)) {
|
|
@@ -5242,7 +5628,7 @@ var GuideApp = ({ initialTopic, onExit }) => {
|
|
|
5242
5628
|
onExit();
|
|
5243
5629
|
}
|
|
5244
5630
|
}, [isSearchOpen, focusArea, currentTopic, onExit]);
|
|
5245
|
-
|
|
5631
|
+
useInput9((input5, key) => {
|
|
5246
5632
|
if (isSearchOpen) {
|
|
5247
5633
|
return;
|
|
5248
5634
|
}
|
|
@@ -5318,13 +5704,13 @@ var GuideApp = ({ initialTopic, onExit }) => {
|
|
|
5318
5704
|
});
|
|
5319
5705
|
const renderContent = () => {
|
|
5320
5706
|
if (loading) {
|
|
5321
|
-
return /* @__PURE__ */
|
|
5707
|
+
return /* @__PURE__ */ React24.createElement(Box20, { padding: 1 }, /* @__PURE__ */ React24.createElement(Text20, { dimColor: true }, "Loading..."));
|
|
5322
5708
|
}
|
|
5323
5709
|
if (error) {
|
|
5324
|
-
return /* @__PURE__ */
|
|
5710
|
+
return /* @__PURE__ */ React24.createElement(Box20, { padding: 1 }, /* @__PURE__ */ React24.createElement(Text20, { color: "red" }, "Error: ", error));
|
|
5325
5711
|
}
|
|
5326
5712
|
if (content && currentTopic) {
|
|
5327
|
-
return /* @__PURE__ */
|
|
5713
|
+
return /* @__PURE__ */ React24.createElement(
|
|
5328
5714
|
ContentPane,
|
|
5329
5715
|
{
|
|
5330
5716
|
title: content.meta.title,
|
|
@@ -5336,9 +5722,9 @@ var GuideApp = ({ initialTopic, onExit }) => {
|
|
|
5336
5722
|
}
|
|
5337
5723
|
);
|
|
5338
5724
|
}
|
|
5339
|
-
return /* @__PURE__ */
|
|
5725
|
+
return /* @__PURE__ */ React24.createElement(WelcomePane, null);
|
|
5340
5726
|
};
|
|
5341
|
-
const renderSidebar = () => /* @__PURE__ */
|
|
5727
|
+
const renderSidebar = () => /* @__PURE__ */ React24.createElement(
|
|
5342
5728
|
Sidebar,
|
|
5343
5729
|
{
|
|
5344
5730
|
mode: sidebarMode,
|
|
@@ -5352,14 +5738,14 @@ var GuideApp = ({ initialTopic, onExit }) => {
|
|
|
5352
5738
|
onSelectSection: handleSelectSection
|
|
5353
5739
|
}
|
|
5354
5740
|
);
|
|
5355
|
-
const renderSearch = () => /* @__PURE__ */
|
|
5741
|
+
const renderSearch = () => /* @__PURE__ */ React24.createElement(
|
|
5356
5742
|
SearchOverlay,
|
|
5357
5743
|
{
|
|
5358
5744
|
onClose: () => setIsSearchOpen(false),
|
|
5359
5745
|
onSelectResult: handleSearchSelect
|
|
5360
5746
|
}
|
|
5361
5747
|
);
|
|
5362
|
-
return /* @__PURE__ */
|
|
5748
|
+
return /* @__PURE__ */ React24.createElement(
|
|
5363
5749
|
Layout,
|
|
5364
5750
|
{
|
|
5365
5751
|
focusArea,
|
|
@@ -5373,12 +5759,12 @@ var GuideApp = ({ initialTopic, onExit }) => {
|
|
|
5373
5759
|
|
|
5374
5760
|
// src/commands/guide.ts
|
|
5375
5761
|
function createGuideCommand() {
|
|
5376
|
-
const cmd = new
|
|
5762
|
+
const cmd = new Command12("guide").description("Trung t\xE2m h\u1ECDc Agentic Coding (interactive)").option(
|
|
5377
5763
|
"--topic <topic>",
|
|
5378
5764
|
"M\u1EDF topic c\u1EE5 th\u1EC3 (intro, rules, workflows, prompts, skills)"
|
|
5379
5765
|
).action(async (options) => {
|
|
5380
|
-
const { waitUntilExit } =
|
|
5381
|
-
|
|
5766
|
+
const { waitUntilExit } = render4(
|
|
5767
|
+
React25.createElement(GuideApp, {
|
|
5382
5768
|
initialTopic: options.topic,
|
|
5383
5769
|
onExit: () => {
|
|
5384
5770
|
process.exit(0);
|
|
@@ -5391,9 +5777,9 @@ function createGuideCommand() {
|
|
|
5391
5777
|
}
|
|
5392
5778
|
|
|
5393
5779
|
// src/commands/chat.ts
|
|
5394
|
-
import { Command as
|
|
5395
|
-
import
|
|
5396
|
-
import { render as
|
|
5780
|
+
import { Command as Command13 } from "commander";
|
|
5781
|
+
import React31 from "react";
|
|
5782
|
+
import { render as render5 } from "ink";
|
|
5397
5783
|
|
|
5398
5784
|
// src/services/llm-proxy.service.ts
|
|
5399
5785
|
var LlmProxyService = class {
|
|
@@ -5620,16 +6006,16 @@ var LlmProxyService = class {
|
|
|
5620
6006
|
};
|
|
5621
6007
|
|
|
5622
6008
|
// src/ui/llm/LlmApp.tsx
|
|
5623
|
-
import
|
|
5624
|
-
import { Box as
|
|
5625
|
-
import
|
|
6009
|
+
import React30, { useState as useState14, useEffect as useEffect7, useMemo as useMemo4, useCallback as useCallback5, useRef as useRef2 } from "react";
|
|
6010
|
+
import { Box as Box25, Text as Text25, useInput as useInput11, useApp as useApp5, useStdout as useStdout2 } from "ink";
|
|
6011
|
+
import Spinner4 from "ink-spinner";
|
|
5626
6012
|
|
|
5627
6013
|
// src/ui/llm/hooks/useChat.ts
|
|
5628
|
-
import { useState as
|
|
6014
|
+
import { useState as useState11, useCallback as useCallback3 } from "react";
|
|
5629
6015
|
function useChat(service) {
|
|
5630
|
-
const [messages, setMessages] =
|
|
5631
|
-
const [isStreaming, setIsStreaming] =
|
|
5632
|
-
const [error, setError] =
|
|
6016
|
+
const [messages, setMessages] = useState11([]);
|
|
6017
|
+
const [isStreaming, setIsStreaming] = useState11(false);
|
|
6018
|
+
const [error, setError] = useState11(null);
|
|
5633
6019
|
const sendMessage = useCallback3(
|
|
5634
6020
|
async (content, model) => {
|
|
5635
6021
|
if (!content.trim() || isStreaming) return;
|
|
@@ -5698,9 +6084,9 @@ function useChat(service) {
|
|
|
5698
6084
|
}
|
|
5699
6085
|
|
|
5700
6086
|
// src/ui/llm/hooks/useLlmApi.ts
|
|
5701
|
-
import { useState as
|
|
6087
|
+
import { useState as useState12, useEffect as useEffect6, useCallback as useCallback4, useRef } from "react";
|
|
5702
6088
|
function useLlmApi(service) {
|
|
5703
|
-
const [state, setState] =
|
|
6089
|
+
const [state, setState] = useState12({
|
|
5704
6090
|
models: [],
|
|
5705
6091
|
limits: null,
|
|
5706
6092
|
usage: null,
|
|
@@ -5733,7 +6119,7 @@ function useLlmApi(service) {
|
|
|
5733
6119
|
}));
|
|
5734
6120
|
}
|
|
5735
6121
|
}, [service]);
|
|
5736
|
-
|
|
6122
|
+
useEffect6(() => {
|
|
5737
6123
|
if (!hasFetched.current) {
|
|
5738
6124
|
hasFetched.current = true;
|
|
5739
6125
|
fetchData(true);
|
|
@@ -5749,35 +6135,35 @@ function useLlmApi(service) {
|
|
|
5749
6135
|
}
|
|
5750
6136
|
|
|
5751
6137
|
// src/ui/llm/components/ChatPanel.tsx
|
|
5752
|
-
import
|
|
5753
|
-
import { Box as
|
|
5754
|
-
import
|
|
6138
|
+
import React28, { memo as memo3 } from "react";
|
|
6139
|
+
import { Box as Box23, Text as Text23 } from "ink";
|
|
6140
|
+
import Spinner3 from "ink-spinner";
|
|
5755
6141
|
|
|
5756
6142
|
// src/ui/llm/components/MessageItem.tsx
|
|
5757
|
-
import
|
|
5758
|
-
import { Box as
|
|
6143
|
+
import React26, { memo } from "react";
|
|
6144
|
+
import { Box as Box21, Text as Text21 } from "ink";
|
|
5759
6145
|
var MessageItem = memo(({ message }) => {
|
|
5760
6146
|
if (message.role === "user") {
|
|
5761
|
-
return /* @__PURE__ */
|
|
6147
|
+
return /* @__PURE__ */ React26.createElement(Box21, { flexDirection: "column", marginBottom: 1 }, /* @__PURE__ */ React26.createElement(Text21, { color: "cyan", bold: true }, "You:"), /* @__PURE__ */ React26.createElement(Text21, { wrap: "wrap" }, message.content));
|
|
5762
6148
|
}
|
|
5763
6149
|
if (message.role === "assistant") {
|
|
5764
|
-
return /* @__PURE__ */
|
|
6150
|
+
return /* @__PURE__ */ React26.createElement(Box21, { flexDirection: "column", marginBottom: 1 }, /* @__PURE__ */ React26.createElement(Text21, { color: "green", bold: true }, "Jai1:"), /* @__PURE__ */ React26.createElement(Text21, { wrap: "wrap" }, message.content));
|
|
5765
6151
|
}
|
|
5766
|
-
return /* @__PURE__ */
|
|
6152
|
+
return /* @__PURE__ */ React26.createElement(Box21, { marginBottom: 1 }, /* @__PURE__ */ React26.createElement(Text21, { dimColor: true, italic: true }, message.content));
|
|
5767
6153
|
});
|
|
5768
6154
|
|
|
5769
6155
|
// src/ui/llm/components/InputBox.tsx
|
|
5770
|
-
import
|
|
5771
|
-
import { Box as
|
|
5772
|
-
import
|
|
6156
|
+
import React27, { memo as memo2 } from "react";
|
|
6157
|
+
import { Box as Box22, Text as Text22 } from "ink";
|
|
6158
|
+
import TextInput4 from "ink-text-input";
|
|
5773
6159
|
var InputBox = memo2(({
|
|
5774
6160
|
value,
|
|
5775
6161
|
onChange,
|
|
5776
6162
|
onSubmit,
|
|
5777
6163
|
disabled = false,
|
|
5778
6164
|
focused = true
|
|
5779
|
-
}) => /* @__PURE__ */
|
|
5780
|
-
|
|
6165
|
+
}) => /* @__PURE__ */ React27.createElement(Box22, { borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React27.createElement(Text22, { color: "cyan" }, "\u276F "), !disabled ? /* @__PURE__ */ React27.createElement(
|
|
6166
|
+
TextInput4,
|
|
5781
6167
|
{
|
|
5782
6168
|
value,
|
|
5783
6169
|
onChange,
|
|
@@ -5785,19 +6171,19 @@ var InputBox = memo2(({
|
|
|
5785
6171
|
placeholder: "Type your message...",
|
|
5786
6172
|
focus: focused
|
|
5787
6173
|
}
|
|
5788
|
-
) : /* @__PURE__ */
|
|
6174
|
+
) : /* @__PURE__ */ React27.createElement(Text22, { dimColor: true }, "Waiting...")));
|
|
5789
6175
|
|
|
5790
6176
|
// src/ui/llm/components/ChatPanel.tsx
|
|
5791
6177
|
var MessageList = memo3(({ messages }) => {
|
|
5792
6178
|
const visible = messages.slice(-8);
|
|
5793
6179
|
const hidden = messages.length - visible.length;
|
|
5794
6180
|
if (visible.length === 0) {
|
|
5795
|
-
return /* @__PURE__ */
|
|
6181
|
+
return /* @__PURE__ */ React28.createElement(Box23, { flexDirection: "column", alignItems: "center", padding: 1 }, /* @__PURE__ */ React28.createElement(Text23, { dimColor: true }, "Start a conversation..."), /* @__PURE__ */ React28.createElement(Text23, { dimColor: true }, "Type / for commands"));
|
|
5796
6182
|
}
|
|
5797
|
-
return /* @__PURE__ */
|
|
6183
|
+
return /* @__PURE__ */ React28.createElement(React28.Fragment, null, hidden > 0 && /* @__PURE__ */ React28.createElement(Text23, { dimColor: true }, "(", hidden, " earlier)"), visible.map((m) => /* @__PURE__ */ React28.createElement(MessageItem, { key: m.id, message: m })));
|
|
5798
6184
|
});
|
|
5799
|
-
var SlashMenu = memo3(({ commands, index }) => /* @__PURE__ */
|
|
5800
|
-
|
|
6185
|
+
var SlashMenu = memo3(({ commands, index }) => /* @__PURE__ */ React28.createElement(Box23, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React28.createElement(Text23, { bold: true, color: "cyan" }, "Commands"), commands.map((cmd, i) => /* @__PURE__ */ React28.createElement(
|
|
6186
|
+
Text23,
|
|
5801
6187
|
{
|
|
5802
6188
|
key: cmd.name,
|
|
5803
6189
|
backgroundColor: i === index ? "cyan" : void 0,
|
|
@@ -5822,7 +6208,7 @@ var ChatPanel = ({
|
|
|
5822
6208
|
minHeight = 15
|
|
5823
6209
|
}) => {
|
|
5824
6210
|
const messagesMinHeight = Math.max(5, minHeight - 4 - (showSlashMenu ? 5 : 0));
|
|
5825
|
-
return /* @__PURE__ */
|
|
6211
|
+
return /* @__PURE__ */ React28.createElement(Box23, { flexDirection: "column" }, /* @__PURE__ */ React28.createElement(Box23, { flexDirection: "column", borderStyle: "round", borderColor: "gray", padding: 1, minHeight: messagesMinHeight }, /* @__PURE__ */ React28.createElement(MessageList, { messages }), isStreaming && /* @__PURE__ */ React28.createElement(Text23, { color: "green" }, /* @__PURE__ */ React28.createElement(Spinner3, { type: "dots" }), " Responding...")), showSlashMenu && slashCommands.length > 0 && /* @__PURE__ */ React28.createElement(SlashMenu, { commands: slashCommands, index: slashMenuIndex }), /* @__PURE__ */ React28.createElement(
|
|
5826
6212
|
InputBox,
|
|
5827
6213
|
{
|
|
5828
6214
|
value: inputValue,
|
|
@@ -5835,8 +6221,8 @@ var ChatPanel = ({
|
|
|
5835
6221
|
};
|
|
5836
6222
|
|
|
5837
6223
|
// src/ui/llm/components/ModelSelector.tsx
|
|
5838
|
-
import
|
|
5839
|
-
import { Box as
|
|
6224
|
+
import React29, { useState as useState13 } from "react";
|
|
6225
|
+
import { Box as Box24, Text as Text24, useInput as useInput10 } from "ink";
|
|
5840
6226
|
var ModelSelector = ({
|
|
5841
6227
|
models,
|
|
5842
6228
|
currentModel,
|
|
@@ -5845,8 +6231,8 @@ var ModelSelector = ({
|
|
|
5845
6231
|
}) => {
|
|
5846
6232
|
const allowedModels = models.filter((m) => m.allowed);
|
|
5847
6233
|
const currentIndex = allowedModels.findIndex((m) => m.id === currentModel);
|
|
5848
|
-
const [selectedIndex, setSelectedIndex] =
|
|
5849
|
-
|
|
6234
|
+
const [selectedIndex, setSelectedIndex] = useState13(Math.max(0, currentIndex));
|
|
6235
|
+
useInput10((input5, key) => {
|
|
5850
6236
|
if (key.escape) {
|
|
5851
6237
|
onCancel();
|
|
5852
6238
|
return;
|
|
@@ -5863,8 +6249,8 @@ var ModelSelector = ({
|
|
|
5863
6249
|
}
|
|
5864
6250
|
});
|
|
5865
6251
|
if (allowedModels.length === 0) {
|
|
5866
|
-
return /* @__PURE__ */
|
|
5867
|
-
|
|
6252
|
+
return /* @__PURE__ */ React29.createElement(
|
|
6253
|
+
Box24,
|
|
5868
6254
|
{
|
|
5869
6255
|
flexDirection: "column",
|
|
5870
6256
|
borderStyle: "round",
|
|
@@ -5872,12 +6258,12 @@ var ModelSelector = ({
|
|
|
5872
6258
|
padding: 1,
|
|
5873
6259
|
width: 60
|
|
5874
6260
|
},
|
|
5875
|
-
/* @__PURE__ */
|
|
5876
|
-
/* @__PURE__ */
|
|
6261
|
+
/* @__PURE__ */ React29.createElement(Text24, { color: "red", bold: true }, "No models available"),
|
|
6262
|
+
/* @__PURE__ */ React29.createElement(Text24, { dimColor: true }, "Press Esc to close")
|
|
5877
6263
|
);
|
|
5878
6264
|
}
|
|
5879
|
-
return /* @__PURE__ */
|
|
5880
|
-
|
|
6265
|
+
return /* @__PURE__ */ React29.createElement(
|
|
6266
|
+
Box24,
|
|
5881
6267
|
{
|
|
5882
6268
|
flexDirection: "column",
|
|
5883
6269
|
borderStyle: "round",
|
|
@@ -5885,8 +6271,8 @@ var ModelSelector = ({
|
|
|
5885
6271
|
padding: 1,
|
|
5886
6272
|
width: 70
|
|
5887
6273
|
},
|
|
5888
|
-
/* @__PURE__ */
|
|
5889
|
-
/* @__PURE__ */
|
|
6274
|
+
/* @__PURE__ */ React29.createElement(Box24, { marginBottom: 1 }, /* @__PURE__ */ React29.createElement(Text24, { bold: true, color: "cyan" }, "\u2699\uFE0F Select Model")),
|
|
6275
|
+
/* @__PURE__ */ React29.createElement(Box24, { flexDirection: "column", marginBottom: 1 }, allowedModels.map((model, i) => {
|
|
5890
6276
|
const isSelected = i === selectedIndex;
|
|
5891
6277
|
const isCurrent = model.id === currentModel;
|
|
5892
6278
|
const icon = isSelected ? "\u25CF" : "\u25CB";
|
|
@@ -5894,8 +6280,8 @@ var ModelSelector = ({
|
|
|
5894
6280
|
if (model.dailyLimit !== void 0 && model.usedToday !== void 0) {
|
|
5895
6281
|
usageText = ` (${model.usedToday}/${model.dailyLimit})`;
|
|
5896
6282
|
}
|
|
5897
|
-
return /* @__PURE__ */
|
|
5898
|
-
|
|
6283
|
+
return /* @__PURE__ */ React29.createElement(Box24, { key: model.id, marginY: 0 }, /* @__PURE__ */ React29.createElement(
|
|
6284
|
+
Text24,
|
|
5899
6285
|
{
|
|
5900
6286
|
backgroundColor: isSelected ? "cyan" : void 0,
|
|
5901
6287
|
color: isSelected ? "black" : "white"
|
|
@@ -5908,7 +6294,7 @@ var ModelSelector = ({
|
|
|
5908
6294
|
usageText
|
|
5909
6295
|
));
|
|
5910
6296
|
})),
|
|
5911
|
-
/* @__PURE__ */
|
|
6297
|
+
/* @__PURE__ */ React29.createElement(Box24, { borderStyle: "single", borderColor: "gray", paddingX: 1 }, /* @__PURE__ */ React29.createElement(Text24, { dimColor: true }, "[\u2191\u2193] Navigate [Enter] Select [Esc] Cancel"))
|
|
5912
6298
|
);
|
|
5913
6299
|
};
|
|
5914
6300
|
|
|
@@ -5919,17 +6305,17 @@ var SLASH_COMMANDS = [
|
|
|
5919
6305
|
{ name: "quit", description: "Exit the chat", aliases: ["q", "exit"] }
|
|
5920
6306
|
];
|
|
5921
6307
|
var ChatApp = ({ service, initialModel }) => {
|
|
5922
|
-
const { exit } =
|
|
6308
|
+
const { exit } = useApp5();
|
|
5923
6309
|
const { stdout } = useStdout2();
|
|
5924
6310
|
const contentHeight = useRef2(Math.max(10, (stdout?.rows || 24) - 6));
|
|
5925
|
-
const [currentView, setCurrentView] =
|
|
5926
|
-
const [showSlashMenu, setShowSlashMenu] =
|
|
5927
|
-
const [slashMenuIndex, setSlashMenuIndex] =
|
|
5928
|
-
const [inputValue, setInputValue] =
|
|
5929
|
-
const [selectedModel, setSelectedModel] =
|
|
6311
|
+
const [currentView, setCurrentView] = useState14("loading");
|
|
6312
|
+
const [showSlashMenu, setShowSlashMenu] = useState14(false);
|
|
6313
|
+
const [slashMenuIndex, setSlashMenuIndex] = useState14(0);
|
|
6314
|
+
const [inputValue, setInputValue] = useState14("");
|
|
6315
|
+
const [selectedModel, setSelectedModel] = useState14("");
|
|
5930
6316
|
const { models, loading, error, refetch } = useLlmApi(service);
|
|
5931
6317
|
const { messages, isStreaming, sendMessage } = useChat(service);
|
|
5932
|
-
|
|
6318
|
+
useEffect7(() => {
|
|
5933
6319
|
if (error && !loading) {
|
|
5934
6320
|
setCurrentView("error");
|
|
5935
6321
|
return;
|
|
@@ -5942,7 +6328,7 @@ var ChatApp = ({ service, initialModel }) => {
|
|
|
5942
6328
|
}
|
|
5943
6329
|
}
|
|
5944
6330
|
}, [models, selectedModel, initialModel, error, loading]);
|
|
5945
|
-
const filteredCommands =
|
|
6331
|
+
const filteredCommands = useMemo4(() => {
|
|
5946
6332
|
if (!inputValue.startsWith("/")) return SLASH_COMMANDS;
|
|
5947
6333
|
const filter = inputValue.slice(1).toLowerCase();
|
|
5948
6334
|
return SLASH_COMMANDS.filter(
|
|
@@ -5972,7 +6358,7 @@ var ChatApp = ({ service, initialModel }) => {
|
|
|
5972
6358
|
}
|
|
5973
6359
|
return false;
|
|
5974
6360
|
}, [refetch, exit]);
|
|
5975
|
-
|
|
6361
|
+
useInput11((input5, key) => {
|
|
5976
6362
|
if (showSlashMenu) {
|
|
5977
6363
|
if (key.upArrow) {
|
|
5978
6364
|
setSlashMenuIndex((i) => Math.max(0, i - 1));
|
|
@@ -6031,18 +6417,18 @@ var ChatApp = ({ service, initialModel }) => {
|
|
|
6031
6417
|
setSelectedModel(id);
|
|
6032
6418
|
setCurrentView("chat");
|
|
6033
6419
|
}, []);
|
|
6034
|
-
const statsView =
|
|
6420
|
+
const statsView = useMemo4(() => {
|
|
6035
6421
|
const allowed = models.filter((m) => m.allowed);
|
|
6036
|
-
return /* @__PURE__ */
|
|
6422
|
+
return /* @__PURE__ */ React30.createElement(Box25, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", padding: 1 }, /* @__PURE__ */ React30.createElement(Text25, { bold: true, color: "cyan" }, "\u{1F4CA} Model Usage Statistics"), allowed.map((m) => {
|
|
6037
6423
|
const limit = m.dailyLimit ?? 0;
|
|
6038
6424
|
const used = m.usedToday ?? 0;
|
|
6039
6425
|
const pct = limit > 0 ? Math.round(used / limit * 100) : 0;
|
|
6040
6426
|
const bar = "\u2588".repeat(Math.round(pct / 5)) + "\u2591".repeat(20 - Math.round(pct / 5));
|
|
6041
|
-
return /* @__PURE__ */
|
|
6042
|
-
}), /* @__PURE__ */
|
|
6427
|
+
return /* @__PURE__ */ React30.createElement(Box25, { key: m.id, flexDirection: "column" }, /* @__PURE__ */ React30.createElement(Text25, { color: m.id === selectedModel ? "yellow" : "white" }, m.id === selectedModel ? "\u25BA " : " ", m.id), /* @__PURE__ */ React30.createElement(Text25, { color: pct > 80 ? "red" : pct > 50 ? "yellow" : "green" }, " ", bar, " ", /* @__PURE__ */ React30.createElement(Text25, { dimColor: true }, used, "/", limit)));
|
|
6428
|
+
}), /* @__PURE__ */ React30.createElement(Text25, { dimColor: true }, "[Esc] Back"));
|
|
6043
6429
|
}, [models, selectedModel]);
|
|
6044
6430
|
const footer = currentView === "error" ? "[Enter/r] Retry \u2022 [Esc] Quit" : currentView === "model" || currentView === "stats" ? "[\u2191\u2193] Navigate \u2022 [Enter] Select \u2022 [Esc] Back" : showSlashMenu ? "[\u2191\u2193] Navigate \u2022 [Enter] Select \u2022 [Esc] Cancel" : "[Tab] Next Model \u2022 [/] Commands \u2022 [Esc] Quit";
|
|
6045
|
-
return /* @__PURE__ */
|
|
6431
|
+
return /* @__PURE__ */ React30.createElement(Box25, { flexDirection: "column" }, /* @__PURE__ */ React30.createElement(Box25, { borderStyle: "double", borderColor: "magenta", paddingX: 1 }, /* @__PURE__ */ React30.createElement(Text25, { bold: true, color: "magenta" }, "\u{1F916} Jai1 Chat"), /* @__PURE__ */ React30.createElement(Box25, { flexGrow: 1 }), /* @__PURE__ */ React30.createElement(Text25, { dimColor: true }, "Model: "), /* @__PURE__ */ React30.createElement(Text25, { color: "yellow", bold: true }, selectedModel || "...")), currentView === "loading" ? /* @__PURE__ */ React30.createElement(Box25, { padding: 2, minHeight: contentHeight.current, alignItems: "center", justifyContent: "center" }, /* @__PURE__ */ React30.createElement(Text25, null, /* @__PURE__ */ React30.createElement(Spinner4, { type: "dots" }), " Loading...")) : currentView === "error" ? /* @__PURE__ */ React30.createElement(Box25, { padding: 2, minHeight: contentHeight.current, alignItems: "center", justifyContent: "center", flexDirection: "column" }, /* @__PURE__ */ React30.createElement(Text25, { color: "red", bold: true }, "Connection Error"), /* @__PURE__ */ React30.createElement(Text25, { color: "red" }, error), /* @__PURE__ */ React30.createElement(Text25, { dimColor: true }, " "), /* @__PURE__ */ React30.createElement(Text25, { dimColor: true }, "Press Enter or 'r' to retry")) : currentView === "model" ? /* @__PURE__ */ React30.createElement(Box25, { padding: 1, minHeight: contentHeight.current, justifyContent: "center", alignItems: "center" }, /* @__PURE__ */ React30.createElement(
|
|
6046
6432
|
ModelSelector,
|
|
6047
6433
|
{
|
|
6048
6434
|
models,
|
|
@@ -6050,7 +6436,7 @@ var ChatApp = ({ service, initialModel }) => {
|
|
|
6050
6436
|
onSelect: onSelectModel,
|
|
6051
6437
|
onCancel: () => setCurrentView("chat")
|
|
6052
6438
|
}
|
|
6053
|
-
)) : currentView === "stats" ? /* @__PURE__ */
|
|
6439
|
+
)) : currentView === "stats" ? /* @__PURE__ */ React30.createElement(Box25, { padding: 1, minHeight: contentHeight.current, justifyContent: "center", alignItems: "center" }, statsView) : /* @__PURE__ */ React30.createElement(
|
|
6054
6440
|
ChatPanel,
|
|
6055
6441
|
{
|
|
6056
6442
|
messages,
|
|
@@ -6064,7 +6450,7 @@ var ChatApp = ({ service, initialModel }) => {
|
|
|
6064
6450
|
slashMenuIndex,
|
|
6065
6451
|
minHeight: contentHeight.current
|
|
6066
6452
|
}
|
|
6067
|
-
), /* @__PURE__ */
|
|
6453
|
+
), /* @__PURE__ */ React30.createElement(Box25, { borderStyle: "single", borderColor: "gray", paddingX: 1 }, /* @__PURE__ */ React30.createElement(Text25, { dimColor: true }, footer)));
|
|
6068
6454
|
};
|
|
6069
6455
|
|
|
6070
6456
|
// src/server/web-chat-server.ts
|
|
@@ -6968,8 +7354,8 @@ async function handleTerminalChat(options) {
|
|
|
6968
7354
|
throw new ValidationError('Not initialized. Run "jai1 auth" first.');
|
|
6969
7355
|
}
|
|
6970
7356
|
const service = new LlmProxyService(config);
|
|
6971
|
-
const { waitUntilExit, clear } =
|
|
6972
|
-
|
|
7357
|
+
const { waitUntilExit, clear } = render5(
|
|
7358
|
+
React31.createElement(ChatApp, {
|
|
6973
7359
|
service,
|
|
6974
7360
|
initialModel: options.model
|
|
6975
7361
|
}),
|
|
@@ -7033,14 +7419,14 @@ async function handleChatCommand(options) {
|
|
|
7033
7419
|
}
|
|
7034
7420
|
}
|
|
7035
7421
|
function createChatCommand() {
|
|
7036
|
-
const cmd = new
|
|
7422
|
+
const cmd = new Command13("chat").description("AI chat with Jai1 LLM Proxy (default: web browser)").option("--model <model>", "Initial model to use (e.g., gpt-4o, claude-3-opus)").option("-t, --terminal", "Use terminal TUI mode instead of web browser").option("--port <port>", "Port for web server (default: auto-find available port)").option("--no-open", "Don't auto-open browser (web mode only)").action(async (options) => {
|
|
7037
7423
|
await handleChatCommand(options);
|
|
7038
7424
|
});
|
|
7039
7425
|
return cmd;
|
|
7040
7426
|
}
|
|
7041
7427
|
|
|
7042
7428
|
// src/commands/openai-keys.ts
|
|
7043
|
-
import { Command as
|
|
7429
|
+
import { Command as Command14 } from "commander";
|
|
7044
7430
|
import chalk7 from "chalk";
|
|
7045
7431
|
import boxen3 from "boxen";
|
|
7046
7432
|
function maskKey2(key) {
|
|
@@ -7110,14 +7496,14 @@ async function handleOpenAiKeysCommand(options) {
|
|
|
7110
7496
|
}
|
|
7111
7497
|
}
|
|
7112
7498
|
function createOpenAiKeysCommand() {
|
|
7113
|
-
const cmd = new
|
|
7499
|
+
const cmd = new Command14("openai-keys").description("Show OpenAI-compatible API credentials and info").option("--full", "Show full API key (unmasked)").action(async (options) => {
|
|
7114
7500
|
await handleOpenAiKeysCommand(options);
|
|
7115
7501
|
});
|
|
7116
7502
|
return cmd;
|
|
7117
7503
|
}
|
|
7118
7504
|
|
|
7119
7505
|
// src/commands/stats.ts
|
|
7120
|
-
import { Command as
|
|
7506
|
+
import { Command as Command15 } from "commander";
|
|
7121
7507
|
import Table2 from "cli-table3";
|
|
7122
7508
|
import chalk8 from "chalk";
|
|
7123
7509
|
async function handleStatsCommand() {
|
|
@@ -7212,14 +7598,14 @@ async function handleStatsCommand() {
|
|
|
7212
7598
|
}
|
|
7213
7599
|
}
|
|
7214
7600
|
function createStatsCommand() {
|
|
7215
|
-
const cmd = new
|
|
7601
|
+
const cmd = new Command15("stats").description("Hi\u1EC3n th\u1ECB th\u1ED1ng k\xEA s\u1EED d\u1EE5ng LLM v\xE0 gi\u1EDBi h\u1EA1n").action(async () => {
|
|
7216
7602
|
await handleStatsCommand();
|
|
7217
7603
|
});
|
|
7218
7604
|
return cmd;
|
|
7219
7605
|
}
|
|
7220
7606
|
|
|
7221
7607
|
// src/commands/translate.ts
|
|
7222
|
-
import { Command as
|
|
7608
|
+
import { Command as Command16 } from "commander";
|
|
7223
7609
|
|
|
7224
7610
|
// src/services/translation.service.ts
|
|
7225
7611
|
import { promises as fs10 } from "fs";
|
|
@@ -7567,18 +7953,18 @@ async function handleFolderTranslation(service, folderPath, options) {
|
|
|
7567
7953
|
}
|
|
7568
7954
|
}
|
|
7569
7955
|
function createTranslateCommand() {
|
|
7570
|
-
const cmd = new
|
|
7956
|
+
const cmd = new Command16("translate").description("D\u1ECBch v\u0103n b\u1EA3n, file ho\u1EB7c th\u01B0 m\u1EE5c b\u1EB1ng AI").argument("<input>", "Chu\u1ED7i v\u0103n b\u1EA3n, \u0111\u01B0\u1EDDng d\u1EABn file ho\u1EB7c th\u01B0 m\u1EE5c").option("--to <language>", "M\xE3 ng\xF4n ng\u1EEF \u0111\xEDch (m\u1EB7c \u0111\u1ECBnh: vi)", "vi").option("-o, --output <path>", "\u0110\u01B0\u1EDDng d\u1EABn output (file/th\u01B0 m\u1EE5c)").option("--dry-run", "Xem tr\u01B0\u1EDBc kh\xF4ng l\u01B0u file").option("--concurrency <number>", "S\u1ED1 file x\u1EED l\xFD song song (m\u1EB7c \u0111\u1ECBnh: 3)", "3").option("--model <model>", "Model LLM (m\u1EB7c \u0111\u1ECBnh: gpt-5.1-codex-mini)").option("--json", "Xu\u1EA5t k\u1EBFt qu\u1EA3 d\u1EA1ng JSON").action(async (input5, options) => {
|
|
7571
7957
|
await handleTranslate(input5, options);
|
|
7572
7958
|
});
|
|
7573
7959
|
return cmd;
|
|
7574
7960
|
}
|
|
7575
7961
|
|
|
7576
7962
|
// src/commands/image/index.ts
|
|
7577
|
-
import { Command as
|
|
7963
|
+
import { Command as Command21 } from "commander";
|
|
7578
7964
|
import chalk9 from "chalk";
|
|
7579
7965
|
|
|
7580
7966
|
// src/commands/image/gen.ts
|
|
7581
|
-
import { Command as
|
|
7967
|
+
import { Command as Command17 } from "commander";
|
|
7582
7968
|
|
|
7583
7969
|
// src/services/image.service.ts
|
|
7584
7970
|
var ImageService = class {
|
|
@@ -7683,7 +8069,7 @@ var SUPPORTED_SIZES = [
|
|
|
7683
8069
|
// 3:4 (portrait)
|
|
7684
8070
|
];
|
|
7685
8071
|
function createImageGenCommand() {
|
|
7686
|
-
return new
|
|
8072
|
+
return new Command17("gen").description("Generate an image from text prompt").argument("<prompt>", "Image description prompt").option("-m, --model <model>", "Model to use", "gemini-3-pro-image-preview").option("-s, --size <size>", `Image size: ${SUPPORTED_SIZES.join(", ")}`, "1024x1024").option("-q, --quality <quality>", "Image quality: standard, hd", "hd").option("--no-display", "Don't display image in terminal").action(async (prompt, options) => {
|
|
7687
8073
|
const configService = new ConfigService();
|
|
7688
8074
|
const config = await configService.load();
|
|
7689
8075
|
if (!config) {
|
|
@@ -7749,9 +8135,9 @@ function createImageGenCommand() {
|
|
|
7749
8135
|
}
|
|
7750
8136
|
|
|
7751
8137
|
// src/commands/image/list.ts
|
|
7752
|
-
import { Command as
|
|
8138
|
+
import { Command as Command18 } from "commander";
|
|
7753
8139
|
function createImageListCommand() {
|
|
7754
|
-
return new
|
|
8140
|
+
return new Command18("list").description("List generated images").option("-m, --model <model>", "Filter by model").option("-l, --limit <number>", "Number of results", "20").option("-o, --offset <number>", "Offset for pagination", "0").action(async (options) => {
|
|
7755
8141
|
const configService = new ConfigService();
|
|
7756
8142
|
const config = await configService.load();
|
|
7757
8143
|
if (!config) {
|
|
@@ -7787,9 +8173,9 @@ function createImageListCommand() {
|
|
|
7787
8173
|
}
|
|
7788
8174
|
|
|
7789
8175
|
// src/commands/image/info.ts
|
|
7790
|
-
import { Command as
|
|
8176
|
+
import { Command as Command19 } from "commander";
|
|
7791
8177
|
function createImageInfoCommand() {
|
|
7792
|
-
return new
|
|
8178
|
+
return new Command19("info").description("Get detailed info about an image").argument("<id>", "Image ID").action(async (id) => {
|
|
7793
8179
|
const configService = new ConfigService();
|
|
7794
8180
|
const config = await configService.load();
|
|
7795
8181
|
if (!config) {
|
|
@@ -7823,10 +8209,10 @@ function createImageInfoCommand() {
|
|
|
7823
8209
|
}
|
|
7824
8210
|
|
|
7825
8211
|
// src/commands/image/delete.ts
|
|
7826
|
-
import { Command as
|
|
8212
|
+
import { Command as Command20 } from "commander";
|
|
7827
8213
|
import { confirm as confirm4 } from "@inquirer/prompts";
|
|
7828
8214
|
function createImageDeleteCommand() {
|
|
7829
|
-
return new
|
|
8215
|
+
return new Command20("delete").description("Delete a generated image").argument("<id>", "Image ID").option("-y, --yes", "Skip confirmation").action(async (id, options) => {
|
|
7830
8216
|
const configService = new ConfigService();
|
|
7831
8217
|
const config = await configService.load();
|
|
7832
8218
|
if (!config) {
|
|
@@ -7868,7 +8254,7 @@ function showImageHelp() {
|
|
|
7868
8254
|
console.log(chalk9.dim('Ch\u1EA1y "jai1 image <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt'));
|
|
7869
8255
|
}
|
|
7870
8256
|
function createImageCommand() {
|
|
7871
|
-
const cmd = new
|
|
8257
|
+
const cmd = new Command21("image").description("Image generation commands (Coming Soon)").action(() => {
|
|
7872
8258
|
showImageHelp();
|
|
7873
8259
|
});
|
|
7874
8260
|
cmd.addCommand(createImageGenCommand());
|
|
@@ -7879,7 +8265,7 @@ function createImageCommand() {
|
|
|
7879
8265
|
}
|
|
7880
8266
|
|
|
7881
8267
|
// src/commands/feedback.ts
|
|
7882
|
-
import { Command as
|
|
8268
|
+
import { Command as Command22 } from "commander";
|
|
7883
8269
|
import { select as select2, input, confirm as confirm5 } from "@inquirer/prompts";
|
|
7884
8270
|
import os from "os";
|
|
7885
8271
|
import { promises as fs11 } from "fs";
|
|
@@ -8088,18 +8474,18 @@ async function handleFeedbackCommand(options) {
|
|
|
8088
8474
|
}
|
|
8089
8475
|
}
|
|
8090
8476
|
function createFeedbackCommand() {
|
|
8091
|
-
const cmd = new
|
|
8477
|
+
const cmd = new Command22("feedback").alias("report").description("Submit bug reports, feature requests, or suggestions").option("--type <type>", "Feedback type: bug, feature, suggestion").option("--title <title>", "Feedback title (max 200 chars)").option("--message <message>", "Feedback message (max 4000 chars)").option("--context <json>", "Additional context as JSON").option("--no-context", "Do not include automatic context").option("--json", "Output JSON format").action(async (options) => {
|
|
8092
8478
|
await handleFeedbackCommand(options);
|
|
8093
8479
|
});
|
|
8094
8480
|
return cmd;
|
|
8095
8481
|
}
|
|
8096
8482
|
|
|
8097
8483
|
// src/commands/utils/index.ts
|
|
8098
|
-
import { Command as
|
|
8484
|
+
import { Command as Command36 } from "commander";
|
|
8099
8485
|
import chalk10 from "chalk";
|
|
8100
8486
|
|
|
8101
8487
|
// src/commands/utils/password.ts
|
|
8102
|
-
import { Command as
|
|
8488
|
+
import { Command as Command23 } from "commander";
|
|
8103
8489
|
|
|
8104
8490
|
// src/services/utils.service.ts
|
|
8105
8491
|
import crypto2 from "crypto";
|
|
@@ -8368,7 +8754,7 @@ async function handlePasswordGeneration(options) {
|
|
|
8368
8754
|
}
|
|
8369
8755
|
}
|
|
8370
8756
|
function createPasswordCommand() {
|
|
8371
|
-
const cmd = new
|
|
8757
|
+
const cmd = new Command23("password").description("Generate secure random password").option("-l, --length <number>", "Password length", "16").option("--no-lowercase", "Exclude lowercase letters").option("--no-uppercase", "Exclude uppercase letters").option("--no-digits", "Exclude digits").option("--no-symbols", "Exclude symbols").option("--symbol-chars <chars>", "Custom symbol characters").option("-c, --count <number>", "Number of passwords to generate", "1").addHelpText("after", `
|
|
8372
8758
|
Examples:
|
|
8373
8759
|
$ jai1 utils password
|
|
8374
8760
|
$ jai1 utils password --length 24
|
|
@@ -8386,7 +8772,7 @@ Examples:
|
|
|
8386
8772
|
}
|
|
8387
8773
|
|
|
8388
8774
|
// src/commands/utils/uuid.ts
|
|
8389
|
-
import { Command as
|
|
8775
|
+
import { Command as Command24 } from "commander";
|
|
8390
8776
|
async function handleUuidGeneration(options) {
|
|
8391
8777
|
const service = new UtilsService();
|
|
8392
8778
|
try {
|
|
@@ -8414,7 +8800,7 @@ async function handleUuidGeneration(options) {
|
|
|
8414
8800
|
}
|
|
8415
8801
|
}
|
|
8416
8802
|
function createUuidCommand() {
|
|
8417
|
-
const cmd = new
|
|
8803
|
+
const cmd = new Command24("uuid").description("Generate UUID v4 identifier").option("-c, --count <number>", "Number of UUIDs to generate", "1").option("--uppercase", "Output in uppercase").option("--no-hyphens", "Remove hyphens from output").addHelpText("after", `
|
|
8418
8804
|
Examples:
|
|
8419
8805
|
$ jai1 utils uuid
|
|
8420
8806
|
$ jai1 utils uuid --count 10
|
|
@@ -8431,7 +8817,7 @@ Examples:
|
|
|
8431
8817
|
}
|
|
8432
8818
|
|
|
8433
8819
|
// src/commands/utils/hash.ts
|
|
8434
|
-
import { Command as
|
|
8820
|
+
import { Command as Command25 } from "commander";
|
|
8435
8821
|
async function handleHashGeneration(input5, options) {
|
|
8436
8822
|
const service = new UtilsService();
|
|
8437
8823
|
try {
|
|
@@ -8471,7 +8857,7 @@ async function handleHashGeneration(input5, options) {
|
|
|
8471
8857
|
}
|
|
8472
8858
|
}
|
|
8473
8859
|
function createHashCommand() {
|
|
8474
|
-
const cmd = new
|
|
8860
|
+
const cmd = new Command25("hash").description("Generate hash (MD5, SHA, bcrypt)").argument("[input]", "Text to hash").option(
|
|
8475
8861
|
"-a, --algorithm <algorithm>",
|
|
8476
8862
|
"Hash algorithm (md5, sha1, sha256, sha512, bcrypt)",
|
|
8477
8863
|
"sha256"
|
|
@@ -8493,7 +8879,7 @@ Examples:
|
|
|
8493
8879
|
}
|
|
8494
8880
|
|
|
8495
8881
|
// src/commands/utils/base64-encode.ts
|
|
8496
|
-
import { Command as
|
|
8882
|
+
import { Command as Command26 } from "commander";
|
|
8497
8883
|
import { readFile as readFile2 } from "fs/promises";
|
|
8498
8884
|
async function handleBase64Encode(input5, options) {
|
|
8499
8885
|
const service = new UtilsService();
|
|
@@ -8526,7 +8912,7 @@ async function handleBase64Encode(input5, options) {
|
|
|
8526
8912
|
}
|
|
8527
8913
|
}
|
|
8528
8914
|
function createBase64EncodeCommand() {
|
|
8529
|
-
const cmd = new
|
|
8915
|
+
const cmd = new Command26("base64-encode").description("Encode text or file to Base64").argument("[input]", "Text to encode").option("-f, --file <path>", "Encode file contents").option("--url-safe", "Use URL-safe Base64 encoding").addHelpText("after", `
|
|
8530
8916
|
Examples:
|
|
8531
8917
|
$ jai1 utils base64-encode "hello world"
|
|
8532
8918
|
$ jai1 utils base64-encode "hello world" --url-safe
|
|
@@ -8539,7 +8925,7 @@ Examples:
|
|
|
8539
8925
|
}
|
|
8540
8926
|
|
|
8541
8927
|
// src/commands/utils/base64-decode.ts
|
|
8542
|
-
import { Command as
|
|
8928
|
+
import { Command as Command27 } from "commander";
|
|
8543
8929
|
import { readFile as readFile3, writeFile } from "fs/promises";
|
|
8544
8930
|
async function handleBase64Decode(input5, options) {
|
|
8545
8931
|
const service = new UtilsService();
|
|
@@ -8571,7 +8957,7 @@ async function handleBase64Decode(input5, options) {
|
|
|
8571
8957
|
}
|
|
8572
8958
|
}
|
|
8573
8959
|
function createBase64DecodeCommand() {
|
|
8574
|
-
const cmd = new
|
|
8960
|
+
const cmd = new Command27("base64-decode").description("Decode Base64 string").argument("[input]", "Base64 string to decode").option("-f, --file <path>", "Decode from file").option("-o, --output <path>", "Write decoded output to file").addHelpText("after", `
|
|
8575
8961
|
Examples:
|
|
8576
8962
|
$ jai1 utils base64-decode "aGVsbG8gd29ybGQ="
|
|
8577
8963
|
$ jai1 utils base64-decode --file ./encoded.txt
|
|
@@ -8584,7 +8970,7 @@ Examples:
|
|
|
8584
8970
|
}
|
|
8585
8971
|
|
|
8586
8972
|
// src/commands/utils/http.ts
|
|
8587
|
-
import { Command as
|
|
8973
|
+
import { Command as Command28 } from "commander";
|
|
8588
8974
|
import { readFile as readFile4 } from "fs/promises";
|
|
8589
8975
|
async function handleHttpRequest(url, options) {
|
|
8590
8976
|
const service = new UtilsService();
|
|
@@ -8650,7 +9036,7 @@ async function handleHttpRequest(url, options) {
|
|
|
8650
9036
|
}
|
|
8651
9037
|
}
|
|
8652
9038
|
function createHttpCommand() {
|
|
8653
|
-
const cmd = new
|
|
9039
|
+
const cmd = new Command28("http").description("Make HTTP request with formatted output").argument("<url>", "Target URL").option("-X, --method <method>", "HTTP method", "GET").option("-H, --header <header...>", "Request headers (repeatable)").option("-d, --data <data>", "Request body (JSON string)").option("--file <path>", "Read body from file").option("--timeout <ms>", "Request timeout in milliseconds", "30000").option("--no-follow", "Do not follow redirects").option("--only-headers", "Show only response headers").option("--only-body", "Show only response body").addHelpText("after", `
|
|
8654
9040
|
Examples:
|
|
8655
9041
|
$ jai1 utils http https://api.example.com/users
|
|
8656
9042
|
$ jai1 utils http https://api.example.com/users -X POST -d '{"name":"John"}'
|
|
@@ -8668,7 +9054,7 @@ Examples:
|
|
|
8668
9054
|
}
|
|
8669
9055
|
|
|
8670
9056
|
// src/commands/utils/jwt.ts
|
|
8671
|
-
import { Command as
|
|
9057
|
+
import { Command as Command29 } from "commander";
|
|
8672
9058
|
async function handleJwtDecode(token) {
|
|
8673
9059
|
const service = new UtilsService();
|
|
8674
9060
|
try {
|
|
@@ -8707,7 +9093,7 @@ async function handleJwtEncode(options) {
|
|
|
8707
9093
|
}
|
|
8708
9094
|
}
|
|
8709
9095
|
function createJwtCommand() {
|
|
8710
|
-
const jwtCommand = new
|
|
9096
|
+
const jwtCommand = new Command29("jwt").description("Decode and encode JWT tokens");
|
|
8711
9097
|
jwtCommand.command("decode").description("Decode JWT token").argument("<token>", "JWT token to decode").addHelpText("after", `
|
|
8712
9098
|
Examples:
|
|
8713
9099
|
$ jai1 utils jwt decode "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
|
|
@@ -8728,7 +9114,7 @@ Examples:
|
|
|
8728
9114
|
}
|
|
8729
9115
|
|
|
8730
9116
|
// src/commands/utils/unix-time.ts
|
|
8731
|
-
import { Command as
|
|
9117
|
+
import { Command as Command30 } from "commander";
|
|
8732
9118
|
async function handleUnixTime(input5, options) {
|
|
8733
9119
|
const service = new UtilsService();
|
|
8734
9120
|
try {
|
|
@@ -8776,7 +9162,7 @@ async function handleUnixTime(input5, options) {
|
|
|
8776
9162
|
}
|
|
8777
9163
|
}
|
|
8778
9164
|
function createUnixTimeCommand() {
|
|
8779
|
-
const cmd = new
|
|
9165
|
+
const cmd = new Command30("unix-time").description("Convert unix timestamps to/from dates").argument("[input]", "Unix timestamp or date string").option("-f, --format <format>", "Output format (iso, local, utc)", "iso").option("--ms", "Use milliseconds instead of seconds").addHelpText("after", `
|
|
8780
9166
|
Examples:
|
|
8781
9167
|
$ jai1 utils unix-time
|
|
8782
9168
|
$ jai1 utils unix-time 1702550400
|
|
@@ -8791,7 +9177,7 @@ Examples:
|
|
|
8791
9177
|
}
|
|
8792
9178
|
|
|
8793
9179
|
// src/commands/utils/timezone.ts
|
|
8794
|
-
import { Command as
|
|
9180
|
+
import { Command as Command31 } from "commander";
|
|
8795
9181
|
async function handleTimezoneConversion(time, options) {
|
|
8796
9182
|
const service = new UtilsService();
|
|
8797
9183
|
try {
|
|
@@ -8828,7 +9214,7 @@ async function handleTimezoneConversion(time, options) {
|
|
|
8828
9214
|
}
|
|
8829
9215
|
}
|
|
8830
9216
|
function createTimezoneCommand() {
|
|
8831
|
-
const cmd = new
|
|
9217
|
+
const cmd = new Command31("timezone").description("Convert time between timezones").argument("[time]", 'Time to convert (e.g., "2024-01-15 10:00")').option("--from <timezone>", "Source timezone").option("--to <timezone>", "Target timezone").option("--list", "Show available timezones").addHelpText("after", `
|
|
8832
9218
|
Examples:
|
|
8833
9219
|
$ jai1 utils timezone --list
|
|
8834
9220
|
$ jai1 utils timezone "2024-01-15 10:00" --from "America/New_York" --to "Asia/Tokyo"
|
|
@@ -8841,7 +9227,7 @@ Examples:
|
|
|
8841
9227
|
}
|
|
8842
9228
|
|
|
8843
9229
|
// src/commands/utils/url-encode.ts
|
|
8844
|
-
import { Command as
|
|
9230
|
+
import { Command as Command32 } from "commander";
|
|
8845
9231
|
async function handleUrlEncode(input5, options) {
|
|
8846
9232
|
const service = new UtilsService();
|
|
8847
9233
|
try {
|
|
@@ -8862,7 +9248,7 @@ async function handleUrlEncode(input5, options) {
|
|
|
8862
9248
|
}
|
|
8863
9249
|
}
|
|
8864
9250
|
function createUrlEncodeCommand() {
|
|
8865
|
-
const cmd = new
|
|
9251
|
+
const cmd = new Command32("url-encode").description("Encode URL component or full URL").argument("<input>", "Text to encode").option("--full", "Encode full URL (use encodeURI instead of encodeURIComponent)").addHelpText("after", `
|
|
8866
9252
|
Examples:
|
|
8867
9253
|
$ jai1 utils url-encode "hello world"
|
|
8868
9254
|
$ jai1 utils url-encode "hello world & test"
|
|
@@ -8875,7 +9261,7 @@ Examples:
|
|
|
8875
9261
|
}
|
|
8876
9262
|
|
|
8877
9263
|
// src/commands/utils/url-decode.ts
|
|
8878
|
-
import { Command as
|
|
9264
|
+
import { Command as Command33 } from "commander";
|
|
8879
9265
|
async function handleUrlDecode(input5, options) {
|
|
8880
9266
|
const service = new UtilsService();
|
|
8881
9267
|
try {
|
|
@@ -8896,7 +9282,7 @@ async function handleUrlDecode(input5, options) {
|
|
|
8896
9282
|
}
|
|
8897
9283
|
}
|
|
8898
9284
|
function createUrlDecodeCommand() {
|
|
8899
|
-
const cmd = new
|
|
9285
|
+
const cmd = new Command33("url-decode").description("Decode URL-encoded string").argument("<input>", "Text to decode").option("--full", "Decode full URL (use decodeURI instead of decodeURIComponent)").addHelpText("after", `
|
|
8900
9286
|
Examples:
|
|
8901
9287
|
$ jai1 utils url-decode "hello%20world"
|
|
8902
9288
|
$ jai1 utils url-decode "hello%20world%20%26%20test"
|
|
@@ -8909,7 +9295,7 @@ Examples:
|
|
|
8909
9295
|
}
|
|
8910
9296
|
|
|
8911
9297
|
// src/commands/utils/cron.ts
|
|
8912
|
-
import { Command as
|
|
9298
|
+
import { Command as Command34 } from "commander";
|
|
8913
9299
|
import cronstrue from "cronstrue";
|
|
8914
9300
|
async function handleCronParse(expression) {
|
|
8915
9301
|
try {
|
|
@@ -8952,7 +9338,7 @@ async function handleCronParse(expression) {
|
|
|
8952
9338
|
}
|
|
8953
9339
|
}
|
|
8954
9340
|
function createCronCommand() {
|
|
8955
|
-
const cmd = new
|
|
9341
|
+
const cmd = new Command34("cron").description("Parse and explain cron expression").argument("<expression>", 'Cron expression (e.g., "0 5 * * *")').addHelpText("after", `
|
|
8956
9342
|
Examples:
|
|
8957
9343
|
$ jai1 utils cron "0 5 * * *"
|
|
8958
9344
|
$ jai1 utils cron "*/15 * * * *"
|
|
@@ -8966,7 +9352,7 @@ Examples:
|
|
|
8966
9352
|
}
|
|
8967
9353
|
|
|
8968
9354
|
// src/commands/utils/markdown-preview.ts
|
|
8969
|
-
import { Command as
|
|
9355
|
+
import { Command as Command35 } from "commander";
|
|
8970
9356
|
import { readFile as readFile5 } from "fs/promises";
|
|
8971
9357
|
import { marked as marked2 } from "marked";
|
|
8972
9358
|
import TerminalRenderer2 from "marked-terminal";
|
|
@@ -9005,7 +9391,7 @@ ${code.trim()}
|
|
|
9005
9391
|
}
|
|
9006
9392
|
}
|
|
9007
9393
|
function createMarkdownPreviewCommand() {
|
|
9008
|
-
const cmd = new
|
|
9394
|
+
const cmd = new Command35("markdown-preview").description("Preview markdown file in terminal").argument("<file>", "Markdown file path").option("--raw", "Show raw markdown instead of rendered").addHelpText("after", `
|
|
9009
9395
|
Examples:
|
|
9010
9396
|
$ jai1 utils markdown-preview README.md
|
|
9011
9397
|
$ jai1 utils markdown-preview ./docs/guide.md
|
|
@@ -9018,28 +9404,28 @@ Examples:
|
|
|
9018
9404
|
}
|
|
9019
9405
|
|
|
9020
9406
|
// src/commands/utils/interactive.ts
|
|
9021
|
-
import
|
|
9022
|
-
import { render as
|
|
9407
|
+
import React44 from "react";
|
|
9408
|
+
import { render as render6 } from "ink";
|
|
9023
9409
|
|
|
9024
9410
|
// src/ui/utils/UtilsApp.tsx
|
|
9025
|
-
import
|
|
9026
|
-
import { Box as
|
|
9411
|
+
import React43, { useState as useState26 } from "react";
|
|
9412
|
+
import { Box as Box37, Text as Text37, useInput as useInput23, useApp as useApp6 } from "ink";
|
|
9027
9413
|
|
|
9028
9414
|
// src/ui/utils/views/PasswordView.tsx
|
|
9029
|
-
import
|
|
9030
|
-
import { Box as
|
|
9031
|
-
import
|
|
9415
|
+
import React32, { useState as useState15 } from "react";
|
|
9416
|
+
import { Box as Box26, Text as Text26, useInput as useInput12 } from "ink";
|
|
9417
|
+
import TextInput5 from "ink-text-input";
|
|
9032
9418
|
var PasswordView = () => {
|
|
9033
|
-
const [length, setLength] =
|
|
9034
|
-
const [count, setCount] =
|
|
9035
|
-
const [passwords, setPasswords] =
|
|
9036
|
-
const [focusedField, setFocusedField] =
|
|
9037
|
-
const [copiedIndex, setCopiedIndex] =
|
|
9419
|
+
const [length, setLength] = useState15("16");
|
|
9420
|
+
const [count, setCount] = useState15("1");
|
|
9421
|
+
const [passwords, setPasswords] = useState15([]);
|
|
9422
|
+
const [focusedField, setFocusedField] = useState15("length");
|
|
9423
|
+
const [copiedIndex, setCopiedIndex] = useState15(null);
|
|
9038
9424
|
const service = new UtilsService();
|
|
9039
|
-
|
|
9425
|
+
React32.useEffect(() => {
|
|
9040
9426
|
handleGenerate();
|
|
9041
9427
|
}, []);
|
|
9042
|
-
|
|
9428
|
+
useInput12((input5, key) => {
|
|
9043
9429
|
if (key.tab) {
|
|
9044
9430
|
if (focusedField === "length") setFocusedField("count");
|
|
9045
9431
|
else if (focusedField === "count") setFocusedField("generate");
|
|
@@ -9077,8 +9463,8 @@ var PasswordView = () => {
|
|
|
9077
9463
|
} catch (error) {
|
|
9078
9464
|
}
|
|
9079
9465
|
};
|
|
9080
|
-
return /* @__PURE__ */
|
|
9081
|
-
|
|
9466
|
+
return /* @__PURE__ */ React32.createElement(Box26, { flexDirection: "column" }, /* @__PURE__ */ React32.createElement(Box26, { marginBottom: 1 }, /* @__PURE__ */ React32.createElement(Text26, { bold: true, color: "cyan" }, "\u{1F510} Password Generator")), /* @__PURE__ */ React32.createElement(
|
|
9467
|
+
Box26,
|
|
9082
9468
|
{
|
|
9083
9469
|
flexDirection: "column",
|
|
9084
9470
|
borderStyle: "single",
|
|
@@ -9087,11 +9473,11 @@ var PasswordView = () => {
|
|
|
9087
9473
|
paddingY: 1,
|
|
9088
9474
|
marginBottom: 1
|
|
9089
9475
|
},
|
|
9090
|
-
/* @__PURE__ */
|
|
9091
|
-
/* @__PURE__ */
|
|
9092
|
-
/* @__PURE__ */
|
|
9093
|
-
/* @__PURE__ */
|
|
9094
|
-
|
|
9476
|
+
/* @__PURE__ */ React32.createElement(Text26, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
|
|
9477
|
+
/* @__PURE__ */ React32.createElement(Box26, { marginBottom: 1 }, /* @__PURE__ */ React32.createElement(Box26, { width: 20 }, /* @__PURE__ */ React32.createElement(Text26, { color: focusedField === "length" ? "green" : void 0 }, focusedField === "length" ? "\u25B6 " : " ", "Length:")), /* @__PURE__ */ React32.createElement(Box26, { width: 10 }, focusedField === "length" ? /* @__PURE__ */ React32.createElement(TextInput5, { value: length, onChange: setLength }) : /* @__PURE__ */ React32.createElement(Text26, null, length)), /* @__PURE__ */ React32.createElement(Text26, { dimColor: true }, "(characters)")),
|
|
9478
|
+
/* @__PURE__ */ React32.createElement(Box26, { marginBottom: 1 }, /* @__PURE__ */ React32.createElement(Box26, { width: 20 }, /* @__PURE__ */ React32.createElement(Text26, { color: focusedField === "count" ? "green" : void 0 }, focusedField === "count" ? "\u25B6 " : " ", "Count:")), /* @__PURE__ */ React32.createElement(Box26, { width: 10 }, focusedField === "count" ? /* @__PURE__ */ React32.createElement(TextInput5, { value: count, onChange: setCount }) : /* @__PURE__ */ React32.createElement(Text26, null, count)), /* @__PURE__ */ React32.createElement(Text26, { dimColor: true }, "(passwords to generate)")),
|
|
9479
|
+
/* @__PURE__ */ React32.createElement(Box26, { marginTop: 1 }, /* @__PURE__ */ React32.createElement(
|
|
9480
|
+
Text26,
|
|
9095
9481
|
{
|
|
9096
9482
|
bold: true,
|
|
9097
9483
|
backgroundColor: focusedField === "generate" ? "green" : void 0,
|
|
@@ -9100,8 +9486,8 @@ var PasswordView = () => {
|
|
|
9100
9486
|
focusedField === "generate" ? "\u25B6 " : " ",
|
|
9101
9487
|
"[ Generate Passwords ]"
|
|
9102
9488
|
))
|
|
9103
|
-
), passwords.length > 0 && /* @__PURE__ */
|
|
9104
|
-
|
|
9489
|
+
), passwords.length > 0 && /* @__PURE__ */ React32.createElement(
|
|
9490
|
+
Box26,
|
|
9105
9491
|
{
|
|
9106
9492
|
flexDirection: "column",
|
|
9107
9493
|
borderStyle: "single",
|
|
@@ -9109,27 +9495,27 @@ var PasswordView = () => {
|
|
|
9109
9495
|
paddingX: 2,
|
|
9110
9496
|
paddingY: 1
|
|
9111
9497
|
},
|
|
9112
|
-
/* @__PURE__ */
|
|
9113
|
-
passwords.map((password, index) => /* @__PURE__ */
|
|
9114
|
-
), /* @__PURE__ */
|
|
9498
|
+
/* @__PURE__ */ React32.createElement(Text26, { bold: true, color: "green", marginBottom: 1 }, "\u2713 Generated Passwords:"),
|
|
9499
|
+
passwords.map((password, index) => /* @__PURE__ */ React32.createElement(Box26, { key: index, marginBottom: 0 }, /* @__PURE__ */ React32.createElement(Box26, { width: 4 }, /* @__PURE__ */ React32.createElement(Text26, { dimColor: true }, index + 1, ".")), /* @__PURE__ */ React32.createElement(Box26, { flexGrow: 1 }, /* @__PURE__ */ React32.createElement(Text26, null, password)), copiedIndex === index && /* @__PURE__ */ React32.createElement(Text26, { color: "green" }, " \u2713 Copied!")))
|
|
9500
|
+
), /* @__PURE__ */ React32.createElement(Box26, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 2 }, /* @__PURE__ */ React32.createElement(Text26, { dimColor: true }, "Tab: Next field | Enter: Generate | C: Copy | Esc: Back")));
|
|
9115
9501
|
};
|
|
9116
9502
|
|
|
9117
9503
|
// src/ui/utils/views/UuidView.tsx
|
|
9118
|
-
import
|
|
9119
|
-
import { Box as
|
|
9120
|
-
import
|
|
9504
|
+
import React33, { useState as useState16 } from "react";
|
|
9505
|
+
import { Box as Box27, Text as Text27, useInput as useInput13 } from "ink";
|
|
9506
|
+
import TextInput6 from "ink-text-input";
|
|
9121
9507
|
var UuidView = () => {
|
|
9122
|
-
const [count, setCount] =
|
|
9123
|
-
const [uppercase, setUppercase] =
|
|
9124
|
-
const [noHyphens, setNoHyphens] =
|
|
9125
|
-
const [uuids, setUuids] =
|
|
9126
|
-
const [focusedField, setFocusedField] =
|
|
9127
|
-
const [copiedIndex, setCopiedIndex] =
|
|
9508
|
+
const [count, setCount] = useState16("1");
|
|
9509
|
+
const [uppercase, setUppercase] = useState16(false);
|
|
9510
|
+
const [noHyphens, setNoHyphens] = useState16(false);
|
|
9511
|
+
const [uuids, setUuids] = useState16([]);
|
|
9512
|
+
const [focusedField, setFocusedField] = useState16("count");
|
|
9513
|
+
const [copiedIndex, setCopiedIndex] = useState16(null);
|
|
9128
9514
|
const service = new UtilsService();
|
|
9129
|
-
|
|
9515
|
+
React33.useEffect(() => {
|
|
9130
9516
|
handleGenerate();
|
|
9131
9517
|
}, []);
|
|
9132
|
-
|
|
9518
|
+
useInput13((input5, key) => {
|
|
9133
9519
|
if (key.tab) {
|
|
9134
9520
|
const fields = ["count", "uppercase", "hyphens", "generate"];
|
|
9135
9521
|
const currentIndex = fields.indexOf(focusedField);
|
|
@@ -9164,8 +9550,8 @@ var UuidView = () => {
|
|
|
9164
9550
|
} catch (error) {
|
|
9165
9551
|
}
|
|
9166
9552
|
};
|
|
9167
|
-
return /* @__PURE__ */
|
|
9168
|
-
|
|
9553
|
+
return /* @__PURE__ */ React33.createElement(Box27, { flexDirection: "column" }, /* @__PURE__ */ React33.createElement(Box27, { marginBottom: 1 }, /* @__PURE__ */ React33.createElement(Text27, { bold: true, color: "cyan" }, "\u{1F194} UUID Generator")), /* @__PURE__ */ React33.createElement(
|
|
9554
|
+
Box27,
|
|
9169
9555
|
{
|
|
9170
9556
|
flexDirection: "column",
|
|
9171
9557
|
borderStyle: "single",
|
|
@@ -9174,12 +9560,12 @@ var UuidView = () => {
|
|
|
9174
9560
|
paddingY: 1,
|
|
9175
9561
|
marginBottom: 1
|
|
9176
9562
|
},
|
|
9177
|
-
/* @__PURE__ */
|
|
9178
|
-
/* @__PURE__ */
|
|
9179
|
-
/* @__PURE__ */
|
|
9180
|
-
/* @__PURE__ */
|
|
9181
|
-
/* @__PURE__ */
|
|
9182
|
-
|
|
9563
|
+
/* @__PURE__ */ React33.createElement(Text27, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
|
|
9564
|
+
/* @__PURE__ */ React33.createElement(Box27, { marginBottom: 1 }, /* @__PURE__ */ React33.createElement(Box27, { width: 20 }, /* @__PURE__ */ React33.createElement(Text27, { color: focusedField === "count" ? "green" : void 0 }, focusedField === "count" ? "\u25B6 " : " ", "Count:")), /* @__PURE__ */ React33.createElement(Box27, { width: 10 }, focusedField === "count" ? /* @__PURE__ */ React33.createElement(TextInput6, { value: count, onChange: setCount }) : /* @__PURE__ */ React33.createElement(Text27, null, count))),
|
|
9565
|
+
/* @__PURE__ */ React33.createElement(Box27, { marginBottom: 1 }, /* @__PURE__ */ React33.createElement(Text27, { color: focusedField === "uppercase" ? "green" : void 0 }, focusedField === "uppercase" ? "\u25B6 " : " ", "[", uppercase ? "\u2713" : " ", "] Uppercase")),
|
|
9566
|
+
/* @__PURE__ */ React33.createElement(Box27, { marginBottom: 1 }, /* @__PURE__ */ React33.createElement(Text27, { color: focusedField === "hyphens" ? "green" : void 0 }, focusedField === "hyphens" ? "\u25B6 " : " ", "[", noHyphens ? "\u2713" : " ", "] No Hyphens")),
|
|
9567
|
+
/* @__PURE__ */ React33.createElement(Box27, { marginTop: 1 }, /* @__PURE__ */ React33.createElement(
|
|
9568
|
+
Text27,
|
|
9183
9569
|
{
|
|
9184
9570
|
bold: true,
|
|
9185
9571
|
backgroundColor: focusedField === "generate" ? "green" : void 0,
|
|
@@ -9188,8 +9574,8 @@ var UuidView = () => {
|
|
|
9188
9574
|
focusedField === "generate" ? "\u25B6 " : " ",
|
|
9189
9575
|
"[ Generate UUIDs ]"
|
|
9190
9576
|
))
|
|
9191
|
-
), uuids.length > 0 && /* @__PURE__ */
|
|
9192
|
-
|
|
9577
|
+
), uuids.length > 0 && /* @__PURE__ */ React33.createElement(
|
|
9578
|
+
Box27,
|
|
9193
9579
|
{
|
|
9194
9580
|
flexDirection: "column",
|
|
9195
9581
|
borderStyle: "single",
|
|
@@ -9197,27 +9583,27 @@ var UuidView = () => {
|
|
|
9197
9583
|
paddingX: 2,
|
|
9198
9584
|
paddingY: 1
|
|
9199
9585
|
},
|
|
9200
|
-
/* @__PURE__ */
|
|
9201
|
-
uuids.map((uuid, index) => /* @__PURE__ */
|
|
9202
|
-
), /* @__PURE__ */
|
|
9586
|
+
/* @__PURE__ */ React33.createElement(Text27, { bold: true, color: "green", marginBottom: 1 }, "\u2713 Generated UUIDs:"),
|
|
9587
|
+
uuids.map((uuid, index) => /* @__PURE__ */ React33.createElement(Box27, { key: index, marginBottom: 0 }, /* @__PURE__ */ React33.createElement(Box27, { width: 4 }, /* @__PURE__ */ React33.createElement(Text27, { dimColor: true }, index + 1, ".")), /* @__PURE__ */ React33.createElement(Box27, { flexGrow: 1 }, /* @__PURE__ */ React33.createElement(Text27, null, uuid)), copiedIndex === index && /* @__PURE__ */ React33.createElement(Text27, { color: "green" }, " \u2713 Copied!")))
|
|
9588
|
+
), /* @__PURE__ */ React33.createElement(Box27, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 2 }, /* @__PURE__ */ React33.createElement(Text27, { dimColor: true }, "Tab: Next | Enter: Toggle/Generate | C: Copy | Esc: Back")));
|
|
9203
9589
|
};
|
|
9204
9590
|
|
|
9205
9591
|
// src/ui/utils/views/HashView.tsx
|
|
9206
|
-
import
|
|
9207
|
-
import { Box as
|
|
9208
|
-
import
|
|
9592
|
+
import React34, { useState as useState17 } from "react";
|
|
9593
|
+
import { Box as Box28, Text as Text28, useInput as useInput14 } from "ink";
|
|
9594
|
+
import TextInput7 from "ink-text-input";
|
|
9209
9595
|
var ALGORITHMS = ["sha256", "sha512", "sha1", "md5", "bcrypt"];
|
|
9210
9596
|
var HashView = () => {
|
|
9211
|
-
const [text, setText] =
|
|
9212
|
-
const [algorithm, setAlgorithm] =
|
|
9213
|
-
const [hash, setHash] =
|
|
9214
|
-
const [focusedField, setFocusedField] =
|
|
9215
|
-
const [copied, setCopied] =
|
|
9597
|
+
const [text, setText] = useState17("hello world");
|
|
9598
|
+
const [algorithm, setAlgorithm] = useState17("sha256");
|
|
9599
|
+
const [hash, setHash] = useState17("");
|
|
9600
|
+
const [focusedField, setFocusedField] = useState17("text");
|
|
9601
|
+
const [copied, setCopied] = useState17(false);
|
|
9216
9602
|
const service = new UtilsService();
|
|
9217
|
-
|
|
9603
|
+
React34.useEffect(() => {
|
|
9218
9604
|
handleGenerate();
|
|
9219
9605
|
}, []);
|
|
9220
|
-
|
|
9606
|
+
useInput14((input5, key) => {
|
|
9221
9607
|
if (key.tab) {
|
|
9222
9608
|
const fields = ["text", "algorithm", "generate"];
|
|
9223
9609
|
const currentIndex = fields.indexOf(focusedField);
|
|
@@ -9254,8 +9640,8 @@ var HashView = () => {
|
|
|
9254
9640
|
} catch (error) {
|
|
9255
9641
|
}
|
|
9256
9642
|
};
|
|
9257
|
-
return /* @__PURE__ */
|
|
9258
|
-
|
|
9643
|
+
return /* @__PURE__ */ React34.createElement(Box28, { flexDirection: "column" }, /* @__PURE__ */ React34.createElement(Box28, { marginBottom: 1 }, /* @__PURE__ */ React34.createElement(Text28, { bold: true, color: "cyan" }, "\u{1F512} Hash Generator")), /* @__PURE__ */ React34.createElement(
|
|
9644
|
+
Box28,
|
|
9259
9645
|
{
|
|
9260
9646
|
flexDirection: "column",
|
|
9261
9647
|
borderStyle: "single",
|
|
@@ -9264,11 +9650,11 @@ var HashView = () => {
|
|
|
9264
9650
|
paddingY: 1,
|
|
9265
9651
|
marginBottom: 1
|
|
9266
9652
|
},
|
|
9267
|
-
/* @__PURE__ */
|
|
9268
|
-
/* @__PURE__ */
|
|
9269
|
-
/* @__PURE__ */
|
|
9270
|
-
/* @__PURE__ */
|
|
9271
|
-
|
|
9653
|
+
/* @__PURE__ */ React34.createElement(Text28, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
|
|
9654
|
+
/* @__PURE__ */ React34.createElement(Box28, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React34.createElement(Box28, { marginBottom: 0 }, /* @__PURE__ */ React34.createElement(Text28, { color: focusedField === "text" ? "green" : void 0 }, focusedField === "text" ? "\u25B6 " : " ", "Text to hash:")), /* @__PURE__ */ React34.createElement(Box28, { marginLeft: 2, width: 60 }, focusedField === "text" ? /* @__PURE__ */ React34.createElement(TextInput7, { value: text, onChange: setText, placeholder: "Enter text..." }) : /* @__PURE__ */ React34.createElement(Text28, { dimColor: !text }, text || "(empty)"))),
|
|
9655
|
+
/* @__PURE__ */ React34.createElement(Box28, { marginBottom: 1 }, /* @__PURE__ */ React34.createElement(Box28, { width: 20 }, /* @__PURE__ */ React34.createElement(Text28, { color: focusedField === "algorithm" ? "green" : void 0 }, focusedField === "algorithm" ? "\u25B6 " : " ", "Algorithm:")), /* @__PURE__ */ React34.createElement(Text28, { bold: true, color: focusedField === "algorithm" ? "yellow" : void 0 }, algorithm.toUpperCase()), focusedField === "algorithm" && /* @__PURE__ */ React34.createElement(Text28, { dimColor: true }, " (\u2190 \u2192 to change)")),
|
|
9656
|
+
/* @__PURE__ */ React34.createElement(Box28, { marginTop: 1 }, /* @__PURE__ */ React34.createElement(
|
|
9657
|
+
Text28,
|
|
9272
9658
|
{
|
|
9273
9659
|
bold: true,
|
|
9274
9660
|
backgroundColor: focusedField === "generate" ? "green" : void 0,
|
|
@@ -9277,8 +9663,8 @@ var HashView = () => {
|
|
|
9277
9663
|
focusedField === "generate" ? "\u25B6 " : " ",
|
|
9278
9664
|
"[ Generate Hash ]"
|
|
9279
9665
|
))
|
|
9280
|
-
), hash && /* @__PURE__ */
|
|
9281
|
-
|
|
9666
|
+
), hash && /* @__PURE__ */ React34.createElement(
|
|
9667
|
+
Box28,
|
|
9282
9668
|
{
|
|
9283
9669
|
flexDirection: "column",
|
|
9284
9670
|
borderStyle: "single",
|
|
@@ -9286,25 +9672,25 @@ var HashView = () => {
|
|
|
9286
9672
|
paddingX: 2,
|
|
9287
9673
|
paddingY: 1
|
|
9288
9674
|
},
|
|
9289
|
-
/* @__PURE__ */
|
|
9290
|
-
/* @__PURE__ */
|
|
9291
|
-
), /* @__PURE__ */
|
|
9675
|
+
/* @__PURE__ */ React34.createElement(Box28, { marginBottom: 1 }, /* @__PURE__ */ React34.createElement(Text28, { bold: true, color: "green" }, "\u2713 Hash Result:"), copied && /* @__PURE__ */ React34.createElement(Box28, { marginLeft: 2 }, /* @__PURE__ */ React34.createElement(Text28, { color: "green" }, "\u2713 Copied to clipboard!"))),
|
|
9676
|
+
/* @__PURE__ */ React34.createElement(Box28, { flexDirection: "column" }, /* @__PURE__ */ React34.createElement(Text28, { dimColor: true }, "Algorithm: ", algorithm.toUpperCase()), /* @__PURE__ */ React34.createElement(Box28, { marginTop: 1 }, /* @__PURE__ */ React34.createElement(Text28, { wrap: "wrap" }, hash)))
|
|
9677
|
+
), /* @__PURE__ */ React34.createElement(Box28, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 2 }, /* @__PURE__ */ React34.createElement(Text28, { dimColor: true }, "Tab: Next | \u2190/\u2192: Change algorithm | Enter: Generate | C: Copy | Esc: Back")));
|
|
9292
9678
|
};
|
|
9293
9679
|
|
|
9294
9680
|
// src/ui/utils/views/Base64View.tsx
|
|
9295
|
-
import
|
|
9296
|
-
import { Box as
|
|
9297
|
-
import
|
|
9681
|
+
import React35, { useState as useState18 } from "react";
|
|
9682
|
+
import { Box as Box29, Text as Text29, useInput as useInput15 } from "ink";
|
|
9683
|
+
import TextInput8 from "ink-text-input";
|
|
9298
9684
|
var Base64View = () => {
|
|
9299
|
-
const [input5, setInput] =
|
|
9300
|
-
const [mode, setMode] =
|
|
9301
|
-
const [urlSafe, setUrlSafe] =
|
|
9302
|
-
const [result, setResult] =
|
|
9303
|
-
const [error, setError] =
|
|
9304
|
-
const [focusedField, setFocusedField] =
|
|
9305
|
-
const [copied, setCopied] =
|
|
9685
|
+
const [input5, setInput] = useState18("");
|
|
9686
|
+
const [mode, setMode] = useState18("encode");
|
|
9687
|
+
const [urlSafe, setUrlSafe] = useState18(false);
|
|
9688
|
+
const [result, setResult] = useState18("");
|
|
9689
|
+
const [error, setError] = useState18("");
|
|
9690
|
+
const [focusedField, setFocusedField] = useState18("input");
|
|
9691
|
+
const [copied, setCopied] = useState18(false);
|
|
9306
9692
|
const service = new UtilsService();
|
|
9307
|
-
|
|
9693
|
+
useInput15((input6, key) => {
|
|
9308
9694
|
if (key.tab) {
|
|
9309
9695
|
const fields = ["input", "mode", "urlsafe", "convert"];
|
|
9310
9696
|
const currentIndex = fields.indexOf(focusedField);
|
|
@@ -9352,8 +9738,8 @@ var Base64View = () => {
|
|
|
9352
9738
|
} catch (error2) {
|
|
9353
9739
|
}
|
|
9354
9740
|
};
|
|
9355
|
-
return /* @__PURE__ */
|
|
9356
|
-
|
|
9741
|
+
return /* @__PURE__ */ React35.createElement(Box29, { flexDirection: "column" }, /* @__PURE__ */ React35.createElement(Box29, { marginBottom: 1 }, /* @__PURE__ */ React35.createElement(Text29, { bold: true, color: "cyan" }, "\u{1F4DD} Base64 Encoder/Decoder")), /* @__PURE__ */ React35.createElement(
|
|
9742
|
+
Box29,
|
|
9357
9743
|
{
|
|
9358
9744
|
flexDirection: "column",
|
|
9359
9745
|
borderStyle: "single",
|
|
@@ -9362,12 +9748,12 @@ var Base64View = () => {
|
|
|
9362
9748
|
paddingY: 1,
|
|
9363
9749
|
marginBottom: 1
|
|
9364
9750
|
},
|
|
9365
|
-
/* @__PURE__ */
|
|
9366
|
-
/* @__PURE__ */
|
|
9367
|
-
/* @__PURE__ */
|
|
9368
|
-
mode === "encode" && /* @__PURE__ */
|
|
9369
|
-
/* @__PURE__ */
|
|
9370
|
-
|
|
9751
|
+
/* @__PURE__ */ React35.createElement(Text29, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
|
|
9752
|
+
/* @__PURE__ */ React35.createElement(Box29, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React35.createElement(Box29, { marginBottom: 0 }, /* @__PURE__ */ React35.createElement(Text29, { color: focusedField === "input" ? "green" : void 0 }, focusedField === "input" ? "\u25B6 " : " ", "Input text:")), /* @__PURE__ */ React35.createElement(Box29, { marginLeft: 2, width: 60 }, focusedField === "input" ? /* @__PURE__ */ React35.createElement(TextInput8, { value: input5, onChange: setInput, placeholder: "Enter text..." }) : /* @__PURE__ */ React35.createElement(Text29, { dimColor: !input5 }, input5 || "(empty)"))),
|
|
9753
|
+
/* @__PURE__ */ React35.createElement(Box29, { marginBottom: 1 }, /* @__PURE__ */ React35.createElement(Box29, { width: 20 }, /* @__PURE__ */ React35.createElement(Text29, { color: focusedField === "mode" ? "green" : void 0 }, focusedField === "mode" ? "\u25B6 " : " ", "Mode:")), /* @__PURE__ */ React35.createElement(Text29, { bold: true, color: focusedField === "mode" ? "yellow" : void 0 }, mode === "encode" ? "ENCODE" : "DECODE"), focusedField === "mode" && /* @__PURE__ */ React35.createElement(Text29, { dimColor: true }, " (Enter to toggle)")),
|
|
9754
|
+
mode === "encode" && /* @__PURE__ */ React35.createElement(Box29, { marginBottom: 1 }, /* @__PURE__ */ React35.createElement(Text29, { color: focusedField === "urlsafe" ? "green" : void 0 }, focusedField === "urlsafe" ? "\u25B6 " : " ", "[", urlSafe ? "\u2713" : " ", "] URL-Safe (+ \u2192 -, / \u2192 _)")),
|
|
9755
|
+
/* @__PURE__ */ React35.createElement(Box29, { marginTop: 1 }, /* @__PURE__ */ React35.createElement(
|
|
9756
|
+
Text29,
|
|
9371
9757
|
{
|
|
9372
9758
|
bold: true,
|
|
9373
9759
|
backgroundColor: focusedField === "convert" ? "green" : void 0,
|
|
@@ -9378,8 +9764,8 @@ var Base64View = () => {
|
|
|
9378
9764
|
mode === "encode" ? "Encode" : "Decode",
|
|
9379
9765
|
" ]"
|
|
9380
9766
|
))
|
|
9381
|
-
), error && /* @__PURE__ */
|
|
9382
|
-
|
|
9767
|
+
), error && /* @__PURE__ */ React35.createElement(
|
|
9768
|
+
Box29,
|
|
9383
9769
|
{
|
|
9384
9770
|
flexDirection: "column",
|
|
9385
9771
|
borderStyle: "single",
|
|
@@ -9388,9 +9774,9 @@ var Base64View = () => {
|
|
|
9388
9774
|
paddingY: 1,
|
|
9389
9775
|
marginBottom: 1
|
|
9390
9776
|
},
|
|
9391
|
-
/* @__PURE__ */
|
|
9392
|
-
), result && /* @__PURE__ */
|
|
9393
|
-
|
|
9777
|
+
/* @__PURE__ */ React35.createElement(Text29, { color: "red" }, "\u2717 Error: ", error)
|
|
9778
|
+
), result && /* @__PURE__ */ React35.createElement(
|
|
9779
|
+
Box29,
|
|
9394
9780
|
{
|
|
9395
9781
|
flexDirection: "column",
|
|
9396
9782
|
borderStyle: "single",
|
|
@@ -9398,24 +9784,24 @@ var Base64View = () => {
|
|
|
9398
9784
|
paddingX: 2,
|
|
9399
9785
|
paddingY: 1
|
|
9400
9786
|
},
|
|
9401
|
-
/* @__PURE__ */
|
|
9402
|
-
/* @__PURE__ */
|
|
9403
|
-
), /* @__PURE__ */
|
|
9787
|
+
/* @__PURE__ */ React35.createElement(Box29, { marginBottom: 1 }, /* @__PURE__ */ React35.createElement(Text29, { bold: true, color: "green" }, "\u2713 Result:"), copied && /* @__PURE__ */ React35.createElement(Box29, { marginLeft: 2 }, /* @__PURE__ */ React35.createElement(Text29, { color: "green" }, "\u2713 Copied to clipboard!"))),
|
|
9788
|
+
/* @__PURE__ */ React35.createElement(Box29, { flexDirection: "column" }, /* @__PURE__ */ React35.createElement(Text29, { dimColor: true }, "Mode: ", mode.toUpperCase()), /* @__PURE__ */ React35.createElement(Box29, { marginTop: 1 }, /* @__PURE__ */ React35.createElement(Text29, { wrap: "wrap" }, result)))
|
|
9789
|
+
), /* @__PURE__ */ React35.createElement(Box29, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 2 }, /* @__PURE__ */ React35.createElement(Text29, { dimColor: true }, "Tab: Next | Enter: Toggle/Convert | C: Copy | Esc: Back")));
|
|
9404
9790
|
};
|
|
9405
9791
|
|
|
9406
9792
|
// src/ui/utils/views/UrlView.tsx
|
|
9407
|
-
import
|
|
9408
|
-
import { Box as
|
|
9409
|
-
import
|
|
9793
|
+
import React36, { useState as useState19 } from "react";
|
|
9794
|
+
import { Box as Box30, Text as Text30, useInput as useInput16 } from "ink";
|
|
9795
|
+
import TextInput9 from "ink-text-input";
|
|
9410
9796
|
var UrlView = () => {
|
|
9411
|
-
const [input5, setInput] =
|
|
9412
|
-
const [mode, setMode] =
|
|
9413
|
-
const [fullUrl, setFullUrl] =
|
|
9414
|
-
const [result, setResult] =
|
|
9415
|
-
const [focusedField, setFocusedField] =
|
|
9416
|
-
const [copied, setCopied] =
|
|
9797
|
+
const [input5, setInput] = useState19("");
|
|
9798
|
+
const [mode, setMode] = useState19("encode");
|
|
9799
|
+
const [fullUrl, setFullUrl] = useState19(false);
|
|
9800
|
+
const [result, setResult] = useState19("");
|
|
9801
|
+
const [focusedField, setFocusedField] = useState19("input");
|
|
9802
|
+
const [copied, setCopied] = useState19(false);
|
|
9417
9803
|
const service = new UtilsService();
|
|
9418
|
-
|
|
9804
|
+
useInput16((input6, key) => {
|
|
9419
9805
|
if (key.tab) {
|
|
9420
9806
|
const fields = ["input", "mode", "full", "convert"];
|
|
9421
9807
|
const currentIndex = fields.indexOf(focusedField);
|
|
@@ -9453,8 +9839,8 @@ var UrlView = () => {
|
|
|
9453
9839
|
} catch (error) {
|
|
9454
9840
|
}
|
|
9455
9841
|
};
|
|
9456
|
-
return /* @__PURE__ */
|
|
9457
|
-
|
|
9842
|
+
return /* @__PURE__ */ React36.createElement(Box30, { flexDirection: "column" }, /* @__PURE__ */ React36.createElement(Box30, { marginBottom: 1 }, /* @__PURE__ */ React36.createElement(Text30, { bold: true, color: "cyan" }, "\u{1F517} URL Encoder/Decoder")), /* @__PURE__ */ React36.createElement(
|
|
9843
|
+
Box30,
|
|
9458
9844
|
{
|
|
9459
9845
|
flexDirection: "column",
|
|
9460
9846
|
borderStyle: "single",
|
|
@@ -9463,12 +9849,12 @@ var UrlView = () => {
|
|
|
9463
9849
|
paddingY: 1,
|
|
9464
9850
|
marginBottom: 1
|
|
9465
9851
|
},
|
|
9466
|
-
/* @__PURE__ */
|
|
9467
|
-
/* @__PURE__ */
|
|
9468
|
-
/* @__PURE__ */
|
|
9469
|
-
/* @__PURE__ */
|
|
9470
|
-
/* @__PURE__ */
|
|
9471
|
-
|
|
9852
|
+
/* @__PURE__ */ React36.createElement(Text30, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
|
|
9853
|
+
/* @__PURE__ */ React36.createElement(Box30, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React36.createElement(Box30, { marginBottom: 0 }, /* @__PURE__ */ React36.createElement(Text30, { color: focusedField === "input" ? "green" : void 0 }, focusedField === "input" ? "\u25B6 " : " ", "Input text:")), /* @__PURE__ */ React36.createElement(Box30, { marginLeft: 2, width: 60 }, focusedField === "input" ? /* @__PURE__ */ React36.createElement(TextInput9, { value: input5, onChange: setInput, placeholder: "Enter text or URL..." }) : /* @__PURE__ */ React36.createElement(Text30, { dimColor: !input5 }, input5 || "(empty)"))),
|
|
9854
|
+
/* @__PURE__ */ React36.createElement(Box30, { marginBottom: 1 }, /* @__PURE__ */ React36.createElement(Box30, { width: 20 }, /* @__PURE__ */ React36.createElement(Text30, { color: focusedField === "mode" ? "green" : void 0 }, focusedField === "mode" ? "\u25B6 " : " ", "Mode:")), /* @__PURE__ */ React36.createElement(Text30, { bold: true, color: focusedField === "mode" ? "yellow" : void 0 }, mode === "encode" ? "ENCODE" : "DECODE"), focusedField === "mode" && /* @__PURE__ */ React36.createElement(Text30, { dimColor: true }, " (Enter to toggle)")),
|
|
9855
|
+
/* @__PURE__ */ React36.createElement(Box30, { marginBottom: 1 }, /* @__PURE__ */ React36.createElement(Text30, { color: focusedField === "full" ? "green" : void 0 }, focusedField === "full" ? "\u25B6 " : " ", "[", fullUrl ? "\u2713" : " ", "] Full URL (encode/decode entire URL)")),
|
|
9856
|
+
/* @__PURE__ */ React36.createElement(Box30, { marginTop: 1 }, /* @__PURE__ */ React36.createElement(
|
|
9857
|
+
Text30,
|
|
9472
9858
|
{
|
|
9473
9859
|
bold: true,
|
|
9474
9860
|
backgroundColor: focusedField === "convert" ? "green" : void 0,
|
|
@@ -9479,8 +9865,8 @@ var UrlView = () => {
|
|
|
9479
9865
|
mode === "encode" ? "Encode" : "Decode",
|
|
9480
9866
|
" ]"
|
|
9481
9867
|
))
|
|
9482
|
-
), result && /* @__PURE__ */
|
|
9483
|
-
|
|
9868
|
+
), result && /* @__PURE__ */ React36.createElement(
|
|
9869
|
+
Box30,
|
|
9484
9870
|
{
|
|
9485
9871
|
flexDirection: "column",
|
|
9486
9872
|
borderStyle: "single",
|
|
@@ -9488,26 +9874,26 @@ var UrlView = () => {
|
|
|
9488
9874
|
paddingX: 2,
|
|
9489
9875
|
paddingY: 1
|
|
9490
9876
|
},
|
|
9491
|
-
/* @__PURE__ */
|
|
9492
|
-
/* @__PURE__ */
|
|
9493
|
-
), /* @__PURE__ */
|
|
9877
|
+
/* @__PURE__ */ React36.createElement(Box30, { marginBottom: 1 }, /* @__PURE__ */ React36.createElement(Text30, { bold: true, color: "green" }, "\u2713 Result:"), copied && /* @__PURE__ */ React36.createElement(Box30, { marginLeft: 2 }, /* @__PURE__ */ React36.createElement(Text30, { color: "green" }, "\u2713 Copied to clipboard!"))),
|
|
9878
|
+
/* @__PURE__ */ React36.createElement(Box30, { flexDirection: "column" }, /* @__PURE__ */ React36.createElement(Text30, { dimColor: true }, "Mode: ", mode.toUpperCase(), " ", fullUrl ? "(Full URL)" : "(Component)"), /* @__PURE__ */ React36.createElement(Box30, { marginTop: 1 }, /* @__PURE__ */ React36.createElement(Text30, { wrap: "wrap" }, result)))
|
|
9879
|
+
), /* @__PURE__ */ React36.createElement(Box30, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 2 }, /* @__PURE__ */ React36.createElement(Text30, { dimColor: true }, "Tab: Next | Enter: Toggle/Convert | C: Copy | Esc: Back")));
|
|
9494
9880
|
};
|
|
9495
9881
|
|
|
9496
9882
|
// src/ui/utils/views/UnixTimeView.tsx
|
|
9497
|
-
import
|
|
9498
|
-
import { Box as
|
|
9499
|
-
import
|
|
9883
|
+
import React37, { useState as useState20 } from "react";
|
|
9884
|
+
import { Box as Box31, Text as Text31, useInput as useInput17 } from "ink";
|
|
9885
|
+
import TextInput10 from "ink-text-input";
|
|
9500
9886
|
var UnixTimeView = () => {
|
|
9501
|
-
const [input5, setInput] =
|
|
9502
|
-
const [mode, setMode] =
|
|
9503
|
-
const [format, setFormat] =
|
|
9504
|
-
const [useMs, setUseMs] =
|
|
9505
|
-
const [result, setResult] =
|
|
9506
|
-
const [error, setError] =
|
|
9507
|
-
const [focusedField, setFocusedField] =
|
|
9508
|
-
const [copied, setCopied] =
|
|
9887
|
+
const [input5, setInput] = useState20("");
|
|
9888
|
+
const [mode, setMode] = useState20("now");
|
|
9889
|
+
const [format, setFormat] = useState20("iso");
|
|
9890
|
+
const [useMs, setUseMs] = useState20(false);
|
|
9891
|
+
const [result, setResult] = useState20("");
|
|
9892
|
+
const [error, setError] = useState20("");
|
|
9893
|
+
const [focusedField, setFocusedField] = useState20("mode");
|
|
9894
|
+
const [copied, setCopied] = useState20(false);
|
|
9509
9895
|
const service = new UtilsService();
|
|
9510
|
-
|
|
9896
|
+
useInput17((input6, key) => {
|
|
9511
9897
|
if (key.tab) {
|
|
9512
9898
|
const fields = mode === "now" ? ["mode", "ms", "convert"] : mode === "to-human" ? ["mode", "input", "format", "convert"] : ["mode", "input", "convert"];
|
|
9513
9899
|
const currentIndex = fields.indexOf(focusedField);
|
|
@@ -9568,8 +9954,8 @@ var UnixTimeView = () => {
|
|
|
9568
9954
|
} catch (error2) {
|
|
9569
9955
|
}
|
|
9570
9956
|
};
|
|
9571
|
-
return /* @__PURE__ */
|
|
9572
|
-
|
|
9957
|
+
return /* @__PURE__ */ React37.createElement(Box31, { flexDirection: "column" }, /* @__PURE__ */ React37.createElement(Box31, { marginBottom: 1 }, /* @__PURE__ */ React37.createElement(Text31, { bold: true, color: "cyan" }, "\u{1F552} Unix Time Converter")), /* @__PURE__ */ React37.createElement(
|
|
9958
|
+
Box31,
|
|
9573
9959
|
{
|
|
9574
9960
|
flexDirection: "column",
|
|
9575
9961
|
borderStyle: "single",
|
|
@@ -9578,20 +9964,20 @@ var UnixTimeView = () => {
|
|
|
9578
9964
|
paddingY: 1,
|
|
9579
9965
|
marginBottom: 1
|
|
9580
9966
|
},
|
|
9581
|
-
/* @__PURE__ */
|
|
9582
|
-
/* @__PURE__ */
|
|
9583
|
-
mode !== "now" && /* @__PURE__ */
|
|
9584
|
-
|
|
9967
|
+
/* @__PURE__ */ React37.createElement(Text31, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
|
|
9968
|
+
/* @__PURE__ */ React37.createElement(Box31, { marginBottom: 1 }, /* @__PURE__ */ React37.createElement(Box31, { width: 20 }, /* @__PURE__ */ React37.createElement(Text31, { color: focusedField === "mode" ? "green" : void 0 }, focusedField === "mode" ? "\u25B6 " : " ", "Mode:")), /* @__PURE__ */ React37.createElement(Text31, { bold: true, color: focusedField === "mode" ? "yellow" : void 0 }, mode === "now" ? "CURRENT TIME" : mode === "to-human" ? "TIMESTAMP \u2192 HUMAN" : "HUMAN \u2192 TIMESTAMP"), focusedField === "mode" && /* @__PURE__ */ React37.createElement(Text31, { dimColor: true }, " (Enter to cycle)")),
|
|
9969
|
+
mode !== "now" && /* @__PURE__ */ React37.createElement(Box31, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React37.createElement(Box31, { marginBottom: 0 }, /* @__PURE__ */ React37.createElement(Text31, { color: focusedField === "input" ? "green" : void 0 }, focusedField === "input" ? "\u25B6 " : " ", mode === "to-human" ? "Timestamp:" : "Date string:")), /* @__PURE__ */ React37.createElement(Box31, { marginLeft: 2, width: 50 }, focusedField === "input" ? /* @__PURE__ */ React37.createElement(
|
|
9970
|
+
TextInput10,
|
|
9585
9971
|
{
|
|
9586
9972
|
value: input5,
|
|
9587
9973
|
onChange: setInput,
|
|
9588
9974
|
placeholder: mode === "to-human" ? "1702550400" : "2024-01-15 10:30:00"
|
|
9589
9975
|
}
|
|
9590
|
-
) : /* @__PURE__ */
|
|
9591
|
-
mode === "to-human" && /* @__PURE__ */
|
|
9592
|
-
mode === "now" && /* @__PURE__ */
|
|
9593
|
-
/* @__PURE__ */
|
|
9594
|
-
|
|
9976
|
+
) : /* @__PURE__ */ React37.createElement(Text31, { dimColor: !input5 }, input5 || "(empty)"))),
|
|
9977
|
+
mode === "to-human" && /* @__PURE__ */ React37.createElement(Box31, { marginBottom: 1 }, /* @__PURE__ */ React37.createElement(Box31, { width: 20 }, /* @__PURE__ */ React37.createElement(Text31, { color: focusedField === "format" ? "green" : void 0 }, focusedField === "format" ? "\u25B6 " : " ", "Format:")), /* @__PURE__ */ React37.createElement(Text31, { bold: true, color: focusedField === "format" ? "yellow" : void 0 }, format.toUpperCase()), focusedField === "format" && /* @__PURE__ */ React37.createElement(Text31, { dimColor: true }, " (Enter to cycle)")),
|
|
9978
|
+
mode === "now" && /* @__PURE__ */ React37.createElement(Box31, { marginBottom: 1 }, /* @__PURE__ */ React37.createElement(Text31, { color: focusedField === "ms" ? "green" : void 0 }, focusedField === "ms" ? "\u25B6 " : " ", "[", useMs ? "\u2713" : " ", "] Milliseconds")),
|
|
9979
|
+
/* @__PURE__ */ React37.createElement(Box31, { marginTop: 1 }, /* @__PURE__ */ React37.createElement(
|
|
9980
|
+
Text31,
|
|
9595
9981
|
{
|
|
9596
9982
|
bold: true,
|
|
9597
9983
|
backgroundColor: focusedField === "convert" ? "green" : void 0,
|
|
@@ -9602,8 +9988,8 @@ var UnixTimeView = () => {
|
|
|
9602
9988
|
mode === "now" ? "Get Current" : "Convert",
|
|
9603
9989
|
" ]"
|
|
9604
9990
|
))
|
|
9605
|
-
), error && /* @__PURE__ */
|
|
9606
|
-
|
|
9991
|
+
), error && /* @__PURE__ */ React37.createElement(
|
|
9992
|
+
Box31,
|
|
9607
9993
|
{
|
|
9608
9994
|
flexDirection: "column",
|
|
9609
9995
|
borderStyle: "single",
|
|
@@ -9612,9 +9998,9 @@ var UnixTimeView = () => {
|
|
|
9612
9998
|
paddingY: 1,
|
|
9613
9999
|
marginBottom: 1
|
|
9614
10000
|
},
|
|
9615
|
-
/* @__PURE__ */
|
|
9616
|
-
), result && /* @__PURE__ */
|
|
9617
|
-
|
|
10001
|
+
/* @__PURE__ */ React37.createElement(Text31, { color: "red" }, "\u2717 Error: ", error)
|
|
10002
|
+
), result && /* @__PURE__ */ React37.createElement(
|
|
10003
|
+
Box31,
|
|
9618
10004
|
{
|
|
9619
10005
|
flexDirection: "column",
|
|
9620
10006
|
borderStyle: "single",
|
|
@@ -9622,26 +10008,26 @@ var UnixTimeView = () => {
|
|
|
9622
10008
|
paddingX: 2,
|
|
9623
10009
|
paddingY: 1
|
|
9624
10010
|
},
|
|
9625
|
-
/* @__PURE__ */
|
|
9626
|
-
/* @__PURE__ */
|
|
9627
|
-
), /* @__PURE__ */
|
|
10011
|
+
/* @__PURE__ */ React37.createElement(Box31, { marginBottom: 1 }, /* @__PURE__ */ React37.createElement(Text31, { bold: true, color: "green" }, "\u2713 Result:"), copied && /* @__PURE__ */ React37.createElement(Box31, { marginLeft: 2 }, /* @__PURE__ */ React37.createElement(Text31, { color: "green" }, "\u2713 Copied to clipboard!"))),
|
|
10012
|
+
/* @__PURE__ */ React37.createElement(Box31, { flexDirection: "column" }, /* @__PURE__ */ React37.createElement(Box31, { marginTop: 1 }, /* @__PURE__ */ React37.createElement(Text31, { wrap: "wrap" }, result)))
|
|
10013
|
+
), /* @__PURE__ */ React37.createElement(Box31, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 2 }, /* @__PURE__ */ React37.createElement(Text31, { dimColor: true }, "Tab: Next | Enter: Toggle/Convert | C: Copy | Esc: Back")));
|
|
9628
10014
|
};
|
|
9629
10015
|
|
|
9630
10016
|
// src/ui/utils/views/JwtView.tsx
|
|
9631
|
-
import
|
|
9632
|
-
import { Box as
|
|
9633
|
-
import
|
|
10017
|
+
import React38, { useState as useState21 } from "react";
|
|
10018
|
+
import { Box as Box32, Text as Text32, useInput as useInput18 } from "ink";
|
|
10019
|
+
import TextInput11 from "ink-text-input";
|
|
9634
10020
|
var JwtView = () => {
|
|
9635
|
-
const [mode, setMode] =
|
|
9636
|
-
const [token, setToken] =
|
|
9637
|
-
const [payload, setPayload] =
|
|
9638
|
-
const [secret, setSecret] =
|
|
9639
|
-
const [result, setResult] =
|
|
9640
|
-
const [error, setError] =
|
|
9641
|
-
const [focusedField, setFocusedField] =
|
|
9642
|
-
const [copied, setCopied] =
|
|
10021
|
+
const [mode, setMode] = useState21("decode");
|
|
10022
|
+
const [token, setToken] = useState21("");
|
|
10023
|
+
const [payload, setPayload] = useState21("");
|
|
10024
|
+
const [secret, setSecret] = useState21("");
|
|
10025
|
+
const [result, setResult] = useState21({});
|
|
10026
|
+
const [error, setError] = useState21("");
|
|
10027
|
+
const [focusedField, setFocusedField] = useState21("mode");
|
|
10028
|
+
const [copied, setCopied] = useState21(false);
|
|
9643
10029
|
const service = new UtilsService();
|
|
9644
|
-
|
|
10030
|
+
useInput18((input5, key) => {
|
|
9645
10031
|
if (key.tab) {
|
|
9646
10032
|
const fields = mode === "decode" ? ["mode", "token", "process"] : ["mode", "payload", "secret", "process"];
|
|
9647
10033
|
const currentIndex = fields.indexOf(focusedField);
|
|
@@ -9696,8 +10082,8 @@ var JwtView = () => {
|
|
|
9696
10082
|
} catch (error2) {
|
|
9697
10083
|
}
|
|
9698
10084
|
};
|
|
9699
|
-
return /* @__PURE__ */
|
|
9700
|
-
|
|
10085
|
+
return /* @__PURE__ */ React38.createElement(Box32, { flexDirection: "column" }, /* @__PURE__ */ React38.createElement(Box32, { marginBottom: 1 }, /* @__PURE__ */ React38.createElement(Text32, { bold: true, color: "cyan" }, "\u{1F511} JWT Decoder/Encoder")), /* @__PURE__ */ React38.createElement(
|
|
10086
|
+
Box32,
|
|
9701
10087
|
{
|
|
9702
10088
|
flexDirection: "column",
|
|
9703
10089
|
borderStyle: "single",
|
|
@@ -9706,33 +10092,33 @@ var JwtView = () => {
|
|
|
9706
10092
|
paddingY: 1,
|
|
9707
10093
|
marginBottom: 1
|
|
9708
10094
|
},
|
|
9709
|
-
/* @__PURE__ */
|
|
9710
|
-
/* @__PURE__ */
|
|
9711
|
-
mode === "decode" ? /* @__PURE__ */
|
|
9712
|
-
|
|
10095
|
+
/* @__PURE__ */ React38.createElement(Text32, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
|
|
10096
|
+
/* @__PURE__ */ React38.createElement(Box32, { marginBottom: 1 }, /* @__PURE__ */ React38.createElement(Box32, { width: 20 }, /* @__PURE__ */ React38.createElement(Text32, { color: focusedField === "mode" ? "green" : void 0 }, focusedField === "mode" ? "\u25B6 " : " ", "Mode:")), /* @__PURE__ */ React38.createElement(Text32, { bold: true, color: focusedField === "mode" ? "yellow" : void 0 }, mode === "decode" ? "DECODE" : "ENCODE"), focusedField === "mode" && /* @__PURE__ */ React38.createElement(Text32, { dimColor: true }, " (Enter to toggle)")),
|
|
10097
|
+
mode === "decode" ? /* @__PURE__ */ React38.createElement(Box32, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React38.createElement(Box32, { marginBottom: 0 }, /* @__PURE__ */ React38.createElement(Text32, { color: focusedField === "token" ? "green" : void 0 }, focusedField === "token" ? "\u25B6 " : " ", "JWT Token:")), /* @__PURE__ */ React38.createElement(Box32, { marginLeft: 2, width: 60 }, focusedField === "token" ? /* @__PURE__ */ React38.createElement(
|
|
10098
|
+
TextInput11,
|
|
9713
10099
|
{
|
|
9714
10100
|
value: token,
|
|
9715
10101
|
onChange: setToken,
|
|
9716
10102
|
placeholder: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
|
9717
10103
|
}
|
|
9718
|
-
) : /* @__PURE__ */
|
|
9719
|
-
|
|
10104
|
+
) : /* @__PURE__ */ React38.createElement(Text32, { dimColor: !token }, token || "(empty)"))) : /* @__PURE__ */ React38.createElement(React38.Fragment, null, /* @__PURE__ */ React38.createElement(Box32, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React38.createElement(Box32, { marginBottom: 0 }, /* @__PURE__ */ React38.createElement(Text32, { color: focusedField === "payload" ? "green" : void 0 }, focusedField === "payload" ? "\u25B6 " : " ", "Payload (JSON):")), /* @__PURE__ */ React38.createElement(Box32, { marginLeft: 2, width: 60 }, focusedField === "payload" ? /* @__PURE__ */ React38.createElement(
|
|
10105
|
+
TextInput11,
|
|
9720
10106
|
{
|
|
9721
10107
|
value: payload,
|
|
9722
10108
|
onChange: setPayload,
|
|
9723
10109
|
placeholder: '{"sub":"123","name":"John"}'
|
|
9724
10110
|
}
|
|
9725
|
-
) : /* @__PURE__ */
|
|
9726
|
-
|
|
10111
|
+
) : /* @__PURE__ */ React38.createElement(Text32, { dimColor: !payload }, payload || "(empty)"))), /* @__PURE__ */ React38.createElement(Box32, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React38.createElement(Box32, { marginBottom: 0 }, /* @__PURE__ */ React38.createElement(Text32, { color: focusedField === "secret" ? "green" : void 0 }, focusedField === "secret" ? "\u25B6 " : " ", "Secret Key:")), /* @__PURE__ */ React38.createElement(Box32, { marginLeft: 2, width: 60 }, focusedField === "secret" ? /* @__PURE__ */ React38.createElement(
|
|
10112
|
+
TextInput11,
|
|
9727
10113
|
{
|
|
9728
10114
|
value: secret,
|
|
9729
10115
|
onChange: setSecret,
|
|
9730
10116
|
placeholder: "your-secret-key",
|
|
9731
10117
|
mask: "*"
|
|
9732
10118
|
}
|
|
9733
|
-
) : /* @__PURE__ */
|
|
9734
|
-
/* @__PURE__ */
|
|
9735
|
-
|
|
10119
|
+
) : /* @__PURE__ */ React38.createElement(Text32, { dimColor: !secret }, secret ? "*".repeat(secret.length) : "(empty)")))),
|
|
10120
|
+
/* @__PURE__ */ React38.createElement(Box32, { marginTop: 1 }, /* @__PURE__ */ React38.createElement(
|
|
10121
|
+
Text32,
|
|
9736
10122
|
{
|
|
9737
10123
|
bold: true,
|
|
9738
10124
|
backgroundColor: focusedField === "process" ? "green" : void 0,
|
|
@@ -9743,8 +10129,8 @@ var JwtView = () => {
|
|
|
9743
10129
|
mode === "decode" ? "Decode" : "Encode",
|
|
9744
10130
|
" ]"
|
|
9745
10131
|
))
|
|
9746
|
-
), error && /* @__PURE__ */
|
|
9747
|
-
|
|
10132
|
+
), error && /* @__PURE__ */ React38.createElement(
|
|
10133
|
+
Box32,
|
|
9748
10134
|
{
|
|
9749
10135
|
flexDirection: "column",
|
|
9750
10136
|
borderStyle: "single",
|
|
@@ -9753,9 +10139,9 @@ var JwtView = () => {
|
|
|
9753
10139
|
paddingY: 1,
|
|
9754
10140
|
marginBottom: 1
|
|
9755
10141
|
},
|
|
9756
|
-
/* @__PURE__ */
|
|
9757
|
-
), (result.header || result.token) && /* @__PURE__ */
|
|
9758
|
-
|
|
10142
|
+
/* @__PURE__ */ React38.createElement(Text32, { color: "red" }, "\u2717 Error: ", error)
|
|
10143
|
+
), (result.header || result.token) && /* @__PURE__ */ React38.createElement(
|
|
10144
|
+
Box32,
|
|
9759
10145
|
{
|
|
9760
10146
|
flexDirection: "column",
|
|
9761
10147
|
borderStyle: "single",
|
|
@@ -9763,23 +10149,23 @@ var JwtView = () => {
|
|
|
9763
10149
|
paddingX: 2,
|
|
9764
10150
|
paddingY: 1
|
|
9765
10151
|
},
|
|
9766
|
-
/* @__PURE__ */
|
|
9767
|
-
/* @__PURE__ */
|
|
9768
|
-
), /* @__PURE__ */
|
|
10152
|
+
/* @__PURE__ */ React38.createElement(Box32, { marginBottom: 1 }, /* @__PURE__ */ React38.createElement(Text32, { bold: true, color: "green" }, "\u2713 Result:"), copied && result.token && /* @__PURE__ */ React38.createElement(Box32, { marginLeft: 2 }, /* @__PURE__ */ React38.createElement(Text32, { color: "green" }, "\u2713 Copied to clipboard!"))),
|
|
10153
|
+
/* @__PURE__ */ React38.createElement(Box32, { flexDirection: "column" }, result.header && /* @__PURE__ */ React38.createElement(React38.Fragment, null, /* @__PURE__ */ React38.createElement(Text32, { bold: true, color: "yellow" }, "Header:"), /* @__PURE__ */ React38.createElement(Text32, null, JSON.stringify(result.header, null, 2)), /* @__PURE__ */ React38.createElement(Text32, null, " "), /* @__PURE__ */ React38.createElement(Text32, { bold: true, color: "yellow" }, "Payload:"), /* @__PURE__ */ React38.createElement(Text32, null, JSON.stringify(result.payload, null, 2)), /* @__PURE__ */ React38.createElement(Text32, null, " "), /* @__PURE__ */ React38.createElement(Text32, { bold: true, color: "yellow" }, "Signature:"), /* @__PURE__ */ React38.createElement(Text32, { dimColor: true }, result.signature)), result.token && /* @__PURE__ */ React38.createElement(React38.Fragment, null, /* @__PURE__ */ React38.createElement(Text32, { bold: true, color: "yellow" }, "Token:"), /* @__PURE__ */ React38.createElement(Text32, { wrap: "wrap" }, result.token)))
|
|
10154
|
+
), /* @__PURE__ */ React38.createElement(Box32, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 2 }, /* @__PURE__ */ React38.createElement(Text32, { dimColor: true }, "Tab: Next | Enter: Toggle/", mode === "decode" ? "Decode" : "Encode", " | C: Copy | Esc: Back")));
|
|
9769
10155
|
};
|
|
9770
10156
|
|
|
9771
10157
|
// src/ui/utils/views/CronView.tsx
|
|
9772
|
-
import
|
|
9773
|
-
import { Box as
|
|
9774
|
-
import
|
|
10158
|
+
import React39, { useState as useState22 } from "react";
|
|
10159
|
+
import { Box as Box33, Text as Text33, useInput as useInput19 } from "ink";
|
|
10160
|
+
import TextInput12 from "ink-text-input";
|
|
9775
10161
|
var CronView = () => {
|
|
9776
|
-
const [expression, setExpression] =
|
|
9777
|
-
const [result, setResult] =
|
|
9778
|
-
const [error, setError] =
|
|
9779
|
-
const [focusedField, setFocusedField] =
|
|
9780
|
-
const [copied, setCopied] =
|
|
10162
|
+
const [expression, setExpression] = useState22("");
|
|
10163
|
+
const [result, setResult] = useState22(null);
|
|
10164
|
+
const [error, setError] = useState22("");
|
|
10165
|
+
const [focusedField, setFocusedField] = useState22("expression");
|
|
10166
|
+
const [copied, setCopied] = useState22(false);
|
|
9781
10167
|
const service = new UtilsService();
|
|
9782
|
-
|
|
10168
|
+
useInput19((input5, key) => {
|
|
9783
10169
|
if (key.tab) {
|
|
9784
10170
|
setFocusedField(focusedField === "expression" ? "parse" : "expression");
|
|
9785
10171
|
} else if (key.return) {
|
|
@@ -9817,8 +10203,8 @@ ${result.nextRuns.join("\n")}`;
|
|
|
9817
10203
|
} catch (error2) {
|
|
9818
10204
|
}
|
|
9819
10205
|
};
|
|
9820
|
-
return /* @__PURE__ */
|
|
9821
|
-
|
|
10206
|
+
return /* @__PURE__ */ React39.createElement(Box33, { flexDirection: "column" }, /* @__PURE__ */ React39.createElement(Box33, { marginBottom: 1 }, /* @__PURE__ */ React39.createElement(Text33, { bold: true, color: "cyan" }, "\u23F0 Cron Expression Parser")), /* @__PURE__ */ React39.createElement(
|
|
10207
|
+
Box33,
|
|
9822
10208
|
{
|
|
9823
10209
|
flexDirection: "column",
|
|
9824
10210
|
borderStyle: "single",
|
|
@@ -9827,18 +10213,18 @@ ${result.nextRuns.join("\n")}`;
|
|
|
9827
10213
|
paddingY: 1,
|
|
9828
10214
|
marginBottom: 1
|
|
9829
10215
|
},
|
|
9830
|
-
/* @__PURE__ */
|
|
9831
|
-
/* @__PURE__ */
|
|
9832
|
-
|
|
10216
|
+
/* @__PURE__ */ React39.createElement(Text33, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
|
|
10217
|
+
/* @__PURE__ */ React39.createElement(Box33, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React39.createElement(Box33, { marginBottom: 0 }, /* @__PURE__ */ React39.createElement(Text33, { color: focusedField === "expression" ? "green" : void 0 }, focusedField === "expression" ? "\u25B6 " : " ", "Cron Expression:")), /* @__PURE__ */ React39.createElement(Box33, { marginLeft: 2, width: 50 }, focusedField === "expression" ? /* @__PURE__ */ React39.createElement(
|
|
10218
|
+
TextInput12,
|
|
9833
10219
|
{
|
|
9834
10220
|
value: expression,
|
|
9835
10221
|
onChange: setExpression,
|
|
9836
10222
|
placeholder: "0 5 * * * (5-field or 6-field)"
|
|
9837
10223
|
}
|
|
9838
|
-
) : /* @__PURE__ */
|
|
9839
|
-
/* @__PURE__ */
|
|
9840
|
-
/* @__PURE__ */
|
|
9841
|
-
|
|
10224
|
+
) : /* @__PURE__ */ React39.createElement(Text33, { dimColor: !expression }, expression || "(empty)"))),
|
|
10225
|
+
/* @__PURE__ */ React39.createElement(Box33, { marginTop: 1, marginBottom: 1 }, /* @__PURE__ */ React39.createElement(Text33, { dimColor: true }, 'Examples: "0 5 * * *" (daily at 5am), "*/15 * * * *" (every 15 min)')),
|
|
10226
|
+
/* @__PURE__ */ React39.createElement(Box33, { marginTop: 1 }, /* @__PURE__ */ React39.createElement(
|
|
10227
|
+
Text33,
|
|
9842
10228
|
{
|
|
9843
10229
|
bold: true,
|
|
9844
10230
|
backgroundColor: focusedField === "parse" ? "green" : void 0,
|
|
@@ -9847,8 +10233,8 @@ ${result.nextRuns.join("\n")}`;
|
|
|
9847
10233
|
focusedField === "parse" ? "\u25B6 " : " ",
|
|
9848
10234
|
"[ Parse Expression ]"
|
|
9849
10235
|
))
|
|
9850
|
-
), error && /* @__PURE__ */
|
|
9851
|
-
|
|
10236
|
+
), error && /* @__PURE__ */ React39.createElement(
|
|
10237
|
+
Box33,
|
|
9852
10238
|
{
|
|
9853
10239
|
flexDirection: "column",
|
|
9854
10240
|
borderStyle: "single",
|
|
@@ -9857,9 +10243,9 @@ ${result.nextRuns.join("\n")}`;
|
|
|
9857
10243
|
paddingY: 1,
|
|
9858
10244
|
marginBottom: 1
|
|
9859
10245
|
},
|
|
9860
|
-
/* @__PURE__ */
|
|
9861
|
-
), result && /* @__PURE__ */
|
|
9862
|
-
|
|
10246
|
+
/* @__PURE__ */ React39.createElement(Text33, { color: "red" }, "\u2717 Error: ", error)
|
|
10247
|
+
), result && /* @__PURE__ */ React39.createElement(
|
|
10248
|
+
Box33,
|
|
9863
10249
|
{
|
|
9864
10250
|
flexDirection: "column",
|
|
9865
10251
|
borderStyle: "single",
|
|
@@ -9867,25 +10253,25 @@ ${result.nextRuns.join("\n")}`;
|
|
|
9867
10253
|
paddingX: 2,
|
|
9868
10254
|
paddingY: 1
|
|
9869
10255
|
},
|
|
9870
|
-
/* @__PURE__ */
|
|
9871
|
-
/* @__PURE__ */
|
|
9872
|
-
), /* @__PURE__ */
|
|
10256
|
+
/* @__PURE__ */ React39.createElement(Box33, { marginBottom: 1 }, /* @__PURE__ */ React39.createElement(Text33, { bold: true, color: "green" }, "\u2713 Result:"), copied && /* @__PURE__ */ React39.createElement(Box33, { marginLeft: 2 }, /* @__PURE__ */ React39.createElement(Text33, { color: "green" }, "\u2713 Copied to clipboard!"))),
|
|
10257
|
+
/* @__PURE__ */ React39.createElement(Box33, { flexDirection: "column" }, /* @__PURE__ */ React39.createElement(Text33, { bold: true, color: "yellow" }, "Expression:"), /* @__PURE__ */ React39.createElement(Text33, null, expression), /* @__PURE__ */ React39.createElement(Text33, null, " "), /* @__PURE__ */ React39.createElement(Text33, { bold: true, color: "yellow" }, "Meaning:"), /* @__PURE__ */ React39.createElement(Text33, null, result.description), /* @__PURE__ */ React39.createElement(Text33, null, " "), /* @__PURE__ */ React39.createElement(Text33, { bold: true, color: "yellow" }, "Next 5 executions:"), result.nextRuns.map((run, index) => /* @__PURE__ */ React39.createElement(Text33, { key: index }, " ", index + 1, ". ", run)))
|
|
10258
|
+
), /* @__PURE__ */ React39.createElement(Box33, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 2 }, /* @__PURE__ */ React39.createElement(Text33, { dimColor: true }, "Tab: Next | Enter: Parse | C: Copy | Esc: Back")));
|
|
9873
10259
|
};
|
|
9874
10260
|
|
|
9875
10261
|
// src/ui/utils/views/TimezoneView.tsx
|
|
9876
|
-
import
|
|
9877
|
-
import { Box as
|
|
9878
|
-
import
|
|
10262
|
+
import React40, { useState as useState23 } from "react";
|
|
10263
|
+
import { Box as Box34, Text as Text34, useInput as useInput20 } from "ink";
|
|
10264
|
+
import TextInput13 from "ink-text-input";
|
|
9879
10265
|
var TimezoneView = () => {
|
|
9880
|
-
const [time, setTime] =
|
|
9881
|
-
const [fromTz, setFromTz] =
|
|
9882
|
-
const [toTz, setToTz] =
|
|
9883
|
-
const [result, setResult] =
|
|
9884
|
-
const [error, setError] =
|
|
9885
|
-
const [focusedField, setFocusedField] =
|
|
9886
|
-
const [copied, setCopied] =
|
|
10266
|
+
const [time, setTime] = useState23("");
|
|
10267
|
+
const [fromTz, setFromTz] = useState23("UTC");
|
|
10268
|
+
const [toTz, setToTz] = useState23("America/New_York");
|
|
10269
|
+
const [result, setResult] = useState23("");
|
|
10270
|
+
const [error, setError] = useState23("");
|
|
10271
|
+
const [focusedField, setFocusedField] = useState23("time");
|
|
10272
|
+
const [copied, setCopied] = useState23(false);
|
|
9887
10273
|
const service = new UtilsService();
|
|
9888
|
-
|
|
10274
|
+
useInput20((input5, key) => {
|
|
9889
10275
|
if (key.tab) {
|
|
9890
10276
|
const fields = ["time", "from", "to", "convert"];
|
|
9891
10277
|
const currentIndex = fields.indexOf(focusedField);
|
|
@@ -9924,8 +10310,8 @@ var TimezoneView = () => {
|
|
|
9924
10310
|
} catch (error2) {
|
|
9925
10311
|
}
|
|
9926
10312
|
};
|
|
9927
|
-
return /* @__PURE__ */
|
|
9928
|
-
|
|
10313
|
+
return /* @__PURE__ */ React40.createElement(Box34, { flexDirection: "column" }, /* @__PURE__ */ React40.createElement(Box34, { marginBottom: 1 }, /* @__PURE__ */ React40.createElement(Text34, { bold: true, color: "cyan" }, "\u{1F30D} Timezone Converter")), /* @__PURE__ */ React40.createElement(
|
|
10314
|
+
Box34,
|
|
9929
10315
|
{
|
|
9930
10316
|
flexDirection: "column",
|
|
9931
10317
|
borderStyle: "single",
|
|
@@ -9934,34 +10320,34 @@ var TimezoneView = () => {
|
|
|
9934
10320
|
paddingY: 1,
|
|
9935
10321
|
marginBottom: 1
|
|
9936
10322
|
},
|
|
9937
|
-
/* @__PURE__ */
|
|
9938
|
-
/* @__PURE__ */
|
|
9939
|
-
|
|
10323
|
+
/* @__PURE__ */ React40.createElement(Text34, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
|
|
10324
|
+
/* @__PURE__ */ React40.createElement(Box34, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React40.createElement(Box34, { marginBottom: 0 }, /* @__PURE__ */ React40.createElement(Text34, { color: focusedField === "time" ? "green" : void 0 }, focusedField === "time" ? "\u25B6 " : " ", "Time:")), /* @__PURE__ */ React40.createElement(Box34, { marginLeft: 2, width: 50 }, focusedField === "time" ? /* @__PURE__ */ React40.createElement(
|
|
10325
|
+
TextInput13,
|
|
9940
10326
|
{
|
|
9941
10327
|
value: time,
|
|
9942
10328
|
onChange: setTime,
|
|
9943
10329
|
placeholder: "2024-01-15 10:00:00"
|
|
9944
10330
|
}
|
|
9945
|
-
) : /* @__PURE__ */
|
|
9946
|
-
/* @__PURE__ */
|
|
9947
|
-
|
|
10331
|
+
) : /* @__PURE__ */ React40.createElement(Text34, { dimColor: !time }, time || "(empty)"))),
|
|
10332
|
+
/* @__PURE__ */ React40.createElement(Box34, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React40.createElement(Box34, { marginBottom: 0 }, /* @__PURE__ */ React40.createElement(Text34, { color: focusedField === "from" ? "green" : void 0 }, focusedField === "from" ? "\u25B6 " : " ", "From Timezone:")), /* @__PURE__ */ React40.createElement(Box34, { marginLeft: 2, width: 50 }, focusedField === "from" ? /* @__PURE__ */ React40.createElement(
|
|
10333
|
+
TextInput13,
|
|
9948
10334
|
{
|
|
9949
10335
|
value: fromTz,
|
|
9950
10336
|
onChange: setFromTz,
|
|
9951
10337
|
placeholder: "UTC or America/New_York"
|
|
9952
10338
|
}
|
|
9953
|
-
) : /* @__PURE__ */
|
|
9954
|
-
/* @__PURE__ */
|
|
9955
|
-
|
|
10339
|
+
) : /* @__PURE__ */ React40.createElement(Text34, { dimColor: !fromTz }, fromTz || "(empty)"))),
|
|
10340
|
+
/* @__PURE__ */ React40.createElement(Box34, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React40.createElement(Box34, { marginBottom: 0 }, /* @__PURE__ */ React40.createElement(Text34, { color: focusedField === "to" ? "green" : void 0 }, focusedField === "to" ? "\u25B6 " : " ", "To Timezone:")), /* @__PURE__ */ React40.createElement(Box34, { marginLeft: 2, width: 50 }, focusedField === "to" ? /* @__PURE__ */ React40.createElement(
|
|
10341
|
+
TextInput13,
|
|
9956
10342
|
{
|
|
9957
10343
|
value: toTz,
|
|
9958
10344
|
onChange: setToTz,
|
|
9959
10345
|
placeholder: "Asia/Tokyo or Europe/London"
|
|
9960
10346
|
}
|
|
9961
|
-
) : /* @__PURE__ */
|
|
9962
|
-
/* @__PURE__ */
|
|
9963
|
-
/* @__PURE__ */
|
|
9964
|
-
|
|
10347
|
+
) : /* @__PURE__ */ React40.createElement(Text34, { dimColor: !toTz }, toTz || "(empty)"))),
|
|
10348
|
+
/* @__PURE__ */ React40.createElement(Box34, { marginBottom: 1 }, /* @__PURE__ */ React40.createElement(Text34, { dimColor: true }, "Common: UTC, America/New_York, Europe/London, Asia/Tokyo")),
|
|
10349
|
+
/* @__PURE__ */ React40.createElement(Box34, { marginTop: 1 }, /* @__PURE__ */ React40.createElement(
|
|
10350
|
+
Text34,
|
|
9965
10351
|
{
|
|
9966
10352
|
bold: true,
|
|
9967
10353
|
backgroundColor: focusedField === "convert" ? "green" : void 0,
|
|
@@ -9970,8 +10356,8 @@ var TimezoneView = () => {
|
|
|
9970
10356
|
focusedField === "convert" ? "\u25B6 " : " ",
|
|
9971
10357
|
"[ Convert ]"
|
|
9972
10358
|
))
|
|
9973
|
-
), error && /* @__PURE__ */
|
|
9974
|
-
|
|
10359
|
+
), error && /* @__PURE__ */ React40.createElement(
|
|
10360
|
+
Box34,
|
|
9975
10361
|
{
|
|
9976
10362
|
flexDirection: "column",
|
|
9977
10363
|
borderStyle: "single",
|
|
@@ -9980,9 +10366,9 @@ var TimezoneView = () => {
|
|
|
9980
10366
|
paddingY: 1,
|
|
9981
10367
|
marginBottom: 1
|
|
9982
10368
|
},
|
|
9983
|
-
/* @__PURE__ */
|
|
9984
|
-
), result && /* @__PURE__ */
|
|
9985
|
-
|
|
10369
|
+
/* @__PURE__ */ React40.createElement(Text34, { color: "red" }, "\u2717 Error: ", error)
|
|
10370
|
+
), result && /* @__PURE__ */ React40.createElement(
|
|
10371
|
+
Box34,
|
|
9986
10372
|
{
|
|
9987
10373
|
flexDirection: "column",
|
|
9988
10374
|
borderStyle: "single",
|
|
@@ -9990,28 +10376,28 @@ var TimezoneView = () => {
|
|
|
9990
10376
|
paddingX: 2,
|
|
9991
10377
|
paddingY: 1
|
|
9992
10378
|
},
|
|
9993
|
-
/* @__PURE__ */
|
|
9994
|
-
/* @__PURE__ */
|
|
9995
|
-
), /* @__PURE__ */
|
|
10379
|
+
/* @__PURE__ */ React40.createElement(Box34, { marginBottom: 1 }, /* @__PURE__ */ React40.createElement(Text34, { bold: true, color: "green" }, "\u2713 Result:"), copied && /* @__PURE__ */ React40.createElement(Box34, { marginLeft: 2 }, /* @__PURE__ */ React40.createElement(Text34, { color: "green" }, "\u2713 Copied to clipboard!"))),
|
|
10380
|
+
/* @__PURE__ */ React40.createElement(Box34, { flexDirection: "column" }, /* @__PURE__ */ React40.createElement(Text34, { dimColor: true }, "From: ", fromTz), /* @__PURE__ */ React40.createElement(Text34, { dimColor: true }, "To: ", toTz), /* @__PURE__ */ React40.createElement(Box34, { marginTop: 1 }, /* @__PURE__ */ React40.createElement(Text34, { wrap: "wrap" }, result)))
|
|
10381
|
+
), /* @__PURE__ */ React40.createElement(Box34, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 2 }, /* @__PURE__ */ React40.createElement(Text34, { dimColor: true }, "Tab: Next | Enter: Convert | C: Copy | Esc: Back")));
|
|
9996
10382
|
};
|
|
9997
10383
|
|
|
9998
10384
|
// src/ui/utils/views/HttpView.tsx
|
|
9999
|
-
import
|
|
10000
|
-
import { Box as
|
|
10001
|
-
import
|
|
10385
|
+
import React41, { useState as useState24 } from "react";
|
|
10386
|
+
import { Box as Box35, Text as Text35, useInput as useInput21 } from "ink";
|
|
10387
|
+
import TextInput14 from "ink-text-input";
|
|
10002
10388
|
var METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE"];
|
|
10003
10389
|
var HttpView = () => {
|
|
10004
|
-
const [url, setUrl] =
|
|
10005
|
-
const [method, setMethod] =
|
|
10006
|
-
const [headers, setHeaders] =
|
|
10007
|
-
const [body, setBody] =
|
|
10008
|
-
const [response, setResponse] =
|
|
10009
|
-
const [error, setError] =
|
|
10010
|
-
const [loading, setLoading] =
|
|
10011
|
-
const [focusedField, setFocusedField] =
|
|
10012
|
-
const [copied, setCopied] =
|
|
10390
|
+
const [url, setUrl] = useState24("");
|
|
10391
|
+
const [method, setMethod] = useState24("GET");
|
|
10392
|
+
const [headers, setHeaders] = useState24("");
|
|
10393
|
+
const [body, setBody] = useState24("");
|
|
10394
|
+
const [response, setResponse] = useState24(null);
|
|
10395
|
+
const [error, setError] = useState24("");
|
|
10396
|
+
const [loading, setLoading] = useState24(false);
|
|
10397
|
+
const [focusedField, setFocusedField] = useState24("url");
|
|
10398
|
+
const [copied, setCopied] = useState24(false);
|
|
10013
10399
|
const service = new UtilsService();
|
|
10014
|
-
|
|
10400
|
+
useInput21((input5, key) => {
|
|
10015
10401
|
if (loading) return;
|
|
10016
10402
|
if (key.tab) {
|
|
10017
10403
|
const fields = ["url", "method", "headers", "body", "send"];
|
|
@@ -10072,8 +10458,8 @@ var HttpView = () => {
|
|
|
10072
10458
|
} catch (error2) {
|
|
10073
10459
|
}
|
|
10074
10460
|
};
|
|
10075
|
-
return /* @__PURE__ */
|
|
10076
|
-
|
|
10461
|
+
return /* @__PURE__ */ React41.createElement(Box35, { flexDirection: "column" }, /* @__PURE__ */ React41.createElement(Box35, { marginBottom: 1 }, /* @__PURE__ */ React41.createElement(Text35, { bold: true, color: "cyan" }, "\u{1F310} HTTP Request")), /* @__PURE__ */ React41.createElement(
|
|
10462
|
+
Box35,
|
|
10077
10463
|
{
|
|
10078
10464
|
flexDirection: "column",
|
|
10079
10465
|
borderStyle: "single",
|
|
@@ -10082,34 +10468,34 @@ var HttpView = () => {
|
|
|
10082
10468
|
paddingY: 1,
|
|
10083
10469
|
marginBottom: 1
|
|
10084
10470
|
},
|
|
10085
|
-
/* @__PURE__ */
|
|
10086
|
-
/* @__PURE__ */
|
|
10087
|
-
|
|
10471
|
+
/* @__PURE__ */ React41.createElement(Text35, { bold: true, color: "yellow", marginBottom: 1 }, "Request:"),
|
|
10472
|
+
/* @__PURE__ */ React41.createElement(Box35, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React41.createElement(Box35, { marginBottom: 0 }, /* @__PURE__ */ React41.createElement(Text35, { color: focusedField === "url" ? "green" : void 0 }, focusedField === "url" ? "\u25B6 " : " ", "URL:")), /* @__PURE__ */ React41.createElement(Box35, { marginLeft: 2, width: 60 }, focusedField === "url" ? /* @__PURE__ */ React41.createElement(
|
|
10473
|
+
TextInput14,
|
|
10088
10474
|
{
|
|
10089
10475
|
value: url,
|
|
10090
10476
|
onChange: setUrl,
|
|
10091
10477
|
placeholder: "https://api.example.com/endpoint"
|
|
10092
10478
|
}
|
|
10093
|
-
) : /* @__PURE__ */
|
|
10094
|
-
/* @__PURE__ */
|
|
10095
|
-
/* @__PURE__ */
|
|
10096
|
-
|
|
10479
|
+
) : /* @__PURE__ */ React41.createElement(Text35, { dimColor: !url }, url || "(empty)"))),
|
|
10480
|
+
/* @__PURE__ */ React41.createElement(Box35, { marginBottom: 1 }, /* @__PURE__ */ React41.createElement(Box35, { width: 20 }, /* @__PURE__ */ React41.createElement(Text35, { color: focusedField === "method" ? "green" : void 0 }, focusedField === "method" ? "\u25B6 " : " ", "Method:")), /* @__PURE__ */ React41.createElement(Text35, { bold: true, color: focusedField === "method" ? "yellow" : void 0 }, method), focusedField === "method" && /* @__PURE__ */ React41.createElement(Text35, { dimColor: true }, " (\u2190 \u2192 to change)")),
|
|
10481
|
+
/* @__PURE__ */ React41.createElement(Box35, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React41.createElement(Box35, { marginBottom: 0 }, /* @__PURE__ */ React41.createElement(Text35, { color: focusedField === "headers" ? "green" : void 0 }, focusedField === "headers" ? "\u25B6 " : " ", "Headers (one per line, Key: Value):")), /* @__PURE__ */ React41.createElement(Box35, { marginLeft: 2, width: 60 }, focusedField === "headers" ? /* @__PURE__ */ React41.createElement(
|
|
10482
|
+
TextInput14,
|
|
10097
10483
|
{
|
|
10098
10484
|
value: headers,
|
|
10099
10485
|
onChange: setHeaders,
|
|
10100
10486
|
placeholder: "Authorization: Bearer token"
|
|
10101
10487
|
}
|
|
10102
|
-
) : /* @__PURE__ */
|
|
10103
|
-
(method === "POST" || method === "PUT" || method === "PATCH") && /* @__PURE__ */
|
|
10104
|
-
|
|
10488
|
+
) : /* @__PURE__ */ React41.createElement(Text35, { dimColor: !headers }, headers || "(none)"))),
|
|
10489
|
+
(method === "POST" || method === "PUT" || method === "PATCH") && /* @__PURE__ */ React41.createElement(Box35, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React41.createElement(Box35, { marginBottom: 0 }, /* @__PURE__ */ React41.createElement(Text35, { color: focusedField === "body" ? "green" : void 0 }, focusedField === "body" ? "\u25B6 " : " ", "Body (JSON):")), /* @__PURE__ */ React41.createElement(Box35, { marginLeft: 2, width: 60 }, focusedField === "body" ? /* @__PURE__ */ React41.createElement(
|
|
10490
|
+
TextInput14,
|
|
10105
10491
|
{
|
|
10106
10492
|
value: body,
|
|
10107
10493
|
onChange: setBody,
|
|
10108
10494
|
placeholder: '{"key":"value"}'
|
|
10109
10495
|
}
|
|
10110
|
-
) : /* @__PURE__ */
|
|
10111
|
-
/* @__PURE__ */
|
|
10112
|
-
|
|
10496
|
+
) : /* @__PURE__ */ React41.createElement(Text35, { dimColor: !body }, body || "(empty)"))),
|
|
10497
|
+
/* @__PURE__ */ React41.createElement(Box35, { marginTop: 1 }, /* @__PURE__ */ React41.createElement(
|
|
10498
|
+
Text35,
|
|
10113
10499
|
{
|
|
10114
10500
|
bold: true,
|
|
10115
10501
|
backgroundColor: focusedField === "send" ? "green" : void 0,
|
|
@@ -10120,8 +10506,8 @@ var HttpView = () => {
|
|
|
10120
10506
|
loading ? "Sending..." : "Send Request",
|
|
10121
10507
|
" ]"
|
|
10122
10508
|
))
|
|
10123
|
-
), error && /* @__PURE__ */
|
|
10124
|
-
|
|
10509
|
+
), error && /* @__PURE__ */ React41.createElement(
|
|
10510
|
+
Box35,
|
|
10125
10511
|
{
|
|
10126
10512
|
flexDirection: "column",
|
|
10127
10513
|
borderStyle: "single",
|
|
@@ -10130,9 +10516,9 @@ var HttpView = () => {
|
|
|
10130
10516
|
paddingY: 1,
|
|
10131
10517
|
marginBottom: 1
|
|
10132
10518
|
},
|
|
10133
|
-
/* @__PURE__ */
|
|
10134
|
-
), response && /* @__PURE__ */
|
|
10135
|
-
|
|
10519
|
+
/* @__PURE__ */ React41.createElement(Text35, { color: "red" }, "\u2717 Error: ", error)
|
|
10520
|
+
), response && /* @__PURE__ */ React41.createElement(
|
|
10521
|
+
Box35,
|
|
10136
10522
|
{
|
|
10137
10523
|
flexDirection: "column",
|
|
10138
10524
|
borderStyle: "single",
|
|
@@ -10140,23 +10526,23 @@ var HttpView = () => {
|
|
|
10140
10526
|
paddingX: 2,
|
|
10141
10527
|
paddingY: 1
|
|
10142
10528
|
},
|
|
10143
|
-
/* @__PURE__ */
|
|
10144
|
-
/* @__PURE__ */
|
|
10145
|
-
), /* @__PURE__ */
|
|
10529
|
+
/* @__PURE__ */ React41.createElement(Box35, { marginBottom: 1 }, /* @__PURE__ */ React41.createElement(Text35, { bold: true, color: "green" }, "\u2713 Response:"), copied && /* @__PURE__ */ React41.createElement(Box35, { marginLeft: 2 }, /* @__PURE__ */ React41.createElement(Text35, { color: "green" }, "\u2713 Copied body to clipboard!"))),
|
|
10530
|
+
/* @__PURE__ */ React41.createElement(Box35, { flexDirection: "column" }, /* @__PURE__ */ React41.createElement(Text35, null, "Status: ", /* @__PURE__ */ React41.createElement(Text35, { color: response.status < 400 ? "green" : "red" }, response.status)), /* @__PURE__ */ React41.createElement(Text35, null, "Time: ", response.time, "ms"), /* @__PURE__ */ React41.createElement(Text35, null, "Size: ", response.size), /* @__PURE__ */ React41.createElement(Text35, null, " "), /* @__PURE__ */ React41.createElement(Text35, { bold: true, color: "yellow" }, "Headers:"), Object.entries(response.headers).slice(0, 5).map(([key, value]) => /* @__PURE__ */ React41.createElement(Text35, { key, dimColor: true }, " ", key, ": ", value)), /* @__PURE__ */ React41.createElement(Text35, null, " "), /* @__PURE__ */ React41.createElement(Text35, { bold: true, color: "yellow" }, "Body:"), /* @__PURE__ */ React41.createElement(Text35, null, typeof response.body === "string" ? response.body.slice(0, 500) : JSON.stringify(response.body, null, 2).slice(0, 500)))
|
|
10531
|
+
), /* @__PURE__ */ React41.createElement(Box35, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 2 }, /* @__PURE__ */ React41.createElement(Text35, { dimColor: true }, "Tab: Next | \u2190/\u2192: Change method | Enter: Send | C: Copy body | Esc: Back")));
|
|
10146
10532
|
};
|
|
10147
10533
|
|
|
10148
10534
|
// src/ui/utils/views/MarkdownView.tsx
|
|
10149
|
-
import
|
|
10150
|
-
import { Box as
|
|
10151
|
-
import
|
|
10535
|
+
import React42, { useState as useState25 } from "react";
|
|
10536
|
+
import { Box as Box36, Text as Text36, useInput as useInput22 } from "ink";
|
|
10537
|
+
import TextInput15 from "ink-text-input";
|
|
10152
10538
|
import * as fs12 from "fs";
|
|
10153
10539
|
import * as path7 from "path";
|
|
10154
10540
|
var MarkdownView = () => {
|
|
10155
|
-
const [filePath, setFilePath] =
|
|
10156
|
-
const [content, setContent] =
|
|
10157
|
-
const [error, setError] =
|
|
10158
|
-
const [focusedField, setFocusedField] =
|
|
10159
|
-
|
|
10541
|
+
const [filePath, setFilePath] = useState25("");
|
|
10542
|
+
const [content, setContent] = useState25("");
|
|
10543
|
+
const [error, setError] = useState25("");
|
|
10544
|
+
const [focusedField, setFocusedField] = useState25("file");
|
|
10545
|
+
useInput22((input5, key) => {
|
|
10160
10546
|
if (key.tab) {
|
|
10161
10547
|
setFocusedField(focusedField === "file" ? "preview" : "file");
|
|
10162
10548
|
} else if (key.return) {
|
|
@@ -10197,8 +10583,8 @@ ${code.trim()}
|
|
|
10197
10583
|
setContent("");
|
|
10198
10584
|
}
|
|
10199
10585
|
};
|
|
10200
|
-
return /* @__PURE__ */
|
|
10201
|
-
|
|
10586
|
+
return /* @__PURE__ */ React42.createElement(Box36, { flexDirection: "column" }, /* @__PURE__ */ React42.createElement(Box36, { marginBottom: 1 }, /* @__PURE__ */ React42.createElement(Text36, { bold: true, color: "cyan" }, "\u{1F4C4} Markdown Preview")), /* @__PURE__ */ React42.createElement(
|
|
10587
|
+
Box36,
|
|
10202
10588
|
{
|
|
10203
10589
|
flexDirection: "column",
|
|
10204
10590
|
borderStyle: "single",
|
|
@@ -10207,17 +10593,17 @@ ${code.trim()}
|
|
|
10207
10593
|
paddingY: 1,
|
|
10208
10594
|
marginBottom: 1
|
|
10209
10595
|
},
|
|
10210
|
-
/* @__PURE__ */
|
|
10211
|
-
/* @__PURE__ */
|
|
10212
|
-
|
|
10596
|
+
/* @__PURE__ */ React42.createElement(Text36, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
|
|
10597
|
+
/* @__PURE__ */ React42.createElement(Box36, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React42.createElement(Box36, { marginBottom: 0 }, /* @__PURE__ */ React42.createElement(Text36, { color: focusedField === "file" ? "green" : void 0 }, focusedField === "file" ? "\u25B6 " : " ", "File path:")), /* @__PURE__ */ React42.createElement(Box36, { marginLeft: 2, width: 60 }, focusedField === "file" ? /* @__PURE__ */ React42.createElement(
|
|
10598
|
+
TextInput15,
|
|
10213
10599
|
{
|
|
10214
10600
|
value: filePath,
|
|
10215
10601
|
onChange: setFilePath,
|
|
10216
10602
|
placeholder: "./README.md or /path/to/file.md"
|
|
10217
10603
|
}
|
|
10218
|
-
) : /* @__PURE__ */
|
|
10219
|
-
/* @__PURE__ */
|
|
10220
|
-
|
|
10604
|
+
) : /* @__PURE__ */ React42.createElement(Text36, { dimColor: !filePath }, filePath || "(empty)"))),
|
|
10605
|
+
/* @__PURE__ */ React42.createElement(Box36, { marginTop: 1 }, /* @__PURE__ */ React42.createElement(
|
|
10606
|
+
Text36,
|
|
10221
10607
|
{
|
|
10222
10608
|
bold: true,
|
|
10223
10609
|
backgroundColor: focusedField === "preview" ? "green" : void 0,
|
|
@@ -10226,8 +10612,8 @@ ${code.trim()}
|
|
|
10226
10612
|
focusedField === "preview" ? "\u25B6 " : " ",
|
|
10227
10613
|
"[ Preview File ]"
|
|
10228
10614
|
))
|
|
10229
|
-
), error && /* @__PURE__ */
|
|
10230
|
-
|
|
10615
|
+
), error && /* @__PURE__ */ React42.createElement(
|
|
10616
|
+
Box36,
|
|
10231
10617
|
{
|
|
10232
10618
|
flexDirection: "column",
|
|
10233
10619
|
borderStyle: "single",
|
|
@@ -10236,9 +10622,9 @@ ${code.trim()}
|
|
|
10236
10622
|
paddingY: 1,
|
|
10237
10623
|
marginBottom: 1
|
|
10238
10624
|
},
|
|
10239
|
-
/* @__PURE__ */
|
|
10240
|
-
), content && /* @__PURE__ */
|
|
10241
|
-
|
|
10625
|
+
/* @__PURE__ */ React42.createElement(Text36, { color: "red" }, "\u2717 Error: ", error)
|
|
10626
|
+
), content && /* @__PURE__ */ React42.createElement(
|
|
10627
|
+
Box36,
|
|
10242
10628
|
{
|
|
10243
10629
|
flexDirection: "column",
|
|
10244
10630
|
borderStyle: "single",
|
|
@@ -10246,9 +10632,9 @@ ${code.trim()}
|
|
|
10246
10632
|
paddingX: 2,
|
|
10247
10633
|
paddingY: 1
|
|
10248
10634
|
},
|
|
10249
|
-
/* @__PURE__ */
|
|
10250
|
-
/* @__PURE__ */
|
|
10251
|
-
), /* @__PURE__ */
|
|
10635
|
+
/* @__PURE__ */ React42.createElement(Box36, { marginBottom: 1 }, /* @__PURE__ */ React42.createElement(Text36, { bold: true, color: "green" }, "\u2713 Preview:")),
|
|
10636
|
+
/* @__PURE__ */ React42.createElement(Box36, { flexDirection: "column" }, /* @__PURE__ */ React42.createElement(Text36, null, content))
|
|
10637
|
+
), /* @__PURE__ */ React42.createElement(Box36, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 2 }, /* @__PURE__ */ React42.createElement(Text36, { dimColor: true }, "Tab: Next | Enter: Preview | Esc: Back")));
|
|
10252
10638
|
};
|
|
10253
10639
|
|
|
10254
10640
|
// src/ui/utils/UtilsApp.tsx
|
|
@@ -10268,10 +10654,10 @@ var MENU_ITEMS2 = [
|
|
|
10268
10654
|
{ id: "markdown", icon: "\u{1F4C4}", label: "Markdown", description: "Preview markdown" }
|
|
10269
10655
|
];
|
|
10270
10656
|
var UtilsApp = ({ onExit }) => {
|
|
10271
|
-
const [selectedIndex, setSelectedIndex] =
|
|
10272
|
-
const [activeView, setActiveView] =
|
|
10273
|
-
const { exit } =
|
|
10274
|
-
|
|
10657
|
+
const [selectedIndex, setSelectedIndex] = useState26(0);
|
|
10658
|
+
const [activeView, setActiveView] = useState26(null);
|
|
10659
|
+
const { exit } = useApp6();
|
|
10660
|
+
useInput23((input5, key) => {
|
|
10275
10661
|
if (activeView) {
|
|
10276
10662
|
if (key.escape) {
|
|
10277
10663
|
setActiveView(null);
|
|
@@ -10289,8 +10675,8 @@ var UtilsApp = ({ onExit }) => {
|
|
|
10289
10675
|
exit();
|
|
10290
10676
|
}
|
|
10291
10677
|
});
|
|
10292
|
-
return /* @__PURE__ */
|
|
10293
|
-
|
|
10678
|
+
return /* @__PURE__ */ React43.createElement(Box37, { flexDirection: "column", width: "100%", height: "100%" }, /* @__PURE__ */ React43.createElement(
|
|
10679
|
+
Box37,
|
|
10294
10680
|
{
|
|
10295
10681
|
borderStyle: "single",
|
|
10296
10682
|
borderColor: "cyan",
|
|
@@ -10298,10 +10684,10 @@ var UtilsApp = ({ onExit }) => {
|
|
|
10298
10684
|
paddingY: 0,
|
|
10299
10685
|
marginBottom: 1
|
|
10300
10686
|
},
|
|
10301
|
-
/* @__PURE__ */
|
|
10302
|
-
/* @__PURE__ */
|
|
10303
|
-
), /* @__PURE__ */
|
|
10304
|
-
|
|
10687
|
+
/* @__PURE__ */ React43.createElement(Text37, { bold: true, color: "cyan" }, "\u{1F6E0}\uFE0F Developer Utilities - Interactive Mode"),
|
|
10688
|
+
/* @__PURE__ */ React43.createElement(Box37, { marginLeft: "auto" }, /* @__PURE__ */ React43.createElement(Text37, { dimColor: true }, "Press Ctrl+Q to quit"))
|
|
10689
|
+
), /* @__PURE__ */ React43.createElement(Box37, { flexGrow: 1 }, /* @__PURE__ */ React43.createElement(
|
|
10690
|
+
Box37,
|
|
10305
10691
|
{
|
|
10306
10692
|
flexDirection: "column",
|
|
10307
10693
|
width: 30,
|
|
@@ -10311,9 +10697,9 @@ var UtilsApp = ({ onExit }) => {
|
|
|
10311
10697
|
paddingY: 1,
|
|
10312
10698
|
marginRight: 1
|
|
10313
10699
|
},
|
|
10314
|
-
/* @__PURE__ */
|
|
10315
|
-
MENU_ITEMS2.map((item, index) => /* @__PURE__ */
|
|
10316
|
-
|
|
10700
|
+
/* @__PURE__ */ React43.createElement(Box37, { marginBottom: 1 }, /* @__PURE__ */ React43.createElement(Text37, { bold: true, color: "yellow" }, "Select Utility:")),
|
|
10701
|
+
MENU_ITEMS2.map((item, index) => /* @__PURE__ */ React43.createElement(Box37, { key: item.id, marginBottom: 0 }, /* @__PURE__ */ React43.createElement(
|
|
10702
|
+
Text37,
|
|
10317
10703
|
{
|
|
10318
10704
|
color: selectedIndex === index && !activeView ? "green" : void 0,
|
|
10319
10705
|
bold: selectedIndex === index && !activeView,
|
|
@@ -10324,9 +10710,9 @@ var UtilsApp = ({ onExit }) => {
|
|
|
10324
10710
|
" ",
|
|
10325
10711
|
item.label
|
|
10326
10712
|
))),
|
|
10327
|
-
/* @__PURE__ */
|
|
10328
|
-
), /* @__PURE__ */
|
|
10329
|
-
|
|
10713
|
+
/* @__PURE__ */ React43.createElement(Box37, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 1 }, /* @__PURE__ */ React43.createElement(Text37, { dimColor: true }, "\u2191/\u2193: Navigate", "\n", "Enter: Select", "\n", "Esc: Back/Quit"))
|
|
10714
|
+
), /* @__PURE__ */ React43.createElement(
|
|
10715
|
+
Box37,
|
|
10330
10716
|
{
|
|
10331
10717
|
flexDirection: "column",
|
|
10332
10718
|
flexGrow: 1,
|
|
@@ -10335,21 +10721,21 @@ var UtilsApp = ({ onExit }) => {
|
|
|
10335
10721
|
paddingX: 2,
|
|
10336
10722
|
paddingY: 1
|
|
10337
10723
|
},
|
|
10338
|
-
activeView ? /* @__PURE__ */
|
|
10339
|
-
)), /* @__PURE__ */
|
|
10340
|
-
|
|
10724
|
+
activeView ? /* @__PURE__ */ React43.createElement(ActiveUtilityView, { utilityType: activeView }) : /* @__PURE__ */ React43.createElement(WelcomeView, { selectedItem: MENU_ITEMS2[selectedIndex] })
|
|
10725
|
+
)), /* @__PURE__ */ React43.createElement(
|
|
10726
|
+
Box37,
|
|
10341
10727
|
{
|
|
10342
10728
|
borderStyle: "single",
|
|
10343
10729
|
borderColor: "gray",
|
|
10344
10730
|
paddingX: 2,
|
|
10345
10731
|
marginTop: 1
|
|
10346
10732
|
},
|
|
10347
|
-
/* @__PURE__ */
|
|
10733
|
+
/* @__PURE__ */ React43.createElement(Text37, { dimColor: true }, "jai1-cli | Use arrow keys or j/k to navigate")
|
|
10348
10734
|
));
|
|
10349
10735
|
};
|
|
10350
10736
|
var WelcomeView = ({ selectedItem }) => {
|
|
10351
|
-
return /* @__PURE__ */
|
|
10352
|
-
|
|
10737
|
+
return /* @__PURE__ */ React43.createElement(Box37, { flexDirection: "column" }, /* @__PURE__ */ React43.createElement(Box37, { marginBottom: 1 }, /* @__PURE__ */ React43.createElement(Text37, { bold: true, color: "cyan" }, "Welcome to Developer Utilities")), /* @__PURE__ */ React43.createElement(Box37, { marginBottom: 2 }, /* @__PURE__ */ React43.createElement(Text37, null, "Select a utility from the left menu to get started.")), /* @__PURE__ */ React43.createElement(
|
|
10738
|
+
Box37,
|
|
10353
10739
|
{
|
|
10354
10740
|
borderStyle: "single",
|
|
10355
10741
|
borderColor: "yellow",
|
|
@@ -10357,49 +10743,49 @@ var WelcomeView = ({ selectedItem }) => {
|
|
|
10357
10743
|
paddingY: 1,
|
|
10358
10744
|
marginBottom: 2
|
|
10359
10745
|
},
|
|
10360
|
-
/* @__PURE__ */
|
|
10361
|
-
), /* @__PURE__ */
|
|
10746
|
+
/* @__PURE__ */ React43.createElement(Box37, { flexDirection: "column" }, /* @__PURE__ */ React43.createElement(Text37, { bold: true, color: "yellow" }, selectedItem.icon, " ", selectedItem.label), /* @__PURE__ */ React43.createElement(Text37, { dimColor: true }, selectedItem.description))
|
|
10747
|
+
), /* @__PURE__ */ React43.createElement(Box37, { marginBottom: 1 }, /* @__PURE__ */ React43.createElement(Text37, { bold: true }, "Quick Actions:")), /* @__PURE__ */ React43.createElement(Box37, { flexDirection: "column", marginLeft: 2 }, /* @__PURE__ */ React43.createElement(Text37, null, "\u2022 Press ", /* @__PURE__ */ React43.createElement(Text37, { color: "green" }, "Enter"), " to open selected utility"), /* @__PURE__ */ React43.createElement(Text37, null, "\u2022 Use ", /* @__PURE__ */ React43.createElement(Text37, { color: "green" }, "\u2191/\u2193"), " or ", /* @__PURE__ */ React43.createElement(Text37, { color: "green" }, "j/k"), " to navigate"), /* @__PURE__ */ React43.createElement(Text37, null, "\u2022 Press ", /* @__PURE__ */ React43.createElement(Text37, { color: "green" }, "Esc"), " to go back or quit"), /* @__PURE__ */ React43.createElement(Text37, null, "\u2022 Press ", /* @__PURE__ */ React43.createElement(Text37, { color: "green" }, "Ctrl+Q"), " to quit anytime")), /* @__PURE__ */ React43.createElement(Box37, { marginTop: 2 }, /* @__PURE__ */ React43.createElement(Text37, { dimColor: true }, "\u{1F4A1} Tip: Each utility provides an interactive interface for easy usage.")));
|
|
10362
10748
|
};
|
|
10363
10749
|
var ActiveUtilityView = ({ utilityType }) => {
|
|
10364
10750
|
switch (utilityType) {
|
|
10365
10751
|
case "password":
|
|
10366
|
-
return /* @__PURE__ */
|
|
10752
|
+
return /* @__PURE__ */ React43.createElement(PasswordView, null);
|
|
10367
10753
|
case "uuid":
|
|
10368
|
-
return /* @__PURE__ */
|
|
10754
|
+
return /* @__PURE__ */ React43.createElement(UuidView, null);
|
|
10369
10755
|
case "hash":
|
|
10370
|
-
return /* @__PURE__ */
|
|
10756
|
+
return /* @__PURE__ */ React43.createElement(HashView, null);
|
|
10371
10757
|
case "base64-encode":
|
|
10372
10758
|
case "base64-decode":
|
|
10373
|
-
return /* @__PURE__ */
|
|
10759
|
+
return /* @__PURE__ */ React43.createElement(Base64View, null);
|
|
10374
10760
|
case "url-encode":
|
|
10375
10761
|
case "url-decode":
|
|
10376
|
-
return /* @__PURE__ */
|
|
10762
|
+
return /* @__PURE__ */ React43.createElement(UrlView, null);
|
|
10377
10763
|
case "unix-time":
|
|
10378
|
-
return /* @__PURE__ */
|
|
10764
|
+
return /* @__PURE__ */ React43.createElement(UnixTimeView, null);
|
|
10379
10765
|
case "jwt":
|
|
10380
|
-
return /* @__PURE__ */
|
|
10766
|
+
return /* @__PURE__ */ React43.createElement(JwtView, null);
|
|
10381
10767
|
case "cron":
|
|
10382
|
-
return /* @__PURE__ */
|
|
10768
|
+
return /* @__PURE__ */ React43.createElement(CronView, null);
|
|
10383
10769
|
case "timezone":
|
|
10384
|
-
return /* @__PURE__ */
|
|
10770
|
+
return /* @__PURE__ */ React43.createElement(TimezoneView, null);
|
|
10385
10771
|
case "http":
|
|
10386
|
-
return /* @__PURE__ */
|
|
10772
|
+
return /* @__PURE__ */ React43.createElement(HttpView, null);
|
|
10387
10773
|
case "markdown":
|
|
10388
|
-
return /* @__PURE__ */
|
|
10774
|
+
return /* @__PURE__ */ React43.createElement(MarkdownView, null);
|
|
10389
10775
|
default:
|
|
10390
|
-
return /* @__PURE__ */
|
|
10776
|
+
return /* @__PURE__ */ React43.createElement(PlaceholderView, { utilityType });
|
|
10391
10777
|
}
|
|
10392
10778
|
};
|
|
10393
10779
|
var PlaceholderView = ({ utilityType }) => {
|
|
10394
10780
|
const item = MENU_ITEMS2.find((m) => m.id === utilityType);
|
|
10395
|
-
return /* @__PURE__ */
|
|
10781
|
+
return /* @__PURE__ */ React43.createElement(Box37, { flexDirection: "column" }, /* @__PURE__ */ React43.createElement(Box37, { marginBottom: 1 }, /* @__PURE__ */ React43.createElement(Text37, { bold: true, color: "cyan" }, item?.icon, " ", item?.label)), /* @__PURE__ */ React43.createElement(Box37, { borderStyle: "single", borderColor: "yellow", paddingX: 2, paddingY: 1 }, /* @__PURE__ */ React43.createElement(Text37, null, "\u{1F6A7} This utility view is under construction.", "\n", "\n", "For now, use the command-line version:", "\n", /* @__PURE__ */ React43.createElement(Text37, { color: "green" }, "$ jai1 utils ", utilityType, " --help"), "\n", "\n", "Press ", /* @__PURE__ */ React43.createElement(Text37, { color: "yellow" }, "Esc"), " to return to the menu.")));
|
|
10396
10782
|
};
|
|
10397
10783
|
|
|
10398
10784
|
// src/commands/utils/interactive.ts
|
|
10399
10785
|
async function runInteractiveMode() {
|
|
10400
10786
|
return new Promise((resolve4) => {
|
|
10401
|
-
const { unmount, waitUntilExit } =
|
|
10402
|
-
|
|
10787
|
+
const { unmount, waitUntilExit } = render6(
|
|
10788
|
+
React44.createElement(UtilsApp, {
|
|
10403
10789
|
onExit: () => {
|
|
10404
10790
|
unmount();
|
|
10405
10791
|
resolve4();
|
|
@@ -10450,7 +10836,7 @@ function showUtilsHelp() {
|
|
|
10450
10836
|
console.log(chalk10.dim('Ch\u1EA1y "jai1 utils <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt'));
|
|
10451
10837
|
}
|
|
10452
10838
|
function createUtilsCommand() {
|
|
10453
|
-
const utilsCommand = new
|
|
10839
|
+
const utilsCommand = new Command36("utils").description("Developer utilities for common tasks").option("-i, --interactive", "Run in interactive mode");
|
|
10454
10840
|
utilsCommand.addCommand(createPasswordCommand());
|
|
10455
10841
|
utilsCommand.addCommand(createUuidCommand());
|
|
10456
10842
|
utilsCommand.addCommand(createHashCommand());
|
|
@@ -10475,11 +10861,11 @@ function createUtilsCommand() {
|
|
|
10475
10861
|
}
|
|
10476
10862
|
|
|
10477
10863
|
// src/commands/deps/index.ts
|
|
10478
|
-
import { Command as
|
|
10864
|
+
import { Command as Command39 } from "commander";
|
|
10479
10865
|
import chalk13 from "chalk";
|
|
10480
10866
|
|
|
10481
10867
|
// src/commands/deps/check.ts
|
|
10482
|
-
import { Command as
|
|
10868
|
+
import { Command as Command37 } from "commander";
|
|
10483
10869
|
import chalk11 from "chalk";
|
|
10484
10870
|
import Table3 from "cli-table3";
|
|
10485
10871
|
import ora from "ora";
|
|
@@ -11075,7 +11461,7 @@ var DepsPythonService = class {
|
|
|
11075
11461
|
|
|
11076
11462
|
// src/commands/deps/check.ts
|
|
11077
11463
|
function createDepsCheckCommand() {
|
|
11078
|
-
const checkCommand = new
|
|
11464
|
+
const checkCommand = new Command37("check").description("Ki\u1EC3m tra c\xE1c packages c\u1EA7n upgrade").action(async () => {
|
|
11079
11465
|
const cwd = process.cwd();
|
|
11080
11466
|
const detector = new DepsDetectorService();
|
|
11081
11467
|
const spinner = ora("\u0110ang ph\xE1t hi\u1EC7n lo\u1EA1i project...").start();
|
|
@@ -11180,13 +11566,13 @@ async function checkEcosystem(ecosystem, manager, cwd) {
|
|
|
11180
11566
|
}
|
|
11181
11567
|
|
|
11182
11568
|
// src/commands/deps/upgrade.ts
|
|
11183
|
-
import { Command as
|
|
11569
|
+
import { Command as Command38 } from "commander";
|
|
11184
11570
|
import { checkbox as checkbox3, confirm as confirm6 } from "@inquirer/prompts";
|
|
11185
11571
|
import chalk12 from "chalk";
|
|
11186
11572
|
import ora2 from "ora";
|
|
11187
11573
|
import Table4 from "cli-table3";
|
|
11188
11574
|
function createDepsUpgradeCommand() {
|
|
11189
|
-
return new
|
|
11575
|
+
return new Command38("upgrade").description("Upgrade packages l\xEAn version m\u1EDBi nh\u1EA5t").option("--all", "Upgrade t\u1EA5t c\u1EA3 kh\xF4ng c\u1EA7n ch\u1ECDn").action(async (options) => {
|
|
11190
11576
|
await handleDepsUpgrade(options);
|
|
11191
11577
|
});
|
|
11192
11578
|
}
|
|
@@ -11399,7 +11785,7 @@ function showDepsHelp() {
|
|
|
11399
11785
|
console.log(chalk13.dim('Ch\u1EA1y "jai1 deps <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt'));
|
|
11400
11786
|
}
|
|
11401
11787
|
function createDepsCommand() {
|
|
11402
|
-
const depsCommand = new
|
|
11788
|
+
const depsCommand = new Command39("deps").description("Qu\u1EA3n l\xFD dependencies trong project").action(() => {
|
|
11403
11789
|
showDepsHelp();
|
|
11404
11790
|
});
|
|
11405
11791
|
depsCommand.addCommand(createDepsCheckCommand());
|
|
@@ -11408,11 +11794,11 @@ function createDepsCommand() {
|
|
|
11408
11794
|
}
|
|
11409
11795
|
|
|
11410
11796
|
// src/commands/kit/index.ts
|
|
11411
|
-
import { Command as
|
|
11797
|
+
import { Command as Command43 } from "commander";
|
|
11412
11798
|
import chalk15 from "chalk";
|
|
11413
11799
|
|
|
11414
11800
|
// src/commands/kit/list.ts
|
|
11415
|
-
import { Command as
|
|
11801
|
+
import { Command as Command40 } from "commander";
|
|
11416
11802
|
import chalk14 from "chalk";
|
|
11417
11803
|
import Table5 from "cli-table3";
|
|
11418
11804
|
|
|
@@ -11481,7 +11867,7 @@ var StarterKitService = class {
|
|
|
11481
11867
|
|
|
11482
11868
|
// src/commands/kit/list.ts
|
|
11483
11869
|
function createKitListCommand() {
|
|
11484
|
-
return new
|
|
11870
|
+
return new Command40("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) => {
|
|
11485
11871
|
const configService = new ConfigService();
|
|
11486
11872
|
const config = await configService.load();
|
|
11487
11873
|
if (!config) {
|
|
@@ -11547,9 +11933,9 @@ function createKitListCommand() {
|
|
|
11547
11933
|
}
|
|
11548
11934
|
|
|
11549
11935
|
// src/commands/kit/info.ts
|
|
11550
|
-
import { Command as
|
|
11936
|
+
import { Command as Command41 } from "commander";
|
|
11551
11937
|
function createKitInfoCommand() {
|
|
11552
|
-
return new
|
|
11938
|
+
return new Command41("info").description("Show detailed information about a starter kit").argument("<slug>", "Starter kit slug").action(async (slug) => {
|
|
11553
11939
|
const configService = new ConfigService();
|
|
11554
11940
|
const config = await configService.load();
|
|
11555
11941
|
if (!config) {
|
|
@@ -11598,7 +11984,7 @@ Post-Init Commands:`);
|
|
|
11598
11984
|
}
|
|
11599
11985
|
|
|
11600
11986
|
// src/commands/kit/create.ts
|
|
11601
|
-
import { Command as
|
|
11987
|
+
import { Command as Command42 } from "commander";
|
|
11602
11988
|
import { promises as fs18 } from "fs";
|
|
11603
11989
|
import { join as join8 } from "path";
|
|
11604
11990
|
import { select as select3, input as input2, checkbox as checkbox4 } from "@inquirer/prompts";
|
|
@@ -11643,7 +12029,7 @@ var HookExecutor = class {
|
|
|
11643
12029
|
|
|
11644
12030
|
// src/commands/kit/create.ts
|
|
11645
12031
|
function createKitCreateCommand() {
|
|
11646
|
-
return new
|
|
12032
|
+
return new Command42("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) => {
|
|
11647
12033
|
const configService = new ConfigService();
|
|
11648
12034
|
const config = await configService.load();
|
|
11649
12035
|
if (!config) {
|
|
@@ -11750,7 +12136,7 @@ function createKitCreateCommand() {
|
|
|
11750
12136
|
const ideChoices = [
|
|
11751
12137
|
{ name: "Cursor", value: "cursor" },
|
|
11752
12138
|
{ name: "Windsurf", value: "windsurf" },
|
|
11753
|
-
{ name: "Claude Code", value: "
|
|
12139
|
+
{ name: "Claude Code", value: "claudecode" },
|
|
11754
12140
|
{ name: "Antigravity", value: "antigravity" },
|
|
11755
12141
|
{ name: "OpenCode", value: "opencode" }
|
|
11756
12142
|
];
|
|
@@ -11773,7 +12159,7 @@ function createKitCreateCommand() {
|
|
|
11773
12159
|
selectedIdes = answer;
|
|
11774
12160
|
}
|
|
11775
12161
|
if (selectedIdes.length > 0) {
|
|
11776
|
-
await execa2("jai1", ["ide", "sync", ...selectedIdes], {
|
|
12162
|
+
await execa2("jai1", ["ide", "sync", "--ide", ...selectedIdes, "--type", "rules", "workflows", "commands"], {
|
|
11777
12163
|
cwd: targetDir,
|
|
11778
12164
|
stdio: "inherit"
|
|
11779
12165
|
});
|
|
@@ -11838,7 +12224,7 @@ function showKitHelp() {
|
|
|
11838
12224
|
console.log(chalk15.dim('Ch\u1EA1y "jai1 kit <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt'));
|
|
11839
12225
|
}
|
|
11840
12226
|
function createKitCommand() {
|
|
11841
|
-
const cmd = new
|
|
12227
|
+
const cmd = new Command43("kit").description("Manage starter kits for new projects").action(() => {
|
|
11842
12228
|
showKitHelp();
|
|
11843
12229
|
});
|
|
11844
12230
|
cmd.addCommand(createKitListCommand());
|
|
@@ -11848,15 +12234,15 @@ function createKitCommand() {
|
|
|
11848
12234
|
}
|
|
11849
12235
|
|
|
11850
12236
|
// src/commands/rules/index.ts
|
|
11851
|
-
import { Command as
|
|
12237
|
+
import { Command as Command50 } from "commander";
|
|
11852
12238
|
import chalk17 from "chalk";
|
|
11853
12239
|
|
|
11854
12240
|
// src/commands/rules/list.ts
|
|
11855
|
-
import { Command as
|
|
12241
|
+
import { Command as Command44 } from "commander";
|
|
11856
12242
|
import chalk16 from "chalk";
|
|
11857
12243
|
import Table6 from "cli-table3";
|
|
11858
12244
|
function createRulesListCommand() {
|
|
11859
|
-
return new
|
|
12245
|
+
return new Command44("list").description("List available rule presets").option("--json", "Output as JSON").action(async (options) => {
|
|
11860
12246
|
const configService = new ConfigService();
|
|
11861
12247
|
const config = await configService.load();
|
|
11862
12248
|
if (!config) {
|
|
@@ -11922,7 +12308,7 @@ function createRulesListCommand() {
|
|
|
11922
12308
|
}
|
|
11923
12309
|
|
|
11924
12310
|
// src/commands/rules/init.ts
|
|
11925
|
-
import { Command as
|
|
12311
|
+
import { Command as Command45 } from "commander";
|
|
11926
12312
|
import { promises as fs20 } from "fs";
|
|
11927
12313
|
import { join as join10 } from "path";
|
|
11928
12314
|
import { select as select4, confirm as confirm7 } from "@inquirer/prompts";
|
|
@@ -12047,7 +12433,7 @@ var ProjectConfigService = class {
|
|
|
12047
12433
|
|
|
12048
12434
|
// src/commands/rules/init.ts
|
|
12049
12435
|
function createRulesInitCommand() {
|
|
12050
|
-
return new
|
|
12436
|
+
return new Command45("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) => {
|
|
12051
12437
|
const configService = new ConfigService();
|
|
12052
12438
|
const config = await configService.load();
|
|
12053
12439
|
if (!config) {
|
|
@@ -12179,7 +12565,7 @@ async function applyAgentsMdFormat(bundle) {
|
|
|
12179
12565
|
}
|
|
12180
12566
|
|
|
12181
12567
|
// src/commands/rules/apply.ts
|
|
12182
|
-
import { Command as
|
|
12568
|
+
import { Command as Command46 } from "commander";
|
|
12183
12569
|
import { promises as fs22 } from "fs";
|
|
12184
12570
|
import { join as join12 } from "path";
|
|
12185
12571
|
import { select as select5, confirm as confirm8, checkbox as checkbox5 } from "@inquirer/prompts";
|
|
@@ -12695,7 +13081,7 @@ Restoring backup from ${metadata.timestamp}...`);
|
|
|
12695
13081
|
|
|
12696
13082
|
// src/commands/rules/apply.ts
|
|
12697
13083
|
function createRulesApplyCommand() {
|
|
12698
|
-
return new
|
|
13084
|
+
return new Command46("apply").description("Apply rule preset to project with multi-IDE support").argument("[preset]", "Preset slug to apply (optional)").option("--ides <ides>", "Comma-separated list of IDE formats (cursor,windsurf,antigravity,claude,agentsmd,gemini)").option("--skip-backup", "Skip backup creation").option("-y, --yes", "Skip all confirmations (auto mode)").action(async (presetSlug, options) => {
|
|
12699
13085
|
const configService = new ConfigService();
|
|
12700
13086
|
const config = await configService.load();
|
|
12701
13087
|
if (!config) {
|
|
@@ -12937,11 +13323,11 @@ function createRulesApplyCommand() {
|
|
|
12937
13323
|
}
|
|
12938
13324
|
|
|
12939
13325
|
// src/commands/rules/restore.ts
|
|
12940
|
-
import { Command as
|
|
13326
|
+
import { Command as Command47 } from "commander";
|
|
12941
13327
|
import { join as join13 } from "path";
|
|
12942
13328
|
import { select as select6, confirm as confirm9 } from "@inquirer/prompts";
|
|
12943
13329
|
function createRulesRestoreCommand() {
|
|
12944
|
-
return new
|
|
13330
|
+
return new Command47("restore").description("Restore rules from a backup").option("--latest", "Restore the most recent backup").option("-y, --yes", "Skip confirmation").action(async (options) => {
|
|
12945
13331
|
const backupService = new BackupService();
|
|
12946
13332
|
const backups = await backupService.listBackups();
|
|
12947
13333
|
if (backups.length === 0) {
|
|
@@ -13010,12 +13396,12 @@ function formatTimestamp(timestamp) {
|
|
|
13010
13396
|
}
|
|
13011
13397
|
|
|
13012
13398
|
// src/commands/rules/sync.ts
|
|
13013
|
-
import { Command as
|
|
13399
|
+
import { Command as Command48 } from "commander";
|
|
13014
13400
|
import { promises as fs23 } from "fs";
|
|
13015
13401
|
import { join as join14 } from "path";
|
|
13016
13402
|
import { checkbox as checkbox6, confirm as confirm10, Separator } from "@inquirer/prompts";
|
|
13017
13403
|
function createRulesSyncCommand() {
|
|
13018
|
-
return new
|
|
13404
|
+
return new Command48("sync").description("Regenerate rule outputs for all configured IDEs").option("--ides <ides>", "Comma-separated list of IDEs to sync (default: all configured)").option("--detect", "Auto-detect active IDEs instead of using config").option("-y, --yes", "Skip confirmations").action(async (options) => {
|
|
13019
13405
|
const rulePresetDir = join14(process.cwd(), ".jai1", "rule-preset");
|
|
13020
13406
|
const presetJsonPath = join14(rulePresetDir, "preset.json");
|
|
13021
13407
|
let presetExists = false;
|
|
@@ -13233,11 +13619,11 @@ function buildIdeChoices(currentIdes, detected, suggestions) {
|
|
|
13233
13619
|
}
|
|
13234
13620
|
|
|
13235
13621
|
// src/commands/rules/info.ts
|
|
13236
|
-
import { Command as
|
|
13622
|
+
import { Command as Command49 } from "commander";
|
|
13237
13623
|
import { promises as fs24 } from "fs";
|
|
13238
13624
|
import { join as join15 } from "path";
|
|
13239
13625
|
function createRulesInfoCommand() {
|
|
13240
|
-
return new
|
|
13626
|
+
return new Command49("info").description("Show current preset information").option("--json", "Output as JSON").action(async (options) => {
|
|
13241
13627
|
const projectConfigService = new ProjectConfigService();
|
|
13242
13628
|
const rulesConfig = await projectConfigService.loadRules();
|
|
13243
13629
|
if (!rulesConfig) {
|
|
@@ -13359,7 +13745,7 @@ function showRulesHelp() {
|
|
|
13359
13745
|
console.log(chalk17.dim('Ch\u1EA1y "jai1 rules <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt'));
|
|
13360
13746
|
}
|
|
13361
13747
|
function createRulesCommand() {
|
|
13362
|
-
const rulesCommand = new
|
|
13748
|
+
const rulesCommand = new Command50("rules").description("Manage rule presets for AI agents").action(() => {
|
|
13363
13749
|
showRulesHelp();
|
|
13364
13750
|
});
|
|
13365
13751
|
rulesCommand.addCommand(createRulesListCommand());
|
|
@@ -13372,7 +13758,7 @@ function createRulesCommand() {
|
|
|
13372
13758
|
}
|
|
13373
13759
|
|
|
13374
13760
|
// src/commands/upgrade.ts
|
|
13375
|
-
import { Command as
|
|
13761
|
+
import { Command as Command51 } from "commander";
|
|
13376
13762
|
import { confirm as confirm11 } from "@inquirer/prompts";
|
|
13377
13763
|
import { execSync as execSync4 } from "child_process";
|
|
13378
13764
|
var colors3 = {
|
|
@@ -13384,7 +13770,7 @@ var colors3 = {
|
|
|
13384
13770
|
bold: "\x1B[1m"
|
|
13385
13771
|
};
|
|
13386
13772
|
function createUpgradeCommand() {
|
|
13387
|
-
return new
|
|
13773
|
+
return new Command51("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) => {
|
|
13388
13774
|
await handleUpgrade(options);
|
|
13389
13775
|
});
|
|
13390
13776
|
}
|
|
@@ -13532,11 +13918,11 @@ function getInstallCommand(packageManager2) {
|
|
|
13532
13918
|
}
|
|
13533
13919
|
|
|
13534
13920
|
// src/commands/clean.ts
|
|
13535
|
-
import { Command as
|
|
13921
|
+
import { Command as Command52 } from "commander";
|
|
13536
13922
|
import { confirm as confirm12, select as select7 } from "@inquirer/prompts";
|
|
13537
13923
|
import { join as join16 } from "path";
|
|
13538
13924
|
function createCleanCommand() {
|
|
13539
|
-
return new
|
|
13925
|
+
return new Command52("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) => {
|
|
13540
13926
|
await handleClean(options);
|
|
13541
13927
|
});
|
|
13542
13928
|
}
|
|
@@ -13650,7 +14036,7 @@ async function cleanTarget(target, skipConfirm) {
|
|
|
13650
14036
|
}
|
|
13651
14037
|
|
|
13652
14038
|
// src/commands/redmine/check.ts
|
|
13653
|
-
import { Command as
|
|
14039
|
+
import { Command as Command53 } from "commander";
|
|
13654
14040
|
|
|
13655
14041
|
// src/services/redmine-config.service.ts
|
|
13656
14042
|
import { readFile as readFile7 } from "fs/promises";
|
|
@@ -13957,7 +14343,7 @@ async function checkConnectivity(config) {
|
|
|
13957
14343
|
|
|
13958
14344
|
// src/commands/redmine/check.ts
|
|
13959
14345
|
function createRedmineCheckCommand() {
|
|
13960
|
-
const cmd = new
|
|
14346
|
+
const cmd = new Command53("check").description("Check Redmine connectivity").option("-c, --config <path>", "Config file path", "redmine.config.yaml").option("--json", "Output as JSON").action(async (options) => {
|
|
13961
14347
|
await handleRedmineCheck(options);
|
|
13962
14348
|
});
|
|
13963
14349
|
return cmd;
|
|
@@ -13985,7 +14371,7 @@ async function handleRedmineCheck(options) {
|
|
|
13985
14371
|
}
|
|
13986
14372
|
|
|
13987
14373
|
// src/commands/redmine/sync-issue.ts
|
|
13988
|
-
import { Command as
|
|
14374
|
+
import { Command as Command54 } from "commander";
|
|
13989
14375
|
|
|
13990
14376
|
// src/sync-issue.ts
|
|
13991
14377
|
import { resolve as resolve3, relative } from "path";
|
|
@@ -14369,7 +14755,7 @@ function extractIssueIdFromUrl(url) {
|
|
|
14369
14755
|
|
|
14370
14756
|
// src/commands/redmine/sync-issue.ts
|
|
14371
14757
|
function createSyncIssueCommand() {
|
|
14372
|
-
const cmd = new
|
|
14758
|
+
const cmd = new Command54("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) => {
|
|
14373
14759
|
await handleSyncIssue(options);
|
|
14374
14760
|
});
|
|
14375
14761
|
return cmd;
|
|
@@ -14413,7 +14799,7 @@ async function handleSyncIssue(options) {
|
|
|
14413
14799
|
}
|
|
14414
14800
|
|
|
14415
14801
|
// src/commands/redmine/sync-project.ts
|
|
14416
|
-
import { Command as
|
|
14802
|
+
import { Command as Command55 } from "commander";
|
|
14417
14803
|
|
|
14418
14804
|
// src/sync-project.ts
|
|
14419
14805
|
async function syncProject(config, options = {}) {
|
|
@@ -14483,7 +14869,7 @@ async function syncProject(config, options = {}) {
|
|
|
14483
14869
|
|
|
14484
14870
|
// src/commands/redmine/sync-project.ts
|
|
14485
14871
|
function createSyncProjectCommand() {
|
|
14486
|
-
const cmd = new
|
|
14872
|
+
const cmd = new Command55("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) => {
|
|
14487
14873
|
await handleSyncProject(options);
|
|
14488
14874
|
});
|
|
14489
14875
|
return cmd;
|
|
@@ -14538,12 +14924,12 @@ async function handleSyncProject(options) {
|
|
|
14538
14924
|
}
|
|
14539
14925
|
|
|
14540
14926
|
// src/commands/framework/info.ts
|
|
14541
|
-
import { Command as
|
|
14927
|
+
import { Command as Command56 } from "commander";
|
|
14542
14928
|
import { promises as fs25 } from "fs";
|
|
14543
14929
|
import { join as join17 } from "path";
|
|
14544
14930
|
import { homedir as homedir5 } from "os";
|
|
14545
14931
|
function createInfoCommand() {
|
|
14546
|
-
const cmd = new
|
|
14932
|
+
const cmd = new Command56("info").description("Show jai1-client configuration and status").option("--json", "Output as JSON").option("--verbose", "Show detailed information").action(async (options) => {
|
|
14547
14933
|
await handleInfo(options);
|
|
14548
14934
|
});
|
|
14549
14935
|
return cmd;
|
|
@@ -14599,7 +14985,7 @@ async function getProjectStatus2() {
|
|
|
14599
14985
|
}
|
|
14600
14986
|
|
|
14601
14987
|
// src/commands/self-update.ts
|
|
14602
|
-
import { Command as
|
|
14988
|
+
import { Command as Command57 } from "commander";
|
|
14603
14989
|
import { confirm as confirm13 } from "@inquirer/prompts";
|
|
14604
14990
|
import { execSync as execSync5 } from "child_process";
|
|
14605
14991
|
var colors4 = {
|
|
@@ -14611,7 +14997,7 @@ var colors4 = {
|
|
|
14611
14997
|
bold: "\x1B[1m"
|
|
14612
14998
|
};
|
|
14613
14999
|
function createSelfUpdateCommand() {
|
|
14614
|
-
return new
|
|
15000
|
+
return new Command57("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) => {
|
|
14615
15001
|
await handleSelfUpdate(options);
|
|
14616
15002
|
});
|
|
14617
15003
|
}
|
|
@@ -14751,10 +15137,10 @@ function getInstallCommand2(packageManager2) {
|
|
|
14751
15137
|
}
|
|
14752
15138
|
|
|
14753
15139
|
// src/commands/clear-backups.ts
|
|
14754
|
-
import { Command as
|
|
15140
|
+
import { Command as Command58 } from "commander";
|
|
14755
15141
|
import { confirm as confirm14 } from "@inquirer/prompts";
|
|
14756
15142
|
function createClearBackupsCommand() {
|
|
14757
|
-
return new
|
|
15143
|
+
return new Command58("clear-backups").description("Clear backup files").option("-y, --yes", "Skip confirmation").action(async (options) => {
|
|
14758
15144
|
const service = new ComponentsService();
|
|
14759
15145
|
const backups = await service.listBackups(process.cwd());
|
|
14760
15146
|
if (backups.length === 0) {
|
|
@@ -14779,7 +15165,7 @@ function createClearBackupsCommand() {
|
|
|
14779
15165
|
}
|
|
14780
15166
|
|
|
14781
15167
|
// src/commands/vscode/index.ts
|
|
14782
|
-
import { Command as
|
|
15168
|
+
import { Command as Command59 } from "commander";
|
|
14783
15169
|
import { checkbox as checkbox7, confirm as confirm15, select as select8 } from "@inquirer/prompts";
|
|
14784
15170
|
import fs26 from "fs/promises";
|
|
14785
15171
|
import path12 from "path";
|
|
@@ -14919,7 +15305,7 @@ var PERFORMANCE_GROUPS2 = {
|
|
|
14919
15305
|
}
|
|
14920
15306
|
};
|
|
14921
15307
|
function createVSCodeCommand() {
|
|
14922
|
-
const vscodeCommand = new
|
|
15308
|
+
const vscodeCommand = new Command59("vscode").description("Qu\u1EA3n l\xFD c\xE0i \u0111\u1EB7t VSCode cho d\u1EF1 \xE1n hi\u1EC7n t\u1EA1i");
|
|
14923
15309
|
vscodeCommand.action(async () => {
|
|
14924
15310
|
await interactiveMode2();
|
|
14925
15311
|
});
|
|
@@ -15090,11 +15476,11 @@ async function resetSettings2(groupKeys) {
|
|
|
15090
15476
|
}
|
|
15091
15477
|
|
|
15092
15478
|
// src/commands/context.ts
|
|
15093
|
-
import
|
|
15094
|
-
import { render as
|
|
15095
|
-
import { Command as
|
|
15479
|
+
import React45 from "react";
|
|
15480
|
+
import { render as render7 } from "ink";
|
|
15481
|
+
import { Command as Command60 } from "commander";
|
|
15096
15482
|
function createContextCommand() {
|
|
15097
|
-
const cmd = new
|
|
15483
|
+
const cmd = new Command60("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) => {
|
|
15098
15484
|
let initialIDE;
|
|
15099
15485
|
if (options.ide) {
|
|
15100
15486
|
const validIDEs = ["cursor", "windsurf", "antigravity", "jai1"];
|
|
@@ -15119,8 +15505,8 @@ function createContextCommand() {
|
|
|
15119
15505
|
await printStats2();
|
|
15120
15506
|
return;
|
|
15121
15507
|
}
|
|
15122
|
-
const { waitUntilExit } =
|
|
15123
|
-
|
|
15508
|
+
const { waitUntilExit } = render7(
|
|
15509
|
+
React45.createElement(ContextApp, {
|
|
15124
15510
|
initialIDE,
|
|
15125
15511
|
initialType,
|
|
15126
15512
|
onExit: () => {
|
|
@@ -15171,10 +15557,10 @@ async function printStats2() {
|
|
|
15171
15557
|
}
|
|
15172
15558
|
|
|
15173
15559
|
// src/commands/migrate-ide.ts
|
|
15174
|
-
import { Command as
|
|
15560
|
+
import { Command as Command61 } from "commander";
|
|
15175
15561
|
import { checkbox as checkbox8, confirm as confirm16 } from "@inquirer/prompts";
|
|
15176
15562
|
function createMigrateIdeCommand() {
|
|
15177
|
-
const cmd = new
|
|
15563
|
+
const cmd = new Command61("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) => {
|
|
15178
15564
|
await runMigrateIde(options);
|
|
15179
15565
|
});
|
|
15180
15566
|
return cmd;
|
|
@@ -15330,7 +15716,7 @@ function showUnknownCommand(commandName) {
|
|
|
15330
15716
|
}
|
|
15331
15717
|
|
|
15332
15718
|
// src/cli.ts
|
|
15333
|
-
var program = new
|
|
15719
|
+
var program = new Command62();
|
|
15334
15720
|
if (process.argv.includes("-v") || process.argv.includes("--version")) {
|
|
15335
15721
|
console.log(package_default.version);
|
|
15336
15722
|
if (!process.argv.includes("--skip-update-check")) {
|
|
@@ -15348,6 +15734,7 @@ program.option("--verbose", "Enable verbose logging", false).option("--json", "O
|
|
|
15348
15734
|
program.addCommand(createAuthCommand());
|
|
15349
15735
|
program.addCommand(createStatusCommand());
|
|
15350
15736
|
program.addCommand(createApplyCommand());
|
|
15737
|
+
program.addCommand(createApplyNewCommand());
|
|
15351
15738
|
program.addCommand(createUpdateCommand());
|
|
15352
15739
|
program.addCommand(createCheckCommand());
|
|
15353
15740
|
program.addCommand(createIdeCommand());
|
|
@@ -15364,9 +15751,9 @@ program.addCommand(createKitCommand());
|
|
|
15364
15751
|
program.addCommand(createRulesCommand());
|
|
15365
15752
|
program.addCommand(createUpgradeCommand());
|
|
15366
15753
|
program.addCommand(createCleanCommand());
|
|
15367
|
-
var redmineCommand = new
|
|
15754
|
+
var redmineCommand = new Command62("redmine").description("Redmine context sync commands");
|
|
15368
15755
|
redmineCommand.addCommand(createRedmineCheckCommand());
|
|
15369
|
-
var syncCommand = new
|
|
15756
|
+
var syncCommand = new Command62("sync").description("Sync Redmine issues to markdown files");
|
|
15370
15757
|
syncCommand.addCommand(createSyncIssueCommand());
|
|
15371
15758
|
syncCommand.addCommand(createSyncProjectCommand());
|
|
15372
15759
|
redmineCommand.addCommand(syncCommand);
|