@jvittechs/j 1.0.14 → 1.0.16
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 +952 -1406
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -42,7 +42,7 @@ function checkNodeVersion() {
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
// src/cli.ts
|
|
45
|
-
import { Command as
|
|
45
|
+
import { Command as Command78 } from "commander";
|
|
46
46
|
|
|
47
47
|
// src/errors/index.ts
|
|
48
48
|
var Jai1Error = class extends Error {
|
|
@@ -169,7 +169,7 @@ import { basename as basename4 } from "path";
|
|
|
169
169
|
// package.json
|
|
170
170
|
var package_default = {
|
|
171
171
|
name: "@jvittechs/j",
|
|
172
|
-
version: "1.0.
|
|
172
|
+
version: "1.0.16",
|
|
173
173
|
description: "A unified CLI tool for JV-IT TECHS developers to manage Jai1 Framework. Supports both `j` and `jai1` commands. Please contact TeamAI for usage instructions.",
|
|
174
174
|
type: "module",
|
|
175
175
|
bin: {
|
|
@@ -2608,316 +2608,11 @@ async function handleCheck(options) {
|
|
|
2608
2608
|
|
|
2609
2609
|
// src/commands/ide/index.ts
|
|
2610
2610
|
import { Command as Command11 } from "commander";
|
|
2611
|
-
import
|
|
2611
|
+
import chalk7 from "chalk";
|
|
2612
2612
|
|
|
2613
|
-
// src/commands/
|
|
2614
|
-
import React12 from "react";
|
|
2615
|
-
import { render as render3 } from "ink";
|
|
2613
|
+
// src/commands/context.ts
|
|
2616
2614
|
import { Command as Command7 } from "commander";
|
|
2617
|
-
|
|
2618
|
-
// src/ui/context/ContextApp.tsx
|
|
2619
|
-
import React11, { useState as useState7, useEffect as useEffect3 } from "react";
|
|
2620
|
-
import { Box as Box8, Text as Text9, useInput as useInput7, useApp as useApp3 } from "ink";
|
|
2621
|
-
|
|
2622
|
-
// src/ui/context/views/MainMenuView.tsx
|
|
2623
|
-
import React7, { useState as useState3 } from "react";
|
|
2624
|
-
import { Box as Box4, Text as Text5, useInput as useInput3 } from "ink";
|
|
2625
|
-
var MainMenuView = ({ ideContexts, onSelect }) => {
|
|
2626
|
-
const [selectedIndex, setSelectedIndex] = useState3(0);
|
|
2627
|
-
const menuItems = [
|
|
2628
|
-
{
|
|
2629
|
-
ide: "cursor",
|
|
2630
|
-
icon: "\u{1F52E}",
|
|
2631
|
-
title: "Cursor",
|
|
2632
|
-
itemCount: ideContexts.find((ctx) => ctx.ide === "cursor")?.stats.totalItems || 0,
|
|
2633
|
-
available: ideContexts.some((ctx) => ctx.ide === "cursor")
|
|
2634
|
-
},
|
|
2635
|
-
{
|
|
2636
|
-
ide: "windsurf",
|
|
2637
|
-
icon: "\u{1F3C4}",
|
|
2638
|
-
title: "Windsurf",
|
|
2639
|
-
itemCount: ideContexts.find((ctx) => ctx.ide === "windsurf")?.stats.totalItems || 0,
|
|
2640
|
-
available: ideContexts.some((ctx) => ctx.ide === "windsurf")
|
|
2641
|
-
},
|
|
2642
|
-
{
|
|
2643
|
-
ide: "antigravity",
|
|
2644
|
-
icon: "\u{1F680}",
|
|
2645
|
-
title: "Antigravity",
|
|
2646
|
-
itemCount: ideContexts.find((ctx) => ctx.ide === "antigravity")?.stats.totalItems || 0,
|
|
2647
|
-
available: ideContexts.some((ctx) => ctx.ide === "antigravity")
|
|
2648
|
-
},
|
|
2649
|
-
{
|
|
2650
|
-
ide: "jai1",
|
|
2651
|
-
icon: "\u{1F916}",
|
|
2652
|
-
title: "Jai1 Framework",
|
|
2653
|
-
itemCount: ideContexts.find((ctx) => ctx.ide === "jai1")?.stats.totalItems || 0,
|
|
2654
|
-
available: ideContexts.some((ctx) => ctx.ide === "jai1")
|
|
2655
|
-
}
|
|
2656
|
-
];
|
|
2657
|
-
useInput3((input5, key) => {
|
|
2658
|
-
if (key.upArrow) {
|
|
2659
|
-
setSelectedIndex((prev) => Math.max(0, prev - 1));
|
|
2660
|
-
} else if (key.downArrow) {
|
|
2661
|
-
setSelectedIndex((prev) => Math.min(menuItems.length - 1, prev + 1));
|
|
2662
|
-
} else if (key.return) {
|
|
2663
|
-
const item = menuItems[selectedIndex];
|
|
2664
|
-
if (item && item.available) {
|
|
2665
|
-
onSelect(item.ide);
|
|
2666
|
-
}
|
|
2667
|
-
}
|
|
2668
|
-
}, { isActive: true });
|
|
2669
|
-
const formatSummary = (item) => {
|
|
2670
|
-
if (!item.available) {
|
|
2671
|
-
return "Kh\xF4ng c\xF3 context";
|
|
2672
|
-
}
|
|
2673
|
-
const ctx = ideContexts.find((c) => c.ide === item.ide);
|
|
2674
|
-
if (!ctx) return "";
|
|
2675
|
-
const parts = [];
|
|
2676
|
-
if (ctx.stats.byType.rules) parts.push(`${ctx.stats.byType.rules} rules`);
|
|
2677
|
-
if (ctx.stats.byType.workflows) parts.push(`${ctx.stats.byType.workflows} workflows`);
|
|
2678
|
-
if (ctx.stats.byType.skills) parts.push(`${ctx.stats.byType.skills} skills`);
|
|
2679
|
-
if (ctx.stats.byType.agents) parts.push(`${ctx.stats.byType.agents} agents`);
|
|
2680
|
-
if (ctx.stats.byType.prompts) parts.push(`${ctx.stats.byType.prompts} prompts`);
|
|
2681
|
-
return parts.join(", ") || `${item.itemCount} items`;
|
|
2682
|
-
};
|
|
2683
|
-
return /* @__PURE__ */ React7.createElement(Box4, { flexDirection: "column" }, /* @__PURE__ */ React7.createElement(
|
|
2684
|
-
Box4,
|
|
2685
|
-
{
|
|
2686
|
-
flexDirection: "column",
|
|
2687
|
-
borderStyle: "round",
|
|
2688
|
-
borderColor: "cyan",
|
|
2689
|
-
padding: 1,
|
|
2690
|
-
marginBottom: 1
|
|
2691
|
-
},
|
|
2692
|
-
/* @__PURE__ */ React7.createElement(Text5, null, "Ch\xE0o m\u1EEBng \u0111\u1EBFn v\u1EDBi ", /* @__PURE__ */ React7.createElement(Text5, { bold: true, color: "cyan" }, "Jai1 Context"), "!"),
|
|
2693
|
-
/* @__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.")
|
|
2694
|
-
), /* @__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) => {
|
|
2695
|
-
const isSelected = index === selectedIndex;
|
|
2696
|
-
const dimmed = !item.available;
|
|
2697
|
-
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"));
|
|
2698
|
-
})), 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.")));
|
|
2699
|
-
};
|
|
2700
|
-
|
|
2701
|
-
// src/ui/context/views/IDEOverviewView.tsx
|
|
2702
|
-
import React8, { useState as useState4 } from "react";
|
|
2703
|
-
import { Box as Box5, Text as Text6, useInput as useInput4 } from "ink";
|
|
2704
|
-
var IDEOverviewView = ({
|
|
2705
|
-
ideContext,
|
|
2706
|
-
onSelectType,
|
|
2707
|
-
onBack
|
|
2708
|
-
}) => {
|
|
2709
|
-
const [selectedTabIndex, setSelectedTabIndex] = useState4(0);
|
|
2710
|
-
const tabs = [];
|
|
2711
|
-
if (ideContext.stats.byType.rules) {
|
|
2712
|
-
tabs.push({
|
|
2713
|
-
type: "rules",
|
|
2714
|
-
label: "Rules",
|
|
2715
|
-
icon: "\u{1F4DC}",
|
|
2716
|
-
count: ideContext.stats.byType.rules
|
|
2717
|
-
});
|
|
2718
|
-
}
|
|
2719
|
-
if (ideContext.stats.byType.workflows) {
|
|
2720
|
-
tabs.push({
|
|
2721
|
-
type: "workflows",
|
|
2722
|
-
label: "Workflows",
|
|
2723
|
-
icon: "\u{1F504}",
|
|
2724
|
-
count: ideContext.stats.byType.workflows
|
|
2725
|
-
});
|
|
2726
|
-
}
|
|
2727
|
-
if (ideContext.stats.byType.skills) {
|
|
2728
|
-
tabs.push({
|
|
2729
|
-
type: "skills",
|
|
2730
|
-
label: "Skills",
|
|
2731
|
-
icon: "\u{1F6E0}",
|
|
2732
|
-
count: ideContext.stats.byType.skills
|
|
2733
|
-
});
|
|
2734
|
-
}
|
|
2735
|
-
if (ideContext.stats.byType.agents) {
|
|
2736
|
-
tabs.push({
|
|
2737
|
-
type: "agents",
|
|
2738
|
-
label: "Agents",
|
|
2739
|
-
icon: "\u{1F916}",
|
|
2740
|
-
count: ideContext.stats.byType.agents
|
|
2741
|
-
});
|
|
2742
|
-
}
|
|
2743
|
-
if (ideContext.stats.byType.prompts) {
|
|
2744
|
-
tabs.push({
|
|
2745
|
-
type: "prompts",
|
|
2746
|
-
label: "Prompts",
|
|
2747
|
-
icon: "\u{1F4AC}",
|
|
2748
|
-
count: ideContext.stats.byType.prompts
|
|
2749
|
-
});
|
|
2750
|
-
}
|
|
2751
|
-
if (ideContext.stats.byType.context) {
|
|
2752
|
-
tabs.push({
|
|
2753
|
-
type: "context",
|
|
2754
|
-
label: "Context",
|
|
2755
|
-
icon: "\u{1F4CB}",
|
|
2756
|
-
count: ideContext.stats.byType.context
|
|
2757
|
-
});
|
|
2758
|
-
}
|
|
2759
|
-
useInput4((input5, key) => {
|
|
2760
|
-
if (key.tab || key.rightArrow) {
|
|
2761
|
-
setSelectedTabIndex((prev) => Math.min(tabs.length - 1, prev + 1));
|
|
2762
|
-
} else if (key.leftArrow) {
|
|
2763
|
-
setSelectedTabIndex((prev) => Math.max(0, prev - 1));
|
|
2764
|
-
}
|
|
2765
|
-
const num = parseInt(input5, 10);
|
|
2766
|
-
if (!isNaN(num) && num >= 1 && num <= tabs.length) {
|
|
2767
|
-
setSelectedTabIndex(num - 1);
|
|
2768
|
-
}
|
|
2769
|
-
if (key.return) {
|
|
2770
|
-
const tab = tabs[selectedTabIndex];
|
|
2771
|
-
if (tab) {
|
|
2772
|
-
onSelectType(tab.type);
|
|
2773
|
-
}
|
|
2774
|
-
}
|
|
2775
|
-
}, { isActive: true });
|
|
2776
|
-
const currentTab = tabs[selectedTabIndex];
|
|
2777
|
-
const currentItems = currentTab ? ideContext?.items?.filter((item) => item.type === currentTab.type) ?? [] : [];
|
|
2778
|
-
const formatSize = (bytes) => {
|
|
2779
|
-
if (bytes < 1024) return `${bytes}B`;
|
|
2780
|
-
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;
|
|
2781
|
-
return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
|
|
2782
|
-
};
|
|
2783
|
-
const formatDate = (date) => {
|
|
2784
|
-
return date.toLocaleDateString("vi-VN", {
|
|
2785
|
-
year: "numeric",
|
|
2786
|
-
month: "2-digit",
|
|
2787
|
-
day: "2-digit"
|
|
2788
|
-
});
|
|
2789
|
-
};
|
|
2790
|
-
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(
|
|
2791
|
-
Box5,
|
|
2792
|
-
{
|
|
2793
|
-
flexDirection: "column",
|
|
2794
|
-
borderStyle: "round",
|
|
2795
|
-
borderColor: "cyan",
|
|
2796
|
-
padding: 1,
|
|
2797
|
-
marginBottom: 1
|
|
2798
|
-
},
|
|
2799
|
-
/* @__PURE__ */ React8.createElement(Text6, { bold: true }, "\u{1F4CA} T\u1ED5ng quan"),
|
|
2800
|
-
/* @__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)))))
|
|
2801
|
-
), /* @__PURE__ */ React8.createElement(Box5, { flexDirection: "column", borderStyle: "round", borderColor: "gray", padding: 1 }, /* @__PURE__ */ React8.createElement(Box5, { marginBottom: 1 }, tabs.map((tab, index) => {
|
|
2802
|
-
const isSelected = index === selectedTabIndex;
|
|
2803
|
-
return /* @__PURE__ */ React8.createElement(Box5, { key: tab.type, marginRight: 1 }, /* @__PURE__ */ React8.createElement(
|
|
2804
|
-
Text6,
|
|
2805
|
-
{
|
|
2806
|
-
color: isSelected ? "cyan" : "gray",
|
|
2807
|
-
bold: isSelected,
|
|
2808
|
-
inverse: isSelected
|
|
2809
|
-
},
|
|
2810
|
-
" ",
|
|
2811
|
-
tab.icon,
|
|
2812
|
-
" ",
|
|
2813
|
-
tab.label,
|
|
2814
|
-
" (",
|
|
2815
|
-
tab.count,
|
|
2816
|
-
")",
|
|
2817
|
-
" "
|
|
2818
|
-
));
|
|
2819
|
-
})), 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)));
|
|
2820
|
-
};
|
|
2821
|
-
|
|
2822
|
-
// src/ui/context/views/ListView.tsx
|
|
2823
|
-
import React9, { useState as useState5 } from "react";
|
|
2824
|
-
import { Box as Box6, Text as Text7, useInput as useInput5 } from "ink";
|
|
2825
|
-
var ListView = ({ items, contentType, onSelect, onBack }) => {
|
|
2826
|
-
const [selectedIndex, setSelectedIndex] = useState5(0);
|
|
2827
|
-
useInput5((input5, key) => {
|
|
2828
|
-
if (key.upArrow) {
|
|
2829
|
-
setSelectedIndex((prev) => Math.max(0, prev - 1));
|
|
2830
|
-
} else if (key.downArrow) {
|
|
2831
|
-
setSelectedIndex((prev) => Math.min(items.length - 1, prev + 1));
|
|
2832
|
-
} else if (key.return) {
|
|
2833
|
-
const item = items[selectedIndex];
|
|
2834
|
-
if (item) {
|
|
2835
|
-
onSelect(item);
|
|
2836
|
-
}
|
|
2837
|
-
}
|
|
2838
|
-
}, { isActive: true });
|
|
2839
|
-
const getTypeLabel = () => {
|
|
2840
|
-
switch (contentType) {
|
|
2841
|
-
case "rules":
|
|
2842
|
-
return "\u{1F4DC} Rules";
|
|
2843
|
-
case "workflows":
|
|
2844
|
-
return "\u{1F504} Workflows";
|
|
2845
|
-
case "skills":
|
|
2846
|
-
return "\u{1F6E0} Skills";
|
|
2847
|
-
case "agents":
|
|
2848
|
-
return "\u{1F916} Agents";
|
|
2849
|
-
case "prompts":
|
|
2850
|
-
return "\u{1F4AC} Prompts";
|
|
2851
|
-
case "context":
|
|
2852
|
-
return "\u{1F4CB} Context";
|
|
2853
|
-
default:
|
|
2854
|
-
return contentType;
|
|
2855
|
-
}
|
|
2856
|
-
};
|
|
2857
|
-
const formatSize = (bytes) => {
|
|
2858
|
-
if (bytes < 1024) return `${bytes}B`;
|
|
2859
|
-
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;
|
|
2860
|
-
return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
|
|
2861
|
-
};
|
|
2862
|
-
if (items.length === 0) {
|
|
2863
|
-
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")));
|
|
2864
|
-
}
|
|
2865
|
-
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) => {
|
|
2866
|
-
const isSelected = index === selectedIndex;
|
|
2867
|
-
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)));
|
|
2868
|
-
})));
|
|
2869
|
-
};
|
|
2870
|
-
|
|
2871
|
-
// src/ui/context/views/DetailView.tsx
|
|
2872
|
-
import React10, { useState as useState6 } from "react";
|
|
2873
|
-
import { Box as Box7, Text as Text8, useInput as useInput6 } from "ink";
|
|
2874
|
-
var DetailView = ({ item, scrollPosition: initialScroll, onBack }) => {
|
|
2875
|
-
const [scrollPosition, setScrollPosition] = useState6(initialScroll);
|
|
2876
|
-
const maxVisibleLines = 25;
|
|
2877
|
-
const maxScroll = Math.max(0, item.previewLines.length - maxVisibleLines);
|
|
2878
|
-
useInput6((input5, key) => {
|
|
2879
|
-
if (key.upArrow || input5 === "k") {
|
|
2880
|
-
setScrollPosition((prev) => Math.max(0, prev - 1));
|
|
2881
|
-
} else if (key.downArrow || input5 === "j") {
|
|
2882
|
-
setScrollPosition((prev) => Math.min(maxScroll, prev + 1));
|
|
2883
|
-
} else if (key.pageDown || input5 === "d") {
|
|
2884
|
-
setScrollPosition((prev) => Math.min(maxScroll, prev + 5));
|
|
2885
|
-
} else if (key.pageUp || input5 === "u") {
|
|
2886
|
-
setScrollPosition((prev) => Math.max(0, prev - 5));
|
|
2887
|
-
} else if (input5 === "g") {
|
|
2888
|
-
setScrollPosition(0);
|
|
2889
|
-
} else if (input5 === "G") {
|
|
2890
|
-
setScrollPosition(maxScroll);
|
|
2891
|
-
} else if (key.escape || key.backspace) {
|
|
2892
|
-
onBack();
|
|
2893
|
-
}
|
|
2894
|
-
}, { isActive: true });
|
|
2895
|
-
const formatSize = (bytes) => {
|
|
2896
|
-
if (bytes < 1024) return `${bytes}B`;
|
|
2897
|
-
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;
|
|
2898
|
-
return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
|
|
2899
|
-
};
|
|
2900
|
-
const formatDate = (date) => {
|
|
2901
|
-
return date.toLocaleString("vi-VN", {
|
|
2902
|
-
year: "numeric",
|
|
2903
|
-
month: "2-digit",
|
|
2904
|
-
day: "2-digit",
|
|
2905
|
-
hour: "2-digit",
|
|
2906
|
-
minute: "2-digit"
|
|
2907
|
-
});
|
|
2908
|
-
};
|
|
2909
|
-
const visibleLines = item.previewLines.slice(
|
|
2910
|
-
scrollPosition,
|
|
2911
|
-
scrollPosition + maxVisibleLines
|
|
2912
|
-
);
|
|
2913
|
-
const hasMoreAbove = scrollPosition > 0;
|
|
2914
|
-
const hasMoreBelow = scrollPosition + maxVisibleLines < item.previewLines.length;
|
|
2915
|
-
const scrollPercentage = item.previewLines.length <= maxVisibleLines ? 100 : Math.round(scrollPosition / maxScroll * 100);
|
|
2916
|
-
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) => {
|
|
2917
|
-
const lineNumber = scrollPosition + index + 1;
|
|
2918
|
-
return /* @__PURE__ */ React10.createElement(Box7, { key: index }, /* @__PURE__ */ React10.createElement(Text8, { dimColor: true }, lineNumber.toString().padStart(3, " "), "\u2502 "), /* @__PURE__ */ React10.createElement(Text8, null, line));
|
|
2919
|
-
})), 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")));
|
|
2920
|
-
};
|
|
2615
|
+
import chalk6 from "chalk";
|
|
2921
2616
|
|
|
2922
2617
|
// src/services/context-scanner.service.ts
|
|
2923
2618
|
import { promises as fs6 } from "fs";
|
|
@@ -3267,201 +2962,133 @@ var ContextScannerService = class {
|
|
|
3267
2962
|
}
|
|
3268
2963
|
};
|
|
3269
2964
|
|
|
3270
|
-
// src/
|
|
3271
|
-
var
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
|
|
3280
|
-
|
|
3281
|
-
const
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
}
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
}
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
IDEOverviewView,
|
|
3343
|
-
{
|
|
3344
|
-
ideContext: currentIDEContext,
|
|
3345
|
-
onSelectType: handleSelectType,
|
|
3346
|
-
onBack: handleBack
|
|
3347
|
-
}
|
|
3348
|
-
) : null;
|
|
3349
|
-
case "list":
|
|
3350
|
-
return /* @__PURE__ */ React11.createElement(
|
|
3351
|
-
ListView,
|
|
3352
|
-
{
|
|
3353
|
-
items: currentItems,
|
|
3354
|
-
contentType: selectedType,
|
|
3355
|
-
onSelect: handleSelectItem,
|
|
3356
|
-
onBack: handleBack
|
|
3357
|
-
}
|
|
3358
|
-
);
|
|
3359
|
-
case "detail":
|
|
3360
|
-
return selectedItem ? /* @__PURE__ */ React11.createElement(
|
|
3361
|
-
DetailView,
|
|
3362
|
-
{
|
|
3363
|
-
item: selectedItem,
|
|
3364
|
-
scrollPosition,
|
|
3365
|
-
onBack: handleBack
|
|
3366
|
-
}
|
|
3367
|
-
) : null;
|
|
3368
|
-
default:
|
|
3369
|
-
return /* @__PURE__ */ React11.createElement(MainMenuView, { ideContexts, onSelect: handleSelectIDE });
|
|
2965
|
+
// src/commands/context.ts
|
|
2966
|
+
var MAX_TOKENS = 256e3;
|
|
2967
|
+
var SYSTEM_PROMPT_TOKENS = 1e4;
|
|
2968
|
+
var COMPACT_BUFFER_TOKENS = 56e3;
|
|
2969
|
+
var BAR_WIDTH = 50;
|
|
2970
|
+
var CHARS_PER_TOKEN = 4;
|
|
2971
|
+
function estimateTokens(bytes) {
|
|
2972
|
+
return Math.ceil(bytes / CHARS_PER_TOKEN);
|
|
2973
|
+
}
|
|
2974
|
+
function formatTokens(n) {
|
|
2975
|
+
if (n >= 1e3) {
|
|
2976
|
+
const k = n / 1e3;
|
|
2977
|
+
return k % 1 === 0 ? `${k}k` : `${k.toFixed(1)}k`;
|
|
2978
|
+
}
|
|
2979
|
+
return String(n);
|
|
2980
|
+
}
|
|
2981
|
+
function formatNumber(n) {
|
|
2982
|
+
return n.toLocaleString("en-US");
|
|
2983
|
+
}
|
|
2984
|
+
function pct(value, total) {
|
|
2985
|
+
return (value / total * 100).toFixed(1) + "%";
|
|
2986
|
+
}
|
|
2987
|
+
function renderStackedBar(segments, total, width) {
|
|
2988
|
+
let bar = "";
|
|
2989
|
+
let usedCols = 0;
|
|
2990
|
+
for (let i = 0; i < segments.length; i++) {
|
|
2991
|
+
const seg = segments[i];
|
|
2992
|
+
const isLast = i === segments.length - 1;
|
|
2993
|
+
const cols = isLast ? width - usedCols : Math.round(seg.tokens / total * width);
|
|
2994
|
+
if (cols > 0) {
|
|
2995
|
+
bar += seg.color(seg.char.repeat(cols));
|
|
2996
|
+
usedCols += cols;
|
|
2997
|
+
}
|
|
2998
|
+
}
|
|
2999
|
+
return bar;
|
|
3000
|
+
}
|
|
3001
|
+
function renderIDEContext(ideContext) {
|
|
3002
|
+
const { config, items } = ideContext;
|
|
3003
|
+
const ruleItems = items.filter((item) => item.type === "rules");
|
|
3004
|
+
const rulesTotalBytes = ruleItems.reduce((sum, item) => sum + item.fileSize, 0);
|
|
3005
|
+
const rulesTokens = estimateTokens(rulesTotalBytes);
|
|
3006
|
+
const usedTokens = SYSTEM_PROMPT_TOKENS + rulesTokens;
|
|
3007
|
+
const userPromptTokens = Math.max(0, MAX_TOKENS - SYSTEM_PROMPT_TOKENS - rulesTokens - COMPACT_BUFFER_TOKENS);
|
|
3008
|
+
console.log(`${chalk6.dim("\u2514")} ${chalk6.bold("Context Usage")}`);
|
|
3009
|
+
const segments = [
|
|
3010
|
+
{ tokens: SYSTEM_PROMPT_TOKENS, char: "\u2593", color: chalk6.yellow },
|
|
3011
|
+
{ tokens: rulesTokens, char: "\u2593", color: chalk6.red },
|
|
3012
|
+
{ tokens: userPromptTokens, char: "\u2591", color: chalk6.dim },
|
|
3013
|
+
{ tokens: COMPACT_BUFFER_TOKENS, char: "\u2592", color: chalk6.magenta }
|
|
3014
|
+
];
|
|
3015
|
+
const barLine = renderStackedBar(segments, MAX_TOKENS, BAR_WIDTH);
|
|
3016
|
+
const summary = `${config.icon} ${config.name} \xB7 ${formatTokens(usedTokens)}/${formatTokens(MAX_TOKENS)} tokens (${pct(usedTokens, MAX_TOKENS)})`;
|
|
3017
|
+
console.log(` ${barLine} ${chalk6.bold(summary)}`);
|
|
3018
|
+
const legendItems = [
|
|
3019
|
+
{ icon: "\u{1F7E1}", label: "System prompt", tokens: SYSTEM_PROMPT_TOKENS },
|
|
3020
|
+
{ icon: "\u{1F534}", label: "IDE Rules", tokens: rulesTokens },
|
|
3021
|
+
{ icon: "\u2B1C", label: "Free space", tokens: userPromptTokens },
|
|
3022
|
+
{ icon: "\u{1F7E3}", label: "Autocompact buffer", tokens: COMPACT_BUFFER_TOKENS }
|
|
3023
|
+
];
|
|
3024
|
+
const pad = " ".repeat(BAR_WIDTH + 5);
|
|
3025
|
+
for (const item of legendItems) {
|
|
3026
|
+
console.log(`${pad} ${item.icon} ${item.label}: ${formatTokens(item.tokens)} tokens (${pct(item.tokens, MAX_TOKENS)})`);
|
|
3027
|
+
}
|
|
3028
|
+
if (ruleItems.length > 0) {
|
|
3029
|
+
console.log("");
|
|
3030
|
+
console.log(` ${chalk6.bold("Rules")} ${chalk6.dim(`\xB7 ${config.basePath}/rules`)}`);
|
|
3031
|
+
const sorted = [...ruleItems].sort((a, b) => b.fileSize - a.fileSize);
|
|
3032
|
+
for (const rule of sorted) {
|
|
3033
|
+
const tokens = estimateTokens(rule.fileSize);
|
|
3034
|
+
const name = typeof rule.name === "string" ? rule.name : rule.relativePath;
|
|
3035
|
+
const badge = rule.alwaysApply ? chalk6.dim(" [always]") : "";
|
|
3036
|
+
console.log(` ${chalk6.dim("\u2514")} ${name}${badge}: ${formatNumber(tokens)} tokens`);
|
|
3370
3037
|
}
|
|
3371
|
-
}
|
|
3372
|
-
const
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
|
|
3379
|
-
|
|
3380
|
-
|
|
3381
|
-
return "[\u2191\u2193/j/k] Cu\u1ED9n \xB7 [PgUp/u PgDn/d] Cu\u1ED9n nhanh \xB7 [g/G] \u0110\u1EA7u/Cu\u1ED1i \xB7 [Esc/\u2190] Quay l\u1EA1i \xB7 [q] Tho\xE1t";
|
|
3382
|
-
default:
|
|
3383
|
-
return "[q] Tho\xE1t";
|
|
3038
|
+
}
|
|
3039
|
+
const workflowItems = items.filter((item) => item.type === "workflows");
|
|
3040
|
+
if (workflowItems.length > 0) {
|
|
3041
|
+
console.log("");
|
|
3042
|
+
console.log(` ${chalk6.bold("Workflows")} ${chalk6.dim(`\xB7 ${config.basePath}/workflows`)}`);
|
|
3043
|
+
const sorted = [...workflowItems].sort((a, b) => b.fileSize - a.fileSize);
|
|
3044
|
+
for (const wf of sorted) {
|
|
3045
|
+
const tokens = estimateTokens(wf.fileSize);
|
|
3046
|
+
const name = typeof wf.name === "string" ? wf.name : wf.relativePath;
|
|
3047
|
+
console.log(` ${chalk6.dim("\u2514")} ${name}: ${formatNumber(tokens)} tokens`);
|
|
3384
3048
|
}
|
|
3385
|
-
}
|
|
3386
|
-
|
|
3387
|
-
}
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
console.error(
|
|
3397
|
-
console.error(` Valid IDEs: ${validIDEs.join(", ")}`);
|
|
3049
|
+
}
|
|
3050
|
+
console.log("");
|
|
3051
|
+
}
|
|
3052
|
+
function createContextCommand() {
|
|
3053
|
+
const cmd = new Command7("context").description("Visualize IDE context window token budget").argument("[ide]", "Show specific IDE only (cursor, windsurf, antigravity)").action(async (ideArg) => {
|
|
3054
|
+
const name = getCliName();
|
|
3055
|
+
const validIDEs = ["cursor", "windsurf", "antigravity"];
|
|
3056
|
+
if (ideArg) {
|
|
3057
|
+
if (!validIDEs.includes(ideArg)) {
|
|
3058
|
+
console.error(chalk6.red(`\u274C Invalid IDE: ${ideArg}`));
|
|
3059
|
+
console.error(chalk6.dim(` Valid IDEs: ${validIDEs.join(", ")}`));
|
|
3060
|
+
console.error(chalk6.dim(` Usage: ${name} context [ide]`));
|
|
3398
3061
|
process.exit(1);
|
|
3399
3062
|
}
|
|
3400
|
-
initialIDE = options.target;
|
|
3401
3063
|
}
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3064
|
+
const scanner = new ContextScannerService();
|
|
3065
|
+
const targetIDEs = ideArg ? [ideArg] : validIDEs;
|
|
3066
|
+
console.log("");
|
|
3067
|
+
console.log(` ${chalk6.bgGray.white.bold(" /context ")}`);
|
|
3068
|
+
let found = false;
|
|
3069
|
+
for (const ide of targetIDEs) {
|
|
3070
|
+
try {
|
|
3071
|
+
const ideContext = await scanner.scanIDE(ide);
|
|
3072
|
+
const config = IDE_CONFIGS[ide];
|
|
3073
|
+
if (config) {
|
|
3074
|
+
renderIDEContext(ideContext);
|
|
3075
|
+
found = true;
|
|
3076
|
+
}
|
|
3077
|
+
} catch {
|
|
3409
3078
|
}
|
|
3410
|
-
initialType = options.type;
|
|
3411
3079
|
}
|
|
3412
|
-
if (
|
|
3413
|
-
|
|
3414
|
-
|
|
3080
|
+
if (!found) {
|
|
3081
|
+
console.log(chalk6.yellow(" \u26A0\uFE0F No IDEs detected in this project."));
|
|
3082
|
+
console.log(chalk6.dim(` Run "${name} apply" to install context for your IDE.
|
|
3083
|
+
`));
|
|
3415
3084
|
}
|
|
3416
|
-
const { waitUntilExit } = render3(
|
|
3417
|
-
React12.createElement(ContextApp, {
|
|
3418
|
-
initialIDE,
|
|
3419
|
-
initialType,
|
|
3420
|
-
onExit: () => {
|
|
3421
|
-
process.exit(0);
|
|
3422
|
-
}
|
|
3423
|
-
})
|
|
3424
|
-
);
|
|
3425
|
-
await waitUntilExit();
|
|
3426
3085
|
});
|
|
3427
3086
|
return cmd;
|
|
3428
3087
|
}
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
const context = await scanner.scanAll();
|
|
3434
|
-
if (context.ides.length === 0) {
|
|
3435
|
-
console.log("\u26A0\uFE0F No context found");
|
|
3436
|
-
console.log(" Run `jai1 apply` to install context for your IDE.\n");
|
|
3437
|
-
return;
|
|
3438
|
-
}
|
|
3439
|
-
console.log("\u{1F4CA} Context Statistics\n");
|
|
3440
|
-
console.log(`\u{1F4C1} Project: ${context.projectPath}`);
|
|
3441
|
-
console.log(`\u{1F550} Scan time: ${context.scanTime.toLocaleString("en-US")}
|
|
3442
|
-
`);
|
|
3443
|
-
for (const ideContext of context.ides) {
|
|
3444
|
-
console.log(`${ideContext.config.icon} ${ideContext.config.name}`);
|
|
3445
|
-
console.log(` Path: ${ideContext.config.basePath}`);
|
|
3446
|
-
console.log(` Items: ${ideContext.stats.totalItems}`);
|
|
3447
|
-
const types = [];
|
|
3448
|
-
if (ideContext.stats.byType.rules) types.push(`${ideContext.stats.byType.rules} rules`);
|
|
3449
|
-
if (ideContext.stats.byType.workflows) types.push(`${ideContext.stats.byType.workflows} workflows`);
|
|
3450
|
-
if (ideContext.stats.byType.skills) types.push(`${ideContext.stats.byType.skills} skills`);
|
|
3451
|
-
if (ideContext.stats.byType.agents) types.push(`${ideContext.stats.byType.agents} agents`);
|
|
3452
|
-
if (ideContext.stats.byType.prompts) types.push(`${ideContext.stats.byType.prompts} prompts`);
|
|
3453
|
-
if (ideContext.stats.byType.context) types.push(`${ideContext.stats.byType.context} context`);
|
|
3454
|
-
if (types.length > 0) {
|
|
3455
|
-
console.log(` Breakdown: ${types.join(", ")}`);
|
|
3456
|
-
}
|
|
3457
|
-
console.log("");
|
|
3458
|
-
}
|
|
3459
|
-
console.log(`\u2705 Total: ${context.totalItems} items
|
|
3460
|
-
`);
|
|
3461
|
-
} catch (error) {
|
|
3462
|
-
console.error("\u274C Error scanning context:", error);
|
|
3463
|
-
process.exit(1);
|
|
3464
|
-
}
|
|
3088
|
+
|
|
3089
|
+
// src/commands/ide/context.ts
|
|
3090
|
+
function createContextSubcommand() {
|
|
3091
|
+
return createContextCommand();
|
|
3465
3092
|
}
|
|
3466
3093
|
|
|
3467
3094
|
// src/commands/ide/setup.ts
|
|
@@ -4342,24 +3969,24 @@ function getConfidenceEmoji(confidence) {
|
|
|
4342
3969
|
|
|
4343
3970
|
// src/commands/ide/index.ts
|
|
4344
3971
|
function showIdeHelp() {
|
|
4345
|
-
console.log(
|
|
3972
|
+
console.log(chalk7.bold.cyan("\u{1F5A5}\uFE0F jai1 ide") + chalk7.dim(" - IDE integration v\xE0 c\u1EA5u h\xECnh"));
|
|
4346
3973
|
console.log();
|
|
4347
|
-
console.log(
|
|
4348
|
-
console.log(` ${
|
|
4349
|
-
console.log(` ${
|
|
4350
|
-
console.log(` ${
|
|
4351
|
-
console.log(` ${
|
|
3974
|
+
console.log(chalk7.bold("C\xE1c l\u1EC7nh:"));
|
|
3975
|
+
console.log(` ${chalk7.cyan("context")} Duy\u1EC7t v\xE0 kh\xE1m ph\xE1 IDE context`);
|
|
3976
|
+
console.log(` ${chalk7.cyan("setup")} C\u1EA5u h\xECnh IDE settings (VSCode optimizations)`);
|
|
3977
|
+
console.log(` ${chalk7.cyan("sync")} \u0110\u1ED3ng b\u1ED9 .jai1 content \u0111\u1EBFn IDE directories`);
|
|
3978
|
+
console.log(` ${chalk7.cyan("status")} Hi\u1EC3n th\u1ECB c\xE1c IDE \u0111\u01B0\u1EE3c ph\xE1t hi\u1EC7n v\xE0 tr\u1EA1ng th\xE1i`);
|
|
4352
3979
|
console.log();
|
|
4353
|
-
console.log(
|
|
4354
|
-
console.log(
|
|
3980
|
+
console.log(chalk7.bold("IDEs \u0111\u01B0\u1EE3c h\u1ED7 tr\u1EE3:"));
|
|
3981
|
+
console.log(chalk7.dim(" Cursor, Windsurf, VSCode, Trae, Claude"));
|
|
4355
3982
|
console.log();
|
|
4356
|
-
console.log(
|
|
4357
|
-
console.log(
|
|
4358
|
-
console.log(
|
|
4359
|
-
console.log(
|
|
4360
|
-
console.log(
|
|
3983
|
+
console.log(chalk7.bold("V\xED d\u1EE5:"));
|
|
3984
|
+
console.log(chalk7.dim(" $ jai1 ide status"));
|
|
3985
|
+
console.log(chalk7.dim(" $ jai1 ide setup --optimize"));
|
|
3986
|
+
console.log(chalk7.dim(" $ jai1 ide sync"));
|
|
3987
|
+
console.log(chalk7.dim(" $ jai1 ide context"));
|
|
4361
3988
|
console.log();
|
|
4362
|
-
console.log(
|
|
3989
|
+
console.log(chalk7.dim('Ch\u1EA1y "jai1 ide <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt'));
|
|
4363
3990
|
}
|
|
4364
3991
|
function createIdeCommand() {
|
|
4365
3992
|
const ideCommand = new Command11("ide").description("IDE integration and configuration commands").action(() => {
|
|
@@ -4374,7 +4001,7 @@ function createIdeCommand() {
|
|
|
4374
4001
|
|
|
4375
4002
|
// src/commands/guide.ts
|
|
4376
4003
|
import { Command as Command12 } from "commander";
|
|
4377
|
-
import
|
|
4004
|
+
import chalk8 from "chalk";
|
|
4378
4005
|
function createGuideCommand() {
|
|
4379
4006
|
const cmd = new Command12("guide").description("H\u01B0\u1EDBng d\u1EABn s\u1EED d\u1EE5ng nhanh").action(() => {
|
|
4380
4007
|
const name = getCliName();
|
|
@@ -4383,66 +4010,66 @@ function createGuideCommand() {
|
|
|
4383
4010
|
return cmd;
|
|
4384
4011
|
}
|
|
4385
4012
|
function showGuide(name) {
|
|
4386
|
-
console.log(
|
|
4387
|
-
console.log(
|
|
4388
|
-
console.log(` ${
|
|
4389
|
-
console.log(` ${
|
|
4390
|
-
console.log(` ${
|
|
4013
|
+
console.log(chalk8.cyan.bold("\n\u{1F4D6} Jai1 Framework - H\u01B0\u1EDBng d\u1EABn s\u1EED d\u1EE5ng nhanh\n"));
|
|
4014
|
+
console.log(chalk8.bold("\u2501\u2501\u2501 THI\u1EBET L\u1EACP \u2501\u2501\u2501"));
|
|
4015
|
+
console.log(` ${chalk8.cyan(`${name} auth`)} X\xE1c th\u1EF1c v\xE0 c\u1EA5u h\xECnh client`);
|
|
4016
|
+
console.log(` ${chalk8.cyan(`${name} status`)} Hi\u1EC3n th\u1ECB tr\u1EA1ng th\xE1i c\u1EA5u h\xECnh`);
|
|
4017
|
+
console.log(` ${chalk8.cyan(`${name} doctor`)} Chu\u1EA9n \u0111o\xE1n project hi\u1EC7n t\u1EA1i`);
|
|
4391
4018
|
console.log();
|
|
4392
|
-
console.log(
|
|
4393
|
-
console.log(` ${
|
|
4394
|
-
console.log(` ${
|
|
4395
|
-
console.log(` ${
|
|
4396
|
-
console.log(` ${
|
|
4397
|
-
console.log(` ${
|
|
4019
|
+
console.log(chalk8.bold("\u2501\u2501\u2501 CORE PACKAGE \u2501\u2501\u2501"));
|
|
4020
|
+
console.log(` ${chalk8.cyan(`${name} apply`)} C\xE0i \u0111\u1EB7t components (interactive)`);
|
|
4021
|
+
console.log(` ${chalk8.cyan(`${name} apply core`)} C\xE0i core package (headless)`);
|
|
4022
|
+
console.log(` ${chalk8.cyan(`${name} check`)} Ki\u1EC3m tra c\u1EADp nh\u1EADt t\u1EEB server`);
|
|
4023
|
+
console.log(` ${chalk8.cyan(`${name} update`)} C\u1EADp nh\u1EADt components \u0111\xE3 c\xE0i`);
|
|
4024
|
+
console.log(` ${chalk8.cyan(`${name} upgrade`)} C\u1EADp nh\u1EADt CLI client`);
|
|
4398
4025
|
console.log();
|
|
4399
|
-
console.log(
|
|
4400
|
-
console.log(
|
|
4401
|
-
console.log(
|
|
4402
|
-
console.log(
|
|
4403
|
-
console.log(
|
|
4404
|
-
console.log(
|
|
4026
|
+
console.log(chalk8.dim(" Workflow ph\u1ED5 bi\u1EBFn:"));
|
|
4027
|
+
console.log(chalk8.dim(` 1. ${name} auth # \u0110\u0103ng nh\u1EADp l\u1EA7n \u0111\u1EA7u`));
|
|
4028
|
+
console.log(chalk8.dim(` 2. ${name} apply core # C\xE0i core package`));
|
|
4029
|
+
console.log(chalk8.dim(` 3. ${name} rules apply # C\u1EA5u h\xECnh rules cho IDE`));
|
|
4030
|
+
console.log(chalk8.dim(` 4. ${name} ide sync # \u0110\u1ED3ng b\u1ED9 sang IDE`));
|
|
4031
|
+
console.log(chalk8.dim(` 5. ${name} check # Ki\u1EC3m tra c\u1EADp nh\u1EADt \u0111\u1ECBnh k\u1EF3`));
|
|
4405
4032
|
console.log();
|
|
4406
|
-
console.log(
|
|
4407
|
-
console.log(` ${
|
|
4408
|
-
console.log(` ${
|
|
4409
|
-
console.log(` ${
|
|
4410
|
-
console.log(` ${
|
|
4033
|
+
console.log(chalk8.bold("\u2501\u2501\u2501 IDE \u2501\u2501\u2501"));
|
|
4034
|
+
console.log(` ${chalk8.cyan(`${name} ide status`)} C\xE1c IDE \u0111\u01B0\u1EE3c ph\xE1t hi\u1EC7n`);
|
|
4035
|
+
console.log(` ${chalk8.cyan(`${name} ide setup`)} C\u1EA5u h\xECnh IDE (VSCode optimizations)`);
|
|
4036
|
+
console.log(` ${chalk8.cyan(`${name} ide sync`)} \u0110\u1ED3ng b\u1ED9 .jai1 content \u0111\u1EBFn IDE`);
|
|
4037
|
+
console.log(` ${chalk8.cyan(`${name} rules apply`)} C\u1EA5u h\xECnh rules cho IDE`);
|
|
4411
4038
|
console.log();
|
|
4412
|
-
console.log(
|
|
4413
|
-
console.log(` ${
|
|
4414
|
-
console.log(` ${
|
|
4415
|
-
console.log(` ${
|
|
4416
|
-
console.log(` ${
|
|
4417
|
-
console.log(` ${
|
|
4418
|
-
console.log(` ${
|
|
4419
|
-
console.log(` ${
|
|
4039
|
+
console.log(chalk8.bold("\u2501\u2501\u2501 TASK MANAGEMENT \u2501\u2501\u2501"));
|
|
4040
|
+
console.log(` ${chalk8.cyan(`${name} t add`)} ${chalk8.dim('"title"')} ${chalk8.dim("[-p 0-3] [-P parent]")} T\u1EA1o task`);
|
|
4041
|
+
console.log(` ${chalk8.cyan(`${name} t list`)} ${chalk8.dim("[-s status] [-P parent]")} Li\u1EC7t k\xEA tasks`);
|
|
4042
|
+
console.log(` ${chalk8.cyan(`${name} t ready`)} Tasks s\u1EB5n s\xE0ng`);
|
|
4043
|
+
console.log(` ${chalk8.cyan(`${name} t pick`)} Claim & b\u1EAFt \u0111\u1EA7u`);
|
|
4044
|
+
console.log(` ${chalk8.cyan(`${name} t done`)} ${chalk8.dim("<id>")} Ho\xE0n th\xE0nh task`);
|
|
4045
|
+
console.log(` ${chalk8.cyan(`${name} t summary`)} Dashboard t\u1ED5ng quan`);
|
|
4046
|
+
console.log(` ${chalk8.cyan(`${name} t guide`)} H\u01B0\u1EDBng d\u1EABn chi ti\u1EBFt`);
|
|
4420
4047
|
console.log();
|
|
4421
|
-
console.log(
|
|
4422
|
-
console.log(` ${
|
|
4423
|
-
console.log(` ${
|
|
4424
|
-
console.log(` ${
|
|
4425
|
-
console.log(` ${
|
|
4426
|
-
console.log(` ${
|
|
4048
|
+
console.log(chalk8.bold("\u2501\u2501\u2501 WORKFLOWS (d\xF9ng trong IDE) \u2501\u2501\u2501"));
|
|
4049
|
+
console.log(` ${chalk8.cyan("/improve")} ${chalk8.dim("[feature]")} Ph\xE2n t\xEDch & \u0111\u1EC1 xu\u1EA5t c\u1EA3i thi\u1EC7n project`);
|
|
4050
|
+
console.log(` ${chalk8.cyan("/plan")} ${chalk8.dim("[task]")} L\xEAn k\u1EBF ho\u1EA1ch nhanh \u2192 tasks \u2192 implement`);
|
|
4051
|
+
console.log(` ${chalk8.cyan("/develop-feature")} ${chalk8.dim("[feature]")} Ph\xE1t tri\u1EC3n t\xEDnh n\u0103ng (FRD \u2192 TDD \u2192 Code)`);
|
|
4052
|
+
console.log(` ${chalk8.cyan("/fix-bug")} ${chalk8.dim("[bug]")} Ph\xE2n t\xEDch & s\u1EEDa bug`);
|
|
4053
|
+
console.log(` ${chalk8.cyan("/commit-it")} Commit an to\xE0n v\u1EDBi message chi ti\u1EBFt`);
|
|
4427
4054
|
console.log();
|
|
4428
|
-
console.log(
|
|
4429
|
-
console.log(
|
|
4430
|
-
console.log(
|
|
4431
|
-
console.log(
|
|
4055
|
+
console.log(chalk8.dim(" Workflow c\u1EA3i thi\u1EC7n project:"));
|
|
4056
|
+
console.log(chalk8.dim(" 1. /improve # Ph\xE2n t\xEDch & \u0111\u1EC1 xu\u1EA5t"));
|
|
4057
|
+
console.log(chalk8.dim(" 2. Ch\u1ECDn improvements c\u1EA7n l\xE0m # User x\xE1c nh\u1EADn"));
|
|
4058
|
+
console.log(chalk8.dim(" 3. \u2192 T\u1EF1 \u0111\u1ED9ng g\u1ECDi /plan # T\u1EA1o tasks & implement"));
|
|
4432
4059
|
console.log();
|
|
4433
|
-
console.log(
|
|
4434
|
-
console.log(` ${
|
|
4435
|
-
console.log(` ${
|
|
4436
|
-
console.log(` ${
|
|
4060
|
+
console.log(chalk8.bold("\u2501\u2501\u2501 AI TOOLS \u2501\u2501\u2501"));
|
|
4061
|
+
console.log(` ${chalk8.cyan(`${name} chat`)} Chat AI qua Jai1 LLM Proxy`);
|
|
4062
|
+
console.log(` ${chalk8.cyan(`${name} translate`)} D\u1ECBch v\u0103n b\u1EA3n/file b\u1EB1ng AI`);
|
|
4063
|
+
console.log(` ${chalk8.cyan(`${name} image`)} T\u1EA1o \u1EA3nh b\u1EB1ng AI`);
|
|
4437
4064
|
console.log();
|
|
4438
|
-
console.log(
|
|
4439
|
-
console.log(
|
|
4065
|
+
console.log(chalk8.dim(`\u{1F4A1} Ch\u1EA1y "${name} <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt t\u1EEBng l\u1EC7nh.`));
|
|
4066
|
+
console.log(chalk8.dim(`\u{1F4A1} Ch\u1EA1y "${name} t guide" \u0111\u1EC3 xem h\u01B0\u1EDBng d\u1EABn task management \u0111\u1EA7y \u0111\u1EE7.`));
|
|
4440
4067
|
console.log();
|
|
4441
4068
|
}
|
|
4442
4069
|
|
|
4443
4070
|
// src/commands/doctor.ts
|
|
4444
4071
|
import { Command as Command13 } from "commander";
|
|
4445
|
-
import
|
|
4072
|
+
import chalk9 from "chalk";
|
|
4446
4073
|
import { promises as fs9 } from "fs";
|
|
4447
4074
|
import { join as join6 } from "path";
|
|
4448
4075
|
var CORE_FILES = [
|
|
@@ -4470,8 +4097,8 @@ async function runDoctor(options) {
|
|
|
4470
4097
|
const name = getCliName();
|
|
4471
4098
|
const results = [];
|
|
4472
4099
|
if (!options.json) {
|
|
4473
|
-
console.log(
|
|
4474
|
-
console.log(
|
|
4100
|
+
console.log(chalk9.cyan.bold("\n\u{1FA7A} Jai1 Doctor\n"));
|
|
4101
|
+
console.log(chalk9.dim(` \u0110ang ki\u1EC3m tra project t\u1EA1i: ${process.cwd()}
|
|
4475
4102
|
`));
|
|
4476
4103
|
}
|
|
4477
4104
|
results.push(await checkAuth(name));
|
|
@@ -4484,27 +4111,27 @@ async function runDoctor(options) {
|
|
|
4484
4111
|
return;
|
|
4485
4112
|
}
|
|
4486
4113
|
for (const result of results) {
|
|
4487
|
-
const icon = result.passed ?
|
|
4488
|
-
const label = result.passed ?
|
|
4489
|
-
console.log(` ${icon} ${
|
|
4114
|
+
const icon = result.passed ? chalk9.green("\u2713") : chalk9.red("\u2717");
|
|
4115
|
+
const label = result.passed ? chalk9.green(result.message) : chalk9.red(result.message);
|
|
4116
|
+
console.log(` ${icon} ${chalk9.bold(result.name)}: ${label}`);
|
|
4490
4117
|
if (result.details && result.details.length > 0) {
|
|
4491
4118
|
for (const detail of result.details) {
|
|
4492
|
-
console.log(
|
|
4119
|
+
console.log(chalk9.dim(` ${detail}`));
|
|
4493
4120
|
}
|
|
4494
4121
|
}
|
|
4495
4122
|
if (!result.passed && result.suggestion) {
|
|
4496
|
-
console.log(
|
|
4123
|
+
console.log(chalk9.yellow(` \u{1F4A1} ${result.suggestion}`));
|
|
4497
4124
|
}
|
|
4498
4125
|
console.log();
|
|
4499
4126
|
}
|
|
4500
4127
|
const passed = results.filter((r) => r.passed).length;
|
|
4501
4128
|
const total = results.length;
|
|
4502
4129
|
if (passed === total) {
|
|
4503
|
-
console.log(
|
|
4130
|
+
console.log(chalk9.green.bold(` \u2705 T\u1EA5t c\u1EA3 ${total} ki\u1EC3m tra \u0111\xE3 pass!
|
|
4504
4131
|
`));
|
|
4505
4132
|
} else {
|
|
4506
4133
|
console.log(
|
|
4507
|
-
|
|
4134
|
+
chalk9.yellow(` \u26A0\uFE0F ${passed}/${total} ki\u1EC3m tra pass. Xem g\u1EE3i \xFD \u1EDF tr\xEAn \u0111\u1EC3 s\u1EEDa.
|
|
4508
4135
|
`)
|
|
4509
4136
|
);
|
|
4510
4137
|
}
|
|
@@ -4656,8 +4283,8 @@ async function checkIde(cliName) {
|
|
|
4656
4283
|
|
|
4657
4284
|
// src/commands/chat.ts
|
|
4658
4285
|
import { Command as Command14 } from "commander";
|
|
4659
|
-
import
|
|
4660
|
-
import { render as
|
|
4286
|
+
import React12 from "react";
|
|
4287
|
+
import { render as render3 } from "ink";
|
|
4661
4288
|
|
|
4662
4289
|
// src/services/llm-proxy.service.ts
|
|
4663
4290
|
var LlmProxyService = class {
|
|
@@ -4884,16 +4511,16 @@ var LlmProxyService = class {
|
|
|
4884
4511
|
};
|
|
4885
4512
|
|
|
4886
4513
|
// src/ui/llm/LlmApp.tsx
|
|
4887
|
-
import
|
|
4888
|
-
import { Box as
|
|
4514
|
+
import React11, { useState as useState6, useEffect as useEffect4, useMemo as useMemo3, useCallback as useCallback3, useRef as useRef2 } from "react";
|
|
4515
|
+
import { Box as Box8, Text as Text9, useInput as useInput4, useApp as useApp3, useStdout } from "ink";
|
|
4889
4516
|
import Spinner4 from "ink-spinner";
|
|
4890
4517
|
|
|
4891
4518
|
// src/ui/llm/hooks/useChat.ts
|
|
4892
|
-
import { useState as
|
|
4519
|
+
import { useState as useState3, useCallback } from "react";
|
|
4893
4520
|
function useChat(service) {
|
|
4894
|
-
const [messages, setMessages] =
|
|
4895
|
-
const [isStreaming, setIsStreaming] =
|
|
4896
|
-
const [error, setError] =
|
|
4521
|
+
const [messages, setMessages] = useState3([]);
|
|
4522
|
+
const [isStreaming, setIsStreaming] = useState3(false);
|
|
4523
|
+
const [error, setError] = useState3(null);
|
|
4897
4524
|
const sendMessage = useCallback(
|
|
4898
4525
|
async (content, model) => {
|
|
4899
4526
|
if (!content.trim() || isStreaming) return;
|
|
@@ -4962,9 +4589,9 @@ function useChat(service) {
|
|
|
4962
4589
|
}
|
|
4963
4590
|
|
|
4964
4591
|
// src/ui/llm/hooks/useLlmApi.ts
|
|
4965
|
-
import { useState as
|
|
4592
|
+
import { useState as useState4, useEffect as useEffect3, useCallback as useCallback2, useRef } from "react";
|
|
4966
4593
|
function useLlmApi(service) {
|
|
4967
|
-
const [state, setState] =
|
|
4594
|
+
const [state, setState] = useState4({
|
|
4968
4595
|
models: [],
|
|
4969
4596
|
limits: null,
|
|
4970
4597
|
usage: null,
|
|
@@ -4997,7 +4624,7 @@ function useLlmApi(service) {
|
|
|
4997
4624
|
}));
|
|
4998
4625
|
}
|
|
4999
4626
|
}, [service]);
|
|
5000
|
-
|
|
4627
|
+
useEffect3(() => {
|
|
5001
4628
|
if (!hasFetched.current) {
|
|
5002
4629
|
hasFetched.current = true;
|
|
5003
4630
|
fetchData(true);
|
|
@@ -5013,26 +4640,26 @@ function useLlmApi(service) {
|
|
|
5013
4640
|
}
|
|
5014
4641
|
|
|
5015
4642
|
// src/ui/llm/components/ChatPanel.tsx
|
|
5016
|
-
import
|
|
5017
|
-
import { Box as
|
|
4643
|
+
import React9, { memo as memo3 } from "react";
|
|
4644
|
+
import { Box as Box6, Text as Text7 } from "ink";
|
|
5018
4645
|
import Spinner3 from "ink-spinner";
|
|
5019
4646
|
|
|
5020
4647
|
// src/ui/llm/components/MessageItem.tsx
|
|
5021
|
-
import
|
|
5022
|
-
import { Box as
|
|
4648
|
+
import React7, { memo } from "react";
|
|
4649
|
+
import { Box as Box4, Text as Text5 } from "ink";
|
|
5023
4650
|
var MessageItem = memo(({ message }) => {
|
|
5024
4651
|
if (message.role === "user") {
|
|
5025
|
-
return /* @__PURE__ */
|
|
4652
|
+
return /* @__PURE__ */ React7.createElement(Box4, { flexDirection: "column", marginBottom: 1 }, /* @__PURE__ */ React7.createElement(Text5, { color: "cyan", bold: true }, "You:"), /* @__PURE__ */ React7.createElement(Text5, { wrap: "wrap" }, message.content));
|
|
5026
4653
|
}
|
|
5027
4654
|
if (message.role === "assistant") {
|
|
5028
|
-
return /* @__PURE__ */
|
|
4655
|
+
return /* @__PURE__ */ React7.createElement(Box4, { flexDirection: "column", marginBottom: 1 }, /* @__PURE__ */ React7.createElement(Text5, { color: "green", bold: true }, "Jai1:"), /* @__PURE__ */ React7.createElement(Text5, { wrap: "wrap" }, message.content));
|
|
5029
4656
|
}
|
|
5030
|
-
return /* @__PURE__ */
|
|
4657
|
+
return /* @__PURE__ */ React7.createElement(Box4, { marginBottom: 1 }, /* @__PURE__ */ React7.createElement(Text5, { dimColor: true, italic: true }, message.content));
|
|
5031
4658
|
});
|
|
5032
4659
|
|
|
5033
4660
|
// src/ui/llm/components/InputBox.tsx
|
|
5034
|
-
import
|
|
5035
|
-
import { Box as
|
|
4661
|
+
import React8, { memo as memo2 } from "react";
|
|
4662
|
+
import { Box as Box5, Text as Text6 } from "ink";
|
|
5036
4663
|
import TextInput3 from "ink-text-input";
|
|
5037
4664
|
var InputBox = memo2(({
|
|
5038
4665
|
value,
|
|
@@ -5040,7 +4667,7 @@ var InputBox = memo2(({
|
|
|
5040
4667
|
onSubmit,
|
|
5041
4668
|
disabled = false,
|
|
5042
4669
|
focused = true
|
|
5043
|
-
}) => /* @__PURE__ */
|
|
4670
|
+
}) => /* @__PURE__ */ React8.createElement(Box5, { borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React8.createElement(Text6, { color: "cyan" }, "\u276F "), !disabled ? /* @__PURE__ */ React8.createElement(
|
|
5044
4671
|
TextInput3,
|
|
5045
4672
|
{
|
|
5046
4673
|
value,
|
|
@@ -5049,19 +4676,19 @@ var InputBox = memo2(({
|
|
|
5049
4676
|
placeholder: "Type your message...",
|
|
5050
4677
|
focus: focused
|
|
5051
4678
|
}
|
|
5052
|
-
) : /* @__PURE__ */
|
|
4679
|
+
) : /* @__PURE__ */ React8.createElement(Text6, { dimColor: true }, "Waiting...")));
|
|
5053
4680
|
|
|
5054
4681
|
// src/ui/llm/components/ChatPanel.tsx
|
|
5055
4682
|
var MessageList = memo3(({ messages }) => {
|
|
5056
4683
|
const visible = messages.slice(-8);
|
|
5057
4684
|
const hidden = messages.length - visible.length;
|
|
5058
4685
|
if (visible.length === 0) {
|
|
5059
|
-
return /* @__PURE__ */
|
|
4686
|
+
return /* @__PURE__ */ React9.createElement(Box6, { flexDirection: "column", alignItems: "center", padding: 1 }, /* @__PURE__ */ React9.createElement(Text7, { dimColor: true }, "Start a conversation..."), /* @__PURE__ */ React9.createElement(Text7, { dimColor: true }, "Type / for commands"));
|
|
5060
4687
|
}
|
|
5061
|
-
return /* @__PURE__ */
|
|
4688
|
+
return /* @__PURE__ */ React9.createElement(React9.Fragment, null, hidden > 0 && /* @__PURE__ */ React9.createElement(Text7, { dimColor: true }, "(", hidden, " earlier)"), visible.map((m) => /* @__PURE__ */ React9.createElement(MessageItem, { key: m.id, message: m })));
|
|
5062
4689
|
});
|
|
5063
|
-
var SlashMenu = memo3(({ commands, index }) => /* @__PURE__ */
|
|
5064
|
-
|
|
4690
|
+
var SlashMenu = memo3(({ commands, index }) => /* @__PURE__ */ React9.createElement(Box6, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React9.createElement(Text7, { bold: true, color: "cyan" }, "Commands"), commands.map((cmd, i) => /* @__PURE__ */ React9.createElement(
|
|
4691
|
+
Text7,
|
|
5065
4692
|
{
|
|
5066
4693
|
key: cmd.name,
|
|
5067
4694
|
backgroundColor: i === index ? "cyan" : void 0,
|
|
@@ -5086,7 +4713,7 @@ var ChatPanel = ({
|
|
|
5086
4713
|
minHeight = 15
|
|
5087
4714
|
}) => {
|
|
5088
4715
|
const messagesMinHeight = Math.max(5, minHeight - 4 - (showSlashMenu ? 5 : 0));
|
|
5089
|
-
return /* @__PURE__ */
|
|
4716
|
+
return /* @__PURE__ */ React9.createElement(Box6, { flexDirection: "column" }, /* @__PURE__ */ React9.createElement(Box6, { flexDirection: "column", borderStyle: "round", borderColor: "gray", padding: 1, minHeight: messagesMinHeight }, /* @__PURE__ */ React9.createElement(MessageList, { messages }), isStreaming && /* @__PURE__ */ React9.createElement(Text7, { color: "green" }, /* @__PURE__ */ React9.createElement(Spinner3, { type: "dots" }), " Responding...")), showSlashMenu && slashCommands.length > 0 && /* @__PURE__ */ React9.createElement(SlashMenu, { commands: slashCommands, index: slashMenuIndex }), /* @__PURE__ */ React9.createElement(
|
|
5090
4717
|
InputBox,
|
|
5091
4718
|
{
|
|
5092
4719
|
value: inputValue,
|
|
@@ -5099,8 +4726,8 @@ var ChatPanel = ({
|
|
|
5099
4726
|
};
|
|
5100
4727
|
|
|
5101
4728
|
// src/ui/llm/components/ModelSelector.tsx
|
|
5102
|
-
import
|
|
5103
|
-
import { Box as
|
|
4729
|
+
import React10, { useState as useState5 } from "react";
|
|
4730
|
+
import { Box as Box7, Text as Text8, useInput as useInput3 } from "ink";
|
|
5104
4731
|
var ModelSelector = ({
|
|
5105
4732
|
models,
|
|
5106
4733
|
currentModel,
|
|
@@ -5109,8 +4736,8 @@ var ModelSelector = ({
|
|
|
5109
4736
|
}) => {
|
|
5110
4737
|
const allowedModels = models.filter((m) => m.allowed);
|
|
5111
4738
|
const currentIndex = allowedModels.findIndex((m) => m.id === currentModel);
|
|
5112
|
-
const [selectedIndex, setSelectedIndex] =
|
|
5113
|
-
|
|
4739
|
+
const [selectedIndex, setSelectedIndex] = useState5(Math.max(0, currentIndex));
|
|
4740
|
+
useInput3((input5, key) => {
|
|
5114
4741
|
if (key.escape) {
|
|
5115
4742
|
onCancel();
|
|
5116
4743
|
return;
|
|
@@ -5127,8 +4754,8 @@ var ModelSelector = ({
|
|
|
5127
4754
|
}
|
|
5128
4755
|
});
|
|
5129
4756
|
if (allowedModels.length === 0) {
|
|
5130
|
-
return /* @__PURE__ */
|
|
5131
|
-
|
|
4757
|
+
return /* @__PURE__ */ React10.createElement(
|
|
4758
|
+
Box7,
|
|
5132
4759
|
{
|
|
5133
4760
|
flexDirection: "column",
|
|
5134
4761
|
borderStyle: "round",
|
|
@@ -5136,12 +4763,12 @@ var ModelSelector = ({
|
|
|
5136
4763
|
padding: 1,
|
|
5137
4764
|
width: 60
|
|
5138
4765
|
},
|
|
5139
|
-
/* @__PURE__ */
|
|
5140
|
-
/* @__PURE__ */
|
|
4766
|
+
/* @__PURE__ */ React10.createElement(Text8, { color: "red", bold: true }, "No models available"),
|
|
4767
|
+
/* @__PURE__ */ React10.createElement(Text8, { dimColor: true }, "Press Esc to close")
|
|
5141
4768
|
);
|
|
5142
4769
|
}
|
|
5143
|
-
return /* @__PURE__ */
|
|
5144
|
-
|
|
4770
|
+
return /* @__PURE__ */ React10.createElement(
|
|
4771
|
+
Box7,
|
|
5145
4772
|
{
|
|
5146
4773
|
flexDirection: "column",
|
|
5147
4774
|
borderStyle: "round",
|
|
@@ -5149,8 +4776,8 @@ var ModelSelector = ({
|
|
|
5149
4776
|
padding: 1,
|
|
5150
4777
|
width: 70
|
|
5151
4778
|
},
|
|
5152
|
-
/* @__PURE__ */
|
|
5153
|
-
/* @__PURE__ */
|
|
4779
|
+
/* @__PURE__ */ React10.createElement(Box7, { marginBottom: 1 }, /* @__PURE__ */ React10.createElement(Text8, { bold: true, color: "cyan" }, "\u2699\uFE0F Select Model")),
|
|
4780
|
+
/* @__PURE__ */ React10.createElement(Box7, { flexDirection: "column", marginBottom: 1 }, allowedModels.map((model, i) => {
|
|
5154
4781
|
const isSelected = i === selectedIndex;
|
|
5155
4782
|
const isCurrent = model.id === currentModel;
|
|
5156
4783
|
const icon = isSelected ? "\u25CF" : "\u25CB";
|
|
@@ -5158,8 +4785,8 @@ var ModelSelector = ({
|
|
|
5158
4785
|
if (model.dailyLimit !== void 0 && model.usedToday !== void 0) {
|
|
5159
4786
|
usageText = ` (${model.usedToday}/${model.dailyLimit})`;
|
|
5160
4787
|
}
|
|
5161
|
-
return /* @__PURE__ */
|
|
5162
|
-
|
|
4788
|
+
return /* @__PURE__ */ React10.createElement(Box7, { key: model.id, marginY: 0 }, /* @__PURE__ */ React10.createElement(
|
|
4789
|
+
Text8,
|
|
5163
4790
|
{
|
|
5164
4791
|
backgroundColor: isSelected ? "cyan" : void 0,
|
|
5165
4792
|
color: isSelected ? "black" : "white"
|
|
@@ -5172,7 +4799,7 @@ var ModelSelector = ({
|
|
|
5172
4799
|
usageText
|
|
5173
4800
|
));
|
|
5174
4801
|
})),
|
|
5175
|
-
/* @__PURE__ */
|
|
4802
|
+
/* @__PURE__ */ React10.createElement(Box7, { borderStyle: "single", borderColor: "gray", paddingX: 1 }, /* @__PURE__ */ React10.createElement(Text8, { dimColor: true }, "[\u2191\u2193] Navigate [Enter] Select [Esc] Cancel"))
|
|
5176
4803
|
);
|
|
5177
4804
|
};
|
|
5178
4805
|
|
|
@@ -5183,17 +4810,17 @@ var SLASH_COMMANDS = [
|
|
|
5183
4810
|
{ name: "quit", description: "Exit the chat", aliases: ["q", "exit"] }
|
|
5184
4811
|
];
|
|
5185
4812
|
var ChatApp = ({ service, initialModel }) => {
|
|
5186
|
-
const { exit } =
|
|
4813
|
+
const { exit } = useApp3();
|
|
5187
4814
|
const { stdout } = useStdout();
|
|
5188
4815
|
const contentHeight = useRef2(Math.max(10, (stdout?.rows || 24) - 6));
|
|
5189
|
-
const [currentView, setCurrentView] =
|
|
5190
|
-
const [showSlashMenu, setShowSlashMenu] =
|
|
5191
|
-
const [slashMenuIndex, setSlashMenuIndex] =
|
|
5192
|
-
const [inputValue, setInputValue] =
|
|
5193
|
-
const [selectedModel, setSelectedModel] =
|
|
4816
|
+
const [currentView, setCurrentView] = useState6("loading");
|
|
4817
|
+
const [showSlashMenu, setShowSlashMenu] = useState6(false);
|
|
4818
|
+
const [slashMenuIndex, setSlashMenuIndex] = useState6(0);
|
|
4819
|
+
const [inputValue, setInputValue] = useState6("");
|
|
4820
|
+
const [selectedModel, setSelectedModel] = useState6("");
|
|
5194
4821
|
const { models, loading, error, refetch } = useLlmApi(service);
|
|
5195
4822
|
const { messages, isStreaming, sendMessage } = useChat(service);
|
|
5196
|
-
|
|
4823
|
+
useEffect4(() => {
|
|
5197
4824
|
if (error && !loading) {
|
|
5198
4825
|
setCurrentView("error");
|
|
5199
4826
|
return;
|
|
@@ -5236,7 +4863,7 @@ var ChatApp = ({ service, initialModel }) => {
|
|
|
5236
4863
|
}
|
|
5237
4864
|
return false;
|
|
5238
4865
|
}, [refetch, exit]);
|
|
5239
|
-
|
|
4866
|
+
useInput4((input5, key) => {
|
|
5240
4867
|
if (showSlashMenu) {
|
|
5241
4868
|
if (key.upArrow) {
|
|
5242
4869
|
setSlashMenuIndex((i) => Math.max(0, i - 1));
|
|
@@ -5297,16 +4924,16 @@ var ChatApp = ({ service, initialModel }) => {
|
|
|
5297
4924
|
}, []);
|
|
5298
4925
|
const statsView = useMemo3(() => {
|
|
5299
4926
|
const allowed = models.filter((m) => m.allowed);
|
|
5300
|
-
return /* @__PURE__ */
|
|
4927
|
+
return /* @__PURE__ */ React11.createElement(Box8, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", padding: 1 }, /* @__PURE__ */ React11.createElement(Text9, { bold: true, color: "cyan" }, "\u{1F4CA} Model Usage Statistics"), allowed.map((m) => {
|
|
5301
4928
|
const limit = m.dailyLimit ?? 0;
|
|
5302
4929
|
const used = m.usedToday ?? 0;
|
|
5303
|
-
const
|
|
5304
|
-
const bar = "\u2588".repeat(Math.round(
|
|
5305
|
-
return /* @__PURE__ */
|
|
5306
|
-
}), /* @__PURE__ */
|
|
4930
|
+
const pct2 = limit > 0 ? Math.round(used / limit * 100) : 0;
|
|
4931
|
+
const bar = "\u2588".repeat(Math.round(pct2 / 5)) + "\u2591".repeat(20 - Math.round(pct2 / 5));
|
|
4932
|
+
return /* @__PURE__ */ React11.createElement(Box8, { key: m.id, flexDirection: "column" }, /* @__PURE__ */ React11.createElement(Text9, { color: m.id === selectedModel ? "yellow" : "white" }, m.id === selectedModel ? "\u25BA " : " ", m.id), /* @__PURE__ */ React11.createElement(Text9, { color: pct2 > 80 ? "red" : pct2 > 50 ? "yellow" : "green" }, " ", bar, " ", /* @__PURE__ */ React11.createElement(Text9, { dimColor: true }, used, "/", limit)));
|
|
4933
|
+
}), /* @__PURE__ */ React11.createElement(Text9, { dimColor: true }, "[Esc] Back"));
|
|
5307
4934
|
}, [models, selectedModel]);
|
|
5308
4935
|
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";
|
|
5309
|
-
return /* @__PURE__ */
|
|
4936
|
+
return /* @__PURE__ */ React11.createElement(Box8, { flexDirection: "column" }, /* @__PURE__ */ React11.createElement(Box8, { borderStyle: "double", borderColor: "magenta", paddingX: 1 }, /* @__PURE__ */ React11.createElement(Text9, { bold: true, color: "magenta" }, "\u{1F916} Jai1 Chat"), /* @__PURE__ */ React11.createElement(Box8, { flexGrow: 1 }), /* @__PURE__ */ React11.createElement(Text9, { dimColor: true }, "Model: "), /* @__PURE__ */ React11.createElement(Text9, { color: "yellow", bold: true }, selectedModel || "...")), currentView === "loading" ? /* @__PURE__ */ React11.createElement(Box8, { padding: 2, minHeight: contentHeight.current, alignItems: "center", justifyContent: "center" }, /* @__PURE__ */ React11.createElement(Text9, null, /* @__PURE__ */ React11.createElement(Spinner4, { type: "dots" }), " Loading...")) : currentView === "error" ? /* @__PURE__ */ React11.createElement(Box8, { padding: 2, minHeight: contentHeight.current, alignItems: "center", justifyContent: "center", flexDirection: "column" }, /* @__PURE__ */ React11.createElement(Text9, { color: "red", bold: true }, "Connection Error"), /* @__PURE__ */ React11.createElement(Text9, { color: "red" }, error), /* @__PURE__ */ React11.createElement(Text9, { dimColor: true }, " "), /* @__PURE__ */ React11.createElement(Text9, { dimColor: true }, "Press Enter or 'r' to retry")) : currentView === "model" ? /* @__PURE__ */ React11.createElement(Box8, { padding: 1, minHeight: contentHeight.current, justifyContent: "center", alignItems: "center" }, /* @__PURE__ */ React11.createElement(
|
|
5310
4937
|
ModelSelector,
|
|
5311
4938
|
{
|
|
5312
4939
|
models,
|
|
@@ -5314,7 +4941,7 @@ var ChatApp = ({ service, initialModel }) => {
|
|
|
5314
4941
|
onSelect: onSelectModel,
|
|
5315
4942
|
onCancel: () => setCurrentView("chat")
|
|
5316
4943
|
}
|
|
5317
|
-
)) : currentView === "stats" ? /* @__PURE__ */
|
|
4944
|
+
)) : currentView === "stats" ? /* @__PURE__ */ React11.createElement(Box8, { padding: 1, minHeight: contentHeight.current, justifyContent: "center", alignItems: "center" }, statsView) : /* @__PURE__ */ React11.createElement(
|
|
5318
4945
|
ChatPanel,
|
|
5319
4946
|
{
|
|
5320
4947
|
messages,
|
|
@@ -5328,7 +4955,7 @@ var ChatApp = ({ service, initialModel }) => {
|
|
|
5328
4955
|
slashMenuIndex,
|
|
5329
4956
|
minHeight: contentHeight.current
|
|
5330
4957
|
}
|
|
5331
|
-
), /* @__PURE__ */
|
|
4958
|
+
), /* @__PURE__ */ React11.createElement(Box8, { borderStyle: "single", borderColor: "gray", paddingX: 1 }, /* @__PURE__ */ React11.createElement(Text9, { dimColor: true }, footer)));
|
|
5332
4959
|
};
|
|
5333
4960
|
|
|
5334
4961
|
// src/server/web-chat-server.ts
|
|
@@ -6232,8 +5859,8 @@ async function handleTerminalChat(options) {
|
|
|
6232
5859
|
throw new ValidationError('Not initialized. Run "jai1 auth" first.');
|
|
6233
5860
|
}
|
|
6234
5861
|
const service = new LlmProxyService(config);
|
|
6235
|
-
const { waitUntilExit, clear } =
|
|
6236
|
-
|
|
5862
|
+
const { waitUntilExit, clear } = render3(
|
|
5863
|
+
React12.createElement(ChatApp, {
|
|
6237
5864
|
service,
|
|
6238
5865
|
initialModel: options.model
|
|
6239
5866
|
}),
|
|
@@ -6305,7 +5932,7 @@ function createChatCommand() {
|
|
|
6305
5932
|
|
|
6306
5933
|
// src/commands/openai-keys.ts
|
|
6307
5934
|
import { Command as Command15 } from "commander";
|
|
6308
|
-
import
|
|
5935
|
+
import chalk10 from "chalk";
|
|
6309
5936
|
import boxen3 from "boxen";
|
|
6310
5937
|
function maskKey2(key) {
|
|
6311
5938
|
if (key.length <= 8) return "****";
|
|
@@ -6319,17 +5946,17 @@ async function handleOpenAiKeysCommand(options) {
|
|
|
6319
5946
|
}
|
|
6320
5947
|
const service = new LlmProxyService(config);
|
|
6321
5948
|
console.log(
|
|
6322
|
-
boxen3(
|
|
5949
|
+
boxen3(chalk10.cyan.bold("\u{1F4E1} Jai1 LLM Proxy - OpenAI Compatible API"), {
|
|
6323
5950
|
padding: { top: 0, bottom: 0, left: 1, right: 1 },
|
|
6324
5951
|
borderStyle: "round",
|
|
6325
5952
|
borderColor: "cyan"
|
|
6326
5953
|
})
|
|
6327
5954
|
);
|
|
6328
5955
|
console.log();
|
|
6329
|
-
console.log(
|
|
6330
|
-
console.log(` ${
|
|
5956
|
+
console.log(chalk10.bold("\u{1F511} API Credentials"));
|
|
5957
|
+
console.log(` ${chalk10.dim("BASE_URL:")} ${chalk10.white(service.getBaseUrl())}`);
|
|
6331
5958
|
console.log(
|
|
6332
|
-
` ${
|
|
5959
|
+
` ${chalk10.dim("API_KEY:")} ${options.full ? chalk10.green(service.getApiKey()) : chalk10.yellow(maskKey2(service.getApiKey()))}`
|
|
6333
5960
|
);
|
|
6334
5961
|
console.log();
|
|
6335
5962
|
try {
|
|
@@ -6338,39 +5965,39 @@ async function handleOpenAiKeysCommand(options) {
|
|
|
6338
5965
|
service.getLimits()
|
|
6339
5966
|
]);
|
|
6340
5967
|
const allowedModels = models.filter((m) => m.allowed);
|
|
6341
|
-
console.log(
|
|
5968
|
+
console.log(chalk10.bold("\u{1F4E6} Available Models"));
|
|
6342
5969
|
if (allowedModels.length === 0) {
|
|
6343
|
-
console.log(
|
|
5970
|
+
console.log(chalk10.dim(" Kh\xF4ng c\xF3 models kh\u1EA3 d\u1EE5ng"));
|
|
6344
5971
|
} else {
|
|
6345
5972
|
for (const model of allowedModels) {
|
|
6346
|
-
const usageText = model.dailyLimit !== void 0 && model.usedToday !== void 0 ?
|
|
6347
|
-
console.log(` ${
|
|
5973
|
+
const usageText = model.dailyLimit !== void 0 && model.usedToday !== void 0 ? chalk10.dim(` (${model.usedToday}/${model.dailyLimit} h\xF4m nay)`) : "";
|
|
5974
|
+
console.log(` ${chalk10.green("\u2713")} ${chalk10.white(model.id)}${usageText}`);
|
|
6348
5975
|
}
|
|
6349
5976
|
}
|
|
6350
5977
|
console.log();
|
|
6351
5978
|
const defaultModel = allowedModels[0]?.id || "gpt-4o";
|
|
6352
|
-
console.log(
|
|
5979
|
+
console.log(chalk10.bold("\u{1F4DD} Sample cURL"));
|
|
6353
5980
|
console.log();
|
|
6354
5981
|
const curlSample = options.full ? service.generateFullCurlSample(defaultModel) : service.generateCurlSample(defaultModel);
|
|
6355
5982
|
const curlLines = curlSample.split("\n");
|
|
6356
5983
|
for (const line of curlLines) {
|
|
6357
|
-
console.log(
|
|
5984
|
+
console.log(chalk10.dim(` ${line}`));
|
|
6358
5985
|
}
|
|
6359
5986
|
console.log();
|
|
6360
|
-
console.log(
|
|
6361
|
-
console.log(
|
|
6362
|
-
console.log(
|
|
6363
|
-
console.log(
|
|
5987
|
+
console.log(chalk10.bold("\u{1F4A1} C\xE1ch s\u1EED d\u1EE5ng"));
|
|
5988
|
+
console.log(chalk10.dim(" - Thay th\u1EBF OpenAI API URL v\xE0 API Key"));
|
|
5989
|
+
console.log(chalk10.dim(" - T\u01B0\u01A1ng th\xEDch: OpenAI SDK, LangChain, LlamaIndex, v.v."));
|
|
5990
|
+
console.log(chalk10.dim(' - Ch\u1EA1y "jai1 chat" \u0111\u1EC3 chat tr\u1EF1c ti\u1EBFp'));
|
|
6364
5991
|
if (!options.full) {
|
|
6365
|
-
console.log(
|
|
5992
|
+
console.log(chalk10.dim(' - Ch\u1EA1y "jai1 openai-keys --full" \u0111\u1EC3 hi\u1EC3n th\u1ECB API key \u0111\u1EA7y \u0111\u1EE7'));
|
|
6366
5993
|
}
|
|
6367
5994
|
} catch (error) {
|
|
6368
5995
|
console.log();
|
|
6369
5996
|
console.log(
|
|
6370
|
-
|
|
6371
|
-
|
|
5997
|
+
chalk10.red("\u274C L\u1ED7i khi l\u1EA5y th\xF4ng tin API:"),
|
|
5998
|
+
chalk10.dim(error instanceof Error ? error.message : String(error))
|
|
6372
5999
|
);
|
|
6373
|
-
console.log(
|
|
6000
|
+
console.log(chalk10.dim('\n\u{1F4A1} Ki\u1EC3m tra API URL v\xE0 access key v\u1EDBi "jai1 status"'));
|
|
6374
6001
|
}
|
|
6375
6002
|
}
|
|
6376
6003
|
function createOpenAiKeysCommand() {
|
|
@@ -6383,7 +6010,7 @@ function createOpenAiKeysCommand() {
|
|
|
6383
6010
|
// src/commands/stats.ts
|
|
6384
6011
|
import { Command as Command16 } from "commander";
|
|
6385
6012
|
import Table2 from "cli-table3";
|
|
6386
|
-
import
|
|
6013
|
+
import chalk11 from "chalk";
|
|
6387
6014
|
async function handleStatsCommand() {
|
|
6388
6015
|
const configService = new ConfigService();
|
|
6389
6016
|
const config = await configService.load();
|
|
@@ -6393,8 +6020,8 @@ async function handleStatsCommand() {
|
|
|
6393
6020
|
);
|
|
6394
6021
|
}
|
|
6395
6022
|
const service = new LlmProxyService(config);
|
|
6396
|
-
console.log(
|
|
6397
|
-
console.log(
|
|
6023
|
+
console.log(chalk11.bold("\n\u{1F4CA} Th\u1ED1ng K\xEA S\u1EED D\u1EE5ng LLM"));
|
|
6024
|
+
console.log(chalk11.dim("\u2500".repeat(45)));
|
|
6398
6025
|
try {
|
|
6399
6026
|
const [limits, usage7Days, usageToday] = await Promise.all([
|
|
6400
6027
|
service.getLimits(),
|
|
@@ -6404,7 +6031,7 @@ async function handleStatsCommand() {
|
|
|
6404
6031
|
const today = (/* @__PURE__ */ new Date()).toLocaleDateString("en-CA", {
|
|
6405
6032
|
timeZone: "Asia/Ho_Chi_Minh"
|
|
6406
6033
|
});
|
|
6407
|
-
console.log(
|
|
6034
|
+
console.log(chalk11.cyan("\n\u{1F4C5} Kho\u1EA3ng th\u1EDDi gian: 7 ng\xE0y qua\n"));
|
|
6408
6035
|
const usageByModel = /* @__PURE__ */ new Map();
|
|
6409
6036
|
let total7DaysRequests = 0;
|
|
6410
6037
|
usage7Days.data?.forEach((record) => {
|
|
@@ -6424,16 +6051,16 @@ async function handleStatsCommand() {
|
|
|
6424
6051
|
modelData.today = record.count;
|
|
6425
6052
|
}
|
|
6426
6053
|
});
|
|
6427
|
-
console.log(
|
|
6428
|
-
console.log(` T\u1ED5ng s\u1ED1 y\xEAu c\u1EA7u (7 ng\xE0y): ${
|
|
6054
|
+
console.log(chalk11.bold("\u{1F4C8} T\u1ED5ng quan s\u1EED d\u1EE5ng"));
|
|
6055
|
+
console.log(` T\u1ED5ng s\u1ED1 y\xEAu c\u1EA7u (7 ng\xE0y): ${chalk11.green(total7DaysRequests)}
|
|
6429
6056
|
`);
|
|
6430
|
-
console.log(
|
|
6057
|
+
console.log(chalk11.bold("\u{1F4E6} Th\u1ED1ng k\xEA theo model\n"));
|
|
6431
6058
|
const table = new Table2({
|
|
6432
6059
|
head: [
|
|
6433
|
-
|
|
6434
|
-
|
|
6435
|
-
|
|
6436
|
-
|
|
6060
|
+
chalk11.bold("Model"),
|
|
6061
|
+
chalk11.bold("H\xF4m nay"),
|
|
6062
|
+
chalk11.bold("Gi\u1EDBi h\u1EA1n"),
|
|
6063
|
+
chalk11.bold("T\u1ED5ng 7 ng\xE0y")
|
|
6437
6064
|
],
|
|
6438
6065
|
style: {
|
|
6439
6066
|
head: ["cyan"],
|
|
@@ -6445,7 +6072,7 @@ async function handleStatsCommand() {
|
|
|
6445
6072
|
const rateLimits = limits.effectiveRateLimits || {};
|
|
6446
6073
|
if (allowedModels.length === 0) {
|
|
6447
6074
|
table.push([
|
|
6448
|
-
{ colSpan: 4, content:
|
|
6075
|
+
{ colSpan: 4, content: chalk11.yellow("Kh\xF4ng c\xF3 model n\xE0o kh\u1EA3 d\u1EE5ng") }
|
|
6449
6076
|
]);
|
|
6450
6077
|
} else {
|
|
6451
6078
|
allowedModels.forEach((modelId) => {
|
|
@@ -6454,25 +6081,25 @@ async function handleStatsCommand() {
|
|
|
6454
6081
|
const usagePercent = limit > 0 ? usage.today / limit : 0;
|
|
6455
6082
|
let todayDisplay = `${usage.today}/${limit}`;
|
|
6456
6083
|
if (usagePercent >= 0.9) {
|
|
6457
|
-
todayDisplay =
|
|
6084
|
+
todayDisplay = chalk11.red(todayDisplay);
|
|
6458
6085
|
} else if (usagePercent >= 0.7) {
|
|
6459
|
-
todayDisplay =
|
|
6086
|
+
todayDisplay = chalk11.yellow(todayDisplay);
|
|
6460
6087
|
} else {
|
|
6461
|
-
todayDisplay =
|
|
6088
|
+
todayDisplay = chalk11.green(todayDisplay);
|
|
6462
6089
|
}
|
|
6463
6090
|
table.push([modelId, todayDisplay, `${limit}/ng\xE0y`, String(usage.total7Days)]);
|
|
6464
6091
|
});
|
|
6465
6092
|
}
|
|
6466
6093
|
console.log(table.toString());
|
|
6467
6094
|
console.log(
|
|
6468
|
-
|
|
6095
|
+
chalk11.dim('\n\u{1F4A1} M\u1EB9o: Ch\u1EA1y "jai1 openai-keys" \u0111\u1EC3 xem danh s\xE1ch model kh\u1EA3 d\u1EE5ng')
|
|
6469
6096
|
);
|
|
6470
6097
|
} catch (error) {
|
|
6471
6098
|
console.error(
|
|
6472
|
-
|
|
6099
|
+
chalk11.red("\n\u274C Kh\xF4ng th\u1EC3 l\u1EA5y th\u1ED1ng k\xEA:"),
|
|
6473
6100
|
error instanceof Error ? error.message : String(error)
|
|
6474
6101
|
);
|
|
6475
|
-
console.log(
|
|
6102
|
+
console.log(chalk11.dim('\n\u{1F4A1} Ki\u1EC3m tra k\u1EBFt n\u1ED1i API v\u1EDBi "jai1 status"'));
|
|
6476
6103
|
}
|
|
6477
6104
|
}
|
|
6478
6105
|
function createStatsCommand() {
|
|
@@ -6839,7 +6466,7 @@ function createTranslateCommand() {
|
|
|
6839
6466
|
|
|
6840
6467
|
// src/commands/image/index.ts
|
|
6841
6468
|
import { Command as Command22 } from "commander";
|
|
6842
|
-
import
|
|
6469
|
+
import chalk12 from "chalk";
|
|
6843
6470
|
|
|
6844
6471
|
// src/commands/image/gen.ts
|
|
6845
6472
|
import { Command as Command18 } from "commander";
|
|
@@ -7114,22 +6741,22 @@ function createImageDeleteCommand() {
|
|
|
7114
6741
|
|
|
7115
6742
|
// src/commands/image/index.ts
|
|
7116
6743
|
function showImageHelp() {
|
|
7117
|
-
console.log(
|
|
6744
|
+
console.log(chalk12.bold.cyan("\u{1F3A8} jai1 image") + chalk12.dim(" - Image generation commands"));
|
|
7118
6745
|
console.log();
|
|
7119
|
-
console.log(
|
|
6746
|
+
console.log(chalk12.yellow("\u26A0\uFE0F Coming Soon - T\xEDnh n\u0103ng \u0111ang ph\xE1t tri\u1EC3n"));
|
|
7120
6747
|
console.log();
|
|
7121
|
-
console.log(
|
|
7122
|
-
console.log(` ${
|
|
7123
|
-
console.log(` ${
|
|
7124
|
-
console.log(` ${
|
|
7125
|
-
console.log(` ${
|
|
6748
|
+
console.log(chalk12.bold("C\xE1c l\u1EC7nh:"));
|
|
6749
|
+
console.log(` ${chalk12.cyan("gen")} T\u1EA1o \u1EA3nh t\u1EEB prompt`);
|
|
6750
|
+
console.log(` ${chalk12.cyan("list")} Li\u1EC7t k\xEA c\xE1c \u1EA3nh \u0111\xE3 t\u1EA1o`);
|
|
6751
|
+
console.log(` ${chalk12.cyan("info")} Xem th\xF4ng tin \u1EA3nh`);
|
|
6752
|
+
console.log(` ${chalk12.cyan("delete")} X\xF3a \u1EA3nh`);
|
|
7126
6753
|
console.log();
|
|
7127
|
-
console.log(
|
|
7128
|
-
console.log(
|
|
7129
|
-
console.log(
|
|
7130
|
-
console.log(
|
|
6754
|
+
console.log(chalk12.bold("V\xED d\u1EE5:"));
|
|
6755
|
+
console.log(chalk12.dim(' $ jai1 image gen "a cute cat"'));
|
|
6756
|
+
console.log(chalk12.dim(" $ jai1 image list"));
|
|
6757
|
+
console.log(chalk12.dim(" $ jai1 image info <image-id>"));
|
|
7131
6758
|
console.log();
|
|
7132
|
-
console.log(
|
|
6759
|
+
console.log(chalk12.dim('Ch\u1EA1y "jai1 image <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt'));
|
|
7133
6760
|
}
|
|
7134
6761
|
function createImageCommand() {
|
|
7135
6762
|
const cmd = new Command22("image").description("Image generation commands (Coming Soon)").action(() => {
|
|
@@ -7630,11 +7257,11 @@ async function confirmSubmit(summary, jsonMode) {
|
|
|
7630
7257
|
|
|
7631
7258
|
// src/commands/errors/index.ts
|
|
7632
7259
|
import { Command as Command28 } from "commander";
|
|
7633
|
-
import
|
|
7260
|
+
import chalk14 from "chalk";
|
|
7634
7261
|
|
|
7635
7262
|
// src/commands/errors/list.ts
|
|
7636
7263
|
import { Command as Command25 } from "commander";
|
|
7637
|
-
import
|
|
7264
|
+
import chalk13 from "chalk";
|
|
7638
7265
|
import Table3 from "cli-table3";
|
|
7639
7266
|
function createErrorsListSubcommand() {
|
|
7640
7267
|
return new Command25("list").description("Danh s\xE1ch error logs").option("--json", "Output JSON format").action(async (options) => {
|
|
@@ -7671,7 +7298,7 @@ function createErrorsListSubcommand() {
|
|
|
7671
7298
|
});
|
|
7672
7299
|
for (const log of logs) {
|
|
7673
7300
|
table.push([
|
|
7674
|
-
|
|
7301
|
+
chalk13.cyan(log.id),
|
|
7675
7302
|
log.timestamp || "-",
|
|
7676
7303
|
log.command || "-",
|
|
7677
7304
|
log.message || "-"
|
|
@@ -7750,19 +7377,19 @@ function createErrorsClearSubcommand() {
|
|
|
7750
7377
|
|
|
7751
7378
|
// src/commands/errors/index.ts
|
|
7752
7379
|
function showErrorsHelp() {
|
|
7753
|
-
console.log(
|
|
7380
|
+
console.log(chalk14.bold.cyan("\u{1F9FE} jai1 errors") + chalk14.dim(" - Qu\u1EA3n l\xFD error logs c\u1EE5c b\u1ED9"));
|
|
7754
7381
|
console.log();
|
|
7755
|
-
console.log(
|
|
7756
|
-
console.log(` ${
|
|
7757
|
-
console.log(` ${
|
|
7758
|
-
console.log(` ${
|
|
7382
|
+
console.log(chalk14.bold("C\xE1c l\u1EC7nh:"));
|
|
7383
|
+
console.log(` ${chalk14.cyan("list")} Danh s\xE1ch error logs`);
|
|
7384
|
+
console.log(` ${chalk14.cyan("show")} Xem chi ti\u1EBFt error log`);
|
|
7385
|
+
console.log(` ${chalk14.cyan("clear")} Xo\xE1 error logs`);
|
|
7759
7386
|
console.log();
|
|
7760
|
-
console.log(
|
|
7761
|
-
console.log(
|
|
7762
|
-
console.log(
|
|
7763
|
-
console.log(
|
|
7387
|
+
console.log(chalk14.bold("V\xED d\u1EE5:"));
|
|
7388
|
+
console.log(chalk14.dim(" $ jai1 errors list"));
|
|
7389
|
+
console.log(chalk14.dim(" $ jai1 errors show <id>"));
|
|
7390
|
+
console.log(chalk14.dim(" $ jai1 errors clear --all"));
|
|
7764
7391
|
console.log();
|
|
7765
|
-
console.log(
|
|
7392
|
+
console.log(chalk14.dim('Ch\u1EA1y "jai1 errors <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt'));
|
|
7766
7393
|
}
|
|
7767
7394
|
function createErrorsCommand() {
|
|
7768
7395
|
const errorsCommand = new Command28("errors").description("Manage local error logs").action(() => {
|
|
@@ -7776,7 +7403,7 @@ function createErrorsCommand() {
|
|
|
7776
7403
|
|
|
7777
7404
|
// src/commands/utils/index.ts
|
|
7778
7405
|
import { Command as Command42 } from "commander";
|
|
7779
|
-
import
|
|
7406
|
+
import chalk15 from "chalk";
|
|
7780
7407
|
|
|
7781
7408
|
// src/commands/utils/password.ts
|
|
7782
7409
|
import { Command as Command29 } from "commander";
|
|
@@ -8698,28 +8325,28 @@ Examples:
|
|
|
8698
8325
|
}
|
|
8699
8326
|
|
|
8700
8327
|
// src/commands/utils/interactive.ts
|
|
8701
|
-
import
|
|
8702
|
-
import { render as
|
|
8328
|
+
import React25 from "react";
|
|
8329
|
+
import { render as render4 } from "ink";
|
|
8703
8330
|
|
|
8704
8331
|
// src/ui/utils/UtilsApp.tsx
|
|
8705
|
-
import
|
|
8706
|
-
import { Box as
|
|
8332
|
+
import React24, { useState as useState18 } from "react";
|
|
8333
|
+
import { Box as Box20, Text as Text21, useInput as useInput16, useApp as useApp4 } from "ink";
|
|
8707
8334
|
|
|
8708
8335
|
// src/ui/utils/views/PasswordView.tsx
|
|
8709
|
-
import
|
|
8710
|
-
import { Box as
|
|
8336
|
+
import React13, { useState as useState7 } from "react";
|
|
8337
|
+
import { Box as Box9, Text as Text10, useInput as useInput5 } from "ink";
|
|
8711
8338
|
import TextInput4 from "ink-text-input";
|
|
8712
8339
|
var PasswordView = () => {
|
|
8713
|
-
const [length, setLength] =
|
|
8714
|
-
const [count, setCount] =
|
|
8715
|
-
const [passwords, setPasswords] =
|
|
8716
|
-
const [focusedField, setFocusedField] =
|
|
8717
|
-
const [copiedIndex, setCopiedIndex] =
|
|
8340
|
+
const [length, setLength] = useState7("16");
|
|
8341
|
+
const [count, setCount] = useState7("1");
|
|
8342
|
+
const [passwords, setPasswords] = useState7([]);
|
|
8343
|
+
const [focusedField, setFocusedField] = useState7("length");
|
|
8344
|
+
const [copiedIndex, setCopiedIndex] = useState7(null);
|
|
8718
8345
|
const service = new UtilsService();
|
|
8719
|
-
|
|
8346
|
+
React13.useEffect(() => {
|
|
8720
8347
|
handleGenerate();
|
|
8721
8348
|
}, []);
|
|
8722
|
-
|
|
8349
|
+
useInput5((input5, key) => {
|
|
8723
8350
|
if (key.tab) {
|
|
8724
8351
|
if (focusedField === "length") setFocusedField("count");
|
|
8725
8352
|
else if (focusedField === "count") setFocusedField("generate");
|
|
@@ -8757,8 +8384,8 @@ var PasswordView = () => {
|
|
|
8757
8384
|
} catch (error) {
|
|
8758
8385
|
}
|
|
8759
8386
|
};
|
|
8760
|
-
return /* @__PURE__ */
|
|
8761
|
-
|
|
8387
|
+
return /* @__PURE__ */ React13.createElement(Box9, { flexDirection: "column" }, /* @__PURE__ */ React13.createElement(Box9, { marginBottom: 1 }, /* @__PURE__ */ React13.createElement(Text10, { bold: true, color: "cyan" }, "\u{1F510} Password Generator")), /* @__PURE__ */ React13.createElement(
|
|
8388
|
+
Box9,
|
|
8762
8389
|
{
|
|
8763
8390
|
flexDirection: "column",
|
|
8764
8391
|
borderStyle: "single",
|
|
@@ -8767,11 +8394,11 @@ var PasswordView = () => {
|
|
|
8767
8394
|
paddingY: 1,
|
|
8768
8395
|
marginBottom: 1
|
|
8769
8396
|
},
|
|
8770
|
-
/* @__PURE__ */
|
|
8771
|
-
/* @__PURE__ */
|
|
8772
|
-
/* @__PURE__ */
|
|
8773
|
-
/* @__PURE__ */
|
|
8774
|
-
|
|
8397
|
+
/* @__PURE__ */ React13.createElement(Text10, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
|
|
8398
|
+
/* @__PURE__ */ React13.createElement(Box9, { marginBottom: 1 }, /* @__PURE__ */ React13.createElement(Box9, { width: 20 }, /* @__PURE__ */ React13.createElement(Text10, { color: focusedField === "length" ? "green" : void 0 }, focusedField === "length" ? "\u25B6 " : " ", "Length:")), /* @__PURE__ */ React13.createElement(Box9, { width: 10 }, focusedField === "length" ? /* @__PURE__ */ React13.createElement(TextInput4, { value: length, onChange: setLength }) : /* @__PURE__ */ React13.createElement(Text10, null, length)), /* @__PURE__ */ React13.createElement(Text10, { dimColor: true }, "(characters)")),
|
|
8399
|
+
/* @__PURE__ */ React13.createElement(Box9, { marginBottom: 1 }, /* @__PURE__ */ React13.createElement(Box9, { width: 20 }, /* @__PURE__ */ React13.createElement(Text10, { color: focusedField === "count" ? "green" : void 0 }, focusedField === "count" ? "\u25B6 " : " ", "Count:")), /* @__PURE__ */ React13.createElement(Box9, { width: 10 }, focusedField === "count" ? /* @__PURE__ */ React13.createElement(TextInput4, { value: count, onChange: setCount }) : /* @__PURE__ */ React13.createElement(Text10, null, count)), /* @__PURE__ */ React13.createElement(Text10, { dimColor: true }, "(passwords to generate)")),
|
|
8400
|
+
/* @__PURE__ */ React13.createElement(Box9, { marginTop: 1 }, /* @__PURE__ */ React13.createElement(
|
|
8401
|
+
Text10,
|
|
8775
8402
|
{
|
|
8776
8403
|
bold: true,
|
|
8777
8404
|
backgroundColor: focusedField === "generate" ? "green" : void 0,
|
|
@@ -8780,8 +8407,8 @@ var PasswordView = () => {
|
|
|
8780
8407
|
focusedField === "generate" ? "\u25B6 " : " ",
|
|
8781
8408
|
"[ Generate Passwords ]"
|
|
8782
8409
|
))
|
|
8783
|
-
), passwords.length > 0 && /* @__PURE__ */
|
|
8784
|
-
|
|
8410
|
+
), passwords.length > 0 && /* @__PURE__ */ React13.createElement(
|
|
8411
|
+
Box9,
|
|
8785
8412
|
{
|
|
8786
8413
|
flexDirection: "column",
|
|
8787
8414
|
borderStyle: "single",
|
|
@@ -8789,27 +8416,27 @@ var PasswordView = () => {
|
|
|
8789
8416
|
paddingX: 2,
|
|
8790
8417
|
paddingY: 1
|
|
8791
8418
|
},
|
|
8792
|
-
/* @__PURE__ */
|
|
8793
|
-
passwords.map((password, index) => /* @__PURE__ */
|
|
8794
|
-
), /* @__PURE__ */
|
|
8419
|
+
/* @__PURE__ */ React13.createElement(Text10, { bold: true, color: "green", marginBottom: 1 }, "\u2713 Generated Passwords:"),
|
|
8420
|
+
passwords.map((password, index) => /* @__PURE__ */ React13.createElement(Box9, { key: index, marginBottom: 0 }, /* @__PURE__ */ React13.createElement(Box9, { width: 4 }, /* @__PURE__ */ React13.createElement(Text10, { dimColor: true }, index + 1, ".")), /* @__PURE__ */ React13.createElement(Box9, { flexGrow: 1 }, /* @__PURE__ */ React13.createElement(Text10, null, password)), copiedIndex === index && /* @__PURE__ */ React13.createElement(Text10, { color: "green" }, " \u2713 Copied!")))
|
|
8421
|
+
), /* @__PURE__ */ React13.createElement(Box9, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 2 }, /* @__PURE__ */ React13.createElement(Text10, { dimColor: true }, "Tab: Next field | Enter: Generate | C: Copy | Esc: Back")));
|
|
8795
8422
|
};
|
|
8796
8423
|
|
|
8797
8424
|
// src/ui/utils/views/UuidView.tsx
|
|
8798
|
-
import
|
|
8799
|
-
import { Box as
|
|
8425
|
+
import React14, { useState as useState8 } from "react";
|
|
8426
|
+
import { Box as Box10, Text as Text11, useInput as useInput6 } from "ink";
|
|
8800
8427
|
import TextInput5 from "ink-text-input";
|
|
8801
8428
|
var UuidView = () => {
|
|
8802
|
-
const [count, setCount] =
|
|
8803
|
-
const [uppercase, setUppercase] =
|
|
8804
|
-
const [noHyphens, setNoHyphens] =
|
|
8805
|
-
const [uuids, setUuids] =
|
|
8806
|
-
const [focusedField, setFocusedField] =
|
|
8807
|
-
const [copiedIndex, setCopiedIndex] =
|
|
8429
|
+
const [count, setCount] = useState8("1");
|
|
8430
|
+
const [uppercase, setUppercase] = useState8(false);
|
|
8431
|
+
const [noHyphens, setNoHyphens] = useState8(false);
|
|
8432
|
+
const [uuids, setUuids] = useState8([]);
|
|
8433
|
+
const [focusedField, setFocusedField] = useState8("count");
|
|
8434
|
+
const [copiedIndex, setCopiedIndex] = useState8(null);
|
|
8808
8435
|
const service = new UtilsService();
|
|
8809
|
-
|
|
8436
|
+
React14.useEffect(() => {
|
|
8810
8437
|
handleGenerate();
|
|
8811
8438
|
}, []);
|
|
8812
|
-
|
|
8439
|
+
useInput6((input5, key) => {
|
|
8813
8440
|
if (key.tab) {
|
|
8814
8441
|
const fields = ["count", "uppercase", "hyphens", "generate"];
|
|
8815
8442
|
const currentIndex = fields.indexOf(focusedField);
|
|
@@ -8844,8 +8471,8 @@ var UuidView = () => {
|
|
|
8844
8471
|
} catch (error) {
|
|
8845
8472
|
}
|
|
8846
8473
|
};
|
|
8847
|
-
return /* @__PURE__ */
|
|
8848
|
-
|
|
8474
|
+
return /* @__PURE__ */ React14.createElement(Box10, { flexDirection: "column" }, /* @__PURE__ */ React14.createElement(Box10, { marginBottom: 1 }, /* @__PURE__ */ React14.createElement(Text11, { bold: true, color: "cyan" }, "\u{1F194} UUID Generator")), /* @__PURE__ */ React14.createElement(
|
|
8475
|
+
Box10,
|
|
8849
8476
|
{
|
|
8850
8477
|
flexDirection: "column",
|
|
8851
8478
|
borderStyle: "single",
|
|
@@ -8854,12 +8481,12 @@ var UuidView = () => {
|
|
|
8854
8481
|
paddingY: 1,
|
|
8855
8482
|
marginBottom: 1
|
|
8856
8483
|
},
|
|
8857
|
-
/* @__PURE__ */
|
|
8858
|
-
/* @__PURE__ */
|
|
8859
|
-
/* @__PURE__ */
|
|
8860
|
-
/* @__PURE__ */
|
|
8861
|
-
/* @__PURE__ */
|
|
8862
|
-
|
|
8484
|
+
/* @__PURE__ */ React14.createElement(Text11, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
|
|
8485
|
+
/* @__PURE__ */ React14.createElement(Box10, { marginBottom: 1 }, /* @__PURE__ */ React14.createElement(Box10, { width: 20 }, /* @__PURE__ */ React14.createElement(Text11, { color: focusedField === "count" ? "green" : void 0 }, focusedField === "count" ? "\u25B6 " : " ", "Count:")), /* @__PURE__ */ React14.createElement(Box10, { width: 10 }, focusedField === "count" ? /* @__PURE__ */ React14.createElement(TextInput5, { value: count, onChange: setCount }) : /* @__PURE__ */ React14.createElement(Text11, null, count))),
|
|
8486
|
+
/* @__PURE__ */ React14.createElement(Box10, { marginBottom: 1 }, /* @__PURE__ */ React14.createElement(Text11, { color: focusedField === "uppercase" ? "green" : void 0 }, focusedField === "uppercase" ? "\u25B6 " : " ", "[", uppercase ? "\u2713" : " ", "] Uppercase")),
|
|
8487
|
+
/* @__PURE__ */ React14.createElement(Box10, { marginBottom: 1 }, /* @__PURE__ */ React14.createElement(Text11, { color: focusedField === "hyphens" ? "green" : void 0 }, focusedField === "hyphens" ? "\u25B6 " : " ", "[", noHyphens ? "\u2713" : " ", "] No Hyphens")),
|
|
8488
|
+
/* @__PURE__ */ React14.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React14.createElement(
|
|
8489
|
+
Text11,
|
|
8863
8490
|
{
|
|
8864
8491
|
bold: true,
|
|
8865
8492
|
backgroundColor: focusedField === "generate" ? "green" : void 0,
|
|
@@ -8868,8 +8495,8 @@ var UuidView = () => {
|
|
|
8868
8495
|
focusedField === "generate" ? "\u25B6 " : " ",
|
|
8869
8496
|
"[ Generate UUIDs ]"
|
|
8870
8497
|
))
|
|
8871
|
-
), uuids.length > 0 && /* @__PURE__ */
|
|
8872
|
-
|
|
8498
|
+
), uuids.length > 0 && /* @__PURE__ */ React14.createElement(
|
|
8499
|
+
Box10,
|
|
8873
8500
|
{
|
|
8874
8501
|
flexDirection: "column",
|
|
8875
8502
|
borderStyle: "single",
|
|
@@ -8877,27 +8504,27 @@ var UuidView = () => {
|
|
|
8877
8504
|
paddingX: 2,
|
|
8878
8505
|
paddingY: 1
|
|
8879
8506
|
},
|
|
8880
|
-
/* @__PURE__ */
|
|
8881
|
-
uuids.map((uuid, index) => /* @__PURE__ */
|
|
8882
|
-
), /* @__PURE__ */
|
|
8507
|
+
/* @__PURE__ */ React14.createElement(Text11, { bold: true, color: "green", marginBottom: 1 }, "\u2713 Generated UUIDs:"),
|
|
8508
|
+
uuids.map((uuid, index) => /* @__PURE__ */ React14.createElement(Box10, { key: index, marginBottom: 0 }, /* @__PURE__ */ React14.createElement(Box10, { width: 4 }, /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, index + 1, ".")), /* @__PURE__ */ React14.createElement(Box10, { flexGrow: 1 }, /* @__PURE__ */ React14.createElement(Text11, null, uuid)), copiedIndex === index && /* @__PURE__ */ React14.createElement(Text11, { color: "green" }, " \u2713 Copied!")))
|
|
8509
|
+
), /* @__PURE__ */ React14.createElement(Box10, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 2 }, /* @__PURE__ */ React14.createElement(Text11, { dimColor: true }, "Tab: Next | Enter: Toggle/Generate | C: Copy | Esc: Back")));
|
|
8883
8510
|
};
|
|
8884
8511
|
|
|
8885
8512
|
// src/ui/utils/views/HashView.tsx
|
|
8886
|
-
import
|
|
8887
|
-
import { Box as
|
|
8513
|
+
import React15, { useState as useState9 } from "react";
|
|
8514
|
+
import { Box as Box11, Text as Text12, useInput as useInput7 } from "ink";
|
|
8888
8515
|
import TextInput6 from "ink-text-input";
|
|
8889
8516
|
var ALGORITHMS = ["sha256", "sha512", "sha1", "md5", "bcrypt"];
|
|
8890
8517
|
var HashView = () => {
|
|
8891
|
-
const [text, setText] =
|
|
8892
|
-
const [algorithm, setAlgorithm] =
|
|
8893
|
-
const [hash, setHash] =
|
|
8894
|
-
const [focusedField, setFocusedField] =
|
|
8895
|
-
const [copied, setCopied] =
|
|
8518
|
+
const [text, setText] = useState9("hello world");
|
|
8519
|
+
const [algorithm, setAlgorithm] = useState9("sha256");
|
|
8520
|
+
const [hash, setHash] = useState9("");
|
|
8521
|
+
const [focusedField, setFocusedField] = useState9("text");
|
|
8522
|
+
const [copied, setCopied] = useState9(false);
|
|
8896
8523
|
const service = new UtilsService();
|
|
8897
|
-
|
|
8524
|
+
React15.useEffect(() => {
|
|
8898
8525
|
handleGenerate();
|
|
8899
8526
|
}, []);
|
|
8900
|
-
|
|
8527
|
+
useInput7((input5, key) => {
|
|
8901
8528
|
if (key.tab) {
|
|
8902
8529
|
const fields = ["text", "algorithm", "generate"];
|
|
8903
8530
|
const currentIndex = fields.indexOf(focusedField);
|
|
@@ -8934,8 +8561,8 @@ var HashView = () => {
|
|
|
8934
8561
|
} catch (error) {
|
|
8935
8562
|
}
|
|
8936
8563
|
};
|
|
8937
|
-
return /* @__PURE__ */
|
|
8938
|
-
|
|
8564
|
+
return /* @__PURE__ */ React15.createElement(Box11, { flexDirection: "column" }, /* @__PURE__ */ React15.createElement(Box11, { marginBottom: 1 }, /* @__PURE__ */ React15.createElement(Text12, { bold: true, color: "cyan" }, "\u{1F512} Hash Generator")), /* @__PURE__ */ React15.createElement(
|
|
8565
|
+
Box11,
|
|
8939
8566
|
{
|
|
8940
8567
|
flexDirection: "column",
|
|
8941
8568
|
borderStyle: "single",
|
|
@@ -8944,11 +8571,11 @@ var HashView = () => {
|
|
|
8944
8571
|
paddingY: 1,
|
|
8945
8572
|
marginBottom: 1
|
|
8946
8573
|
},
|
|
8947
|
-
/* @__PURE__ */
|
|
8948
|
-
/* @__PURE__ */
|
|
8949
|
-
/* @__PURE__ */
|
|
8950
|
-
/* @__PURE__ */
|
|
8951
|
-
|
|
8574
|
+
/* @__PURE__ */ React15.createElement(Text12, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
|
|
8575
|
+
/* @__PURE__ */ React15.createElement(Box11, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React15.createElement(Box11, { marginBottom: 0 }, /* @__PURE__ */ React15.createElement(Text12, { color: focusedField === "text" ? "green" : void 0 }, focusedField === "text" ? "\u25B6 " : " ", "Text to hash:")), /* @__PURE__ */ React15.createElement(Box11, { marginLeft: 2, width: 60 }, focusedField === "text" ? /* @__PURE__ */ React15.createElement(TextInput6, { value: text, onChange: setText, placeholder: "Enter text..." }) : /* @__PURE__ */ React15.createElement(Text12, { dimColor: !text }, text || "(empty)"))),
|
|
8576
|
+
/* @__PURE__ */ React15.createElement(Box11, { marginBottom: 1 }, /* @__PURE__ */ React15.createElement(Box11, { width: 20 }, /* @__PURE__ */ React15.createElement(Text12, { color: focusedField === "algorithm" ? "green" : void 0 }, focusedField === "algorithm" ? "\u25B6 " : " ", "Algorithm:")), /* @__PURE__ */ React15.createElement(Text12, { bold: true, color: focusedField === "algorithm" ? "yellow" : void 0 }, algorithm.toUpperCase()), focusedField === "algorithm" && /* @__PURE__ */ React15.createElement(Text12, { dimColor: true }, " (\u2190 \u2192 to change)")),
|
|
8577
|
+
/* @__PURE__ */ React15.createElement(Box11, { marginTop: 1 }, /* @__PURE__ */ React15.createElement(
|
|
8578
|
+
Text12,
|
|
8952
8579
|
{
|
|
8953
8580
|
bold: true,
|
|
8954
8581
|
backgroundColor: focusedField === "generate" ? "green" : void 0,
|
|
@@ -8957,8 +8584,8 @@ var HashView = () => {
|
|
|
8957
8584
|
focusedField === "generate" ? "\u25B6 " : " ",
|
|
8958
8585
|
"[ Generate Hash ]"
|
|
8959
8586
|
))
|
|
8960
|
-
), hash && /* @__PURE__ */
|
|
8961
|
-
|
|
8587
|
+
), hash && /* @__PURE__ */ React15.createElement(
|
|
8588
|
+
Box11,
|
|
8962
8589
|
{
|
|
8963
8590
|
flexDirection: "column",
|
|
8964
8591
|
borderStyle: "single",
|
|
@@ -8966,25 +8593,25 @@ var HashView = () => {
|
|
|
8966
8593
|
paddingX: 2,
|
|
8967
8594
|
paddingY: 1
|
|
8968
8595
|
},
|
|
8969
|
-
/* @__PURE__ */
|
|
8970
|
-
/* @__PURE__ */
|
|
8971
|
-
), /* @__PURE__ */
|
|
8596
|
+
/* @__PURE__ */ React15.createElement(Box11, { marginBottom: 1 }, /* @__PURE__ */ React15.createElement(Text12, { bold: true, color: "green" }, "\u2713 Hash Result:"), copied && /* @__PURE__ */ React15.createElement(Box11, { marginLeft: 2 }, /* @__PURE__ */ React15.createElement(Text12, { color: "green" }, "\u2713 Copied to clipboard!"))),
|
|
8597
|
+
/* @__PURE__ */ React15.createElement(Box11, { flexDirection: "column" }, /* @__PURE__ */ React15.createElement(Text12, { dimColor: true }, "Algorithm: ", algorithm.toUpperCase()), /* @__PURE__ */ React15.createElement(Box11, { marginTop: 1 }, /* @__PURE__ */ React15.createElement(Text12, { wrap: "wrap" }, hash)))
|
|
8598
|
+
), /* @__PURE__ */ React15.createElement(Box11, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 2 }, /* @__PURE__ */ React15.createElement(Text12, { dimColor: true }, "Tab: Next | \u2190/\u2192: Change algorithm | Enter: Generate | C: Copy | Esc: Back")));
|
|
8972
8599
|
};
|
|
8973
8600
|
|
|
8974
8601
|
// src/ui/utils/views/Base64View.tsx
|
|
8975
|
-
import
|
|
8976
|
-
import { Box as
|
|
8602
|
+
import React16, { useState as useState10 } from "react";
|
|
8603
|
+
import { Box as Box12, Text as Text13, useInput as useInput8 } from "ink";
|
|
8977
8604
|
import TextInput7 from "ink-text-input";
|
|
8978
8605
|
var Base64View = () => {
|
|
8979
|
-
const [input5, setInput] =
|
|
8980
|
-
const [mode, setMode] =
|
|
8981
|
-
const [urlSafe, setUrlSafe] =
|
|
8982
|
-
const [result, setResult] =
|
|
8983
|
-
const [error, setError] =
|
|
8984
|
-
const [focusedField, setFocusedField] =
|
|
8985
|
-
const [copied, setCopied] =
|
|
8606
|
+
const [input5, setInput] = useState10("");
|
|
8607
|
+
const [mode, setMode] = useState10("encode");
|
|
8608
|
+
const [urlSafe, setUrlSafe] = useState10(false);
|
|
8609
|
+
const [result, setResult] = useState10("");
|
|
8610
|
+
const [error, setError] = useState10("");
|
|
8611
|
+
const [focusedField, setFocusedField] = useState10("input");
|
|
8612
|
+
const [copied, setCopied] = useState10(false);
|
|
8986
8613
|
const service = new UtilsService();
|
|
8987
|
-
|
|
8614
|
+
useInput8((input6, key) => {
|
|
8988
8615
|
if (key.tab) {
|
|
8989
8616
|
const fields = ["input", "mode", "urlsafe", "convert"];
|
|
8990
8617
|
const currentIndex = fields.indexOf(focusedField);
|
|
@@ -9032,8 +8659,8 @@ var Base64View = () => {
|
|
|
9032
8659
|
} catch (error2) {
|
|
9033
8660
|
}
|
|
9034
8661
|
};
|
|
9035
|
-
return /* @__PURE__ */
|
|
9036
|
-
|
|
8662
|
+
return /* @__PURE__ */ React16.createElement(Box12, { flexDirection: "column" }, /* @__PURE__ */ React16.createElement(Box12, { marginBottom: 1 }, /* @__PURE__ */ React16.createElement(Text13, { bold: true, color: "cyan" }, "\u{1F4DD} Base64 Encoder/Decoder")), /* @__PURE__ */ React16.createElement(
|
|
8663
|
+
Box12,
|
|
9037
8664
|
{
|
|
9038
8665
|
flexDirection: "column",
|
|
9039
8666
|
borderStyle: "single",
|
|
@@ -9042,12 +8669,12 @@ var Base64View = () => {
|
|
|
9042
8669
|
paddingY: 1,
|
|
9043
8670
|
marginBottom: 1
|
|
9044
8671
|
},
|
|
9045
|
-
/* @__PURE__ */
|
|
9046
|
-
/* @__PURE__ */
|
|
9047
|
-
/* @__PURE__ */
|
|
9048
|
-
mode === "encode" && /* @__PURE__ */
|
|
9049
|
-
/* @__PURE__ */
|
|
9050
|
-
|
|
8672
|
+
/* @__PURE__ */ React16.createElement(Text13, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
|
|
8673
|
+
/* @__PURE__ */ React16.createElement(Box12, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React16.createElement(Box12, { marginBottom: 0 }, /* @__PURE__ */ React16.createElement(Text13, { color: focusedField === "input" ? "green" : void 0 }, focusedField === "input" ? "\u25B6 " : " ", "Input text:")), /* @__PURE__ */ React16.createElement(Box12, { marginLeft: 2, width: 60 }, focusedField === "input" ? /* @__PURE__ */ React16.createElement(TextInput7, { value: input5, onChange: setInput, placeholder: "Enter text..." }) : /* @__PURE__ */ React16.createElement(Text13, { dimColor: !input5 }, input5 || "(empty)"))),
|
|
8674
|
+
/* @__PURE__ */ React16.createElement(Box12, { marginBottom: 1 }, /* @__PURE__ */ React16.createElement(Box12, { width: 20 }, /* @__PURE__ */ React16.createElement(Text13, { color: focusedField === "mode" ? "green" : void 0 }, focusedField === "mode" ? "\u25B6 " : " ", "Mode:")), /* @__PURE__ */ React16.createElement(Text13, { bold: true, color: focusedField === "mode" ? "yellow" : void 0 }, mode === "encode" ? "ENCODE" : "DECODE"), focusedField === "mode" && /* @__PURE__ */ React16.createElement(Text13, { dimColor: true }, " (Enter to toggle)")),
|
|
8675
|
+
mode === "encode" && /* @__PURE__ */ React16.createElement(Box12, { marginBottom: 1 }, /* @__PURE__ */ React16.createElement(Text13, { color: focusedField === "urlsafe" ? "green" : void 0 }, focusedField === "urlsafe" ? "\u25B6 " : " ", "[", urlSafe ? "\u2713" : " ", "] URL-Safe (+ \u2192 -, / \u2192 _)")),
|
|
8676
|
+
/* @__PURE__ */ React16.createElement(Box12, { marginTop: 1 }, /* @__PURE__ */ React16.createElement(
|
|
8677
|
+
Text13,
|
|
9051
8678
|
{
|
|
9052
8679
|
bold: true,
|
|
9053
8680
|
backgroundColor: focusedField === "convert" ? "green" : void 0,
|
|
@@ -9058,8 +8685,8 @@ var Base64View = () => {
|
|
|
9058
8685
|
mode === "encode" ? "Encode" : "Decode",
|
|
9059
8686
|
" ]"
|
|
9060
8687
|
))
|
|
9061
|
-
), error && /* @__PURE__ */
|
|
9062
|
-
|
|
8688
|
+
), error && /* @__PURE__ */ React16.createElement(
|
|
8689
|
+
Box12,
|
|
9063
8690
|
{
|
|
9064
8691
|
flexDirection: "column",
|
|
9065
8692
|
borderStyle: "single",
|
|
@@ -9068,9 +8695,9 @@ var Base64View = () => {
|
|
|
9068
8695
|
paddingY: 1,
|
|
9069
8696
|
marginBottom: 1
|
|
9070
8697
|
},
|
|
9071
|
-
/* @__PURE__ */
|
|
9072
|
-
), result && /* @__PURE__ */
|
|
9073
|
-
|
|
8698
|
+
/* @__PURE__ */ React16.createElement(Text13, { color: "red" }, "\u2717 Error: ", error)
|
|
8699
|
+
), result && /* @__PURE__ */ React16.createElement(
|
|
8700
|
+
Box12,
|
|
9074
8701
|
{
|
|
9075
8702
|
flexDirection: "column",
|
|
9076
8703
|
borderStyle: "single",
|
|
@@ -9078,24 +8705,24 @@ var Base64View = () => {
|
|
|
9078
8705
|
paddingX: 2,
|
|
9079
8706
|
paddingY: 1
|
|
9080
8707
|
},
|
|
9081
|
-
/* @__PURE__ */
|
|
9082
|
-
/* @__PURE__ */
|
|
9083
|
-
), /* @__PURE__ */
|
|
8708
|
+
/* @__PURE__ */ React16.createElement(Box12, { marginBottom: 1 }, /* @__PURE__ */ React16.createElement(Text13, { bold: true, color: "green" }, "\u2713 Result:"), copied && /* @__PURE__ */ React16.createElement(Box12, { marginLeft: 2 }, /* @__PURE__ */ React16.createElement(Text13, { color: "green" }, "\u2713 Copied to clipboard!"))),
|
|
8709
|
+
/* @__PURE__ */ React16.createElement(Box12, { flexDirection: "column" }, /* @__PURE__ */ React16.createElement(Text13, { dimColor: true }, "Mode: ", mode.toUpperCase()), /* @__PURE__ */ React16.createElement(Box12, { marginTop: 1 }, /* @__PURE__ */ React16.createElement(Text13, { wrap: "wrap" }, result)))
|
|
8710
|
+
), /* @__PURE__ */ React16.createElement(Box12, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 2 }, /* @__PURE__ */ React16.createElement(Text13, { dimColor: true }, "Tab: Next | Enter: Toggle/Convert | C: Copy | Esc: Back")));
|
|
9084
8711
|
};
|
|
9085
8712
|
|
|
9086
8713
|
// src/ui/utils/views/UrlView.tsx
|
|
9087
|
-
import
|
|
9088
|
-
import { Box as
|
|
8714
|
+
import React17, { useState as useState11 } from "react";
|
|
8715
|
+
import { Box as Box13, Text as Text14, useInput as useInput9 } from "ink";
|
|
9089
8716
|
import TextInput8 from "ink-text-input";
|
|
9090
8717
|
var UrlView = () => {
|
|
9091
|
-
const [input5, setInput] =
|
|
9092
|
-
const [mode, setMode] =
|
|
9093
|
-
const [fullUrl, setFullUrl] =
|
|
9094
|
-
const [result, setResult] =
|
|
9095
|
-
const [focusedField, setFocusedField] =
|
|
9096
|
-
const [copied, setCopied] =
|
|
8718
|
+
const [input5, setInput] = useState11("");
|
|
8719
|
+
const [mode, setMode] = useState11("encode");
|
|
8720
|
+
const [fullUrl, setFullUrl] = useState11(false);
|
|
8721
|
+
const [result, setResult] = useState11("");
|
|
8722
|
+
const [focusedField, setFocusedField] = useState11("input");
|
|
8723
|
+
const [copied, setCopied] = useState11(false);
|
|
9097
8724
|
const service = new UtilsService();
|
|
9098
|
-
|
|
8725
|
+
useInput9((input6, key) => {
|
|
9099
8726
|
if (key.tab) {
|
|
9100
8727
|
const fields = ["input", "mode", "full", "convert"];
|
|
9101
8728
|
const currentIndex = fields.indexOf(focusedField);
|
|
@@ -9133,8 +8760,8 @@ var UrlView = () => {
|
|
|
9133
8760
|
} catch (error) {
|
|
9134
8761
|
}
|
|
9135
8762
|
};
|
|
9136
|
-
return /* @__PURE__ */
|
|
9137
|
-
|
|
8763
|
+
return /* @__PURE__ */ React17.createElement(Box13, { flexDirection: "column" }, /* @__PURE__ */ React17.createElement(Box13, { marginBottom: 1 }, /* @__PURE__ */ React17.createElement(Text14, { bold: true, color: "cyan" }, "\u{1F517} URL Encoder/Decoder")), /* @__PURE__ */ React17.createElement(
|
|
8764
|
+
Box13,
|
|
9138
8765
|
{
|
|
9139
8766
|
flexDirection: "column",
|
|
9140
8767
|
borderStyle: "single",
|
|
@@ -9143,12 +8770,12 @@ var UrlView = () => {
|
|
|
9143
8770
|
paddingY: 1,
|
|
9144
8771
|
marginBottom: 1
|
|
9145
8772
|
},
|
|
9146
|
-
/* @__PURE__ */
|
|
9147
|
-
/* @__PURE__ */
|
|
9148
|
-
/* @__PURE__ */
|
|
9149
|
-
/* @__PURE__ */
|
|
9150
|
-
/* @__PURE__ */
|
|
9151
|
-
|
|
8773
|
+
/* @__PURE__ */ React17.createElement(Text14, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
|
|
8774
|
+
/* @__PURE__ */ React17.createElement(Box13, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React17.createElement(Box13, { marginBottom: 0 }, /* @__PURE__ */ React17.createElement(Text14, { color: focusedField === "input" ? "green" : void 0 }, focusedField === "input" ? "\u25B6 " : " ", "Input text:")), /* @__PURE__ */ React17.createElement(Box13, { marginLeft: 2, width: 60 }, focusedField === "input" ? /* @__PURE__ */ React17.createElement(TextInput8, { value: input5, onChange: setInput, placeholder: "Enter text or URL..." }) : /* @__PURE__ */ React17.createElement(Text14, { dimColor: !input5 }, input5 || "(empty)"))),
|
|
8775
|
+
/* @__PURE__ */ React17.createElement(Box13, { marginBottom: 1 }, /* @__PURE__ */ React17.createElement(Box13, { width: 20 }, /* @__PURE__ */ React17.createElement(Text14, { color: focusedField === "mode" ? "green" : void 0 }, focusedField === "mode" ? "\u25B6 " : " ", "Mode:")), /* @__PURE__ */ React17.createElement(Text14, { bold: true, color: focusedField === "mode" ? "yellow" : void 0 }, mode === "encode" ? "ENCODE" : "DECODE"), focusedField === "mode" && /* @__PURE__ */ React17.createElement(Text14, { dimColor: true }, " (Enter to toggle)")),
|
|
8776
|
+
/* @__PURE__ */ React17.createElement(Box13, { marginBottom: 1 }, /* @__PURE__ */ React17.createElement(Text14, { color: focusedField === "full" ? "green" : void 0 }, focusedField === "full" ? "\u25B6 " : " ", "[", fullUrl ? "\u2713" : " ", "] Full URL (encode/decode entire URL)")),
|
|
8777
|
+
/* @__PURE__ */ React17.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React17.createElement(
|
|
8778
|
+
Text14,
|
|
9152
8779
|
{
|
|
9153
8780
|
bold: true,
|
|
9154
8781
|
backgroundColor: focusedField === "convert" ? "green" : void 0,
|
|
@@ -9159,8 +8786,8 @@ var UrlView = () => {
|
|
|
9159
8786
|
mode === "encode" ? "Encode" : "Decode",
|
|
9160
8787
|
" ]"
|
|
9161
8788
|
))
|
|
9162
|
-
), result && /* @__PURE__ */
|
|
9163
|
-
|
|
8789
|
+
), result && /* @__PURE__ */ React17.createElement(
|
|
8790
|
+
Box13,
|
|
9164
8791
|
{
|
|
9165
8792
|
flexDirection: "column",
|
|
9166
8793
|
borderStyle: "single",
|
|
@@ -9168,26 +8795,26 @@ var UrlView = () => {
|
|
|
9168
8795
|
paddingX: 2,
|
|
9169
8796
|
paddingY: 1
|
|
9170
8797
|
},
|
|
9171
|
-
/* @__PURE__ */
|
|
9172
|
-
/* @__PURE__ */
|
|
9173
|
-
), /* @__PURE__ */
|
|
8798
|
+
/* @__PURE__ */ React17.createElement(Box13, { marginBottom: 1 }, /* @__PURE__ */ React17.createElement(Text14, { bold: true, color: "green" }, "\u2713 Result:"), copied && /* @__PURE__ */ React17.createElement(Box13, { marginLeft: 2 }, /* @__PURE__ */ React17.createElement(Text14, { color: "green" }, "\u2713 Copied to clipboard!"))),
|
|
8799
|
+
/* @__PURE__ */ React17.createElement(Box13, { flexDirection: "column" }, /* @__PURE__ */ React17.createElement(Text14, { dimColor: true }, "Mode: ", mode.toUpperCase(), " ", fullUrl ? "(Full URL)" : "(Component)"), /* @__PURE__ */ React17.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React17.createElement(Text14, { wrap: "wrap" }, result)))
|
|
8800
|
+
), /* @__PURE__ */ React17.createElement(Box13, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 2 }, /* @__PURE__ */ React17.createElement(Text14, { dimColor: true }, "Tab: Next | Enter: Toggle/Convert | C: Copy | Esc: Back")));
|
|
9174
8801
|
};
|
|
9175
8802
|
|
|
9176
8803
|
// src/ui/utils/views/UnixTimeView.tsx
|
|
9177
|
-
import
|
|
9178
|
-
import { Box as
|
|
8804
|
+
import React18, { useState as useState12 } from "react";
|
|
8805
|
+
import { Box as Box14, Text as Text15, useInput as useInput10 } from "ink";
|
|
9179
8806
|
import TextInput9 from "ink-text-input";
|
|
9180
8807
|
var UnixTimeView = () => {
|
|
9181
|
-
const [input5, setInput] =
|
|
9182
|
-
const [mode, setMode] =
|
|
9183
|
-
const [format, setFormat] =
|
|
9184
|
-
const [useMs, setUseMs] =
|
|
9185
|
-
const [result, setResult] =
|
|
9186
|
-
const [error, setError] =
|
|
9187
|
-
const [focusedField, setFocusedField] =
|
|
9188
|
-
const [copied, setCopied] =
|
|
8808
|
+
const [input5, setInput] = useState12("");
|
|
8809
|
+
const [mode, setMode] = useState12("now");
|
|
8810
|
+
const [format, setFormat] = useState12("iso");
|
|
8811
|
+
const [useMs, setUseMs] = useState12(false);
|
|
8812
|
+
const [result, setResult] = useState12("");
|
|
8813
|
+
const [error, setError] = useState12("");
|
|
8814
|
+
const [focusedField, setFocusedField] = useState12("mode");
|
|
8815
|
+
const [copied, setCopied] = useState12(false);
|
|
9189
8816
|
const service = new UtilsService();
|
|
9190
|
-
|
|
8817
|
+
useInput10((input6, key) => {
|
|
9191
8818
|
if (key.tab) {
|
|
9192
8819
|
const fields = mode === "now" ? ["mode", "ms", "convert"] : mode === "to-human" ? ["mode", "input", "format", "convert"] : ["mode", "input", "convert"];
|
|
9193
8820
|
const currentIndex = fields.indexOf(focusedField);
|
|
@@ -9248,8 +8875,8 @@ var UnixTimeView = () => {
|
|
|
9248
8875
|
} catch (error2) {
|
|
9249
8876
|
}
|
|
9250
8877
|
};
|
|
9251
|
-
return /* @__PURE__ */
|
|
9252
|
-
|
|
8878
|
+
return /* @__PURE__ */ React18.createElement(Box14, { flexDirection: "column" }, /* @__PURE__ */ React18.createElement(Box14, { marginBottom: 1 }, /* @__PURE__ */ React18.createElement(Text15, { bold: true, color: "cyan" }, "\u{1F552} Unix Time Converter")), /* @__PURE__ */ React18.createElement(
|
|
8879
|
+
Box14,
|
|
9253
8880
|
{
|
|
9254
8881
|
flexDirection: "column",
|
|
9255
8882
|
borderStyle: "single",
|
|
@@ -9258,20 +8885,20 @@ var UnixTimeView = () => {
|
|
|
9258
8885
|
paddingY: 1,
|
|
9259
8886
|
marginBottom: 1
|
|
9260
8887
|
},
|
|
9261
|
-
/* @__PURE__ */
|
|
9262
|
-
/* @__PURE__ */
|
|
9263
|
-
mode !== "now" && /* @__PURE__ */
|
|
8888
|
+
/* @__PURE__ */ React18.createElement(Text15, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
|
|
8889
|
+
/* @__PURE__ */ React18.createElement(Box14, { marginBottom: 1 }, /* @__PURE__ */ React18.createElement(Box14, { width: 20 }, /* @__PURE__ */ React18.createElement(Text15, { color: focusedField === "mode" ? "green" : void 0 }, focusedField === "mode" ? "\u25B6 " : " ", "Mode:")), /* @__PURE__ */ React18.createElement(Text15, { bold: true, color: focusedField === "mode" ? "yellow" : void 0 }, mode === "now" ? "CURRENT TIME" : mode === "to-human" ? "TIMESTAMP \u2192 HUMAN" : "HUMAN \u2192 TIMESTAMP"), focusedField === "mode" && /* @__PURE__ */ React18.createElement(Text15, { dimColor: true }, " (Enter to cycle)")),
|
|
8890
|
+
mode !== "now" && /* @__PURE__ */ React18.createElement(Box14, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React18.createElement(Box14, { marginBottom: 0 }, /* @__PURE__ */ React18.createElement(Text15, { color: focusedField === "input" ? "green" : void 0 }, focusedField === "input" ? "\u25B6 " : " ", mode === "to-human" ? "Timestamp:" : "Date string:")), /* @__PURE__ */ React18.createElement(Box14, { marginLeft: 2, width: 50 }, focusedField === "input" ? /* @__PURE__ */ React18.createElement(
|
|
9264
8891
|
TextInput9,
|
|
9265
8892
|
{
|
|
9266
8893
|
value: input5,
|
|
9267
8894
|
onChange: setInput,
|
|
9268
8895
|
placeholder: mode === "to-human" ? "1702550400" : "2024-01-15 10:30:00"
|
|
9269
8896
|
}
|
|
9270
|
-
) : /* @__PURE__ */
|
|
9271
|
-
mode === "to-human" && /* @__PURE__ */
|
|
9272
|
-
mode === "now" && /* @__PURE__ */
|
|
9273
|
-
/* @__PURE__ */
|
|
9274
|
-
|
|
8897
|
+
) : /* @__PURE__ */ React18.createElement(Text15, { dimColor: !input5 }, input5 || "(empty)"))),
|
|
8898
|
+
mode === "to-human" && /* @__PURE__ */ React18.createElement(Box14, { marginBottom: 1 }, /* @__PURE__ */ React18.createElement(Box14, { width: 20 }, /* @__PURE__ */ React18.createElement(Text15, { color: focusedField === "format" ? "green" : void 0 }, focusedField === "format" ? "\u25B6 " : " ", "Format:")), /* @__PURE__ */ React18.createElement(Text15, { bold: true, color: focusedField === "format" ? "yellow" : void 0 }, format.toUpperCase()), focusedField === "format" && /* @__PURE__ */ React18.createElement(Text15, { dimColor: true }, " (Enter to cycle)")),
|
|
8899
|
+
mode === "now" && /* @__PURE__ */ React18.createElement(Box14, { marginBottom: 1 }, /* @__PURE__ */ React18.createElement(Text15, { color: focusedField === "ms" ? "green" : void 0 }, focusedField === "ms" ? "\u25B6 " : " ", "[", useMs ? "\u2713" : " ", "] Milliseconds")),
|
|
8900
|
+
/* @__PURE__ */ React18.createElement(Box14, { marginTop: 1 }, /* @__PURE__ */ React18.createElement(
|
|
8901
|
+
Text15,
|
|
9275
8902
|
{
|
|
9276
8903
|
bold: true,
|
|
9277
8904
|
backgroundColor: focusedField === "convert" ? "green" : void 0,
|
|
@@ -9282,8 +8909,8 @@ var UnixTimeView = () => {
|
|
|
9282
8909
|
mode === "now" ? "Get Current" : "Convert",
|
|
9283
8910
|
" ]"
|
|
9284
8911
|
))
|
|
9285
|
-
), error && /* @__PURE__ */
|
|
9286
|
-
|
|
8912
|
+
), error && /* @__PURE__ */ React18.createElement(
|
|
8913
|
+
Box14,
|
|
9287
8914
|
{
|
|
9288
8915
|
flexDirection: "column",
|
|
9289
8916
|
borderStyle: "single",
|
|
@@ -9292,9 +8919,9 @@ var UnixTimeView = () => {
|
|
|
9292
8919
|
paddingY: 1,
|
|
9293
8920
|
marginBottom: 1
|
|
9294
8921
|
},
|
|
9295
|
-
/* @__PURE__ */
|
|
9296
|
-
), result && /* @__PURE__ */
|
|
9297
|
-
|
|
8922
|
+
/* @__PURE__ */ React18.createElement(Text15, { color: "red" }, "\u2717 Error: ", error)
|
|
8923
|
+
), result && /* @__PURE__ */ React18.createElement(
|
|
8924
|
+
Box14,
|
|
9298
8925
|
{
|
|
9299
8926
|
flexDirection: "column",
|
|
9300
8927
|
borderStyle: "single",
|
|
@@ -9302,26 +8929,26 @@ var UnixTimeView = () => {
|
|
|
9302
8929
|
paddingX: 2,
|
|
9303
8930
|
paddingY: 1
|
|
9304
8931
|
},
|
|
9305
|
-
/* @__PURE__ */
|
|
9306
|
-
/* @__PURE__ */
|
|
9307
|
-
), /* @__PURE__ */
|
|
8932
|
+
/* @__PURE__ */ React18.createElement(Box14, { marginBottom: 1 }, /* @__PURE__ */ React18.createElement(Text15, { bold: true, color: "green" }, "\u2713 Result:"), copied && /* @__PURE__ */ React18.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React18.createElement(Text15, { color: "green" }, "\u2713 Copied to clipboard!"))),
|
|
8933
|
+
/* @__PURE__ */ React18.createElement(Box14, { flexDirection: "column" }, /* @__PURE__ */ React18.createElement(Box14, { marginTop: 1 }, /* @__PURE__ */ React18.createElement(Text15, { wrap: "wrap" }, result)))
|
|
8934
|
+
), /* @__PURE__ */ React18.createElement(Box14, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 2 }, /* @__PURE__ */ React18.createElement(Text15, { dimColor: true }, "Tab: Next | Enter: Toggle/Convert | C: Copy | Esc: Back")));
|
|
9308
8935
|
};
|
|
9309
8936
|
|
|
9310
8937
|
// src/ui/utils/views/JwtView.tsx
|
|
9311
|
-
import
|
|
9312
|
-
import { Box as
|
|
8938
|
+
import React19, { useState as useState13 } from "react";
|
|
8939
|
+
import { Box as Box15, Text as Text16, useInput as useInput11 } from "ink";
|
|
9313
8940
|
import TextInput10 from "ink-text-input";
|
|
9314
8941
|
var JwtView = () => {
|
|
9315
|
-
const [mode, setMode] =
|
|
9316
|
-
const [token, setToken] =
|
|
9317
|
-
const [payload, setPayload] =
|
|
9318
|
-
const [secret, setSecret] =
|
|
9319
|
-
const [result, setResult] =
|
|
9320
|
-
const [error, setError] =
|
|
9321
|
-
const [focusedField, setFocusedField] =
|
|
9322
|
-
const [copied, setCopied] =
|
|
8942
|
+
const [mode, setMode] = useState13("decode");
|
|
8943
|
+
const [token, setToken] = useState13("");
|
|
8944
|
+
const [payload, setPayload] = useState13("");
|
|
8945
|
+
const [secret, setSecret] = useState13("");
|
|
8946
|
+
const [result, setResult] = useState13({});
|
|
8947
|
+
const [error, setError] = useState13("");
|
|
8948
|
+
const [focusedField, setFocusedField] = useState13("mode");
|
|
8949
|
+
const [copied, setCopied] = useState13(false);
|
|
9323
8950
|
const service = new UtilsService();
|
|
9324
|
-
|
|
8951
|
+
useInput11((input5, key) => {
|
|
9325
8952
|
if (key.tab) {
|
|
9326
8953
|
const fields = mode === "decode" ? ["mode", "token", "process"] : ["mode", "payload", "secret", "process"];
|
|
9327
8954
|
const currentIndex = fields.indexOf(focusedField);
|
|
@@ -9376,8 +9003,8 @@ var JwtView = () => {
|
|
|
9376
9003
|
} catch (error2) {
|
|
9377
9004
|
}
|
|
9378
9005
|
};
|
|
9379
|
-
return /* @__PURE__ */
|
|
9380
|
-
|
|
9006
|
+
return /* @__PURE__ */ React19.createElement(Box15, { flexDirection: "column" }, /* @__PURE__ */ React19.createElement(Box15, { marginBottom: 1 }, /* @__PURE__ */ React19.createElement(Text16, { bold: true, color: "cyan" }, "\u{1F511} JWT Decoder/Encoder")), /* @__PURE__ */ React19.createElement(
|
|
9007
|
+
Box15,
|
|
9381
9008
|
{
|
|
9382
9009
|
flexDirection: "column",
|
|
9383
9010
|
borderStyle: "single",
|
|
@@ -9386,23 +9013,23 @@ var JwtView = () => {
|
|
|
9386
9013
|
paddingY: 1,
|
|
9387
9014
|
marginBottom: 1
|
|
9388
9015
|
},
|
|
9389
|
-
/* @__PURE__ */
|
|
9390
|
-
/* @__PURE__ */
|
|
9391
|
-
mode === "decode" ? /* @__PURE__ */
|
|
9016
|
+
/* @__PURE__ */ React19.createElement(Text16, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
|
|
9017
|
+
/* @__PURE__ */ React19.createElement(Box15, { marginBottom: 1 }, /* @__PURE__ */ React19.createElement(Box15, { width: 20 }, /* @__PURE__ */ React19.createElement(Text16, { color: focusedField === "mode" ? "green" : void 0 }, focusedField === "mode" ? "\u25B6 " : " ", "Mode:")), /* @__PURE__ */ React19.createElement(Text16, { bold: true, color: focusedField === "mode" ? "yellow" : void 0 }, mode === "decode" ? "DECODE" : "ENCODE"), focusedField === "mode" && /* @__PURE__ */ React19.createElement(Text16, { dimColor: true }, " (Enter to toggle)")),
|
|
9018
|
+
mode === "decode" ? /* @__PURE__ */ React19.createElement(Box15, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React19.createElement(Box15, { marginBottom: 0 }, /* @__PURE__ */ React19.createElement(Text16, { color: focusedField === "token" ? "green" : void 0 }, focusedField === "token" ? "\u25B6 " : " ", "JWT Token:")), /* @__PURE__ */ React19.createElement(Box15, { marginLeft: 2, width: 60 }, focusedField === "token" ? /* @__PURE__ */ React19.createElement(
|
|
9392
9019
|
TextInput10,
|
|
9393
9020
|
{
|
|
9394
9021
|
value: token,
|
|
9395
9022
|
onChange: setToken,
|
|
9396
9023
|
placeholder: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
|
9397
9024
|
}
|
|
9398
|
-
) : /* @__PURE__ */
|
|
9025
|
+
) : /* @__PURE__ */ React19.createElement(Text16, { dimColor: !token }, token || "(empty)"))) : /* @__PURE__ */ React19.createElement(React19.Fragment, null, /* @__PURE__ */ React19.createElement(Box15, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React19.createElement(Box15, { marginBottom: 0 }, /* @__PURE__ */ React19.createElement(Text16, { color: focusedField === "payload" ? "green" : void 0 }, focusedField === "payload" ? "\u25B6 " : " ", "Payload (JSON):")), /* @__PURE__ */ React19.createElement(Box15, { marginLeft: 2, width: 60 }, focusedField === "payload" ? /* @__PURE__ */ React19.createElement(
|
|
9399
9026
|
TextInput10,
|
|
9400
9027
|
{
|
|
9401
9028
|
value: payload,
|
|
9402
9029
|
onChange: setPayload,
|
|
9403
9030
|
placeholder: '{"sub":"123","name":"John"}'
|
|
9404
9031
|
}
|
|
9405
|
-
) : /* @__PURE__ */
|
|
9032
|
+
) : /* @__PURE__ */ React19.createElement(Text16, { dimColor: !payload }, payload || "(empty)"))), /* @__PURE__ */ React19.createElement(Box15, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React19.createElement(Box15, { marginBottom: 0 }, /* @__PURE__ */ React19.createElement(Text16, { color: focusedField === "secret" ? "green" : void 0 }, focusedField === "secret" ? "\u25B6 " : " ", "Secret Key:")), /* @__PURE__ */ React19.createElement(Box15, { marginLeft: 2, width: 60 }, focusedField === "secret" ? /* @__PURE__ */ React19.createElement(
|
|
9406
9033
|
TextInput10,
|
|
9407
9034
|
{
|
|
9408
9035
|
value: secret,
|
|
@@ -9410,9 +9037,9 @@ var JwtView = () => {
|
|
|
9410
9037
|
placeholder: "your-secret-key",
|
|
9411
9038
|
mask: "*"
|
|
9412
9039
|
}
|
|
9413
|
-
) : /* @__PURE__ */
|
|
9414
|
-
/* @__PURE__ */
|
|
9415
|
-
|
|
9040
|
+
) : /* @__PURE__ */ React19.createElement(Text16, { dimColor: !secret }, secret ? "*".repeat(secret.length) : "(empty)")))),
|
|
9041
|
+
/* @__PURE__ */ React19.createElement(Box15, { marginTop: 1 }, /* @__PURE__ */ React19.createElement(
|
|
9042
|
+
Text16,
|
|
9416
9043
|
{
|
|
9417
9044
|
bold: true,
|
|
9418
9045
|
backgroundColor: focusedField === "process" ? "green" : void 0,
|
|
@@ -9423,8 +9050,8 @@ var JwtView = () => {
|
|
|
9423
9050
|
mode === "decode" ? "Decode" : "Encode",
|
|
9424
9051
|
" ]"
|
|
9425
9052
|
))
|
|
9426
|
-
), error && /* @__PURE__ */
|
|
9427
|
-
|
|
9053
|
+
), error && /* @__PURE__ */ React19.createElement(
|
|
9054
|
+
Box15,
|
|
9428
9055
|
{
|
|
9429
9056
|
flexDirection: "column",
|
|
9430
9057
|
borderStyle: "single",
|
|
@@ -9433,9 +9060,9 @@ var JwtView = () => {
|
|
|
9433
9060
|
paddingY: 1,
|
|
9434
9061
|
marginBottom: 1
|
|
9435
9062
|
},
|
|
9436
|
-
/* @__PURE__ */
|
|
9437
|
-
), (result.header || result.token) && /* @__PURE__ */
|
|
9438
|
-
|
|
9063
|
+
/* @__PURE__ */ React19.createElement(Text16, { color: "red" }, "\u2717 Error: ", error)
|
|
9064
|
+
), (result.header || result.token) && /* @__PURE__ */ React19.createElement(
|
|
9065
|
+
Box15,
|
|
9439
9066
|
{
|
|
9440
9067
|
flexDirection: "column",
|
|
9441
9068
|
borderStyle: "single",
|
|
@@ -9443,23 +9070,23 @@ var JwtView = () => {
|
|
|
9443
9070
|
paddingX: 2,
|
|
9444
9071
|
paddingY: 1
|
|
9445
9072
|
},
|
|
9446
|
-
/* @__PURE__ */
|
|
9447
|
-
/* @__PURE__ */
|
|
9448
|
-
), /* @__PURE__ */
|
|
9073
|
+
/* @__PURE__ */ React19.createElement(Box15, { marginBottom: 1 }, /* @__PURE__ */ React19.createElement(Text16, { bold: true, color: "green" }, "\u2713 Result:"), copied && result.token && /* @__PURE__ */ React19.createElement(Box15, { marginLeft: 2 }, /* @__PURE__ */ React19.createElement(Text16, { color: "green" }, "\u2713 Copied to clipboard!"))),
|
|
9074
|
+
/* @__PURE__ */ React19.createElement(Box15, { flexDirection: "column" }, result.header && /* @__PURE__ */ React19.createElement(React19.Fragment, null, /* @__PURE__ */ React19.createElement(Text16, { bold: true, color: "yellow" }, "Header:"), /* @__PURE__ */ React19.createElement(Text16, null, JSON.stringify(result.header, null, 2)), /* @__PURE__ */ React19.createElement(Text16, null, " "), /* @__PURE__ */ React19.createElement(Text16, { bold: true, color: "yellow" }, "Payload:"), /* @__PURE__ */ React19.createElement(Text16, null, JSON.stringify(result.payload, null, 2)), /* @__PURE__ */ React19.createElement(Text16, null, " "), /* @__PURE__ */ React19.createElement(Text16, { bold: true, color: "yellow" }, "Signature:"), /* @__PURE__ */ React19.createElement(Text16, { dimColor: true }, result.signature)), result.token && /* @__PURE__ */ React19.createElement(React19.Fragment, null, /* @__PURE__ */ React19.createElement(Text16, { bold: true, color: "yellow" }, "Token:"), /* @__PURE__ */ React19.createElement(Text16, { wrap: "wrap" }, result.token)))
|
|
9075
|
+
), /* @__PURE__ */ React19.createElement(Box15, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 2 }, /* @__PURE__ */ React19.createElement(Text16, { dimColor: true }, "Tab: Next | Enter: Toggle/", mode === "decode" ? "Decode" : "Encode", " | C: Copy | Esc: Back")));
|
|
9449
9076
|
};
|
|
9450
9077
|
|
|
9451
9078
|
// src/ui/utils/views/CronView.tsx
|
|
9452
|
-
import
|
|
9453
|
-
import { Box as
|
|
9079
|
+
import React20, { useState as useState14 } from "react";
|
|
9080
|
+
import { Box as Box16, Text as Text17, useInput as useInput12 } from "ink";
|
|
9454
9081
|
import TextInput11 from "ink-text-input";
|
|
9455
9082
|
var CronView = () => {
|
|
9456
|
-
const [expression, setExpression] =
|
|
9457
|
-
const [result, setResult] =
|
|
9458
|
-
const [error, setError] =
|
|
9459
|
-
const [focusedField, setFocusedField] =
|
|
9460
|
-
const [copied, setCopied] =
|
|
9083
|
+
const [expression, setExpression] = useState14("");
|
|
9084
|
+
const [result, setResult] = useState14(null);
|
|
9085
|
+
const [error, setError] = useState14("");
|
|
9086
|
+
const [focusedField, setFocusedField] = useState14("expression");
|
|
9087
|
+
const [copied, setCopied] = useState14(false);
|
|
9461
9088
|
const service = new UtilsService();
|
|
9462
|
-
|
|
9089
|
+
useInput12((input5, key) => {
|
|
9463
9090
|
if (key.tab) {
|
|
9464
9091
|
setFocusedField(focusedField === "expression" ? "parse" : "expression");
|
|
9465
9092
|
} else if (key.return) {
|
|
@@ -9497,8 +9124,8 @@ ${result.nextRuns.join("\n")}`;
|
|
|
9497
9124
|
} catch (error2) {
|
|
9498
9125
|
}
|
|
9499
9126
|
};
|
|
9500
|
-
return /* @__PURE__ */
|
|
9501
|
-
|
|
9127
|
+
return /* @__PURE__ */ React20.createElement(Box16, { flexDirection: "column" }, /* @__PURE__ */ React20.createElement(Box16, { marginBottom: 1 }, /* @__PURE__ */ React20.createElement(Text17, { bold: true, color: "cyan" }, "\u23F0 Cron Expression Parser")), /* @__PURE__ */ React20.createElement(
|
|
9128
|
+
Box16,
|
|
9502
9129
|
{
|
|
9503
9130
|
flexDirection: "column",
|
|
9504
9131
|
borderStyle: "single",
|
|
@@ -9507,18 +9134,18 @@ ${result.nextRuns.join("\n")}`;
|
|
|
9507
9134
|
paddingY: 1,
|
|
9508
9135
|
marginBottom: 1
|
|
9509
9136
|
},
|
|
9510
|
-
/* @__PURE__ */
|
|
9511
|
-
/* @__PURE__ */
|
|
9137
|
+
/* @__PURE__ */ React20.createElement(Text17, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
|
|
9138
|
+
/* @__PURE__ */ React20.createElement(Box16, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React20.createElement(Box16, { marginBottom: 0 }, /* @__PURE__ */ React20.createElement(Text17, { color: focusedField === "expression" ? "green" : void 0 }, focusedField === "expression" ? "\u25B6 " : " ", "Cron Expression:")), /* @__PURE__ */ React20.createElement(Box16, { marginLeft: 2, width: 50 }, focusedField === "expression" ? /* @__PURE__ */ React20.createElement(
|
|
9512
9139
|
TextInput11,
|
|
9513
9140
|
{
|
|
9514
9141
|
value: expression,
|
|
9515
9142
|
onChange: setExpression,
|
|
9516
9143
|
placeholder: "0 5 * * * (5-field or 6-field)"
|
|
9517
9144
|
}
|
|
9518
|
-
) : /* @__PURE__ */
|
|
9519
|
-
/* @__PURE__ */
|
|
9520
|
-
/* @__PURE__ */
|
|
9521
|
-
|
|
9145
|
+
) : /* @__PURE__ */ React20.createElement(Text17, { dimColor: !expression }, expression || "(empty)"))),
|
|
9146
|
+
/* @__PURE__ */ React20.createElement(Box16, { marginTop: 1, marginBottom: 1 }, /* @__PURE__ */ React20.createElement(Text17, { dimColor: true }, 'Examples: "0 5 * * *" (daily at 5am), "*/15 * * * *" (every 15 min)')),
|
|
9147
|
+
/* @__PURE__ */ React20.createElement(Box16, { marginTop: 1 }, /* @__PURE__ */ React20.createElement(
|
|
9148
|
+
Text17,
|
|
9522
9149
|
{
|
|
9523
9150
|
bold: true,
|
|
9524
9151
|
backgroundColor: focusedField === "parse" ? "green" : void 0,
|
|
@@ -9527,8 +9154,8 @@ ${result.nextRuns.join("\n")}`;
|
|
|
9527
9154
|
focusedField === "parse" ? "\u25B6 " : " ",
|
|
9528
9155
|
"[ Parse Expression ]"
|
|
9529
9156
|
))
|
|
9530
|
-
), error && /* @__PURE__ */
|
|
9531
|
-
|
|
9157
|
+
), error && /* @__PURE__ */ React20.createElement(
|
|
9158
|
+
Box16,
|
|
9532
9159
|
{
|
|
9533
9160
|
flexDirection: "column",
|
|
9534
9161
|
borderStyle: "single",
|
|
@@ -9537,9 +9164,9 @@ ${result.nextRuns.join("\n")}`;
|
|
|
9537
9164
|
paddingY: 1,
|
|
9538
9165
|
marginBottom: 1
|
|
9539
9166
|
},
|
|
9540
|
-
/* @__PURE__ */
|
|
9541
|
-
), result && /* @__PURE__ */
|
|
9542
|
-
|
|
9167
|
+
/* @__PURE__ */ React20.createElement(Text17, { color: "red" }, "\u2717 Error: ", error)
|
|
9168
|
+
), result && /* @__PURE__ */ React20.createElement(
|
|
9169
|
+
Box16,
|
|
9543
9170
|
{
|
|
9544
9171
|
flexDirection: "column",
|
|
9545
9172
|
borderStyle: "single",
|
|
@@ -9547,25 +9174,25 @@ ${result.nextRuns.join("\n")}`;
|
|
|
9547
9174
|
paddingX: 2,
|
|
9548
9175
|
paddingY: 1
|
|
9549
9176
|
},
|
|
9550
|
-
/* @__PURE__ */
|
|
9551
|
-
/* @__PURE__ */
|
|
9552
|
-
), /* @__PURE__ */
|
|
9177
|
+
/* @__PURE__ */ React20.createElement(Box16, { marginBottom: 1 }, /* @__PURE__ */ React20.createElement(Text17, { bold: true, color: "green" }, "\u2713 Result:"), copied && /* @__PURE__ */ React20.createElement(Box16, { marginLeft: 2 }, /* @__PURE__ */ React20.createElement(Text17, { color: "green" }, "\u2713 Copied to clipboard!"))),
|
|
9178
|
+
/* @__PURE__ */ React20.createElement(Box16, { flexDirection: "column" }, /* @__PURE__ */ React20.createElement(Text17, { bold: true, color: "yellow" }, "Expression:"), /* @__PURE__ */ React20.createElement(Text17, null, expression), /* @__PURE__ */ React20.createElement(Text17, null, " "), /* @__PURE__ */ React20.createElement(Text17, { bold: true, color: "yellow" }, "Meaning:"), /* @__PURE__ */ React20.createElement(Text17, null, result.description), /* @__PURE__ */ React20.createElement(Text17, null, " "), /* @__PURE__ */ React20.createElement(Text17, { bold: true, color: "yellow" }, "Next 5 executions:"), result.nextRuns.map((run, index) => /* @__PURE__ */ React20.createElement(Text17, { key: index }, " ", index + 1, ". ", run)))
|
|
9179
|
+
), /* @__PURE__ */ React20.createElement(Box16, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 2 }, /* @__PURE__ */ React20.createElement(Text17, { dimColor: true }, "Tab: Next | Enter: Parse | C: Copy | Esc: Back")));
|
|
9553
9180
|
};
|
|
9554
9181
|
|
|
9555
9182
|
// src/ui/utils/views/TimezoneView.tsx
|
|
9556
|
-
import
|
|
9557
|
-
import { Box as
|
|
9183
|
+
import React21, { useState as useState15 } from "react";
|
|
9184
|
+
import { Box as Box17, Text as Text18, useInput as useInput13 } from "ink";
|
|
9558
9185
|
import TextInput12 from "ink-text-input";
|
|
9559
9186
|
var TimezoneView = () => {
|
|
9560
|
-
const [time, setTime] =
|
|
9561
|
-
const [fromTz, setFromTz] =
|
|
9562
|
-
const [toTz, setToTz] =
|
|
9563
|
-
const [result, setResult] =
|
|
9564
|
-
const [error, setError] =
|
|
9565
|
-
const [focusedField, setFocusedField] =
|
|
9566
|
-
const [copied, setCopied] =
|
|
9187
|
+
const [time, setTime] = useState15("");
|
|
9188
|
+
const [fromTz, setFromTz] = useState15("UTC");
|
|
9189
|
+
const [toTz, setToTz] = useState15("America/New_York");
|
|
9190
|
+
const [result, setResult] = useState15("");
|
|
9191
|
+
const [error, setError] = useState15("");
|
|
9192
|
+
const [focusedField, setFocusedField] = useState15("time");
|
|
9193
|
+
const [copied, setCopied] = useState15(false);
|
|
9567
9194
|
const service = new UtilsService();
|
|
9568
|
-
|
|
9195
|
+
useInput13((input5, key) => {
|
|
9569
9196
|
if (key.tab) {
|
|
9570
9197
|
const fields = ["time", "from", "to", "convert"];
|
|
9571
9198
|
const currentIndex = fields.indexOf(focusedField);
|
|
@@ -9604,8 +9231,8 @@ var TimezoneView = () => {
|
|
|
9604
9231
|
} catch (error2) {
|
|
9605
9232
|
}
|
|
9606
9233
|
};
|
|
9607
|
-
return /* @__PURE__ */
|
|
9608
|
-
|
|
9234
|
+
return /* @__PURE__ */ React21.createElement(Box17, { flexDirection: "column" }, /* @__PURE__ */ React21.createElement(Box17, { marginBottom: 1 }, /* @__PURE__ */ React21.createElement(Text18, { bold: true, color: "cyan" }, "\u{1F30D} Timezone Converter")), /* @__PURE__ */ React21.createElement(
|
|
9235
|
+
Box17,
|
|
9609
9236
|
{
|
|
9610
9237
|
flexDirection: "column",
|
|
9611
9238
|
borderStyle: "single",
|
|
@@ -9614,34 +9241,34 @@ var TimezoneView = () => {
|
|
|
9614
9241
|
paddingY: 1,
|
|
9615
9242
|
marginBottom: 1
|
|
9616
9243
|
},
|
|
9617
|
-
/* @__PURE__ */
|
|
9618
|
-
/* @__PURE__ */
|
|
9244
|
+
/* @__PURE__ */ React21.createElement(Text18, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
|
|
9245
|
+
/* @__PURE__ */ React21.createElement(Box17, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React21.createElement(Box17, { marginBottom: 0 }, /* @__PURE__ */ React21.createElement(Text18, { color: focusedField === "time" ? "green" : void 0 }, focusedField === "time" ? "\u25B6 " : " ", "Time:")), /* @__PURE__ */ React21.createElement(Box17, { marginLeft: 2, width: 50 }, focusedField === "time" ? /* @__PURE__ */ React21.createElement(
|
|
9619
9246
|
TextInput12,
|
|
9620
9247
|
{
|
|
9621
9248
|
value: time,
|
|
9622
9249
|
onChange: setTime,
|
|
9623
9250
|
placeholder: "2024-01-15 10:00:00"
|
|
9624
9251
|
}
|
|
9625
|
-
) : /* @__PURE__ */
|
|
9626
|
-
/* @__PURE__ */
|
|
9252
|
+
) : /* @__PURE__ */ React21.createElement(Text18, { dimColor: !time }, time || "(empty)"))),
|
|
9253
|
+
/* @__PURE__ */ React21.createElement(Box17, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React21.createElement(Box17, { marginBottom: 0 }, /* @__PURE__ */ React21.createElement(Text18, { color: focusedField === "from" ? "green" : void 0 }, focusedField === "from" ? "\u25B6 " : " ", "From Timezone:")), /* @__PURE__ */ React21.createElement(Box17, { marginLeft: 2, width: 50 }, focusedField === "from" ? /* @__PURE__ */ React21.createElement(
|
|
9627
9254
|
TextInput12,
|
|
9628
9255
|
{
|
|
9629
9256
|
value: fromTz,
|
|
9630
9257
|
onChange: setFromTz,
|
|
9631
9258
|
placeholder: "UTC or America/New_York"
|
|
9632
9259
|
}
|
|
9633
|
-
) : /* @__PURE__ */
|
|
9634
|
-
/* @__PURE__ */
|
|
9260
|
+
) : /* @__PURE__ */ React21.createElement(Text18, { dimColor: !fromTz }, fromTz || "(empty)"))),
|
|
9261
|
+
/* @__PURE__ */ React21.createElement(Box17, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React21.createElement(Box17, { marginBottom: 0 }, /* @__PURE__ */ React21.createElement(Text18, { color: focusedField === "to" ? "green" : void 0 }, focusedField === "to" ? "\u25B6 " : " ", "To Timezone:")), /* @__PURE__ */ React21.createElement(Box17, { marginLeft: 2, width: 50 }, focusedField === "to" ? /* @__PURE__ */ React21.createElement(
|
|
9635
9262
|
TextInput12,
|
|
9636
9263
|
{
|
|
9637
9264
|
value: toTz,
|
|
9638
9265
|
onChange: setToTz,
|
|
9639
9266
|
placeholder: "Asia/Tokyo or Europe/London"
|
|
9640
9267
|
}
|
|
9641
|
-
) : /* @__PURE__ */
|
|
9642
|
-
/* @__PURE__ */
|
|
9643
|
-
/* @__PURE__ */
|
|
9644
|
-
|
|
9268
|
+
) : /* @__PURE__ */ React21.createElement(Text18, { dimColor: !toTz }, toTz || "(empty)"))),
|
|
9269
|
+
/* @__PURE__ */ React21.createElement(Box17, { marginBottom: 1 }, /* @__PURE__ */ React21.createElement(Text18, { dimColor: true }, "Common: UTC, America/New_York, Europe/London, Asia/Tokyo")),
|
|
9270
|
+
/* @__PURE__ */ React21.createElement(Box17, { marginTop: 1 }, /* @__PURE__ */ React21.createElement(
|
|
9271
|
+
Text18,
|
|
9645
9272
|
{
|
|
9646
9273
|
bold: true,
|
|
9647
9274
|
backgroundColor: focusedField === "convert" ? "green" : void 0,
|
|
@@ -9650,8 +9277,8 @@ var TimezoneView = () => {
|
|
|
9650
9277
|
focusedField === "convert" ? "\u25B6 " : " ",
|
|
9651
9278
|
"[ Convert ]"
|
|
9652
9279
|
))
|
|
9653
|
-
), error && /* @__PURE__ */
|
|
9654
|
-
|
|
9280
|
+
), error && /* @__PURE__ */ React21.createElement(
|
|
9281
|
+
Box17,
|
|
9655
9282
|
{
|
|
9656
9283
|
flexDirection: "column",
|
|
9657
9284
|
borderStyle: "single",
|
|
@@ -9660,9 +9287,9 @@ var TimezoneView = () => {
|
|
|
9660
9287
|
paddingY: 1,
|
|
9661
9288
|
marginBottom: 1
|
|
9662
9289
|
},
|
|
9663
|
-
/* @__PURE__ */
|
|
9664
|
-
), result && /* @__PURE__ */
|
|
9665
|
-
|
|
9290
|
+
/* @__PURE__ */ React21.createElement(Text18, { color: "red" }, "\u2717 Error: ", error)
|
|
9291
|
+
), result && /* @__PURE__ */ React21.createElement(
|
|
9292
|
+
Box17,
|
|
9666
9293
|
{
|
|
9667
9294
|
flexDirection: "column",
|
|
9668
9295
|
borderStyle: "single",
|
|
@@ -9670,28 +9297,28 @@ var TimezoneView = () => {
|
|
|
9670
9297
|
paddingX: 2,
|
|
9671
9298
|
paddingY: 1
|
|
9672
9299
|
},
|
|
9673
|
-
/* @__PURE__ */
|
|
9674
|
-
/* @__PURE__ */
|
|
9675
|
-
), /* @__PURE__ */
|
|
9300
|
+
/* @__PURE__ */ React21.createElement(Box17, { marginBottom: 1 }, /* @__PURE__ */ React21.createElement(Text18, { bold: true, color: "green" }, "\u2713 Result:"), copied && /* @__PURE__ */ React21.createElement(Box17, { marginLeft: 2 }, /* @__PURE__ */ React21.createElement(Text18, { color: "green" }, "\u2713 Copied to clipboard!"))),
|
|
9301
|
+
/* @__PURE__ */ React21.createElement(Box17, { flexDirection: "column" }, /* @__PURE__ */ React21.createElement(Text18, { dimColor: true }, "From: ", fromTz), /* @__PURE__ */ React21.createElement(Text18, { dimColor: true }, "To: ", toTz), /* @__PURE__ */ React21.createElement(Box17, { marginTop: 1 }, /* @__PURE__ */ React21.createElement(Text18, { wrap: "wrap" }, result)))
|
|
9302
|
+
), /* @__PURE__ */ React21.createElement(Box17, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 2 }, /* @__PURE__ */ React21.createElement(Text18, { dimColor: true }, "Tab: Next | Enter: Convert | C: Copy | Esc: Back")));
|
|
9676
9303
|
};
|
|
9677
9304
|
|
|
9678
9305
|
// src/ui/utils/views/HttpView.tsx
|
|
9679
|
-
import
|
|
9680
|
-
import { Box as
|
|
9306
|
+
import React22, { useState as useState16 } from "react";
|
|
9307
|
+
import { Box as Box18, Text as Text19, useInput as useInput14 } from "ink";
|
|
9681
9308
|
import TextInput13 from "ink-text-input";
|
|
9682
9309
|
var METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE"];
|
|
9683
9310
|
var HttpView = () => {
|
|
9684
|
-
const [url, setUrl] =
|
|
9685
|
-
const [method, setMethod] =
|
|
9686
|
-
const [headers, setHeaders] =
|
|
9687
|
-
const [body, setBody] =
|
|
9688
|
-
const [response, setResponse] =
|
|
9689
|
-
const [error, setError] =
|
|
9690
|
-
const [loading, setLoading] =
|
|
9691
|
-
const [focusedField, setFocusedField] =
|
|
9692
|
-
const [copied, setCopied] =
|
|
9311
|
+
const [url, setUrl] = useState16("");
|
|
9312
|
+
const [method, setMethod] = useState16("GET");
|
|
9313
|
+
const [headers, setHeaders] = useState16("");
|
|
9314
|
+
const [body, setBody] = useState16("");
|
|
9315
|
+
const [response, setResponse] = useState16(null);
|
|
9316
|
+
const [error, setError] = useState16("");
|
|
9317
|
+
const [loading, setLoading] = useState16(false);
|
|
9318
|
+
const [focusedField, setFocusedField] = useState16("url");
|
|
9319
|
+
const [copied, setCopied] = useState16(false);
|
|
9693
9320
|
const service = new UtilsService();
|
|
9694
|
-
|
|
9321
|
+
useInput14((input5, key) => {
|
|
9695
9322
|
if (loading) return;
|
|
9696
9323
|
if (key.tab) {
|
|
9697
9324
|
const fields = ["url", "method", "headers", "body", "send"];
|
|
@@ -9752,8 +9379,8 @@ var HttpView = () => {
|
|
|
9752
9379
|
} catch (error2) {
|
|
9753
9380
|
}
|
|
9754
9381
|
};
|
|
9755
|
-
return /* @__PURE__ */
|
|
9756
|
-
|
|
9382
|
+
return /* @__PURE__ */ React22.createElement(Box18, { flexDirection: "column" }, /* @__PURE__ */ React22.createElement(Box18, { marginBottom: 1 }, /* @__PURE__ */ React22.createElement(Text19, { bold: true, color: "cyan" }, "\u{1F310} HTTP Request")), /* @__PURE__ */ React22.createElement(
|
|
9383
|
+
Box18,
|
|
9757
9384
|
{
|
|
9758
9385
|
flexDirection: "column",
|
|
9759
9386
|
borderStyle: "single",
|
|
@@ -9762,34 +9389,34 @@ var HttpView = () => {
|
|
|
9762
9389
|
paddingY: 1,
|
|
9763
9390
|
marginBottom: 1
|
|
9764
9391
|
},
|
|
9765
|
-
/* @__PURE__ */
|
|
9766
|
-
/* @__PURE__ */
|
|
9392
|
+
/* @__PURE__ */ React22.createElement(Text19, { bold: true, color: "yellow", marginBottom: 1 }, "Request:"),
|
|
9393
|
+
/* @__PURE__ */ React22.createElement(Box18, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React22.createElement(Box18, { marginBottom: 0 }, /* @__PURE__ */ React22.createElement(Text19, { color: focusedField === "url" ? "green" : void 0 }, focusedField === "url" ? "\u25B6 " : " ", "URL:")), /* @__PURE__ */ React22.createElement(Box18, { marginLeft: 2, width: 60 }, focusedField === "url" ? /* @__PURE__ */ React22.createElement(
|
|
9767
9394
|
TextInput13,
|
|
9768
9395
|
{
|
|
9769
9396
|
value: url,
|
|
9770
9397
|
onChange: setUrl,
|
|
9771
9398
|
placeholder: "https://api.example.com/endpoint"
|
|
9772
9399
|
}
|
|
9773
|
-
) : /* @__PURE__ */
|
|
9774
|
-
/* @__PURE__ */
|
|
9775
|
-
/* @__PURE__ */
|
|
9400
|
+
) : /* @__PURE__ */ React22.createElement(Text19, { dimColor: !url }, url || "(empty)"))),
|
|
9401
|
+
/* @__PURE__ */ React22.createElement(Box18, { marginBottom: 1 }, /* @__PURE__ */ React22.createElement(Box18, { width: 20 }, /* @__PURE__ */ React22.createElement(Text19, { color: focusedField === "method" ? "green" : void 0 }, focusedField === "method" ? "\u25B6 " : " ", "Method:")), /* @__PURE__ */ React22.createElement(Text19, { bold: true, color: focusedField === "method" ? "yellow" : void 0 }, method), focusedField === "method" && /* @__PURE__ */ React22.createElement(Text19, { dimColor: true }, " (\u2190 \u2192 to change)")),
|
|
9402
|
+
/* @__PURE__ */ React22.createElement(Box18, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React22.createElement(Box18, { marginBottom: 0 }, /* @__PURE__ */ React22.createElement(Text19, { color: focusedField === "headers" ? "green" : void 0 }, focusedField === "headers" ? "\u25B6 " : " ", "Headers (one per line, Key: Value):")), /* @__PURE__ */ React22.createElement(Box18, { marginLeft: 2, width: 60 }, focusedField === "headers" ? /* @__PURE__ */ React22.createElement(
|
|
9776
9403
|
TextInput13,
|
|
9777
9404
|
{
|
|
9778
9405
|
value: headers,
|
|
9779
9406
|
onChange: setHeaders,
|
|
9780
9407
|
placeholder: "Authorization: Bearer token"
|
|
9781
9408
|
}
|
|
9782
|
-
) : /* @__PURE__ */
|
|
9783
|
-
(method === "POST" || method === "PUT" || method === "PATCH") && /* @__PURE__ */
|
|
9409
|
+
) : /* @__PURE__ */ React22.createElement(Text19, { dimColor: !headers }, headers || "(none)"))),
|
|
9410
|
+
(method === "POST" || method === "PUT" || method === "PATCH") && /* @__PURE__ */ React22.createElement(Box18, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React22.createElement(Box18, { marginBottom: 0 }, /* @__PURE__ */ React22.createElement(Text19, { color: focusedField === "body" ? "green" : void 0 }, focusedField === "body" ? "\u25B6 " : " ", "Body (JSON):")), /* @__PURE__ */ React22.createElement(Box18, { marginLeft: 2, width: 60 }, focusedField === "body" ? /* @__PURE__ */ React22.createElement(
|
|
9784
9411
|
TextInput13,
|
|
9785
9412
|
{
|
|
9786
9413
|
value: body,
|
|
9787
9414
|
onChange: setBody,
|
|
9788
9415
|
placeholder: '{"key":"value"}'
|
|
9789
9416
|
}
|
|
9790
|
-
) : /* @__PURE__ */
|
|
9791
|
-
/* @__PURE__ */
|
|
9792
|
-
|
|
9417
|
+
) : /* @__PURE__ */ React22.createElement(Text19, { dimColor: !body }, body || "(empty)"))),
|
|
9418
|
+
/* @__PURE__ */ React22.createElement(Box18, { marginTop: 1 }, /* @__PURE__ */ React22.createElement(
|
|
9419
|
+
Text19,
|
|
9793
9420
|
{
|
|
9794
9421
|
bold: true,
|
|
9795
9422
|
backgroundColor: focusedField === "send" ? "green" : void 0,
|
|
@@ -9800,8 +9427,8 @@ var HttpView = () => {
|
|
|
9800
9427
|
loading ? "Sending..." : "Send Request",
|
|
9801
9428
|
" ]"
|
|
9802
9429
|
))
|
|
9803
|
-
), error && /* @__PURE__ */
|
|
9804
|
-
|
|
9430
|
+
), error && /* @__PURE__ */ React22.createElement(
|
|
9431
|
+
Box18,
|
|
9805
9432
|
{
|
|
9806
9433
|
flexDirection: "column",
|
|
9807
9434
|
borderStyle: "single",
|
|
@@ -9810,9 +9437,9 @@ var HttpView = () => {
|
|
|
9810
9437
|
paddingY: 1,
|
|
9811
9438
|
marginBottom: 1
|
|
9812
9439
|
},
|
|
9813
|
-
/* @__PURE__ */
|
|
9814
|
-
), response && /* @__PURE__ */
|
|
9815
|
-
|
|
9440
|
+
/* @__PURE__ */ React22.createElement(Text19, { color: "red" }, "\u2717 Error: ", error)
|
|
9441
|
+
), response && /* @__PURE__ */ React22.createElement(
|
|
9442
|
+
Box18,
|
|
9816
9443
|
{
|
|
9817
9444
|
flexDirection: "column",
|
|
9818
9445
|
borderStyle: "single",
|
|
@@ -9820,23 +9447,23 @@ var HttpView = () => {
|
|
|
9820
9447
|
paddingX: 2,
|
|
9821
9448
|
paddingY: 1
|
|
9822
9449
|
},
|
|
9823
|
-
/* @__PURE__ */
|
|
9824
|
-
/* @__PURE__ */
|
|
9825
|
-
), /* @__PURE__ */
|
|
9450
|
+
/* @__PURE__ */ React22.createElement(Box18, { marginBottom: 1 }, /* @__PURE__ */ React22.createElement(Text19, { bold: true, color: "green" }, "\u2713 Response:"), copied && /* @__PURE__ */ React22.createElement(Box18, { marginLeft: 2 }, /* @__PURE__ */ React22.createElement(Text19, { color: "green" }, "\u2713 Copied body to clipboard!"))),
|
|
9451
|
+
/* @__PURE__ */ React22.createElement(Box18, { flexDirection: "column" }, /* @__PURE__ */ React22.createElement(Text19, null, "Status: ", /* @__PURE__ */ React22.createElement(Text19, { color: response.status < 400 ? "green" : "red" }, response.status)), /* @__PURE__ */ React22.createElement(Text19, null, "Time: ", response.time, "ms"), /* @__PURE__ */ React22.createElement(Text19, null, "Size: ", response.size), /* @__PURE__ */ React22.createElement(Text19, null, " "), /* @__PURE__ */ React22.createElement(Text19, { bold: true, color: "yellow" }, "Headers:"), Object.entries(response.headers).slice(0, 5).map(([key, value]) => /* @__PURE__ */ React22.createElement(Text19, { key, dimColor: true }, " ", key, ": ", value)), /* @__PURE__ */ React22.createElement(Text19, null, " "), /* @__PURE__ */ React22.createElement(Text19, { bold: true, color: "yellow" }, "Body:"), /* @__PURE__ */ React22.createElement(Text19, null, typeof response.body === "string" ? response.body.slice(0, 500) : JSON.stringify(response.body, null, 2).slice(0, 500)))
|
|
9452
|
+
), /* @__PURE__ */ React22.createElement(Box18, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 2 }, /* @__PURE__ */ React22.createElement(Text19, { dimColor: true }, "Tab: Next | \u2190/\u2192: Change method | Enter: Send | C: Copy body | Esc: Back")));
|
|
9826
9453
|
};
|
|
9827
9454
|
|
|
9828
9455
|
// src/ui/utils/views/MarkdownView.tsx
|
|
9829
|
-
import
|
|
9830
|
-
import { Box as
|
|
9456
|
+
import React23, { useState as useState17 } from "react";
|
|
9457
|
+
import { Box as Box19, Text as Text20, useInput as useInput15 } from "ink";
|
|
9831
9458
|
import TextInput14 from "ink-text-input";
|
|
9832
9459
|
import * as fs15 from "fs";
|
|
9833
9460
|
import * as path7 from "path";
|
|
9834
9461
|
var MarkdownView = () => {
|
|
9835
|
-
const [filePath, setFilePath] =
|
|
9836
|
-
const [content, setContent] =
|
|
9837
|
-
const [error, setError] =
|
|
9838
|
-
const [focusedField, setFocusedField] =
|
|
9839
|
-
|
|
9462
|
+
const [filePath, setFilePath] = useState17("");
|
|
9463
|
+
const [content, setContent] = useState17("");
|
|
9464
|
+
const [error, setError] = useState17("");
|
|
9465
|
+
const [focusedField, setFocusedField] = useState17("file");
|
|
9466
|
+
useInput15((input5, key) => {
|
|
9840
9467
|
if (key.tab) {
|
|
9841
9468
|
setFocusedField(focusedField === "file" ? "preview" : "file");
|
|
9842
9469
|
} else if (key.return) {
|
|
@@ -9877,8 +9504,8 @@ ${code.trim()}
|
|
|
9877
9504
|
setContent("");
|
|
9878
9505
|
}
|
|
9879
9506
|
};
|
|
9880
|
-
return /* @__PURE__ */
|
|
9881
|
-
|
|
9507
|
+
return /* @__PURE__ */ React23.createElement(Box19, { flexDirection: "column" }, /* @__PURE__ */ React23.createElement(Box19, { marginBottom: 1 }, /* @__PURE__ */ React23.createElement(Text20, { bold: true, color: "cyan" }, "\u{1F4C4} Markdown Preview")), /* @__PURE__ */ React23.createElement(
|
|
9508
|
+
Box19,
|
|
9882
9509
|
{
|
|
9883
9510
|
flexDirection: "column",
|
|
9884
9511
|
borderStyle: "single",
|
|
@@ -9887,17 +9514,17 @@ ${code.trim()}
|
|
|
9887
9514
|
paddingY: 1,
|
|
9888
9515
|
marginBottom: 1
|
|
9889
9516
|
},
|
|
9890
|
-
/* @__PURE__ */
|
|
9891
|
-
/* @__PURE__ */
|
|
9517
|
+
/* @__PURE__ */ React23.createElement(Text20, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
|
|
9518
|
+
/* @__PURE__ */ React23.createElement(Box19, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React23.createElement(Box19, { marginBottom: 0 }, /* @__PURE__ */ React23.createElement(Text20, { color: focusedField === "file" ? "green" : void 0 }, focusedField === "file" ? "\u25B6 " : " ", "File path:")), /* @__PURE__ */ React23.createElement(Box19, { marginLeft: 2, width: 60 }, focusedField === "file" ? /* @__PURE__ */ React23.createElement(
|
|
9892
9519
|
TextInput14,
|
|
9893
9520
|
{
|
|
9894
9521
|
value: filePath,
|
|
9895
9522
|
onChange: setFilePath,
|
|
9896
9523
|
placeholder: "./README.md or /path/to/file.md"
|
|
9897
9524
|
}
|
|
9898
|
-
) : /* @__PURE__ */
|
|
9899
|
-
/* @__PURE__ */
|
|
9900
|
-
|
|
9525
|
+
) : /* @__PURE__ */ React23.createElement(Text20, { dimColor: !filePath }, filePath || "(empty)"))),
|
|
9526
|
+
/* @__PURE__ */ React23.createElement(Box19, { marginTop: 1 }, /* @__PURE__ */ React23.createElement(
|
|
9527
|
+
Text20,
|
|
9901
9528
|
{
|
|
9902
9529
|
bold: true,
|
|
9903
9530
|
backgroundColor: focusedField === "preview" ? "green" : void 0,
|
|
@@ -9906,8 +9533,8 @@ ${code.trim()}
|
|
|
9906
9533
|
focusedField === "preview" ? "\u25B6 " : " ",
|
|
9907
9534
|
"[ Preview File ]"
|
|
9908
9535
|
))
|
|
9909
|
-
), error && /* @__PURE__ */
|
|
9910
|
-
|
|
9536
|
+
), error && /* @__PURE__ */ React23.createElement(
|
|
9537
|
+
Box19,
|
|
9911
9538
|
{
|
|
9912
9539
|
flexDirection: "column",
|
|
9913
9540
|
borderStyle: "single",
|
|
@@ -9916,9 +9543,9 @@ ${code.trim()}
|
|
|
9916
9543
|
paddingY: 1,
|
|
9917
9544
|
marginBottom: 1
|
|
9918
9545
|
},
|
|
9919
|
-
/* @__PURE__ */
|
|
9920
|
-
), content && /* @__PURE__ */
|
|
9921
|
-
|
|
9546
|
+
/* @__PURE__ */ React23.createElement(Text20, { color: "red" }, "\u2717 Error: ", error)
|
|
9547
|
+
), content && /* @__PURE__ */ React23.createElement(
|
|
9548
|
+
Box19,
|
|
9922
9549
|
{
|
|
9923
9550
|
flexDirection: "column",
|
|
9924
9551
|
borderStyle: "single",
|
|
@@ -9926,9 +9553,9 @@ ${code.trim()}
|
|
|
9926
9553
|
paddingX: 2,
|
|
9927
9554
|
paddingY: 1
|
|
9928
9555
|
},
|
|
9929
|
-
/* @__PURE__ */
|
|
9930
|
-
/* @__PURE__ */
|
|
9931
|
-
), /* @__PURE__ */
|
|
9556
|
+
/* @__PURE__ */ React23.createElement(Box19, { marginBottom: 1 }, /* @__PURE__ */ React23.createElement(Text20, { bold: true, color: "green" }, "\u2713 Preview:")),
|
|
9557
|
+
/* @__PURE__ */ React23.createElement(Box19, { flexDirection: "column" }, /* @__PURE__ */ React23.createElement(Text20, null, content))
|
|
9558
|
+
), /* @__PURE__ */ React23.createElement(Box19, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 2 }, /* @__PURE__ */ React23.createElement(Text20, { dimColor: true }, "Tab: Next | Enter: Preview | Esc: Back")));
|
|
9932
9559
|
};
|
|
9933
9560
|
|
|
9934
9561
|
// src/ui/utils/UtilsApp.tsx
|
|
@@ -9948,10 +9575,10 @@ var MENU_ITEMS = [
|
|
|
9948
9575
|
{ id: "markdown", icon: "\u{1F4C4}", label: "Markdown", description: "Preview markdown" }
|
|
9949
9576
|
];
|
|
9950
9577
|
var UtilsApp = ({ onExit }) => {
|
|
9951
|
-
const [selectedIndex, setSelectedIndex] =
|
|
9952
|
-
const [activeView, setActiveView] =
|
|
9953
|
-
const { exit } =
|
|
9954
|
-
|
|
9578
|
+
const [selectedIndex, setSelectedIndex] = useState18(0);
|
|
9579
|
+
const [activeView, setActiveView] = useState18(null);
|
|
9580
|
+
const { exit } = useApp4();
|
|
9581
|
+
useInput16((input5, key) => {
|
|
9955
9582
|
if (activeView) {
|
|
9956
9583
|
if (key.escape) {
|
|
9957
9584
|
setActiveView(null);
|
|
@@ -9969,8 +9596,8 @@ var UtilsApp = ({ onExit }) => {
|
|
|
9969
9596
|
exit();
|
|
9970
9597
|
}
|
|
9971
9598
|
});
|
|
9972
|
-
return /* @__PURE__ */
|
|
9973
|
-
|
|
9599
|
+
return /* @__PURE__ */ React24.createElement(Box20, { flexDirection: "column", width: "100%", height: "100%" }, /* @__PURE__ */ React24.createElement(
|
|
9600
|
+
Box20,
|
|
9974
9601
|
{
|
|
9975
9602
|
borderStyle: "single",
|
|
9976
9603
|
borderColor: "cyan",
|
|
@@ -9978,10 +9605,10 @@ var UtilsApp = ({ onExit }) => {
|
|
|
9978
9605
|
paddingY: 0,
|
|
9979
9606
|
marginBottom: 1
|
|
9980
9607
|
},
|
|
9981
|
-
/* @__PURE__ */
|
|
9982
|
-
/* @__PURE__ */
|
|
9983
|
-
), /* @__PURE__ */
|
|
9984
|
-
|
|
9608
|
+
/* @__PURE__ */ React24.createElement(Text21, { bold: true, color: "cyan" }, "\u{1F6E0}\uFE0F Developer Utilities - Interactive Mode"),
|
|
9609
|
+
/* @__PURE__ */ React24.createElement(Box20, { marginLeft: "auto" }, /* @__PURE__ */ React24.createElement(Text21, { dimColor: true }, "Press Ctrl+Q to quit"))
|
|
9610
|
+
), /* @__PURE__ */ React24.createElement(Box20, { flexGrow: 1 }, /* @__PURE__ */ React24.createElement(
|
|
9611
|
+
Box20,
|
|
9985
9612
|
{
|
|
9986
9613
|
flexDirection: "column",
|
|
9987
9614
|
width: 30,
|
|
@@ -9991,9 +9618,9 @@ var UtilsApp = ({ onExit }) => {
|
|
|
9991
9618
|
paddingY: 1,
|
|
9992
9619
|
marginRight: 1
|
|
9993
9620
|
},
|
|
9994
|
-
/* @__PURE__ */
|
|
9995
|
-
MENU_ITEMS.map((item, index) => /* @__PURE__ */
|
|
9996
|
-
|
|
9621
|
+
/* @__PURE__ */ React24.createElement(Box20, { marginBottom: 1 }, /* @__PURE__ */ React24.createElement(Text21, { bold: true, color: "yellow" }, "Select Utility:")),
|
|
9622
|
+
MENU_ITEMS.map((item, index) => /* @__PURE__ */ React24.createElement(Box20, { key: item.id, marginBottom: 0 }, /* @__PURE__ */ React24.createElement(
|
|
9623
|
+
Text21,
|
|
9997
9624
|
{
|
|
9998
9625
|
color: selectedIndex === index && !activeView ? "green" : void 0,
|
|
9999
9626
|
bold: selectedIndex === index && !activeView,
|
|
@@ -10004,9 +9631,9 @@ var UtilsApp = ({ onExit }) => {
|
|
|
10004
9631
|
" ",
|
|
10005
9632
|
item.label
|
|
10006
9633
|
))),
|
|
10007
|
-
/* @__PURE__ */
|
|
10008
|
-
), /* @__PURE__ */
|
|
10009
|
-
|
|
9634
|
+
/* @__PURE__ */ React24.createElement(Box20, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 1 }, /* @__PURE__ */ React24.createElement(Text21, { dimColor: true }, "\u2191/\u2193: Navigate", "\n", "Enter: Select", "\n", "Esc: Back/Quit"))
|
|
9635
|
+
), /* @__PURE__ */ React24.createElement(
|
|
9636
|
+
Box20,
|
|
10010
9637
|
{
|
|
10011
9638
|
flexDirection: "column",
|
|
10012
9639
|
flexGrow: 1,
|
|
@@ -10015,21 +9642,21 @@ var UtilsApp = ({ onExit }) => {
|
|
|
10015
9642
|
paddingX: 2,
|
|
10016
9643
|
paddingY: 1
|
|
10017
9644
|
},
|
|
10018
|
-
activeView ? /* @__PURE__ */
|
|
10019
|
-
)), /* @__PURE__ */
|
|
10020
|
-
|
|
9645
|
+
activeView ? /* @__PURE__ */ React24.createElement(ActiveUtilityView, { utilityType: activeView }) : /* @__PURE__ */ React24.createElement(WelcomeView, { selectedItem: MENU_ITEMS[selectedIndex] })
|
|
9646
|
+
)), /* @__PURE__ */ React24.createElement(
|
|
9647
|
+
Box20,
|
|
10021
9648
|
{
|
|
10022
9649
|
borderStyle: "single",
|
|
10023
9650
|
borderColor: "gray",
|
|
10024
9651
|
paddingX: 2,
|
|
10025
9652
|
marginTop: 1
|
|
10026
9653
|
},
|
|
10027
|
-
/* @__PURE__ */
|
|
9654
|
+
/* @__PURE__ */ React24.createElement(Text21, { dimColor: true }, "jai1-cli | Use arrow keys or j/k to navigate")
|
|
10028
9655
|
));
|
|
10029
9656
|
};
|
|
10030
9657
|
var WelcomeView = ({ selectedItem }) => {
|
|
10031
|
-
return /* @__PURE__ */
|
|
10032
|
-
|
|
9658
|
+
return /* @__PURE__ */ React24.createElement(Box20, { flexDirection: "column" }, /* @__PURE__ */ React24.createElement(Box20, { marginBottom: 1 }, /* @__PURE__ */ React24.createElement(Text21, { bold: true, color: "cyan" }, "Welcome to Developer Utilities")), /* @__PURE__ */ React24.createElement(Box20, { marginBottom: 2 }, /* @__PURE__ */ React24.createElement(Text21, null, "Select a utility from the left menu to get started.")), /* @__PURE__ */ React24.createElement(
|
|
9659
|
+
Box20,
|
|
10033
9660
|
{
|
|
10034
9661
|
borderStyle: "single",
|
|
10035
9662
|
borderColor: "yellow",
|
|
@@ -10037,49 +9664,49 @@ var WelcomeView = ({ selectedItem }) => {
|
|
|
10037
9664
|
paddingY: 1,
|
|
10038
9665
|
marginBottom: 2
|
|
10039
9666
|
},
|
|
10040
|
-
/* @__PURE__ */
|
|
10041
|
-
), /* @__PURE__ */
|
|
9667
|
+
/* @__PURE__ */ React24.createElement(Box20, { flexDirection: "column" }, /* @__PURE__ */ React24.createElement(Text21, { bold: true, color: "yellow" }, selectedItem.icon, " ", selectedItem.label), /* @__PURE__ */ React24.createElement(Text21, { dimColor: true }, selectedItem.description))
|
|
9668
|
+
), /* @__PURE__ */ React24.createElement(Box20, { marginBottom: 1 }, /* @__PURE__ */ React24.createElement(Text21, { bold: true }, "Quick Actions:")), /* @__PURE__ */ React24.createElement(Box20, { flexDirection: "column", marginLeft: 2 }, /* @__PURE__ */ React24.createElement(Text21, null, "\u2022 Press ", /* @__PURE__ */ React24.createElement(Text21, { color: "green" }, "Enter"), " to open selected utility"), /* @__PURE__ */ React24.createElement(Text21, null, "\u2022 Use ", /* @__PURE__ */ React24.createElement(Text21, { color: "green" }, "\u2191/\u2193"), " or ", /* @__PURE__ */ React24.createElement(Text21, { color: "green" }, "j/k"), " to navigate"), /* @__PURE__ */ React24.createElement(Text21, null, "\u2022 Press ", /* @__PURE__ */ React24.createElement(Text21, { color: "green" }, "Esc"), " to go back or quit"), /* @__PURE__ */ React24.createElement(Text21, null, "\u2022 Press ", /* @__PURE__ */ React24.createElement(Text21, { color: "green" }, "Ctrl+Q"), " to quit anytime")), /* @__PURE__ */ React24.createElement(Box20, { marginTop: 2 }, /* @__PURE__ */ React24.createElement(Text21, { dimColor: true }, "\u{1F4A1} Tip: Each utility provides an interactive interface for easy usage.")));
|
|
10042
9669
|
};
|
|
10043
9670
|
var ActiveUtilityView = ({ utilityType }) => {
|
|
10044
9671
|
switch (utilityType) {
|
|
10045
9672
|
case "password":
|
|
10046
|
-
return /* @__PURE__ */
|
|
9673
|
+
return /* @__PURE__ */ React24.createElement(PasswordView, null);
|
|
10047
9674
|
case "uuid":
|
|
10048
|
-
return /* @__PURE__ */
|
|
9675
|
+
return /* @__PURE__ */ React24.createElement(UuidView, null);
|
|
10049
9676
|
case "hash":
|
|
10050
|
-
return /* @__PURE__ */
|
|
9677
|
+
return /* @__PURE__ */ React24.createElement(HashView, null);
|
|
10051
9678
|
case "base64-encode":
|
|
10052
9679
|
case "base64-decode":
|
|
10053
|
-
return /* @__PURE__ */
|
|
9680
|
+
return /* @__PURE__ */ React24.createElement(Base64View, null);
|
|
10054
9681
|
case "url-encode":
|
|
10055
9682
|
case "url-decode":
|
|
10056
|
-
return /* @__PURE__ */
|
|
9683
|
+
return /* @__PURE__ */ React24.createElement(UrlView, null);
|
|
10057
9684
|
case "unix-time":
|
|
10058
|
-
return /* @__PURE__ */
|
|
9685
|
+
return /* @__PURE__ */ React24.createElement(UnixTimeView, null);
|
|
10059
9686
|
case "jwt":
|
|
10060
|
-
return /* @__PURE__ */
|
|
9687
|
+
return /* @__PURE__ */ React24.createElement(JwtView, null);
|
|
10061
9688
|
case "cron":
|
|
10062
|
-
return /* @__PURE__ */
|
|
9689
|
+
return /* @__PURE__ */ React24.createElement(CronView, null);
|
|
10063
9690
|
case "timezone":
|
|
10064
|
-
return /* @__PURE__ */
|
|
9691
|
+
return /* @__PURE__ */ React24.createElement(TimezoneView, null);
|
|
10065
9692
|
case "http":
|
|
10066
|
-
return /* @__PURE__ */
|
|
9693
|
+
return /* @__PURE__ */ React24.createElement(HttpView, null);
|
|
10067
9694
|
case "markdown":
|
|
10068
|
-
return /* @__PURE__ */
|
|
9695
|
+
return /* @__PURE__ */ React24.createElement(MarkdownView, null);
|
|
10069
9696
|
default:
|
|
10070
|
-
return /* @__PURE__ */
|
|
9697
|
+
return /* @__PURE__ */ React24.createElement(PlaceholderView, { utilityType });
|
|
10071
9698
|
}
|
|
10072
9699
|
};
|
|
10073
9700
|
var PlaceholderView = ({ utilityType }) => {
|
|
10074
9701
|
const item = MENU_ITEMS.find((m) => m.id === utilityType);
|
|
10075
|
-
return /* @__PURE__ */
|
|
9702
|
+
return /* @__PURE__ */ React24.createElement(Box20, { flexDirection: "column" }, /* @__PURE__ */ React24.createElement(Box20, { marginBottom: 1 }, /* @__PURE__ */ React24.createElement(Text21, { bold: true, color: "cyan" }, item?.icon, " ", item?.label)), /* @__PURE__ */ React24.createElement(Box20, { borderStyle: "single", borderColor: "yellow", paddingX: 2, paddingY: 1 }, /* @__PURE__ */ React24.createElement(Text21, null, "\u{1F6A7} This utility view is under construction.", "\n", "\n", "For now, use the command-line version:", "\n", /* @__PURE__ */ React24.createElement(Text21, { color: "green" }, "$ jai1 utils ", utilityType, " --help"), "\n", "\n", "Press ", /* @__PURE__ */ React24.createElement(Text21, { color: "yellow" }, "Esc"), " to return to the menu.")));
|
|
10076
9703
|
};
|
|
10077
9704
|
|
|
10078
9705
|
// src/commands/utils/interactive.ts
|
|
10079
9706
|
async function runInteractiveMode() {
|
|
10080
9707
|
return new Promise((resolve4) => {
|
|
10081
|
-
const { unmount, waitUntilExit } =
|
|
10082
|
-
|
|
9708
|
+
const { unmount, waitUntilExit } = render4(
|
|
9709
|
+
React25.createElement(UtilsApp, {
|
|
10083
9710
|
onExit: () => {
|
|
10084
9711
|
unmount();
|
|
10085
9712
|
resolve4();
|
|
@@ -10094,40 +9721,40 @@ async function runInteractiveMode() {
|
|
|
10094
9721
|
|
|
10095
9722
|
// src/commands/utils/index.ts
|
|
10096
9723
|
function showUtilsHelp() {
|
|
10097
|
-
console.log(
|
|
9724
|
+
console.log(chalk15.bold.cyan("\u{1F6E0}\uFE0F jai1 utils") + chalk15.dim(" - Developer utilities"));
|
|
10098
9725
|
console.log();
|
|
10099
|
-
console.log(
|
|
10100
|
-
console.log(` ${
|
|
10101
|
-
console.log(` ${
|
|
10102
|
-
console.log(` ${
|
|
10103
|
-
console.log(` ${
|
|
9726
|
+
console.log(chalk15.bold("M\xE3 h\xF3a & B\u1EA3o m\u1EADt:"));
|
|
9727
|
+
console.log(` ${chalk15.cyan("password")} T\u1EA1o m\u1EADt kh\u1EA9u ng\u1EABu nhi\xEAn`);
|
|
9728
|
+
console.log(` ${chalk15.cyan("uuid")} T\u1EA1o UUID v4`);
|
|
9729
|
+
console.log(` ${chalk15.cyan("hash")} Hash text (MD5/SHA/bcrypt)`);
|
|
9730
|
+
console.log(` ${chalk15.cyan("jwt")} Decode/encode JWT tokens`);
|
|
10104
9731
|
console.log();
|
|
10105
|
-
console.log(
|
|
10106
|
-
console.log(` ${
|
|
10107
|
-
console.log(` ${
|
|
10108
|
-
console.log(` ${
|
|
10109
|
-
console.log(` ${
|
|
9732
|
+
console.log(chalk15.bold("Encoding:"));
|
|
9733
|
+
console.log(` ${chalk15.cyan("base64-encode")} Encode sang Base64`);
|
|
9734
|
+
console.log(` ${chalk15.cyan("base64-decode")} Decode t\u1EEB Base64`);
|
|
9735
|
+
console.log(` ${chalk15.cyan("url-encode")} Encode URL components`);
|
|
9736
|
+
console.log(` ${chalk15.cyan("url-decode")} Decode URL components`);
|
|
10110
9737
|
console.log();
|
|
10111
|
-
console.log(
|
|
10112
|
-
console.log(` ${
|
|
10113
|
-
console.log(` ${
|
|
10114
|
-
console.log(` ${
|
|
9738
|
+
console.log(chalk15.bold("Th\u1EDDi gian:"));
|
|
9739
|
+
console.log(` ${chalk15.cyan("unix-time")} Chuy\u1EC3n \u0111\u1ED5i unix timestamp`);
|
|
9740
|
+
console.log(` ${chalk15.cyan("timezone")} Chuy\u1EC3n \u0111\u1ED5i m\xFAi gi\u1EDD`);
|
|
9741
|
+
console.log(` ${chalk15.cyan("cron")} Parse cron expressions`);
|
|
10115
9742
|
console.log();
|
|
10116
|
-
console.log(
|
|
10117
|
-
console.log(` ${
|
|
10118
|
-
console.log(` ${
|
|
9743
|
+
console.log(chalk15.bold("Kh\xE1c:"));
|
|
9744
|
+
console.log(` ${chalk15.cyan("http")} G\u1EEDi HTTP requests`);
|
|
9745
|
+
console.log(` ${chalk15.cyan("markdown-preview")} Xem tr\u01B0\u1EDBc file markdown`);
|
|
10119
9746
|
console.log();
|
|
10120
|
-
console.log(
|
|
10121
|
-
console.log(
|
|
10122
|
-
console.log(
|
|
9747
|
+
console.log(chalk15.bold("Ch\u1EBF \u0111\u1ED9 Interactive:"));
|
|
9748
|
+
console.log(chalk15.dim(" $ jai1 utils -i"));
|
|
9749
|
+
console.log(chalk15.dim(" $ jai1 utils --interactive"));
|
|
10123
9750
|
console.log();
|
|
10124
|
-
console.log(
|
|
10125
|
-
console.log(
|
|
10126
|
-
console.log(
|
|
10127
|
-
console.log(
|
|
10128
|
-
console.log(
|
|
9751
|
+
console.log(chalk15.bold("V\xED d\u1EE5:"));
|
|
9752
|
+
console.log(chalk15.dim(" $ jai1 utils password --length 24"));
|
|
9753
|
+
console.log(chalk15.dim(" $ jai1 utils uuid --count 5"));
|
|
9754
|
+
console.log(chalk15.dim(' $ jai1 utils hash "text" --algorithm sha256'));
|
|
9755
|
+
console.log(chalk15.dim(" $ jai1 utils http https://api.example.com"));
|
|
10129
9756
|
console.log();
|
|
10130
|
-
console.log(
|
|
9757
|
+
console.log(chalk15.dim('Ch\u1EA1y "jai1 utils <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt'));
|
|
10131
9758
|
}
|
|
10132
9759
|
function createUtilsCommand() {
|
|
10133
9760
|
const utilsCommand = new Command42("utils").description("Developer utilities for common tasks").option("-i, --interactive", "Run in interactive mode");
|
|
@@ -10156,11 +9783,11 @@ function createUtilsCommand() {
|
|
|
10156
9783
|
|
|
10157
9784
|
// src/commands/deps/index.ts
|
|
10158
9785
|
import { Command as Command45 } from "commander";
|
|
10159
|
-
import
|
|
9786
|
+
import chalk18 from "chalk";
|
|
10160
9787
|
|
|
10161
9788
|
// src/commands/deps/check.ts
|
|
10162
9789
|
import { Command as Command43 } from "commander";
|
|
10163
|
-
import
|
|
9790
|
+
import chalk16 from "chalk";
|
|
10164
9791
|
import Table4 from "cli-table3";
|
|
10165
9792
|
import ora from "ora";
|
|
10166
9793
|
|
|
@@ -10763,7 +10390,7 @@ function createDepsCheckCommand() {
|
|
|
10763
10390
|
if (projects.length === 0) {
|
|
10764
10391
|
spinner.fail("Kh\xF4ng t\xECm th\u1EA5y project n\xE0o \u0111\u01B0\u1EE3c h\u1ED7 tr\u1EE3");
|
|
10765
10392
|
console.log();
|
|
10766
|
-
console.log(
|
|
10393
|
+
console.log(chalk16.dim("H\u1ED7 tr\u1EE3: Node.js (package.json), PHP (composer.json), Python (requirements.txt/Pipfile)"));
|
|
10767
10394
|
process.exit(1);
|
|
10768
10395
|
}
|
|
10769
10396
|
spinner.succeed(`Ph\xE1t hi\u1EC7n ${projects.length} project:`);
|
|
@@ -10777,7 +10404,7 @@ function createDepsCheckCommand() {
|
|
|
10777
10404
|
await checkEcosystem(project.ecosystem, project.manager, cwd);
|
|
10778
10405
|
}
|
|
10779
10406
|
console.log();
|
|
10780
|
-
console.log(
|
|
10407
|
+
console.log(chalk16.dim('\u{1F4A1} Ch\u1EA1y "jai1 deps upgrade" \u0111\u1EC3 n\xE2ng c\u1EA5p packages.'));
|
|
10781
10408
|
});
|
|
10782
10409
|
return checkCommand;
|
|
10783
10410
|
}
|
|
@@ -10810,7 +10437,7 @@ async function checkEcosystem(ecosystem, manager, cwd) {
|
|
|
10810
10437
|
});
|
|
10811
10438
|
} catch (error) {
|
|
10812
10439
|
spinner.fail(`L\u1ED7i ki\u1EC3m tra ${label}`);
|
|
10813
|
-
console.log(
|
|
10440
|
+
console.log(chalk16.red(error.message));
|
|
10814
10441
|
console.log();
|
|
10815
10442
|
return;
|
|
10816
10443
|
}
|
|
@@ -10823,10 +10450,10 @@ async function checkEcosystem(ecosystem, manager, cwd) {
|
|
|
10823
10450
|
console.log();
|
|
10824
10451
|
const table = new Table4({
|
|
10825
10452
|
head: [
|
|
10826
|
-
|
|
10827
|
-
|
|
10828
|
-
|
|
10829
|
-
|
|
10453
|
+
chalk16.cyan("Package"),
|
|
10454
|
+
chalk16.cyan("Hi\u1EC7n t\u1EA1i"),
|
|
10455
|
+
chalk16.cyan("M\u1EDBi nh\u1EA5t"),
|
|
10456
|
+
chalk16.cyan("Lo\u1EA1i")
|
|
10830
10457
|
],
|
|
10831
10458
|
style: {
|
|
10832
10459
|
head: [],
|
|
@@ -10837,9 +10464,9 @@ async function checkEcosystem(ecosystem, manager, cwd) {
|
|
|
10837
10464
|
const upgradeIcon = pkg.upgradeType === "major" ? "\u{1F534}" : pkg.upgradeType === "minor" ? "\u{1F7E1}" : "\u{1F7E2}";
|
|
10838
10465
|
table.push([
|
|
10839
10466
|
`${upgradeIcon} ${pkg.name}`,
|
|
10840
|
-
|
|
10841
|
-
|
|
10842
|
-
pkg.type === "dev" ?
|
|
10467
|
+
chalk16.dim(pkg.current),
|
|
10468
|
+
chalk16.green(pkg.latest),
|
|
10469
|
+
pkg.type === "dev" ? chalk16.dim("dev") : "dep"
|
|
10843
10470
|
]);
|
|
10844
10471
|
}
|
|
10845
10472
|
console.log(table.toString());
|
|
@@ -10847,13 +10474,13 @@ async function checkEcosystem(ecosystem, manager, cwd) {
|
|
|
10847
10474
|
if (result.isLaravel) {
|
|
10848
10475
|
const blockedPackages = result.packages.filter((p) => p.blockedReason);
|
|
10849
10476
|
if (blockedPackages.length > 0) {
|
|
10850
|
-
console.log(
|
|
10477
|
+
console.log(chalk16.yellow("\u26A0\uFE0F Laravel major version upgrades blocked (nguy hi\u1EC3m):"));
|
|
10851
10478
|
for (const pkg of blockedPackages) {
|
|
10852
|
-
console.log(
|
|
10479
|
+
console.log(chalk16.dim(` - ${pkg.name}: ${pkg.current} \u2192 ${pkg.latest}`));
|
|
10853
10480
|
}
|
|
10854
10481
|
console.log();
|
|
10855
|
-
console.log(
|
|
10856
|
-
console.log(
|
|
10482
|
+
console.log(chalk16.dim("\u{1F4A1} \u0110\u1EC3 n\xE2ng c\u1EA5p Laravel major version, ch\u1EA1y th\u1EE7 c\xF4ng:"));
|
|
10483
|
+
console.log(chalk16.dim(` composer require ${blockedPackages[0].name}:^${blockedPackages[0].latest}`));
|
|
10857
10484
|
console.log();
|
|
10858
10485
|
}
|
|
10859
10486
|
}
|
|
@@ -10862,7 +10489,7 @@ async function checkEcosystem(ecosystem, manager, cwd) {
|
|
|
10862
10489
|
// src/commands/deps/upgrade.ts
|
|
10863
10490
|
import { Command as Command44 } from "commander";
|
|
10864
10491
|
import { checkbox as checkbox3, confirm as confirm8 } from "@inquirer/prompts";
|
|
10865
|
-
import
|
|
10492
|
+
import chalk17 from "chalk";
|
|
10866
10493
|
import ora2 from "ora";
|
|
10867
10494
|
import Table5 from "cli-table3";
|
|
10868
10495
|
function createDepsUpgradeCommand() {
|
|
@@ -10879,7 +10506,7 @@ async function handleDepsUpgrade(options) {
|
|
|
10879
10506
|
if (projects.length === 0) {
|
|
10880
10507
|
spinner.fail("Kh\xF4ng t\xECm th\u1EA5y project n\xE0o \u0111\u01B0\u1EE3c h\u1ED7 tr\u1EE3");
|
|
10881
10508
|
console.log();
|
|
10882
|
-
console.log(
|
|
10509
|
+
console.log(chalk17.dim("H\u1ED7 tr\u1EE3: Node.js (package.json), PHP (composer.json), Python (requirements.txt/Pipfile)"));
|
|
10883
10510
|
process.exit(1);
|
|
10884
10511
|
}
|
|
10885
10512
|
spinner.succeed(`Ph\xE1t hi\u1EC7n ${projects.length} project:`);
|
|
@@ -10893,9 +10520,9 @@ async function handleDepsUpgrade(options) {
|
|
|
10893
10520
|
await upgradeEcosystem(project, cwd, options);
|
|
10894
10521
|
}
|
|
10895
10522
|
console.log();
|
|
10896
|
-
console.log(
|
|
10523
|
+
console.log(chalk17.green("\u2705 Ho\xE0n th\xE0nh!"));
|
|
10897
10524
|
} catch (error) {
|
|
10898
|
-
console.error(
|
|
10525
|
+
console.error(chalk17.red(`
|
|
10899
10526
|
\u274C ${error.message}
|
|
10900
10527
|
`));
|
|
10901
10528
|
process.exit(1);
|
|
@@ -10904,10 +10531,10 @@ async function handleDepsUpgrade(options) {
|
|
|
10904
10531
|
async function upgradeEcosystem(project, cwd, options) {
|
|
10905
10532
|
const service = getService(project.ecosystem);
|
|
10906
10533
|
const label = `${getEcosystemIcon(project.ecosystem)} ${getEcosystemLabel(project.ecosystem)}`;
|
|
10907
|
-
console.log(
|
|
10534
|
+
console.log(chalk17.bold.cyan(`
|
|
10908
10535
|
${"\u2501".repeat(80)}`));
|
|
10909
|
-
console.log(
|
|
10910
|
-
console.log(
|
|
10536
|
+
console.log(chalk17.bold.cyan(`${label}`));
|
|
10537
|
+
console.log(chalk17.bold.cyan("\u2501".repeat(80)));
|
|
10911
10538
|
console.log();
|
|
10912
10539
|
const spinner = ora2("\u0110ang ki\u1EC3m tra packages...").start();
|
|
10913
10540
|
let packages;
|
|
@@ -10918,7 +10545,7 @@ ${"\u2501".repeat(80)}`));
|
|
|
10918
10545
|
packages = result.packages;
|
|
10919
10546
|
} catch (error) {
|
|
10920
10547
|
spinner.fail("L\u1ED7i ki\u1EC3m tra packages");
|
|
10921
|
-
console.log(
|
|
10548
|
+
console.log(chalk17.red(error.message));
|
|
10922
10549
|
return;
|
|
10923
10550
|
}
|
|
10924
10551
|
if (packages.length === 0) {
|
|
@@ -10931,7 +10558,7 @@ ${"\u2501".repeat(80)}`));
|
|
|
10931
10558
|
let selectedPackages;
|
|
10932
10559
|
if (options.all) {
|
|
10933
10560
|
selectedPackages = packages;
|
|
10934
|
-
console.log(
|
|
10561
|
+
console.log(chalk17.cyan(`\u{1F4CB} \u0110\xE3 ch\u1ECDn t\u1EA5t c\u1EA3 ${selectedPackages.length} packages
|
|
10935
10562
|
`));
|
|
10936
10563
|
} else {
|
|
10937
10564
|
try {
|
|
@@ -10949,12 +10576,12 @@ ${"\u2501".repeat(80)}`));
|
|
|
10949
10576
|
theme: checkboxTheme
|
|
10950
10577
|
});
|
|
10951
10578
|
if (selected.length === 0) {
|
|
10952
|
-
console.log(
|
|
10579
|
+
console.log(chalk17.yellow("\u23F8\uFE0F Kh\xF4ng c\xF3 packages n\xE0o \u0111\u01B0\u1EE3c ch\u1ECDn\n"));
|
|
10953
10580
|
return;
|
|
10954
10581
|
}
|
|
10955
10582
|
selectedPackages = packages.filter((p) => selected.includes(p.name));
|
|
10956
10583
|
} catch {
|
|
10957
|
-
console.log(
|
|
10584
|
+
console.log(chalk17.yellow("\n\u23F8\uFE0F \u0110\xE3 h\u1EE7y\n"));
|
|
10958
10585
|
return;
|
|
10959
10586
|
}
|
|
10960
10587
|
}
|
|
@@ -10965,35 +10592,35 @@ ${"\u2501".repeat(80)}`));
|
|
|
10965
10592
|
default: true
|
|
10966
10593
|
});
|
|
10967
10594
|
} catch {
|
|
10968
|
-
console.log(
|
|
10595
|
+
console.log(chalk17.yellow("\n\u23F8\uFE0F \u0110\xE3 h\u1EE7y\n"));
|
|
10969
10596
|
return;
|
|
10970
10597
|
}
|
|
10971
10598
|
if (!shouldProceed) {
|
|
10972
|
-
console.log(
|
|
10599
|
+
console.log(chalk17.yellow("\u23F8\uFE0F Upgrade \u0111\xE3 h\u1EE7y\n"));
|
|
10973
10600
|
return;
|
|
10974
10601
|
}
|
|
10975
10602
|
console.log();
|
|
10976
|
-
console.log(
|
|
10977
|
-
console.log(
|
|
10603
|
+
console.log(chalk17.cyan(`\u{1F527} Package manager: ${project.manager}`));
|
|
10604
|
+
console.log(chalk17.cyan("\u{1F4E5} \u0110ang upgrade...\n"));
|
|
10978
10605
|
const commands = service.getUpgradeCommands(selectedPackages);
|
|
10979
10606
|
try {
|
|
10980
10607
|
if (commands.deps) {
|
|
10981
|
-
console.log(
|
|
10608
|
+
console.log(chalk17.dim(`$ ${commands.deps}
|
|
10982
10609
|
`));
|
|
10983
10610
|
}
|
|
10984
10611
|
if (commands.devDeps) {
|
|
10985
|
-
console.log(
|
|
10612
|
+
console.log(chalk17.dim(`$ ${commands.devDeps}
|
|
10986
10613
|
`));
|
|
10987
10614
|
}
|
|
10988
10615
|
await service.upgrade(cwd, { packages: selectedPackages });
|
|
10989
|
-
console.log(
|
|
10616
|
+
console.log(chalk17.green(`
|
|
10990
10617
|
\u2705 \u0110\xE3 upgrade ${selectedPackages.length} packages th\xE0nh c\xF4ng!`));
|
|
10991
10618
|
} catch (error) {
|
|
10992
|
-
console.error(
|
|
10993
|
-
console.error(
|
|
10994
|
-
console.log(
|
|
10995
|
-
if (commands.deps) console.log(
|
|
10996
|
-
if (commands.devDeps) console.log(
|
|
10619
|
+
console.error(chalk17.red("\n\u274C L\u1ED7i khi upgrade:"));
|
|
10620
|
+
console.error(chalk17.red(error.message));
|
|
10621
|
+
console.log(chalk17.yellow("\n\u{1F4A1} B\u1EA1n c\xF3 th\u1EC3 th\u1EED upgrade th\u1EE7 c\xF4ng:"));
|
|
10622
|
+
if (commands.deps) console.log(chalk17.cyan(` ${commands.deps}`));
|
|
10623
|
+
if (commands.devDeps) console.log(chalk17.cyan(` ${commands.devDeps}`));
|
|
10997
10624
|
console.log();
|
|
10998
10625
|
throw error;
|
|
10999
10626
|
}
|
|
@@ -11001,10 +10628,10 @@ ${"\u2501".repeat(80)}`));
|
|
|
11001
10628
|
function displayUpgradeTable(packages) {
|
|
11002
10629
|
const table = new Table5({
|
|
11003
10630
|
head: [
|
|
11004
|
-
|
|
11005
|
-
|
|
11006
|
-
|
|
11007
|
-
|
|
10631
|
+
chalk17.cyan("Package"),
|
|
10632
|
+
chalk17.cyan("Hi\u1EC7n t\u1EA1i"),
|
|
10633
|
+
chalk17.cyan("M\u1EDBi nh\u1EA5t"),
|
|
10634
|
+
chalk17.cyan("Lo\u1EA1i")
|
|
11008
10635
|
],
|
|
11009
10636
|
style: {
|
|
11010
10637
|
head: [],
|
|
@@ -11015,9 +10642,9 @@ function displayUpgradeTable(packages) {
|
|
|
11015
10642
|
const upgradeIcon = pkg.upgradeType === "major" ? "\u{1F534}" : pkg.upgradeType === "minor" ? "\u{1F7E1}" : "\u{1F7E2}";
|
|
11016
10643
|
table.push([
|
|
11017
10644
|
`${upgradeIcon} ${pkg.name}`,
|
|
11018
|
-
|
|
11019
|
-
|
|
11020
|
-
pkg.type === "dev" ?
|
|
10645
|
+
chalk17.dim(pkg.current),
|
|
10646
|
+
chalk17.green(pkg.latest),
|
|
10647
|
+
pkg.type === "dev" ? chalk17.dim("dev") : "dep"
|
|
11021
10648
|
]);
|
|
11022
10649
|
}
|
|
11023
10650
|
console.log(table.toString());
|
|
@@ -11060,23 +10687,23 @@ function getEcosystemLabel(ecosystem) {
|
|
|
11060
10687
|
|
|
11061
10688
|
// src/commands/deps/index.ts
|
|
11062
10689
|
function showDepsHelp() {
|
|
11063
|
-
console.log(
|
|
10690
|
+
console.log(chalk18.bold.cyan("\u{1F4E6} jai1 deps") + chalk18.dim(" - Qu\u1EA3n l\xFD dependencies trong project"));
|
|
11064
10691
|
console.log();
|
|
11065
|
-
console.log(
|
|
11066
|
-
console.log(` ${
|
|
11067
|
-
console.log(` ${
|
|
10692
|
+
console.log(chalk18.bold("C\xE1c l\u1EC7nh:"));
|
|
10693
|
+
console.log(` ${chalk18.cyan("check")} Ki\u1EC3m tra c\xE1c packages c\u1EA7n upgrade`);
|
|
10694
|
+
console.log(` ${chalk18.cyan("upgrade")} N\xE2ng c\u1EA5p dependencies l\xEAn phi\xEAn b\u1EA3n m\u1EDBi nh\u1EA5t`);
|
|
11068
10695
|
console.log();
|
|
11069
|
-
console.log(
|
|
11070
|
-
console.log(
|
|
11071
|
-
console.log(
|
|
11072
|
-
console.log(
|
|
10696
|
+
console.log(chalk18.bold("H\u1ED7 tr\u1EE3:"));
|
|
10697
|
+
console.log(chalk18.dim(" \u2022 Node.js (npm, pnpm, yarn, bun)"));
|
|
10698
|
+
console.log(chalk18.dim(" \u2022 PHP/Composer (v\u1EDBi b\u1EA3o v\u1EC7 Laravel major version)"));
|
|
10699
|
+
console.log(chalk18.dim(" \u2022 Python (pip, pipenv)"));
|
|
11073
10700
|
console.log();
|
|
11074
|
-
console.log(
|
|
11075
|
-
console.log(
|
|
11076
|
-
console.log(
|
|
11077
|
-
console.log(
|
|
10701
|
+
console.log(chalk18.bold("V\xED d\u1EE5:"));
|
|
10702
|
+
console.log(chalk18.dim(" $ jai1 deps check"));
|
|
10703
|
+
console.log(chalk18.dim(" $ jai1 deps upgrade"));
|
|
10704
|
+
console.log(chalk18.dim(" $ jai1 deps upgrade --all"));
|
|
11078
10705
|
console.log();
|
|
11079
|
-
console.log(
|
|
10706
|
+
console.log(chalk18.dim('Ch\u1EA1y "jai1 deps <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt'));
|
|
11080
10707
|
}
|
|
11081
10708
|
function createDepsCommand() {
|
|
11082
10709
|
const depsCommand = new Command45("deps").description("Qu\u1EA3n l\xFD dependencies trong project").action(() => {
|
|
@@ -11092,13 +10719,13 @@ import { Command as Command56 } from "commander";
|
|
|
11092
10719
|
|
|
11093
10720
|
// src/commands/tasks/add.ts
|
|
11094
10721
|
import { Command as Command46 } from "commander";
|
|
11095
|
-
import
|
|
10722
|
+
import chalk19 from "chalk";
|
|
11096
10723
|
function createTaskAddCommand() {
|
|
11097
10724
|
return new Command46("add").description("Add a new task").argument("<title>", "Task title").option("-p, --priority <n>", "Priority: 0=critical, 1=high, 2=medium, 3=low", "2").option("-P, --parent <parent>", "Parent: feature/xxx, plan/xxx, bug/xxx").option("-t, --tags <tags>", "Comma-separated tags").option("-j, --json", "Output JSON").action(async (title, options) => {
|
|
11098
10725
|
const service = new TaskService();
|
|
11099
10726
|
const priority = Number(options.priority ?? 2);
|
|
11100
10727
|
if (priority < 0 || priority > 3) {
|
|
11101
|
-
console.error(
|
|
10728
|
+
console.error(chalk19.red("\u274C Priority must be 0-3"));
|
|
11102
10729
|
process.exit(1);
|
|
11103
10730
|
}
|
|
11104
10731
|
const tags = options.tags ? options.tags.split(",").map((t) => t.trim()) : [];
|
|
@@ -11114,21 +10741,21 @@ function createTaskAddCommand() {
|
|
|
11114
10741
|
}
|
|
11115
10742
|
const icon = PRIORITY_ICONS[task.priority] || "\u{1F7E1}";
|
|
11116
10743
|
const label = PRIORITY_LABELS[task.priority] || "Medium";
|
|
11117
|
-
console.log(
|
|
11118
|
-
console.log(` ${
|
|
11119
|
-
console.log(` ${
|
|
10744
|
+
console.log(chalk19.green(`\u2705 Task added: ${chalk19.bold(task.id)}`));
|
|
10745
|
+
console.log(` ${chalk19.dim("Title:")} ${task.title}`);
|
|
10746
|
+
console.log(` ${chalk19.dim("Priority:")} ${icon} ${label}`);
|
|
11120
10747
|
if (task.parent) {
|
|
11121
|
-
console.log(` ${
|
|
10748
|
+
console.log(` ${chalk19.dim("Parent:")} ${task.parent}`);
|
|
11122
10749
|
}
|
|
11123
10750
|
if (task.tags.length > 0) {
|
|
11124
|
-
console.log(` ${
|
|
10751
|
+
console.log(` ${chalk19.dim("Tags:")} ${task.tags.join(", ")}`);
|
|
11125
10752
|
}
|
|
11126
10753
|
});
|
|
11127
10754
|
}
|
|
11128
10755
|
|
|
11129
10756
|
// src/commands/tasks/list.ts
|
|
11130
10757
|
import { Command as Command47 } from "commander";
|
|
11131
|
-
import
|
|
10758
|
+
import chalk20 from "chalk";
|
|
11132
10759
|
function createTaskListCommand() {
|
|
11133
10760
|
return new Command47("list").alias("ls").description("List tasks").option("-s, --status <status>", "Filter by status: todo, in_progress, done, cancelled").option("-P, --parent <parent>", "Filter by parent: feature/xxx, plan/xxx").option("-j, --json", "Output JSON").action(async (options) => {
|
|
11134
10761
|
await handleTaskList(options);
|
|
@@ -11149,12 +10776,12 @@ async function handleTaskList(options) {
|
|
|
11149
10776
|
return;
|
|
11150
10777
|
}
|
|
11151
10778
|
if (tasks.length === 0) {
|
|
11152
|
-
console.log(
|
|
10779
|
+
console.log(chalk20.dim("No tasks found."));
|
|
11153
10780
|
return;
|
|
11154
10781
|
}
|
|
11155
10782
|
const doneIds = new Set(allTasks.filter((t) => t.status === "done").map((t) => t.id));
|
|
11156
10783
|
const header = options.parent ? `\u{1F4CB} ${options.parent} (${tasks.length} tasks)` : `\u{1F4CB} All tasks (${tasks.length})`;
|
|
11157
|
-
console.log(
|
|
10784
|
+
console.log(chalk20.bold(header));
|
|
11158
10785
|
console.log();
|
|
11159
10786
|
for (const task of tasks) {
|
|
11160
10787
|
printTaskLine(task, doneIds);
|
|
@@ -11164,23 +10791,23 @@ function printTaskLine(task, doneIds) {
|
|
|
11164
10791
|
const isBlocked = task.status === "todo" && task.depends_on.length > 0 && !task.depends_on.every((id) => doneIds.has(id));
|
|
11165
10792
|
const statusIcon = isBlocked ? BLOCKED_ICON : STATUS_ICONS[task.status] || "\u{1F4CB}";
|
|
11166
10793
|
const priorityIcon = PRIORITY_ICONS[task.priority] || "\u{1F7E1}";
|
|
11167
|
-
let line = ` ${statusIcon} ${
|
|
10794
|
+
let line = ` ${statusIcon} ${chalk20.dim(task.id)} P${task.priority}${priorityIcon} ${task.title}`;
|
|
11168
10795
|
if (task.status === "in_progress" && task.assigned_to) {
|
|
11169
|
-
line +=
|
|
10796
|
+
line += chalk20.cyan(` @${task.assigned_to}`);
|
|
11170
10797
|
}
|
|
11171
10798
|
if (isBlocked) {
|
|
11172
10799
|
const blockedBy = task.depends_on.filter((id) => !doneIds.has(id));
|
|
11173
|
-
line +=
|
|
10800
|
+
line += chalk20.red(` (blocked: ${blockedBy.join(", ")})`);
|
|
11174
10801
|
}
|
|
11175
10802
|
if (task.parent) {
|
|
11176
|
-
line +=
|
|
10803
|
+
line += chalk20.dim(` [${task.parent}]`);
|
|
11177
10804
|
}
|
|
11178
10805
|
console.log(line);
|
|
11179
10806
|
}
|
|
11180
10807
|
|
|
11181
10808
|
// src/commands/tasks/ready.ts
|
|
11182
10809
|
import { Command as Command48 } from "commander";
|
|
11183
|
-
import
|
|
10810
|
+
import chalk21 from "chalk";
|
|
11184
10811
|
function createTaskReadyCommand() {
|
|
11185
10812
|
return new Command48("ready").description("Show tasks ready to pick (not blocked, not assigned)").option("-P, --parent <parent>", "Filter by parent").option("-j, --json", "Output JSON").action(async (options) => {
|
|
11186
10813
|
const service = new TaskService();
|
|
@@ -11190,33 +10817,33 @@ function createTaskReadyCommand() {
|
|
|
11190
10817
|
return;
|
|
11191
10818
|
}
|
|
11192
10819
|
if (tasks.length === 0) {
|
|
11193
|
-
console.log(
|
|
11194
|
-
console.log(
|
|
10820
|
+
console.log(chalk21.dim("No tasks ready to pick."));
|
|
10821
|
+
console.log(chalk21.dim("\u{1F4A1} Check blocked tasks: jai1 t list -s todo"));
|
|
11195
10822
|
return;
|
|
11196
10823
|
}
|
|
11197
|
-
console.log(
|
|
10824
|
+
console.log(chalk21.bold(`\u{1F4CB} Ready to pick (${tasks.length} tasks):`));
|
|
11198
10825
|
console.log();
|
|
11199
10826
|
for (const task of tasks) {
|
|
11200
10827
|
const icon = PRIORITY_ICONS[task.priority] || "\u{1F7E1}";
|
|
11201
|
-
let line = ` P${task.priority}${icon} ${
|
|
10828
|
+
let line = ` P${task.priority}${icon} ${chalk21.dim(task.id)} ${task.title}`;
|
|
11202
10829
|
if (task.parent) {
|
|
11203
|
-
line +=
|
|
10830
|
+
line += chalk21.dim(` [${task.parent}]`);
|
|
11204
10831
|
}
|
|
11205
10832
|
console.log(line);
|
|
11206
10833
|
}
|
|
11207
10834
|
console.log();
|
|
11208
|
-
console.log(
|
|
10835
|
+
console.log(chalk21.dim("\u{1F4A1} Run: jai1 t pick"));
|
|
11209
10836
|
});
|
|
11210
10837
|
}
|
|
11211
10838
|
|
|
11212
10839
|
// src/commands/tasks/update.ts
|
|
11213
10840
|
import { Command as Command49 } from "commander";
|
|
11214
|
-
import
|
|
10841
|
+
import chalk22 from "chalk";
|
|
11215
10842
|
var VALID_STATUSES = ["todo", "in_progress", "done", "cancelled"];
|
|
11216
10843
|
function createTaskUpdateCommand() {
|
|
11217
10844
|
return new Command49("update").description("Update task status").argument("<id>", "Task ID (e.g. T-001)").requiredOption("-s, --status <status>", "New status: todo, in_progress, done, cancelled").option("-j, --json", "Output JSON").action(async (id, options) => {
|
|
11218
10845
|
if (!VALID_STATUSES.includes(options.status)) {
|
|
11219
|
-
console.error(
|
|
10846
|
+
console.error(chalk22.red(`\u274C Invalid status. Must be: ${VALID_STATUSES.join(", ")}`));
|
|
11220
10847
|
process.exit(1);
|
|
11221
10848
|
}
|
|
11222
10849
|
const service = new TaskService();
|
|
@@ -11227,9 +10854,9 @@ function createTaskUpdateCommand() {
|
|
|
11227
10854
|
return;
|
|
11228
10855
|
}
|
|
11229
10856
|
const icon = STATUS_ICONS[task.status] || "\u{1F4CB}";
|
|
11230
|
-
console.log(
|
|
10857
|
+
console.log(chalk22.green(`\u2705 ${task.id} \u2192 ${icon} ${task.status}`));
|
|
11231
10858
|
} catch (error) {
|
|
11232
|
-
console.error(
|
|
10859
|
+
console.error(chalk22.red(`\u274C ${error instanceof Error ? error.message : String(error)}`));
|
|
11233
10860
|
process.exit(1);
|
|
11234
10861
|
}
|
|
11235
10862
|
});
|
|
@@ -11237,14 +10864,14 @@ function createTaskUpdateCommand() {
|
|
|
11237
10864
|
|
|
11238
10865
|
// src/commands/tasks/show.ts
|
|
11239
10866
|
import { Command as Command50 } from "commander";
|
|
11240
|
-
import
|
|
10867
|
+
import chalk23 from "chalk";
|
|
11241
10868
|
function createTaskShowCommand() {
|
|
11242
10869
|
return new Command50("show").description("Show task detail or all tasks under a parent").argument("<query>", "Task ID (T-001) or parent (feature/xxx)").option("-j, --json", "Output JSON").action(async (query, options) => {
|
|
11243
10870
|
const service = new TaskService();
|
|
11244
10871
|
if (query.startsWith("T-")) {
|
|
11245
10872
|
const task = await service.findById(query);
|
|
11246
10873
|
if (!task) {
|
|
11247
|
-
console.error(
|
|
10874
|
+
console.error(chalk23.red(`\u274C Task ${query} not found`));
|
|
11248
10875
|
process.exit(1);
|
|
11249
10876
|
}
|
|
11250
10877
|
if (options.json) {
|
|
@@ -11255,34 +10882,34 @@ function createTaskShowCommand() {
|
|
|
11255
10882
|
const statusIcon = blocked ? BLOCKED_ICON : STATUS_ICONS[task.status] || "\u{1F4CB}";
|
|
11256
10883
|
const priIcon = PRIORITY_ICONS[task.priority] || "\u{1F7E1}";
|
|
11257
10884
|
const priLabel = PRIORITY_LABELS[task.priority] || "Medium";
|
|
11258
|
-
console.log(
|
|
10885
|
+
console.log(chalk23.bold(`
|
|
11259
10886
|
\u{1F4CC} ${task.id}: ${task.title}
|
|
11260
10887
|
`));
|
|
11261
|
-
console.log(` ${
|
|
11262
|
-
console.log(` ${
|
|
10888
|
+
console.log(` ${chalk23.dim("Status:")} ${statusIcon} ${task.status}${blocked ? chalk23.red(" (BLOCKED)") : ""}`);
|
|
10889
|
+
console.log(` ${chalk23.dim("Priority:")} ${priIcon} P${task.priority} ${priLabel}`);
|
|
11263
10890
|
if (task.parent) {
|
|
11264
|
-
console.log(` ${
|
|
10891
|
+
console.log(` ${chalk23.dim("Parent:")} ${task.parent}`);
|
|
11265
10892
|
}
|
|
11266
10893
|
if (task.assigned_to) {
|
|
11267
|
-
console.log(` ${
|
|
10894
|
+
console.log(` ${chalk23.dim("Assigned:")} @${task.assigned_to} (${task.claimed_at})`);
|
|
11268
10895
|
}
|
|
11269
10896
|
if (task.depends_on.length > 0) {
|
|
11270
|
-
console.log(` ${
|
|
10897
|
+
console.log(` ${chalk23.dim("Depends on:")} ${task.depends_on.join(", ")}`);
|
|
11271
10898
|
if (blocked) {
|
|
11272
|
-
console.log(` ${
|
|
10899
|
+
console.log(` ${chalk23.dim("Blocked by:")} ${chalk23.red(blockedBy.join(", "))}`);
|
|
11273
10900
|
}
|
|
11274
10901
|
}
|
|
11275
10902
|
if (task.tags.length > 0) {
|
|
11276
|
-
console.log(` ${
|
|
10903
|
+
console.log(` ${chalk23.dim("Tags:")} ${task.tags.join(", ")}`);
|
|
11277
10904
|
}
|
|
11278
10905
|
if (task.branch) {
|
|
11279
|
-
console.log(` ${
|
|
10906
|
+
console.log(` ${chalk23.dim("Branch:")} ${task.branch}`);
|
|
11280
10907
|
}
|
|
11281
10908
|
if (task.notes) {
|
|
11282
|
-
console.log(` ${
|
|
10909
|
+
console.log(` ${chalk23.dim("Notes:")} ${task.notes}`);
|
|
11283
10910
|
}
|
|
11284
|
-
console.log(` ${
|
|
11285
|
-
console.log(` ${
|
|
10911
|
+
console.log(` ${chalk23.dim("Created:")} ${task.created}`);
|
|
10912
|
+
console.log(` ${chalk23.dim("Updated:")} ${task.updated}`);
|
|
11286
10913
|
console.log();
|
|
11287
10914
|
} else {
|
|
11288
10915
|
const tasks = await service.filter({ parent: query });
|
|
@@ -11291,10 +10918,10 @@ function createTaskShowCommand() {
|
|
|
11291
10918
|
return;
|
|
11292
10919
|
}
|
|
11293
10920
|
if (tasks.length === 0) {
|
|
11294
|
-
console.log(
|
|
10921
|
+
console.log(chalk23.dim(`No tasks for parent: ${query}`));
|
|
11295
10922
|
return;
|
|
11296
10923
|
}
|
|
11297
|
-
console.log(
|
|
10924
|
+
console.log(chalk23.bold(`
|
|
11298
10925
|
\u{1F4CB} ${query} (${tasks.length} tasks)
|
|
11299
10926
|
`));
|
|
11300
10927
|
const allTasks = await service.readAll();
|
|
@@ -11302,11 +10929,11 @@ function createTaskShowCommand() {
|
|
|
11302
10929
|
for (const task of tasks) {
|
|
11303
10930
|
const isBlocked = task.status === "todo" && task.depends_on.length > 0 && !task.depends_on.every((id) => doneIds.has(id));
|
|
11304
10931
|
const icon = isBlocked ? BLOCKED_ICON : STATUS_ICONS[task.status] || "\u{1F4CB}";
|
|
11305
|
-
let line = ` ${icon} ${
|
|
11306
|
-
if (task.assigned_to) line +=
|
|
10932
|
+
let line = ` ${icon} ${chalk23.dim(task.id)} P${task.priority} ${task.title}`;
|
|
10933
|
+
if (task.assigned_to) line += chalk23.cyan(` @${task.assigned_to}`);
|
|
11307
10934
|
if (isBlocked) {
|
|
11308
10935
|
const bb = task.depends_on.filter((id) => !doneIds.has(id));
|
|
11309
|
-
line +=
|
|
10936
|
+
line += chalk23.red(` (blocked: ${bb.join(", ")})`);
|
|
11310
10937
|
}
|
|
11311
10938
|
console.log(line);
|
|
11312
10939
|
}
|
|
@@ -11317,7 +10944,7 @@ function createTaskShowCommand() {
|
|
|
11317
10944
|
|
|
11318
10945
|
// src/commands/tasks/pick.ts
|
|
11319
10946
|
import { Command as Command51 } from "commander";
|
|
11320
|
-
import
|
|
10947
|
+
import chalk24 from "chalk";
|
|
11321
10948
|
import { confirm as confirm9 } from "@inquirer/prompts";
|
|
11322
10949
|
function createTaskPickCommand() {
|
|
11323
10950
|
return new Command51("pick").description("Claim the next available task").option("-j, --json", "Output JSON").action(async (options) => {
|
|
@@ -11328,8 +10955,8 @@ function createTaskPickCommand() {
|
|
|
11328
10955
|
console.log(JSON.stringify({ picked: null, message: "No tasks ready" }));
|
|
11329
10956
|
return;
|
|
11330
10957
|
}
|
|
11331
|
-
console.log(
|
|
11332
|
-
console.log(
|
|
10958
|
+
console.log(chalk24.dim("No tasks ready to pick."));
|
|
10959
|
+
console.log(chalk24.dim('\u{1F4A1} Add tasks first: jai1 t add "..."'));
|
|
11333
10960
|
return;
|
|
11334
10961
|
}
|
|
11335
10962
|
const top = ready[0];
|
|
@@ -11339,13 +10966,13 @@ function createTaskPickCommand() {
|
|
|
11339
10966
|
console.log(JSON.stringify(picked2, null, 2));
|
|
11340
10967
|
return;
|
|
11341
10968
|
}
|
|
11342
|
-
console.log(
|
|
11343
|
-
console.log(` ${
|
|
10969
|
+
console.log(chalk24.bold("\n\u{1F4CC} Next available task:"));
|
|
10970
|
+
console.log(` ${chalk24.bold(top.id)} P${top.priority}${icon} ${top.title}`);
|
|
11344
10971
|
if (top.parent) {
|
|
11345
|
-
console.log(` ${
|
|
10972
|
+
console.log(` ${chalk24.dim("Parent:")} ${top.parent}`);
|
|
11346
10973
|
}
|
|
11347
10974
|
if (ready.length > 1) {
|
|
11348
|
-
console.log(
|
|
10975
|
+
console.log(chalk24.dim(`
|
|
11349
10976
|
+${ready.length - 1} more tasks ready`));
|
|
11350
10977
|
}
|
|
11351
10978
|
const proceed = await confirm9({
|
|
@@ -11353,18 +10980,18 @@ function createTaskPickCommand() {
|
|
|
11353
10980
|
default: true
|
|
11354
10981
|
});
|
|
11355
10982
|
if (!proceed) {
|
|
11356
|
-
console.log(
|
|
10983
|
+
console.log(chalk24.dim("\nCancelled."));
|
|
11357
10984
|
return;
|
|
11358
10985
|
}
|
|
11359
10986
|
const picked = await service.pick(top.id);
|
|
11360
|
-
console.log(
|
|
10987
|
+
console.log(chalk24.green(`
|
|
11361
10988
|
\u2705 ${picked.id} assigned to @${picked.assigned_to}, status \u2192 in_progress`));
|
|
11362
10989
|
});
|
|
11363
10990
|
}
|
|
11364
10991
|
|
|
11365
10992
|
// src/commands/tasks/done.ts
|
|
11366
10993
|
import { Command as Command52 } from "commander";
|
|
11367
|
-
import
|
|
10994
|
+
import chalk25 from "chalk";
|
|
11368
10995
|
function createTaskDoneCommand() {
|
|
11369
10996
|
return new Command52("done").description("Mark task as done").argument("<id>", "Task ID (e.g. T-001)").option("-j, --json", "Output JSON").action(async (id, options) => {
|
|
11370
10997
|
const service = new TaskService();
|
|
@@ -11374,9 +11001,9 @@ function createTaskDoneCommand() {
|
|
|
11374
11001
|
console.log(JSON.stringify(task, null, 2));
|
|
11375
11002
|
return;
|
|
11376
11003
|
}
|
|
11377
|
-
console.log(
|
|
11004
|
+
console.log(chalk25.green(`\u2705 ${task.id}: ${task.title} \u2192 done`));
|
|
11378
11005
|
} catch (error) {
|
|
11379
|
-
console.error(
|
|
11006
|
+
console.error(chalk25.red(`\u274C ${error instanceof Error ? error.message : String(error)}`));
|
|
11380
11007
|
process.exit(1);
|
|
11381
11008
|
}
|
|
11382
11009
|
});
|
|
@@ -11384,7 +11011,7 @@ function createTaskDoneCommand() {
|
|
|
11384
11011
|
|
|
11385
11012
|
// src/commands/tasks/dep.ts
|
|
11386
11013
|
import { Command as Command53 } from "commander";
|
|
11387
|
-
import
|
|
11014
|
+
import chalk26 from "chalk";
|
|
11388
11015
|
function createTaskDepCommand() {
|
|
11389
11016
|
return new Command53("dep").description("Add dependency: child depends on parent").argument("<childId>", "Child task ID (the one that waits)").argument("<parentId>", "Parent task ID (must be done first)").option("-j, --json", "Output JSON").action(async (childId, parentId, options) => {
|
|
11390
11017
|
const service = new TaskService();
|
|
@@ -11394,10 +11021,10 @@ function createTaskDepCommand() {
|
|
|
11394
11021
|
console.log(JSON.stringify(task, null, 2));
|
|
11395
11022
|
return;
|
|
11396
11023
|
}
|
|
11397
|
-
console.log(
|
|
11398
|
-
console.log(
|
|
11024
|
+
console.log(chalk26.green(`\u2705 ${childId} now depends on ${parentId}`));
|
|
11025
|
+
console.log(chalk26.dim(` ${task.title} \u2192 waits for ${parentId}`));
|
|
11399
11026
|
} catch (error) {
|
|
11400
|
-
console.error(
|
|
11027
|
+
console.error(chalk26.red(`\u274C ${error instanceof Error ? error.message : String(error)}`));
|
|
11401
11028
|
process.exit(1);
|
|
11402
11029
|
}
|
|
11403
11030
|
});
|
|
@@ -11405,27 +11032,27 @@ function createTaskDepCommand() {
|
|
|
11405
11032
|
|
|
11406
11033
|
// src/commands/tasks/sync.ts
|
|
11407
11034
|
import { Command as Command54 } from "commander";
|
|
11408
|
-
import
|
|
11035
|
+
import chalk27 from "chalk";
|
|
11409
11036
|
function createTaskSyncCommand() {
|
|
11410
11037
|
return new Command54("sync").description("Sync tasks with git (commit & push only tasks file)").option("--pull", "Pull and merge tasks from origin/main").option("--push", "Commit and push tasks file").action(async (options) => {
|
|
11411
11038
|
const service = new TaskService();
|
|
11412
11039
|
if (options.pull) {
|
|
11413
|
-
console.log(
|
|
11040
|
+
console.log(chalk27.dim("\u23F3 Pulling tasks from origin/main..."));
|
|
11414
11041
|
try {
|
|
11415
11042
|
const result = await service.syncPull();
|
|
11416
|
-
console.log(
|
|
11043
|
+
console.log(chalk27.green(`\u2705 Sync pull complete: ${result.merged} tasks merged`));
|
|
11417
11044
|
} catch (error) {
|
|
11418
|
-
console.error(
|
|
11045
|
+
console.error(chalk27.red(`\u274C ${error instanceof Error ? error.message : String(error)}`));
|
|
11419
11046
|
process.exit(1);
|
|
11420
11047
|
}
|
|
11421
11048
|
return;
|
|
11422
11049
|
}
|
|
11423
|
-
console.log(
|
|
11050
|
+
console.log(chalk27.dim("\u23F3 Syncing tasks to git..."));
|
|
11424
11051
|
try {
|
|
11425
11052
|
await service.syncPush();
|
|
11426
|
-
console.log(
|
|
11053
|
+
console.log(chalk27.green("\u2705 Tasks synced to git"));
|
|
11427
11054
|
} catch (error) {
|
|
11428
|
-
console.error(
|
|
11055
|
+
console.error(chalk27.red(`\u274C ${error instanceof Error ? error.message : String(error)}`));
|
|
11429
11056
|
process.exit(1);
|
|
11430
11057
|
}
|
|
11431
11058
|
});
|
|
@@ -11433,107 +11060,107 @@ function createTaskSyncCommand() {
|
|
|
11433
11060
|
|
|
11434
11061
|
// src/commands/tasks/guide.ts
|
|
11435
11062
|
import { Command as Command55 } from "commander";
|
|
11436
|
-
import
|
|
11063
|
+
import chalk28 from "chalk";
|
|
11437
11064
|
var GUIDE_TEXT = `
|
|
11438
|
-
${
|
|
11439
|
-
|
|
11440
|
-
${
|
|
11441
|
-
${
|
|
11442
|
-
${
|
|
11443
|
-
${
|
|
11444
|
-
${
|
|
11445
|
-
${
|
|
11446
|
-
|
|
11447
|
-
${
|
|
11448
|
-
${
|
|
11449
|
-
${
|
|
11450
|
-
${
|
|
11451
|
-
${
|
|
11452
|
-
|
|
11453
|
-
${
|
|
11454
|
-
${
|
|
11455
|
-
${
|
|
11456
|
-
${
|
|
11457
|
-
${
|
|
11458
|
-
|
|
11459
|
-
${
|
|
11460
|
-
${
|
|
11461
|
-
${
|
|
11462
|
-
${
|
|
11463
|
-
${
|
|
11464
|
-
${
|
|
11465
|
-
${
|
|
11466
|
-
|
|
11467
|
-
${
|
|
11468
|
-
${
|
|
11469
|
-
${
|
|
11470
|
-
|
|
11471
|
-
${
|
|
11472
|
-
${
|
|
11473
|
-
${
|
|
11474
|
-
${
|
|
11475
|
-
|
|
11476
|
-
${
|
|
11477
|
-
${
|
|
11478
|
-
|
|
11479
|
-
${
|
|
11480
|
-
${
|
|
11481
|
-
|
|
11482
|
-
${
|
|
11483
|
-
${
|
|
11484
|
-
|
|
11485
|
-
${
|
|
11486
|
-
${
|
|
11487
|
-
${
|
|
11488
|
-
${
|
|
11489
|
-
|
|
11490
|
-
${
|
|
11491
|
-
${
|
|
11492
|
-
${
|
|
11493
|
-
${
|
|
11494
|
-
|
|
11495
|
-
${
|
|
11496
|
-
${
|
|
11497
|
-
|
|
11498
|
-
${
|
|
11499
|
-
${
|
|
11500
|
-
${
|
|
11501
|
-
|
|
11502
|
-
${
|
|
11503
|
-
${
|
|
11504
|
-
|
|
11505
|
-
${
|
|
11506
|
-
${
|
|
11507
|
-
1. ${
|
|
11508
|
-
2. ${
|
|
11509
|
-
3. ${
|
|
11510
|
-
4. ${
|
|
11511
|
-
|
|
11512
|
-
${
|
|
11513
|
-
1. ${
|
|
11065
|
+
${chalk28.cyan.bold("\u{1F4D6} Jai1 Task Management Guide")}
|
|
11066
|
+
|
|
11067
|
+
${chalk28.bold("\u2501\u2501\u2501 STATUSES \u2501\u2501\u2501")}
|
|
11068
|
+
${chalk28.dim("todo")} \u{1F4CB} Ch\u01B0a b\u1EAFt \u0111\u1EA7u
|
|
11069
|
+
${chalk28.dim("in_progress")} \u{1F535} \u0110ang l\xE0m (bao g\u1ED3m review)
|
|
11070
|
+
${chalk28.dim("done")} \u2705 Ho\xE0n th\xE0nh
|
|
11071
|
+
${chalk28.dim("cancelled")} \u26AB Hu\u1EF7
|
|
11072
|
+
${chalk28.dim("(blocked)")} \u{1F534} Computed: depends_on ch\u01B0a done
|
|
11073
|
+
|
|
11074
|
+
${chalk28.bold("\u2501\u2501\u2501 PRIORITY \u2501\u2501\u2501")}
|
|
11075
|
+
${chalk28.dim("0")} = \u{1F525} Critical \u2014 Prod down, security, block c\u1EA3 team
|
|
11076
|
+
${chalk28.dim("1")} = \u{1F534} High \u2014 Feature ch\xEDnh, deadline g\u1EA7n
|
|
11077
|
+
${chalk28.dim("2")} = \u{1F7E1} Medium \u2014 B\xECnh th\u01B0\u1EDDng (default)
|
|
11078
|
+
${chalk28.dim("3")} = \u{1F7E2} Low \u2014 Nice-to-have, docs, refactor
|
|
11079
|
+
|
|
11080
|
+
${chalk28.bold("\u2501\u2501\u2501 QUICK START \u2501\u2501\u2501")}
|
|
11081
|
+
${chalk28.cyan("jai1 t add")} "Fix login bug" -p 1 -P bug/login
|
|
11082
|
+
${chalk28.cyan("jai1 t ready")} Show tasks s\u1EB5n s\xE0ng
|
|
11083
|
+
${chalk28.cyan("jai1 t pick")} Claim & start working
|
|
11084
|
+
${chalk28.cyan("jai1 t done")} T-003 Mark complete
|
|
11085
|
+
|
|
11086
|
+
${chalk28.bold("\u2501\u2501\u2501 DAILY WORKFLOW \u2501\u2501\u2501")}
|
|
11087
|
+
${chalk28.cyan("jai1 t sync --pull")} Pull latest tasks
|
|
11088
|
+
${chalk28.cyan("jai1 t summary")} Dashboard t\u1ED5ng quan
|
|
11089
|
+
${chalk28.cyan("jai1 t ready")} Xem tasks s\u1EB5n s\xE0ng
|
|
11090
|
+
${chalk28.cyan("jai1 t pick")} Claim task m\u1EDBi
|
|
11091
|
+
${chalk28.cyan("jai1 t done")} T-xxx Ho\xE0n th\xE0nh task
|
|
11092
|
+
${chalk28.cyan("jai1 t sync --push")} Push l\xEAn git
|
|
11093
|
+
|
|
11094
|
+
${chalk28.bold("\u2501\u2501\u2501 ADDING TASKS \u2501\u2501\u2501")}
|
|
11095
|
+
${chalk28.yellow("\u26A0 Lu\xF4n ki\u1EC3m tra duplicate tr\u01B0\u1EDBc khi add:")}
|
|
11096
|
+
${chalk28.cyan("jai1 t list -P")} feature/xxx
|
|
11097
|
+
|
|
11098
|
+
${chalk28.dim("Add cho feature:")}
|
|
11099
|
+
${chalk28.cyan("jai1 t add")} "Setup DB schema" -p 1 -P feature/xxx
|
|
11100
|
+
${chalk28.cyan("jai1 t add")} "Create API" -p 1 -P feature/xxx
|
|
11101
|
+
${chalk28.cyan("jai1 t add")} "Build UI" -p 2 -P feature/xxx
|
|
11102
|
+
|
|
11103
|
+
${chalk28.dim("Add cho plan:")}
|
|
11104
|
+
${chalk28.cyan("jai1 t add")} "Refactor middleware" -p 2 -P plan/xxx
|
|
11105
|
+
|
|
11106
|
+
${chalk28.dim("Add standalone:")}
|
|
11107
|
+
${chalk28.cyan("jai1 t add")} "Fix README typo" -p 3
|
|
11108
|
+
|
|
11109
|
+
${chalk28.dim("Add bug fix:")}
|
|
11110
|
+
${chalk28.cyan("jai1 t add")} "Fix login redirect" -p 1 -P bug/xxx
|
|
11111
|
+
|
|
11112
|
+
${chalk28.bold("\u2501\u2501\u2501 DEPENDENCY \u2501\u2501\u2501")}
|
|
11113
|
+
${chalk28.dim("Task dependency:")}
|
|
11114
|
+
${chalk28.cyan("jai1 t dep")} T-002 T-001 T-002 ch\u1EDD T-001 done
|
|
11115
|
+
${chalk28.cyan("jai1 t dep")} T-003 T-002 T-003 ch\u1EDD T-002 done
|
|
11116
|
+
|
|
11117
|
+
${chalk28.dim("Feature-level dependency:")}
|
|
11118
|
+
${chalk28.dim("# N\u1EBFu feature/auth ph\u1EE5 thu\u1ED9c feature/user-model:")}
|
|
11119
|
+
${chalk28.cyan("jai1 t add")} "[DEP] Wait for feature/user-model" -p 1 -P feature/auth
|
|
11120
|
+
${chalk28.dim("# R\u1ED3i dep n\xF3 v\u1EDBi tasks cu\u1ED1i c\u1EE7a user-model")}
|
|
11121
|
+
|
|
11122
|
+
${chalk28.dim("View deps:")}
|
|
11123
|
+
${chalk28.cyan("jai1 t show")} T-002 Hi\u1EC7n depends_on
|
|
11124
|
+
|
|
11125
|
+
${chalk28.bold("\u2501\u2501\u2501 TEAM COLLABORATION \u2501\u2501\u2501")}
|
|
11126
|
+
${chalk28.yellow("\u26A0 Assignment ch\u1EC9 qua pick \u2014 kh\xF4ng set th\u1EE7 c\xF4ng.")}
|
|
11127
|
+
${chalk28.dim("Khi b\u1EA1n pick \u2192 team th\u1EA5y task \u0111\xE3 c\xF3 ng\u01B0\u1EDDi nh\u1EADn.")}
|
|
11128
|
+
|
|
11129
|
+
${chalk28.dim("Sync morning:")} ${chalk28.cyan("jai1 t sync --pull")}
|
|
11130
|
+
${chalk28.dim("Sync evening:")} ${chalk28.cyan("jai1 t sync --push")}
|
|
11131
|
+
|
|
11132
|
+
${chalk28.bold("\u2501\u2501\u2501 FOR AI AGENTS (Workflow Integration) \u2501\u2501\u2501")}
|
|
11133
|
+
${chalk28.dim("Khi t\u1EA1o tasks t\u1EEB feature/plan:")}
|
|
11134
|
+
1. ${chalk28.cyan("jai1 t list -P")} <parent> Check existing (tr\xE1nh duplicate)
|
|
11135
|
+
2. ${chalk28.cyan("jai1 t add")} "..." -p <0-3> -P <parent> Add t\u1EEBng task
|
|
11136
|
+
3. ${chalk28.cyan("jai1 t dep")} <child> <parent> Set dependencies
|
|
11137
|
+
4. ${chalk28.cyan("jai1 t done")} <id> Mark complete
|
|
11138
|
+
|
|
11139
|
+
${chalk28.dim("Khi implement task ti\u1EBFp theo:")}
|
|
11140
|
+
1. ${chalk28.cyan("jai1 t pick")} (ho\u1EB7c ${chalk28.cyan("jai1 t ready -P")} <parent>)
|
|
11514
11141
|
2. Implement task
|
|
11515
|
-
3. ${
|
|
11142
|
+
3. ${chalk28.cyan("jai1 t done")} <id>
|
|
11516
11143
|
|
|
11517
|
-
${
|
|
11144
|
+
${chalk28.dim("Status transitions:")}
|
|
11518
11145
|
add \u2192 todo (default)
|
|
11519
11146
|
pick \u2192 in_progress (auto assign)
|
|
11520
11147
|
done \u2192 done
|
|
11521
11148
|
update -s \u2192 any valid status
|
|
11522
11149
|
|
|
11523
|
-
${
|
|
11524
|
-
${
|
|
11525
|
-
${
|
|
11526
|
-
${
|
|
11527
|
-
${
|
|
11528
|
-
${
|
|
11529
|
-
${
|
|
11530
|
-
${
|
|
11531
|
-
${
|
|
11532
|
-
${
|
|
11533
|
-
${
|
|
11534
|
-
${
|
|
11535
|
-
|
|
11536
|
-
${
|
|
11150
|
+
${chalk28.bold("\u2501\u2501\u2501 ALL COMMANDS \u2501\u2501\u2501")}
|
|
11151
|
+
${chalk28.cyan("jai1 t list")} [-s status] [-P parent] [-j]
|
|
11152
|
+
${chalk28.cyan("jai1 t ready")} [-P parent] [-j]
|
|
11153
|
+
${chalk28.cyan("jai1 t add")} <title> [-p 0-3] [-P parent] [-t tags] [-j]
|
|
11154
|
+
${chalk28.cyan("jai1 t update")} <id> -s <status> [-j]
|
|
11155
|
+
${chalk28.cyan("jai1 t show")} <id|parent> [-j]
|
|
11156
|
+
${chalk28.cyan("jai1 t pick")} [-j]
|
|
11157
|
+
${chalk28.cyan("jai1 t done")} <id> [-j]
|
|
11158
|
+
${chalk28.cyan("jai1 t dep")} <childId> <parentId> [-j]
|
|
11159
|
+
${chalk28.cyan("jai1 t sync")} [--pull] [--push]
|
|
11160
|
+
${chalk28.cyan("jai1 t summary")} [-j]
|
|
11161
|
+
${chalk28.cyan("jai1 t guide")}
|
|
11162
|
+
|
|
11163
|
+
${chalk28.dim("-j / --json available on all commands (except guide, sync)")}
|
|
11537
11164
|
`;
|
|
11538
11165
|
function createTaskGuideCommand() {
|
|
11539
11166
|
return new Command55("guide").description("Show full task management guide").action(() => {
|
|
@@ -11568,11 +11195,11 @@ function createTasksCommand() {
|
|
|
11568
11195
|
|
|
11569
11196
|
// src/commands/kit/index.ts
|
|
11570
11197
|
import { Command as Command60 } from "commander";
|
|
11571
|
-
import
|
|
11198
|
+
import chalk30 from "chalk";
|
|
11572
11199
|
|
|
11573
11200
|
// src/commands/kit/list.ts
|
|
11574
11201
|
import { Command as Command57 } from "commander";
|
|
11575
|
-
import
|
|
11202
|
+
import chalk29 from "chalk";
|
|
11576
11203
|
import Table6 from "cli-table3";
|
|
11577
11204
|
|
|
11578
11205
|
// src/services/starter-kit.service.ts
|
|
@@ -11646,7 +11273,7 @@ function createKitListCommand() {
|
|
|
11646
11273
|
if (!config) {
|
|
11647
11274
|
throw new ValidationError('Not initialized. Run "jai1 auth" first.');
|
|
11648
11275
|
}
|
|
11649
|
-
console.log(
|
|
11276
|
+
console.log(chalk29.cyan("\u{1F4E6} \u0110ang t\u1EA3i danh s\xE1ch starter kits..."));
|
|
11650
11277
|
console.log();
|
|
11651
11278
|
const kitService = new StarterKitService();
|
|
11652
11279
|
const kits = await kitService.list(config, {
|
|
@@ -11654,9 +11281,9 @@ function createKitListCommand() {
|
|
|
11654
11281
|
search: options.search
|
|
11655
11282
|
});
|
|
11656
11283
|
if (kits.length === 0) {
|
|
11657
|
-
console.log(
|
|
11284
|
+
console.log(chalk29.yellow("Kh\xF4ng t\xECm th\u1EA5y starter kits n\xE0o."));
|
|
11658
11285
|
if (options.category || options.search) {
|
|
11659
|
-
console.log(
|
|
11286
|
+
console.log(chalk29.dim("Th\u1EED b\u1ECF filter \u0111\u1EC3 xem t\u1EA5t c\u1EA3."));
|
|
11660
11287
|
}
|
|
11661
11288
|
return;
|
|
11662
11289
|
}
|
|
@@ -11680,28 +11307,28 @@ function createKitListCommand() {
|
|
|
11680
11307
|
const categoryKits = byCategory[category];
|
|
11681
11308
|
const categoryIcon = category === "frontend" ? "\u{1F3A8}" : category === "backend" ? "\u2699\uFE0F" : category === "fullstack" ? "\u{1F680}" : "\u{1F4E6}";
|
|
11682
11309
|
console.log(
|
|
11683
|
-
|
|
11310
|
+
chalk29.bold(`${categoryIcon} ${category.charAt(0).toUpperCase() + category.slice(1)}`)
|
|
11684
11311
|
);
|
|
11685
11312
|
const table = new Table6({
|
|
11686
11313
|
head: [
|
|
11687
|
-
|
|
11688
|
-
|
|
11689
|
-
|
|
11314
|
+
chalk29.cyan("Slug"),
|
|
11315
|
+
chalk29.cyan("M\xF4 t\u1EA3"),
|
|
11316
|
+
chalk29.cyan("Version")
|
|
11690
11317
|
],
|
|
11691
11318
|
style: { head: [], border: ["gray"] }
|
|
11692
11319
|
});
|
|
11693
11320
|
for (const kit of categoryKits) {
|
|
11694
11321
|
table.push([
|
|
11695
|
-
|
|
11696
|
-
|
|
11697
|
-
|
|
11322
|
+
chalk29.white(kit.slug),
|
|
11323
|
+
chalk29.dim(kit.description.slice(0, 50)),
|
|
11324
|
+
chalk29.green(`v${kit.version}`)
|
|
11698
11325
|
]);
|
|
11699
11326
|
}
|
|
11700
11327
|
console.log(table.toString());
|
|
11701
11328
|
console.log();
|
|
11702
11329
|
}
|
|
11703
|
-
console.log(
|
|
11704
|
-
console.log(
|
|
11330
|
+
console.log(chalk29.dim(`T\u1ED5ng c\u1ED9ng: ${kits.length} starter kit(s)`));
|
|
11331
|
+
console.log(chalk29.dim('\n\u{1F4A1} Ch\u1EA1y "jai1 kit create <slug>" \u0111\u1EC3 t\u1EA1o project m\u1EDBi'));
|
|
11705
11332
|
});
|
|
11706
11333
|
}
|
|
11707
11334
|
|
|
@@ -11981,20 +11608,20 @@ async function getAllFiles(dir) {
|
|
|
11981
11608
|
|
|
11982
11609
|
// src/commands/kit/index.ts
|
|
11983
11610
|
function showKitHelp() {
|
|
11984
|
-
console.log(
|
|
11611
|
+
console.log(chalk30.bold.cyan("\u{1F4E6} jai1 kit") + chalk30.dim(" - Qu\u1EA3n l\xFD starter kits"));
|
|
11985
11612
|
console.log();
|
|
11986
|
-
console.log(
|
|
11987
|
-
console.log(` ${
|
|
11988
|
-
console.log(` ${
|
|
11989
|
-
console.log(` ${
|
|
11613
|
+
console.log(chalk30.bold("C\xE1c l\u1EC7nh:"));
|
|
11614
|
+
console.log(` ${chalk30.cyan("list")} Li\u1EC7t k\xEA c\xE1c starter kits c\xF3 s\u1EB5n`);
|
|
11615
|
+
console.log(` ${chalk30.cyan("info")} Xem chi ti\u1EBFt m\u1ED9t starter kit`);
|
|
11616
|
+
console.log(` ${chalk30.cyan("create")} T\u1EA1o project m\u1EDBi t\u1EEB starter kit`);
|
|
11990
11617
|
console.log();
|
|
11991
|
-
console.log(
|
|
11992
|
-
console.log(
|
|
11993
|
-
console.log(
|
|
11994
|
-
console.log(
|
|
11995
|
-
console.log(
|
|
11618
|
+
console.log(chalk30.bold("V\xED d\u1EE5:"));
|
|
11619
|
+
console.log(chalk30.dim(" $ jai1 kit list"));
|
|
11620
|
+
console.log(chalk30.dim(" $ jai1 kit list --category frontend"));
|
|
11621
|
+
console.log(chalk30.dim(" $ jai1 kit info next-tw4-shadcn"));
|
|
11622
|
+
console.log(chalk30.dim(" $ jai1 kit create next-tw4-shadcn my-project"));
|
|
11996
11623
|
console.log();
|
|
11997
|
-
console.log(
|
|
11624
|
+
console.log(chalk30.dim('Ch\u1EA1y "jai1 kit <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt'));
|
|
11998
11625
|
}
|
|
11999
11626
|
function createKitCommand() {
|
|
12000
11627
|
const cmd = new Command60("kit").description("Manage starter kits for new projects").action(() => {
|
|
@@ -12008,11 +11635,11 @@ function createKitCommand() {
|
|
|
12008
11635
|
|
|
12009
11636
|
// src/commands/rules/index.ts
|
|
12010
11637
|
import { Command as Command67 } from "commander";
|
|
12011
|
-
import
|
|
11638
|
+
import chalk32 from "chalk";
|
|
12012
11639
|
|
|
12013
11640
|
// src/commands/rules/list.ts
|
|
12014
11641
|
import { Command as Command61 } from "commander";
|
|
12015
|
-
import
|
|
11642
|
+
import chalk31 from "chalk";
|
|
12016
11643
|
import Table7 from "cli-table3";
|
|
12017
11644
|
function createRulesListCommand() {
|
|
12018
11645
|
return new Command61("list").description("List available rule presets").option("--json", "Output as JSON").action(async (options) => {
|
|
@@ -12021,7 +11648,7 @@ function createRulesListCommand() {
|
|
|
12021
11648
|
if (!config) {
|
|
12022
11649
|
throw new ValidationError('Not initialized. Run "jai1 auth" first.');
|
|
12023
11650
|
}
|
|
12024
|
-
console.log(
|
|
11651
|
+
console.log(chalk31.cyan("\u{1F4CB} \u0110ang t\u1EA3i danh s\xE1ch rule presets..."));
|
|
12025
11652
|
console.log();
|
|
12026
11653
|
try {
|
|
12027
11654
|
const response = await fetch(`${config.apiUrl}/api/rules/presets`, {
|
|
@@ -12038,23 +11665,23 @@ function createRulesListCommand() {
|
|
|
12038
11665
|
return;
|
|
12039
11666
|
}
|
|
12040
11667
|
if (data.total === 0) {
|
|
12041
|
-
console.log(
|
|
11668
|
+
console.log(chalk31.yellow("Kh\xF4ng c\xF3 presets n\xE0o."));
|
|
12042
11669
|
return;
|
|
12043
11670
|
}
|
|
12044
11671
|
console.log(
|
|
12045
|
-
|
|
11672
|
+
chalk31.green(`\u2713 T\xECm th\u1EA5y ${chalk31.bold(data.total)} preset${data.total > 1 ? "s" : ""}`)
|
|
12046
11673
|
);
|
|
12047
11674
|
console.log();
|
|
12048
11675
|
for (const preset of data.presets) {
|
|
12049
|
-
console.log(
|
|
11676
|
+
console.log(chalk31.bold.cyan(`\u{1F4E6} ${preset.slug}`));
|
|
12050
11677
|
const table = new Table7({
|
|
12051
11678
|
style: { head: [], border: ["gray"], compact: true },
|
|
12052
11679
|
colWidths: [15, 55]
|
|
12053
11680
|
});
|
|
12054
11681
|
table.push(
|
|
12055
|
-
[
|
|
12056
|
-
[
|
|
12057
|
-
[
|
|
11682
|
+
[chalk31.dim("T\xEAn"), chalk31.white(preset.name)],
|
|
11683
|
+
[chalk31.dim("M\xF4 t\u1EA3"), chalk31.white(preset.description)],
|
|
11684
|
+
[chalk31.dim("Version"), chalk31.green(`v${preset.version}`)]
|
|
12058
11685
|
);
|
|
12059
11686
|
const stackParts = [];
|
|
12060
11687
|
if (preset.stack.frontend) stackParts.push(preset.stack.frontend);
|
|
@@ -12062,16 +11689,16 @@ function createRulesListCommand() {
|
|
|
12062
11689
|
if (preset.stack.css) stackParts.push(preset.stack.css);
|
|
12063
11690
|
if (preset.stack.database) stackParts.push(preset.stack.database);
|
|
12064
11691
|
if (stackParts.length > 0) {
|
|
12065
|
-
table.push([
|
|
11692
|
+
table.push([chalk31.dim("Stack"), chalk31.yellow(stackParts.join(" + "))]);
|
|
12066
11693
|
}
|
|
12067
11694
|
table.push(
|
|
12068
|
-
[
|
|
12069
|
-
[
|
|
11695
|
+
[chalk31.dim("Tags"), chalk31.dim(preset.tags.join(", ") || "-")],
|
|
11696
|
+
[chalk31.dim("Downloads"), chalk31.white(preset.downloads.toString())]
|
|
12070
11697
|
);
|
|
12071
11698
|
console.log(table.toString());
|
|
12072
11699
|
console.log();
|
|
12073
11700
|
}
|
|
12074
|
-
console.log(
|
|
11701
|
+
console.log(chalk31.dim('\u{1F4A1} Ch\u1EA1y "jai1 rules apply <name>" \u0111\u1EC3 \xE1p d\u1EE5ng preset'));
|
|
12075
11702
|
} catch (error) {
|
|
12076
11703
|
throw new Error(
|
|
12077
11704
|
`L\u1ED7i khi t\u1EA3i presets: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -13499,23 +13126,23 @@ async function checkIdeFilesExist(ideId, format) {
|
|
|
13499
13126
|
|
|
13500
13127
|
// src/commands/rules/index.ts
|
|
13501
13128
|
function showRulesHelp() {
|
|
13502
|
-
console.log(
|
|
13129
|
+
console.log(chalk32.bold.cyan("\u{1F4CB} jai1 rules") + chalk32.dim(" - Qu\u1EA3n l\xFD rule presets cho AI agents"));
|
|
13503
13130
|
console.log();
|
|
13504
|
-
console.log(
|
|
13505
|
-
console.log(` ${
|
|
13506
|
-
console.log(` ${
|
|
13507
|
-
console.log(` ${
|
|
13508
|
-
console.log(` ${
|
|
13509
|
-
console.log(` ${
|
|
13510
|
-
console.log(` ${
|
|
13131
|
+
console.log(chalk32.bold("C\xE1c l\u1EC7nh:"));
|
|
13132
|
+
console.log(` ${chalk32.cyan("list")} Li\u1EC7t k\xEA c\xE1c presets c\xF3 s\u1EB5n`);
|
|
13133
|
+
console.log(` ${chalk32.cyan("info")} Xem chi ti\u1EBFt m\u1ED9t preset`);
|
|
13134
|
+
console.log(` ${chalk32.cyan("init")} Kh\u1EDFi t\u1EA1o rules t\u1EEB preset`);
|
|
13135
|
+
console.log(` ${chalk32.cyan("apply")} \xC1p d\u1EE5ng preset v\xE0o project`);
|
|
13136
|
+
console.log(` ${chalk32.cyan("sync")} \u0110\u1ED3ng b\u1ED9 rules sang c\xE1c \u0111\u1ECBnh d\u1EA1ng IDE`);
|
|
13137
|
+
console.log(` ${chalk32.cyan("restore")} Kh\xF4i ph\u1EE5c rules t\u1EEB backup`);
|
|
13511
13138
|
console.log();
|
|
13512
|
-
console.log(
|
|
13513
|
-
console.log(
|
|
13514
|
-
console.log(
|
|
13515
|
-
console.log(
|
|
13516
|
-
console.log(
|
|
13139
|
+
console.log(chalk32.bold("V\xED d\u1EE5:"));
|
|
13140
|
+
console.log(chalk32.dim(" $ jai1 rules list"));
|
|
13141
|
+
console.log(chalk32.dim(" $ jai1 rules info react-typescript"));
|
|
13142
|
+
console.log(chalk32.dim(" $ jai1 rules init --preset=react-typescript"));
|
|
13143
|
+
console.log(chalk32.dim(" $ jai1 rules apply react-typescript"));
|
|
13517
13144
|
console.log();
|
|
13518
|
-
console.log(
|
|
13145
|
+
console.log(chalk32.dim('Ch\u1EA1y "jai1 rules <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt'));
|
|
13519
13146
|
}
|
|
13520
13147
|
function createRulesCommand() {
|
|
13521
13148
|
const rulesCommand = new Command67("rules").description("Manage rule presets for AI agents").action(() => {
|
|
@@ -15248,92 +14875,11 @@ async function resetSettings2(groupKeys) {
|
|
|
15248
14875
|
console.log("\u{1F4A1} M\u1EB9o: Kh\u1EDFi \u0111\u1ED9ng l\u1EA1i VSCode \u0111\u1EC3 \xE1p d\u1EE5ng c\xE1c thay \u0111\u1ED5i.");
|
|
15249
14876
|
}
|
|
15250
14877
|
|
|
15251
|
-
// src/commands/context.ts
|
|
15252
|
-
import React32 from "react";
|
|
15253
|
-
import { render as render6 } from "ink";
|
|
15254
|
-
import { Command as Command77 } from "commander";
|
|
15255
|
-
function createContextCommand() {
|
|
15256
|
-
const cmd = new Command77("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) => {
|
|
15257
|
-
let initialIDE;
|
|
15258
|
-
if (options.ide) {
|
|
15259
|
-
const validIDEs = ["cursor", "windsurf", "antigravity", "jai1"];
|
|
15260
|
-
if (!validIDEs.includes(options.ide)) {
|
|
15261
|
-
console.error(`\u274C IDE kh\xF4ng h\u1EE3p l\u1EC7: ${options.ide}`);
|
|
15262
|
-
console.error(` IDE h\u1EE3p l\u1EC7: ${validIDEs.join(", ")}`);
|
|
15263
|
-
process.exit(1);
|
|
15264
|
-
}
|
|
15265
|
-
initialIDE = options.ide;
|
|
15266
|
-
}
|
|
15267
|
-
let initialType;
|
|
15268
|
-
if (options.type) {
|
|
15269
|
-
const validTypes = ["rules", "workflows", "skills", "agents", "prompts", "context"];
|
|
15270
|
-
if (!validTypes.includes(options.type)) {
|
|
15271
|
-
console.error(`\u274C Lo\u1EA1i context kh\xF4ng h\u1EE3p l\u1EC7: ${options.type}`);
|
|
15272
|
-
console.error(` Lo\u1EA1i h\u1EE3p l\u1EC7: ${validTypes.join(", ")}`);
|
|
15273
|
-
process.exit(1);
|
|
15274
|
-
}
|
|
15275
|
-
initialType = options.type;
|
|
15276
|
-
}
|
|
15277
|
-
if (options.stats) {
|
|
15278
|
-
await printStats2();
|
|
15279
|
-
return;
|
|
15280
|
-
}
|
|
15281
|
-
const { waitUntilExit } = render6(
|
|
15282
|
-
React32.createElement(ContextApp, {
|
|
15283
|
-
initialIDE,
|
|
15284
|
-
initialType,
|
|
15285
|
-
onExit: () => {
|
|
15286
|
-
process.exit(0);
|
|
15287
|
-
}
|
|
15288
|
-
})
|
|
15289
|
-
);
|
|
15290
|
-
await waitUntilExit();
|
|
15291
|
-
});
|
|
15292
|
-
return cmd;
|
|
15293
|
-
}
|
|
15294
|
-
async function printStats2() {
|
|
15295
|
-
const scanner = new ContextScannerService();
|
|
15296
|
-
console.log("\u{1F50D} \u0110ang qu\xE9t context...\n");
|
|
15297
|
-
try {
|
|
15298
|
-
const context = await scanner.scanAll();
|
|
15299
|
-
if (context.ides.length === 0) {
|
|
15300
|
-
console.log("\u26A0\uFE0F Kh\xF4ng t\xECm th\u1EA5y context n\xE0o");
|
|
15301
|
-
console.log(" H\xE3y ch\u1EA1y `jai1 apply` \u0111\u1EC3 c\xE0i \u0111\u1EB7t context cho IDE c\u1EE7a b\u1EA1n.\n");
|
|
15302
|
-
return;
|
|
15303
|
-
}
|
|
15304
|
-
console.log("\u{1F4CA} Th\u1ED1ng k\xEA Context\n");
|
|
15305
|
-
console.log(`\u{1F4C1} Project: ${context.projectPath}`);
|
|
15306
|
-
console.log(`\u{1F550} Scan time: ${context.scanTime.toLocaleString("vi-VN")}
|
|
15307
|
-
`);
|
|
15308
|
-
for (const ideContext of context.ides) {
|
|
15309
|
-
console.log(`${ideContext.config.icon} ${ideContext.config.name}`);
|
|
15310
|
-
console.log(` Path: ${ideContext.config.basePath}`);
|
|
15311
|
-
console.log(` Items: ${ideContext.stats.totalItems}`);
|
|
15312
|
-
const types = [];
|
|
15313
|
-
if (ideContext.stats.byType.rules) types.push(`${ideContext.stats.byType.rules} rules`);
|
|
15314
|
-
if (ideContext.stats.byType.workflows) types.push(`${ideContext.stats.byType.workflows} workflows`);
|
|
15315
|
-
if (ideContext.stats.byType.skills) types.push(`${ideContext.stats.byType.skills} skills`);
|
|
15316
|
-
if (ideContext.stats.byType.agents) types.push(`${ideContext.stats.byType.agents} agents`);
|
|
15317
|
-
if (ideContext.stats.byType.prompts) types.push(`${ideContext.stats.byType.prompts} prompts`);
|
|
15318
|
-
if (ideContext.stats.byType.context) types.push(`${ideContext.stats.byType.context} context`);
|
|
15319
|
-
if (types.length > 0) {
|
|
15320
|
-
console.log(` Breakdown: ${types.join(", ")}`);
|
|
15321
|
-
}
|
|
15322
|
-
console.log("");
|
|
15323
|
-
}
|
|
15324
|
-
console.log(`\u2705 T\u1ED5ng: ${context.totalItems} items
|
|
15325
|
-
`);
|
|
15326
|
-
} catch (error) {
|
|
15327
|
-
console.error("\u274C L\u1ED7i khi qu\xE9t context:", error);
|
|
15328
|
-
process.exit(1);
|
|
15329
|
-
}
|
|
15330
|
-
}
|
|
15331
|
-
|
|
15332
14878
|
// src/commands/migrate-ide.ts
|
|
15333
|
-
import { Command as
|
|
14879
|
+
import { Command as Command77 } from "commander";
|
|
15334
14880
|
import { checkbox as checkbox8, confirm as confirm19 } from "@inquirer/prompts";
|
|
15335
14881
|
function createMigrateIdeCommand() {
|
|
15336
|
-
const cmd = new
|
|
14882
|
+
const cmd = new Command77("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) => {
|
|
15337
14883
|
await runMigrateIde(options);
|
|
15338
14884
|
});
|
|
15339
14885
|
return cmd;
|
|
@@ -15442,62 +14988,62 @@ async function runMigrateIde(options) {
|
|
|
15442
14988
|
|
|
15443
14989
|
// src/utils/help-formatter.ts
|
|
15444
14990
|
import boxen4 from "boxen";
|
|
15445
|
-
import
|
|
14991
|
+
import chalk33 from "chalk";
|
|
15446
14992
|
import gradient from "gradient-string";
|
|
15447
14993
|
import figlet from "figlet";
|
|
15448
14994
|
function showCustomHelp(version) {
|
|
15449
14995
|
const title = figlet.textSync("JAI1", { font: "Small" });
|
|
15450
14996
|
console.log(gradient.pastel(title));
|
|
15451
14997
|
console.log(
|
|
15452
|
-
boxen4(
|
|
14998
|
+
boxen4(chalk33.cyan(`Agentic Coding CLI v${version}`), {
|
|
15453
14999
|
padding: { left: 1, right: 1, top: 0, bottom: 0 },
|
|
15454
15000
|
borderStyle: "round",
|
|
15455
15001
|
borderColor: "cyan"
|
|
15456
15002
|
})
|
|
15457
15003
|
);
|
|
15458
|
-
console.log(
|
|
15004
|
+
console.log(chalk33.bold("\n\u{1F527} Thi\u1EBFt l\u1EADp & Th\xF4ng tin"));
|
|
15459
15005
|
console.log(" auth X\xE1c th\u1EF1c v\xE0 c\u1EA5u h\xECnh client");
|
|
15460
15006
|
console.log(" status Hi\u1EC3n th\u1ECB tr\u1EA1ng th\xE1i c\u1EA5u h\xECnh");
|
|
15461
15007
|
console.log(" client-info T\u1EA1o th\xF4ng tin client \u0111\u1EC3 g\u1EEDi \u0111\u1ED9i ph\xE1t tri\u1EC3n");
|
|
15462
15008
|
console.log(" errors Qu\u1EA3n l\xFD error logs c\u1EE5c b\u1ED9");
|
|
15463
15009
|
console.log(" guide H\u01B0\u1EDBng d\u1EABn s\u1EED d\u1EE5ng nhanh");
|
|
15464
15010
|
console.log(" doctor Chu\u1EA9n \u0111o\xE1n project hi\u1EC7n t\u1EA1i");
|
|
15465
|
-
console.log(
|
|
15011
|
+
console.log(chalk33.bold("\n\u{1F4E6} Qu\u1EA3n l\xFD Components"));
|
|
15466
15012
|
console.log(" apply C\xE0i \u0111\u1EB7t components (interactive)");
|
|
15467
15013
|
console.log(" update C\u1EADp nh\u1EADt components \u0111\xE3 c\xE0i");
|
|
15468
15014
|
console.log(" check Ki\u1EC3m tra c\u1EADp nh\u1EADt t\u1EEB server");
|
|
15469
|
-
console.log(
|
|
15015
|
+
console.log(chalk33.bold("\n\u{1F5A5}\uFE0F IDE & T\xEDch h\u1EE3p"));
|
|
15470
15016
|
console.log(" ide L\u1EC7nh c\u1EA5u h\xECnh IDE");
|
|
15471
15017
|
console.log(" chat Chat AI v\u1EDBi Jai1 LLM Proxy");
|
|
15472
15018
|
console.log(" openai-keys Th\xF4ng tin API credentials");
|
|
15473
|
-
console.log(
|
|
15019
|
+
console.log(chalk33.bold("\n\u{1F916} AI Tools"));
|
|
15474
15020
|
console.log(" translate D\u1ECBch v\u0103n b\u1EA3n/file b\u1EB1ng AI");
|
|
15475
15021
|
console.log(" image T\u1EA1o \u1EA3nh (Coming Soon)");
|
|
15476
15022
|
console.log(" stats Th\u1ED1ng k\xEA s\u1EED d\u1EE5ng LLM");
|
|
15477
15023
|
console.log(" feedback G\u1EEDi b\xE1o c\xE1o/\u0111\u1EC1 xu\u1EA5t");
|
|
15478
|
-
console.log(
|
|
15024
|
+
console.log(chalk33.bold("\n\u{1F4C1} Project"));
|
|
15479
15025
|
console.log(" kit Qu\u1EA3n l\xFD starter kits");
|
|
15480
15026
|
console.log(" rules Qu\u1EA3n l\xFD rule presets");
|
|
15481
15027
|
console.log(" deps Qu\u1EA3n l\xFD dependencies");
|
|
15482
15028
|
console.log(" redmine Redmine context sync");
|
|
15483
|
-
console.log(
|
|
15029
|
+
console.log(chalk33.bold("\n\u2699\uFE0F B\u1EA3o tr\xEC"));
|
|
15484
15030
|
console.log(" upgrade C\u1EADp nh\u1EADt CLI client");
|
|
15485
15031
|
console.log(" clean D\u1ECDn d\u1EB9p cache/backup");
|
|
15486
15032
|
console.log(" utils Developer utilities");
|
|
15487
15033
|
const name = getCliName();
|
|
15488
|
-
console.log(
|
|
15034
|
+
console.log(chalk33.dim(`
|
|
15489
15035
|
S\u1EED d\u1EE5ng: ${name} [l\u1EC7nh] --help \u0111\u1EC3 xem chi ti\u1EBFt`));
|
|
15490
15036
|
}
|
|
15491
15037
|
function showUnknownCommand(commandName) {
|
|
15492
|
-
console.error(
|
|
15038
|
+
console.error(chalk33.red(`\u274C L\u1EC7nh kh\xF4ng t\u1ED3n t\u1EA1i: ${commandName}`));
|
|
15493
15039
|
const name = getCliName();
|
|
15494
|
-
console.error(
|
|
15040
|
+
console.error(chalk33.dim(`
|
|
15495
15041
|
G\u1EE3i \xFD: Ch\u1EA1y ${name} --help \u0111\u1EC3 xem danh s\xE1ch l\u1EC7nh`));
|
|
15496
15042
|
}
|
|
15497
15043
|
|
|
15498
15044
|
// src/cli.ts
|
|
15499
15045
|
checkNodeVersion();
|
|
15500
|
-
var program = new
|
|
15046
|
+
var program = new Command78();
|
|
15501
15047
|
if (process.argv.includes("-v") || process.argv.includes("--version")) {
|
|
15502
15048
|
console.log(package_default.version);
|
|
15503
15049
|
if (!process.argv.includes("--skip-update-check")) {
|
|
@@ -15536,9 +15082,9 @@ program.addCommand(createKitCommand());
|
|
|
15536
15082
|
program.addCommand(createRulesCommand());
|
|
15537
15083
|
program.addCommand(createUpgradeCommand());
|
|
15538
15084
|
program.addCommand(createCleanCommand());
|
|
15539
|
-
var redmineCommand = new
|
|
15085
|
+
var redmineCommand = new Command78("redmine").description("Redmine context sync commands");
|
|
15540
15086
|
redmineCommand.addCommand(createRedmineCheckCommand());
|
|
15541
|
-
var syncCommand = new
|
|
15087
|
+
var syncCommand = new Command78("sync").description("Sync Redmine issues to markdown files");
|
|
15542
15088
|
syncCommand.addCommand(createSyncIssueCommand());
|
|
15543
15089
|
syncCommand.addCommand(createSyncProjectCommand());
|
|
15544
15090
|
redmineCommand.addCommand(syncCommand);
|