@jvittechs/j 1.0.14 → 1.0.15
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 +923 -1405
- 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.15",
|
|
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,105 @@ var ContextScannerService = class {
|
|
|
3267
2962
|
}
|
|
3268
2963
|
};
|
|
3269
2964
|
|
|
3270
|
-
// src/
|
|
3271
|
-
var
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
|
|
3280
|
-
|
|
3281
|
-
|
|
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
|
-
const handleSelectType = (type) => {
|
|
3323
|
-
setSelectedType(type);
|
|
3324
|
-
setScreen("list");
|
|
3325
|
-
};
|
|
3326
|
-
const handleSelectItem = (item) => {
|
|
3327
|
-
setSelectedItem(item);
|
|
3328
|
-
setScreen("detail");
|
|
3329
|
-
setScrollPosition(0);
|
|
3330
|
-
};
|
|
3331
|
-
const currentIDEContext = ideContexts.find((ctx) => ctx.ide === selectedIDE);
|
|
3332
|
-
const currentItems = currentIDEContext?.items?.filter((item) => item.type === selectedType) ?? [];
|
|
3333
|
-
const renderContent = () => {
|
|
3334
|
-
if (loading) {
|
|
3335
|
-
return /* @__PURE__ */ React11.createElement(Box8, { padding: 1 }, /* @__PURE__ */ React11.createElement(Text9, null, "\u0110ang qu\xE9t context..."));
|
|
3336
|
-
}
|
|
3337
|
-
switch (screen) {
|
|
3338
|
-
case "menu":
|
|
3339
|
-
return /* @__PURE__ */ React11.createElement(MainMenuView, { ideContexts, onSelect: handleSelectIDE });
|
|
3340
|
-
case "overview":
|
|
3341
|
-
return currentIDEContext ? /* @__PURE__ */ React11.createElement(
|
|
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 });
|
|
3370
|
-
}
|
|
3371
|
-
};
|
|
3372
|
-
const getFooterHints = () => {
|
|
3373
|
-
switch (screen) {
|
|
3374
|
-
case "menu":
|
|
3375
|
-
return "[\u2191\u2193] Ch\u1ECDn \xB7 [Enter] M\u1EDF \xB7 [q] Tho\xE1t";
|
|
3376
|
-
case "overview":
|
|
3377
|
-
return "[Tab/1-6] Chuy\u1EC3n tab \xB7 [Enter] Xem danh s\xE1ch \xB7 [Esc/\u2190] Quay l\u1EA1i \xB7 [q] Tho\xE1t";
|
|
3378
|
-
case "list":
|
|
3379
|
-
return "[\u2191\u2193] Ch\u1ECDn \xB7 [Enter] Chi ti\u1EBFt \xB7 [Esc/\u2190] Quay l\u1EA1i \xB7 [q] Tho\xE1t";
|
|
3380
|
-
case "detail":
|
|
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";
|
|
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 = 40;
|
|
2970
|
+
var CHARS_PER_TOKEN = 4;
|
|
2971
|
+
function estimateTokens(bytes) {
|
|
2972
|
+
return Math.ceil(bytes / CHARS_PER_TOKEN);
|
|
2973
|
+
}
|
|
2974
|
+
function formatNumber(n) {
|
|
2975
|
+
return n.toLocaleString("en-US");
|
|
2976
|
+
}
|
|
2977
|
+
function renderBar(value, total, width, color) {
|
|
2978
|
+
const filled = Math.round(value / total * width);
|
|
2979
|
+
const empty = width - filled;
|
|
2980
|
+
return color("\u2588".repeat(filled)) + chalk6.gray("\u2591".repeat(empty));
|
|
2981
|
+
}
|
|
2982
|
+
function renderPercentage(value, total) {
|
|
2983
|
+
return (value / total * 100).toFixed(1) + "%";
|
|
2984
|
+
}
|
|
2985
|
+
function renderIDEContext(ideContext) {
|
|
2986
|
+
const { config, items } = ideContext;
|
|
2987
|
+
const ruleItems = items.filter((item) => item.type === "rules");
|
|
2988
|
+
const rulesTotalBytes = ruleItems.reduce((sum, item) => sum + item.fileSize, 0);
|
|
2989
|
+
const rulesTokens = estimateTokens(rulesTotalBytes);
|
|
2990
|
+
const userPromptTokens = Math.max(0, MAX_TOKENS - SYSTEM_PROMPT_TOKENS - rulesTokens - COMPACT_BUFFER_TOKENS);
|
|
2991
|
+
console.log("");
|
|
2992
|
+
console.log(chalk6.bold(`${config.icon} ${config.name} Context Window (${formatNumber(MAX_TOKENS)} tokens)`));
|
|
2993
|
+
console.log(chalk6.dim("\u2501".repeat(55)));
|
|
2994
|
+
const segments = [
|
|
2995
|
+
{ icon: "\u{1F4D0}", label: "System Prompt", tokens: SYSTEM_PROMPT_TOKENS, color: chalk6.blue },
|
|
2996
|
+
{ icon: "\u{1F4CF}", label: "IDE Rules", tokens: rulesTokens, color: chalk6.yellow },
|
|
2997
|
+
{ icon: "\u{1F4AC}", label: "User Prompt", tokens: userPromptTokens, color: chalk6.green },
|
|
2998
|
+
{ icon: "\u{1F504}", label: "Compact Buffer", tokens: COMPACT_BUFFER_TOKENS, color: chalk6.magenta }
|
|
2999
|
+
];
|
|
3000
|
+
const maxLabelLen = Math.max(...segments.map((s) => s.label.length));
|
|
3001
|
+
for (const seg of segments) {
|
|
3002
|
+
const label = seg.label.padEnd(maxLabelLen);
|
|
3003
|
+
const bar = renderBar(seg.tokens, MAX_TOKENS, BAR_WIDTH, seg.color);
|
|
3004
|
+
const pct = renderPercentage(seg.tokens, MAX_TOKENS);
|
|
3005
|
+
console.log(` ${seg.icon} ${label} ${bar} ${chalk6.white(formatNumber(seg.tokens).padStart(7))} tokens ${chalk6.dim(`(${pct})`)}`);
|
|
3006
|
+
}
|
|
3007
|
+
if (ruleItems.length > 0) {
|
|
3008
|
+
console.log("");
|
|
3009
|
+
console.log(chalk6.dim(` Rules breakdown (${config.basePath}):`));
|
|
3010
|
+
const sorted = [...ruleItems].sort((a, b) => b.fileSize - a.fileSize);
|
|
3011
|
+
for (const rule of sorted) {
|
|
3012
|
+
const tokens = estimateTokens(rule.fileSize);
|
|
3013
|
+
const name = typeof rule.name === "string" ? rule.name : rule.relativePath;
|
|
3014
|
+
const badge = rule.alwaysApply ? chalk6.cyan(" [always]") : "";
|
|
3015
|
+
console.log(` \u2022 ${chalk6.white(name)}${badge} ${chalk6.dim(formatNumber(tokens) + " tokens")}`);
|
|
3384
3016
|
}
|
|
3385
|
-
}
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
console.error(
|
|
3017
|
+
} else {
|
|
3018
|
+
console.log("");
|
|
3019
|
+
console.log(chalk6.dim(" No rules found."));
|
|
3020
|
+
}
|
|
3021
|
+
console.log("");
|
|
3022
|
+
}
|
|
3023
|
+
function createContextCommand() {
|
|
3024
|
+
const cmd = new Command7("context").description("Visualize IDE context window token budget").argument("[ide]", "Show specific IDE only (cursor, windsurf, antigravity)").action(async (ideArg) => {
|
|
3025
|
+
const name = getCliName();
|
|
3026
|
+
const validIDEs = ["cursor", "windsurf", "antigravity"];
|
|
3027
|
+
if (ideArg) {
|
|
3028
|
+
if (!validIDEs.includes(ideArg)) {
|
|
3029
|
+
console.error(chalk6.red(`\u274C Invalid IDE: ${ideArg}`));
|
|
3030
|
+
console.error(chalk6.dim(` Valid IDEs: ${validIDEs.join(", ")}`));
|
|
3031
|
+
console.error(chalk6.dim(` Usage: ${name} context [ide]`));
|
|
3398
3032
|
process.exit(1);
|
|
3399
3033
|
}
|
|
3400
|
-
initialIDE = options.target;
|
|
3401
3034
|
}
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3035
|
+
const scanner = new ContextScannerService();
|
|
3036
|
+
const targetIDEs = ideArg ? [ideArg] : validIDEs;
|
|
3037
|
+
console.log(chalk6.bold.cyan("\n\u{1F9E0} Context Window Analysis"));
|
|
3038
|
+
console.log(chalk6.dim(` Max context: ${formatNumber(MAX_TOKENS)} tokens
|
|
3039
|
+
`));
|
|
3040
|
+
let found = false;
|
|
3041
|
+
for (const ide of targetIDEs) {
|
|
3042
|
+
try {
|
|
3043
|
+
const ideContext = await scanner.scanIDE(ide);
|
|
3044
|
+
const config = IDE_CONFIGS[ide];
|
|
3045
|
+
if (config) {
|
|
3046
|
+
renderIDEContext(ideContext);
|
|
3047
|
+
found = true;
|
|
3048
|
+
}
|
|
3049
|
+
} catch {
|
|
3409
3050
|
}
|
|
3410
|
-
initialType = options.type;
|
|
3411
3051
|
}
|
|
3412
|
-
if (
|
|
3413
|
-
|
|
3414
|
-
|
|
3052
|
+
if (!found) {
|
|
3053
|
+
console.log(chalk6.yellow("\u26A0\uFE0F No IDEs detected in this project."));
|
|
3054
|
+
console.log(chalk6.dim(` Run "${name} apply" to install context for your IDE.
|
|
3055
|
+
`));
|
|
3415
3056
|
}
|
|
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
3057
|
});
|
|
3427
3058
|
return cmd;
|
|
3428
3059
|
}
|
|
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
|
-
}
|
|
3060
|
+
|
|
3061
|
+
// src/commands/ide/context.ts
|
|
3062
|
+
function createContextSubcommand() {
|
|
3063
|
+
return createContextCommand();
|
|
3465
3064
|
}
|
|
3466
3065
|
|
|
3467
3066
|
// src/commands/ide/setup.ts
|
|
@@ -4342,24 +3941,24 @@ function getConfidenceEmoji(confidence) {
|
|
|
4342
3941
|
|
|
4343
3942
|
// src/commands/ide/index.ts
|
|
4344
3943
|
function showIdeHelp() {
|
|
4345
|
-
console.log(
|
|
3944
|
+
console.log(chalk7.bold.cyan("\u{1F5A5}\uFE0F jai1 ide") + chalk7.dim(" - IDE integration v\xE0 c\u1EA5u h\xECnh"));
|
|
4346
3945
|
console.log();
|
|
4347
|
-
console.log(
|
|
4348
|
-
console.log(` ${
|
|
4349
|
-
console.log(` ${
|
|
4350
|
-
console.log(` ${
|
|
4351
|
-
console.log(` ${
|
|
3946
|
+
console.log(chalk7.bold("C\xE1c l\u1EC7nh:"));
|
|
3947
|
+
console.log(` ${chalk7.cyan("context")} Duy\u1EC7t v\xE0 kh\xE1m ph\xE1 IDE context`);
|
|
3948
|
+
console.log(` ${chalk7.cyan("setup")} C\u1EA5u h\xECnh IDE settings (VSCode optimizations)`);
|
|
3949
|
+
console.log(` ${chalk7.cyan("sync")} \u0110\u1ED3ng b\u1ED9 .jai1 content \u0111\u1EBFn IDE directories`);
|
|
3950
|
+
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
3951
|
console.log();
|
|
4353
|
-
console.log(
|
|
4354
|
-
console.log(
|
|
3952
|
+
console.log(chalk7.bold("IDEs \u0111\u01B0\u1EE3c h\u1ED7 tr\u1EE3:"));
|
|
3953
|
+
console.log(chalk7.dim(" Cursor, Windsurf, VSCode, Trae, Claude"));
|
|
4355
3954
|
console.log();
|
|
4356
|
-
console.log(
|
|
4357
|
-
console.log(
|
|
4358
|
-
console.log(
|
|
4359
|
-
console.log(
|
|
4360
|
-
console.log(
|
|
3955
|
+
console.log(chalk7.bold("V\xED d\u1EE5:"));
|
|
3956
|
+
console.log(chalk7.dim(" $ jai1 ide status"));
|
|
3957
|
+
console.log(chalk7.dim(" $ jai1 ide setup --optimize"));
|
|
3958
|
+
console.log(chalk7.dim(" $ jai1 ide sync"));
|
|
3959
|
+
console.log(chalk7.dim(" $ jai1 ide context"));
|
|
4361
3960
|
console.log();
|
|
4362
|
-
console.log(
|
|
3961
|
+
console.log(chalk7.dim('Ch\u1EA1y "jai1 ide <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt'));
|
|
4363
3962
|
}
|
|
4364
3963
|
function createIdeCommand() {
|
|
4365
3964
|
const ideCommand = new Command11("ide").description("IDE integration and configuration commands").action(() => {
|
|
@@ -4374,7 +3973,7 @@ function createIdeCommand() {
|
|
|
4374
3973
|
|
|
4375
3974
|
// src/commands/guide.ts
|
|
4376
3975
|
import { Command as Command12 } from "commander";
|
|
4377
|
-
import
|
|
3976
|
+
import chalk8 from "chalk";
|
|
4378
3977
|
function createGuideCommand() {
|
|
4379
3978
|
const cmd = new Command12("guide").description("H\u01B0\u1EDBng d\u1EABn s\u1EED d\u1EE5ng nhanh").action(() => {
|
|
4380
3979
|
const name = getCliName();
|
|
@@ -4383,66 +3982,66 @@ function createGuideCommand() {
|
|
|
4383
3982
|
return cmd;
|
|
4384
3983
|
}
|
|
4385
3984
|
function showGuide(name) {
|
|
4386
|
-
console.log(
|
|
4387
|
-
console.log(
|
|
4388
|
-
console.log(` ${
|
|
4389
|
-
console.log(` ${
|
|
4390
|
-
console.log(` ${
|
|
3985
|
+
console.log(chalk8.cyan.bold("\n\u{1F4D6} Jai1 Framework - H\u01B0\u1EDBng d\u1EABn s\u1EED d\u1EE5ng nhanh\n"));
|
|
3986
|
+
console.log(chalk8.bold("\u2501\u2501\u2501 THI\u1EBET L\u1EACP \u2501\u2501\u2501"));
|
|
3987
|
+
console.log(` ${chalk8.cyan(`${name} auth`)} X\xE1c th\u1EF1c v\xE0 c\u1EA5u h\xECnh client`);
|
|
3988
|
+
console.log(` ${chalk8.cyan(`${name} status`)} Hi\u1EC3n th\u1ECB tr\u1EA1ng th\xE1i c\u1EA5u h\xECnh`);
|
|
3989
|
+
console.log(` ${chalk8.cyan(`${name} doctor`)} Chu\u1EA9n \u0111o\xE1n project hi\u1EC7n t\u1EA1i`);
|
|
4391
3990
|
console.log();
|
|
4392
|
-
console.log(
|
|
4393
|
-
console.log(` ${
|
|
4394
|
-
console.log(` ${
|
|
4395
|
-
console.log(` ${
|
|
4396
|
-
console.log(` ${
|
|
4397
|
-
console.log(` ${
|
|
3991
|
+
console.log(chalk8.bold("\u2501\u2501\u2501 CORE PACKAGE \u2501\u2501\u2501"));
|
|
3992
|
+
console.log(` ${chalk8.cyan(`${name} apply`)} C\xE0i \u0111\u1EB7t components (interactive)`);
|
|
3993
|
+
console.log(` ${chalk8.cyan(`${name} apply core`)} C\xE0i core package (headless)`);
|
|
3994
|
+
console.log(` ${chalk8.cyan(`${name} check`)} Ki\u1EC3m tra c\u1EADp nh\u1EADt t\u1EEB server`);
|
|
3995
|
+
console.log(` ${chalk8.cyan(`${name} update`)} C\u1EADp nh\u1EADt components \u0111\xE3 c\xE0i`);
|
|
3996
|
+
console.log(` ${chalk8.cyan(`${name} upgrade`)} C\u1EADp nh\u1EADt CLI client`);
|
|
4398
3997
|
console.log();
|
|
4399
|
-
console.log(
|
|
4400
|
-
console.log(
|
|
4401
|
-
console.log(
|
|
4402
|
-
console.log(
|
|
4403
|
-
console.log(
|
|
4404
|
-
console.log(
|
|
3998
|
+
console.log(chalk8.dim(" Workflow ph\u1ED5 bi\u1EBFn:"));
|
|
3999
|
+
console.log(chalk8.dim(` 1. ${name} auth # \u0110\u0103ng nh\u1EADp l\u1EA7n \u0111\u1EA7u`));
|
|
4000
|
+
console.log(chalk8.dim(` 2. ${name} apply core # C\xE0i core package`));
|
|
4001
|
+
console.log(chalk8.dim(` 3. ${name} rules apply # C\u1EA5u h\xECnh rules cho IDE`));
|
|
4002
|
+
console.log(chalk8.dim(` 4. ${name} ide sync # \u0110\u1ED3ng b\u1ED9 sang IDE`));
|
|
4003
|
+
console.log(chalk8.dim(` 5. ${name} check # Ki\u1EC3m tra c\u1EADp nh\u1EADt \u0111\u1ECBnh k\u1EF3`));
|
|
4405
4004
|
console.log();
|
|
4406
|
-
console.log(
|
|
4407
|
-
console.log(` ${
|
|
4408
|
-
console.log(` ${
|
|
4409
|
-
console.log(` ${
|
|
4410
|
-
console.log(` ${
|
|
4005
|
+
console.log(chalk8.bold("\u2501\u2501\u2501 IDE \u2501\u2501\u2501"));
|
|
4006
|
+
console.log(` ${chalk8.cyan(`${name} ide status`)} C\xE1c IDE \u0111\u01B0\u1EE3c ph\xE1t hi\u1EC7n`);
|
|
4007
|
+
console.log(` ${chalk8.cyan(`${name} ide setup`)} C\u1EA5u h\xECnh IDE (VSCode optimizations)`);
|
|
4008
|
+
console.log(` ${chalk8.cyan(`${name} ide sync`)} \u0110\u1ED3ng b\u1ED9 .jai1 content \u0111\u1EBFn IDE`);
|
|
4009
|
+
console.log(` ${chalk8.cyan(`${name} rules apply`)} C\u1EA5u h\xECnh rules cho IDE`);
|
|
4411
4010
|
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(` ${
|
|
4011
|
+
console.log(chalk8.bold("\u2501\u2501\u2501 TASK MANAGEMENT \u2501\u2501\u2501"));
|
|
4012
|
+
console.log(` ${chalk8.cyan(`${name} t add`)} ${chalk8.dim('"title"')} ${chalk8.dim("[-p 0-3] [-P parent]")} T\u1EA1o task`);
|
|
4013
|
+
console.log(` ${chalk8.cyan(`${name} t list`)} ${chalk8.dim("[-s status] [-P parent]")} Li\u1EC7t k\xEA tasks`);
|
|
4014
|
+
console.log(` ${chalk8.cyan(`${name} t ready`)} Tasks s\u1EB5n s\xE0ng`);
|
|
4015
|
+
console.log(` ${chalk8.cyan(`${name} t pick`)} Claim & b\u1EAFt \u0111\u1EA7u`);
|
|
4016
|
+
console.log(` ${chalk8.cyan(`${name} t done`)} ${chalk8.dim("<id>")} Ho\xE0n th\xE0nh task`);
|
|
4017
|
+
console.log(` ${chalk8.cyan(`${name} t summary`)} Dashboard t\u1ED5ng quan`);
|
|
4018
|
+
console.log(` ${chalk8.cyan(`${name} t guide`)} H\u01B0\u1EDBng d\u1EABn chi ti\u1EBFt`);
|
|
4420
4019
|
console.log();
|
|
4421
|
-
console.log(
|
|
4422
|
-
console.log(` ${
|
|
4423
|
-
console.log(` ${
|
|
4424
|
-
console.log(` ${
|
|
4425
|
-
console.log(` ${
|
|
4426
|
-
console.log(` ${
|
|
4020
|
+
console.log(chalk8.bold("\u2501\u2501\u2501 WORKFLOWS (d\xF9ng trong IDE) \u2501\u2501\u2501"));
|
|
4021
|
+
console.log(` ${chalk8.cyan("/improve")} ${chalk8.dim("[feature]")} Ph\xE2n t\xEDch & \u0111\u1EC1 xu\u1EA5t c\u1EA3i thi\u1EC7n project`);
|
|
4022
|
+
console.log(` ${chalk8.cyan("/plan")} ${chalk8.dim("[task]")} L\xEAn k\u1EBF ho\u1EA1ch nhanh \u2192 tasks \u2192 implement`);
|
|
4023
|
+
console.log(` ${chalk8.cyan("/develop-feature")} ${chalk8.dim("[feature]")} Ph\xE1t tri\u1EC3n t\xEDnh n\u0103ng (FRD \u2192 TDD \u2192 Code)`);
|
|
4024
|
+
console.log(` ${chalk8.cyan("/fix-bug")} ${chalk8.dim("[bug]")} Ph\xE2n t\xEDch & s\u1EEDa bug`);
|
|
4025
|
+
console.log(` ${chalk8.cyan("/commit-it")} Commit an to\xE0n v\u1EDBi message chi ti\u1EBFt`);
|
|
4427
4026
|
console.log();
|
|
4428
|
-
console.log(
|
|
4429
|
-
console.log(
|
|
4430
|
-
console.log(
|
|
4431
|
-
console.log(
|
|
4027
|
+
console.log(chalk8.dim(" Workflow c\u1EA3i thi\u1EC7n project:"));
|
|
4028
|
+
console.log(chalk8.dim(" 1. /improve # Ph\xE2n t\xEDch & \u0111\u1EC1 xu\u1EA5t"));
|
|
4029
|
+
console.log(chalk8.dim(" 2. Ch\u1ECDn improvements c\u1EA7n l\xE0m # User x\xE1c nh\u1EADn"));
|
|
4030
|
+
console.log(chalk8.dim(" 3. \u2192 T\u1EF1 \u0111\u1ED9ng g\u1ECDi /plan # T\u1EA1o tasks & implement"));
|
|
4432
4031
|
console.log();
|
|
4433
|
-
console.log(
|
|
4434
|
-
console.log(` ${
|
|
4435
|
-
console.log(` ${
|
|
4436
|
-
console.log(` ${
|
|
4032
|
+
console.log(chalk8.bold("\u2501\u2501\u2501 AI TOOLS \u2501\u2501\u2501"));
|
|
4033
|
+
console.log(` ${chalk8.cyan(`${name} chat`)} Chat AI qua Jai1 LLM Proxy`);
|
|
4034
|
+
console.log(` ${chalk8.cyan(`${name} translate`)} D\u1ECBch v\u0103n b\u1EA3n/file b\u1EB1ng AI`);
|
|
4035
|
+
console.log(` ${chalk8.cyan(`${name} image`)} T\u1EA1o \u1EA3nh b\u1EB1ng AI`);
|
|
4437
4036
|
console.log();
|
|
4438
|
-
console.log(
|
|
4439
|
-
console.log(
|
|
4037
|
+
console.log(chalk8.dim(`\u{1F4A1} Ch\u1EA1y "${name} <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt t\u1EEBng l\u1EC7nh.`));
|
|
4038
|
+
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
4039
|
console.log();
|
|
4441
4040
|
}
|
|
4442
4041
|
|
|
4443
4042
|
// src/commands/doctor.ts
|
|
4444
4043
|
import { Command as Command13 } from "commander";
|
|
4445
|
-
import
|
|
4044
|
+
import chalk9 from "chalk";
|
|
4446
4045
|
import { promises as fs9 } from "fs";
|
|
4447
4046
|
import { join as join6 } from "path";
|
|
4448
4047
|
var CORE_FILES = [
|
|
@@ -4470,8 +4069,8 @@ async function runDoctor(options) {
|
|
|
4470
4069
|
const name = getCliName();
|
|
4471
4070
|
const results = [];
|
|
4472
4071
|
if (!options.json) {
|
|
4473
|
-
console.log(
|
|
4474
|
-
console.log(
|
|
4072
|
+
console.log(chalk9.cyan.bold("\n\u{1FA7A} Jai1 Doctor\n"));
|
|
4073
|
+
console.log(chalk9.dim(` \u0110ang ki\u1EC3m tra project t\u1EA1i: ${process.cwd()}
|
|
4475
4074
|
`));
|
|
4476
4075
|
}
|
|
4477
4076
|
results.push(await checkAuth(name));
|
|
@@ -4484,27 +4083,27 @@ async function runDoctor(options) {
|
|
|
4484
4083
|
return;
|
|
4485
4084
|
}
|
|
4486
4085
|
for (const result of results) {
|
|
4487
|
-
const icon = result.passed ?
|
|
4488
|
-
const label = result.passed ?
|
|
4489
|
-
console.log(` ${icon} ${
|
|
4086
|
+
const icon = result.passed ? chalk9.green("\u2713") : chalk9.red("\u2717");
|
|
4087
|
+
const label = result.passed ? chalk9.green(result.message) : chalk9.red(result.message);
|
|
4088
|
+
console.log(` ${icon} ${chalk9.bold(result.name)}: ${label}`);
|
|
4490
4089
|
if (result.details && result.details.length > 0) {
|
|
4491
4090
|
for (const detail of result.details) {
|
|
4492
|
-
console.log(
|
|
4091
|
+
console.log(chalk9.dim(` ${detail}`));
|
|
4493
4092
|
}
|
|
4494
4093
|
}
|
|
4495
4094
|
if (!result.passed && result.suggestion) {
|
|
4496
|
-
console.log(
|
|
4095
|
+
console.log(chalk9.yellow(` \u{1F4A1} ${result.suggestion}`));
|
|
4497
4096
|
}
|
|
4498
4097
|
console.log();
|
|
4499
4098
|
}
|
|
4500
4099
|
const passed = results.filter((r) => r.passed).length;
|
|
4501
4100
|
const total = results.length;
|
|
4502
4101
|
if (passed === total) {
|
|
4503
|
-
console.log(
|
|
4102
|
+
console.log(chalk9.green.bold(` \u2705 T\u1EA5t c\u1EA3 ${total} ki\u1EC3m tra \u0111\xE3 pass!
|
|
4504
4103
|
`));
|
|
4505
4104
|
} else {
|
|
4506
4105
|
console.log(
|
|
4507
|
-
|
|
4106
|
+
chalk9.yellow(` \u26A0\uFE0F ${passed}/${total} ki\u1EC3m tra pass. Xem g\u1EE3i \xFD \u1EDF tr\xEAn \u0111\u1EC3 s\u1EEDa.
|
|
4508
4107
|
`)
|
|
4509
4108
|
);
|
|
4510
4109
|
}
|
|
@@ -4656,8 +4255,8 @@ async function checkIde(cliName) {
|
|
|
4656
4255
|
|
|
4657
4256
|
// src/commands/chat.ts
|
|
4658
4257
|
import { Command as Command14 } from "commander";
|
|
4659
|
-
import
|
|
4660
|
-
import { render as
|
|
4258
|
+
import React12 from "react";
|
|
4259
|
+
import { render as render3 } from "ink";
|
|
4661
4260
|
|
|
4662
4261
|
// src/services/llm-proxy.service.ts
|
|
4663
4262
|
var LlmProxyService = class {
|
|
@@ -4884,16 +4483,16 @@ var LlmProxyService = class {
|
|
|
4884
4483
|
};
|
|
4885
4484
|
|
|
4886
4485
|
// src/ui/llm/LlmApp.tsx
|
|
4887
|
-
import
|
|
4888
|
-
import { Box as
|
|
4486
|
+
import React11, { useState as useState6, useEffect as useEffect4, useMemo as useMemo3, useCallback as useCallback3, useRef as useRef2 } from "react";
|
|
4487
|
+
import { Box as Box8, Text as Text9, useInput as useInput4, useApp as useApp3, useStdout } from "ink";
|
|
4889
4488
|
import Spinner4 from "ink-spinner";
|
|
4890
4489
|
|
|
4891
4490
|
// src/ui/llm/hooks/useChat.ts
|
|
4892
|
-
import { useState as
|
|
4491
|
+
import { useState as useState3, useCallback } from "react";
|
|
4893
4492
|
function useChat(service) {
|
|
4894
|
-
const [messages, setMessages] =
|
|
4895
|
-
const [isStreaming, setIsStreaming] =
|
|
4896
|
-
const [error, setError] =
|
|
4493
|
+
const [messages, setMessages] = useState3([]);
|
|
4494
|
+
const [isStreaming, setIsStreaming] = useState3(false);
|
|
4495
|
+
const [error, setError] = useState3(null);
|
|
4897
4496
|
const sendMessage = useCallback(
|
|
4898
4497
|
async (content, model) => {
|
|
4899
4498
|
if (!content.trim() || isStreaming) return;
|
|
@@ -4962,9 +4561,9 @@ function useChat(service) {
|
|
|
4962
4561
|
}
|
|
4963
4562
|
|
|
4964
4563
|
// src/ui/llm/hooks/useLlmApi.ts
|
|
4965
|
-
import { useState as
|
|
4564
|
+
import { useState as useState4, useEffect as useEffect3, useCallback as useCallback2, useRef } from "react";
|
|
4966
4565
|
function useLlmApi(service) {
|
|
4967
|
-
const [state, setState] =
|
|
4566
|
+
const [state, setState] = useState4({
|
|
4968
4567
|
models: [],
|
|
4969
4568
|
limits: null,
|
|
4970
4569
|
usage: null,
|
|
@@ -4997,7 +4596,7 @@ function useLlmApi(service) {
|
|
|
4997
4596
|
}));
|
|
4998
4597
|
}
|
|
4999
4598
|
}, [service]);
|
|
5000
|
-
|
|
4599
|
+
useEffect3(() => {
|
|
5001
4600
|
if (!hasFetched.current) {
|
|
5002
4601
|
hasFetched.current = true;
|
|
5003
4602
|
fetchData(true);
|
|
@@ -5013,26 +4612,26 @@ function useLlmApi(service) {
|
|
|
5013
4612
|
}
|
|
5014
4613
|
|
|
5015
4614
|
// src/ui/llm/components/ChatPanel.tsx
|
|
5016
|
-
import
|
|
5017
|
-
import { Box as
|
|
4615
|
+
import React9, { memo as memo3 } from "react";
|
|
4616
|
+
import { Box as Box6, Text as Text7 } from "ink";
|
|
5018
4617
|
import Spinner3 from "ink-spinner";
|
|
5019
4618
|
|
|
5020
4619
|
// src/ui/llm/components/MessageItem.tsx
|
|
5021
|
-
import
|
|
5022
|
-
import { Box as
|
|
4620
|
+
import React7, { memo } from "react";
|
|
4621
|
+
import { Box as Box4, Text as Text5 } from "ink";
|
|
5023
4622
|
var MessageItem = memo(({ message }) => {
|
|
5024
4623
|
if (message.role === "user") {
|
|
5025
|
-
return /* @__PURE__ */
|
|
4624
|
+
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
4625
|
}
|
|
5027
4626
|
if (message.role === "assistant") {
|
|
5028
|
-
return /* @__PURE__ */
|
|
4627
|
+
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
4628
|
}
|
|
5030
|
-
return /* @__PURE__ */
|
|
4629
|
+
return /* @__PURE__ */ React7.createElement(Box4, { marginBottom: 1 }, /* @__PURE__ */ React7.createElement(Text5, { dimColor: true, italic: true }, message.content));
|
|
5031
4630
|
});
|
|
5032
4631
|
|
|
5033
4632
|
// src/ui/llm/components/InputBox.tsx
|
|
5034
|
-
import
|
|
5035
|
-
import { Box as
|
|
4633
|
+
import React8, { memo as memo2 } from "react";
|
|
4634
|
+
import { Box as Box5, Text as Text6 } from "ink";
|
|
5036
4635
|
import TextInput3 from "ink-text-input";
|
|
5037
4636
|
var InputBox = memo2(({
|
|
5038
4637
|
value,
|
|
@@ -5040,7 +4639,7 @@ var InputBox = memo2(({
|
|
|
5040
4639
|
onSubmit,
|
|
5041
4640
|
disabled = false,
|
|
5042
4641
|
focused = true
|
|
5043
|
-
}) => /* @__PURE__ */
|
|
4642
|
+
}) => /* @__PURE__ */ React8.createElement(Box5, { borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React8.createElement(Text6, { color: "cyan" }, "\u276F "), !disabled ? /* @__PURE__ */ React8.createElement(
|
|
5044
4643
|
TextInput3,
|
|
5045
4644
|
{
|
|
5046
4645
|
value,
|
|
@@ -5049,19 +4648,19 @@ var InputBox = memo2(({
|
|
|
5049
4648
|
placeholder: "Type your message...",
|
|
5050
4649
|
focus: focused
|
|
5051
4650
|
}
|
|
5052
|
-
) : /* @__PURE__ */
|
|
4651
|
+
) : /* @__PURE__ */ React8.createElement(Text6, { dimColor: true }, "Waiting...")));
|
|
5053
4652
|
|
|
5054
4653
|
// src/ui/llm/components/ChatPanel.tsx
|
|
5055
4654
|
var MessageList = memo3(({ messages }) => {
|
|
5056
4655
|
const visible = messages.slice(-8);
|
|
5057
4656
|
const hidden = messages.length - visible.length;
|
|
5058
4657
|
if (visible.length === 0) {
|
|
5059
|
-
return /* @__PURE__ */
|
|
4658
|
+
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
4659
|
}
|
|
5061
|
-
return /* @__PURE__ */
|
|
4660
|
+
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
4661
|
});
|
|
5063
|
-
var SlashMenu = memo3(({ commands, index }) => /* @__PURE__ */
|
|
5064
|
-
|
|
4662
|
+
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(
|
|
4663
|
+
Text7,
|
|
5065
4664
|
{
|
|
5066
4665
|
key: cmd.name,
|
|
5067
4666
|
backgroundColor: i === index ? "cyan" : void 0,
|
|
@@ -5086,7 +4685,7 @@ var ChatPanel = ({
|
|
|
5086
4685
|
minHeight = 15
|
|
5087
4686
|
}) => {
|
|
5088
4687
|
const messagesMinHeight = Math.max(5, minHeight - 4 - (showSlashMenu ? 5 : 0));
|
|
5089
|
-
return /* @__PURE__ */
|
|
4688
|
+
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
4689
|
InputBox,
|
|
5091
4690
|
{
|
|
5092
4691
|
value: inputValue,
|
|
@@ -5099,8 +4698,8 @@ var ChatPanel = ({
|
|
|
5099
4698
|
};
|
|
5100
4699
|
|
|
5101
4700
|
// src/ui/llm/components/ModelSelector.tsx
|
|
5102
|
-
import
|
|
5103
|
-
import { Box as
|
|
4701
|
+
import React10, { useState as useState5 } from "react";
|
|
4702
|
+
import { Box as Box7, Text as Text8, useInput as useInput3 } from "ink";
|
|
5104
4703
|
var ModelSelector = ({
|
|
5105
4704
|
models,
|
|
5106
4705
|
currentModel,
|
|
@@ -5109,8 +4708,8 @@ var ModelSelector = ({
|
|
|
5109
4708
|
}) => {
|
|
5110
4709
|
const allowedModels = models.filter((m) => m.allowed);
|
|
5111
4710
|
const currentIndex = allowedModels.findIndex((m) => m.id === currentModel);
|
|
5112
|
-
const [selectedIndex, setSelectedIndex] =
|
|
5113
|
-
|
|
4711
|
+
const [selectedIndex, setSelectedIndex] = useState5(Math.max(0, currentIndex));
|
|
4712
|
+
useInput3((input5, key) => {
|
|
5114
4713
|
if (key.escape) {
|
|
5115
4714
|
onCancel();
|
|
5116
4715
|
return;
|
|
@@ -5127,8 +4726,8 @@ var ModelSelector = ({
|
|
|
5127
4726
|
}
|
|
5128
4727
|
});
|
|
5129
4728
|
if (allowedModels.length === 0) {
|
|
5130
|
-
return /* @__PURE__ */
|
|
5131
|
-
|
|
4729
|
+
return /* @__PURE__ */ React10.createElement(
|
|
4730
|
+
Box7,
|
|
5132
4731
|
{
|
|
5133
4732
|
flexDirection: "column",
|
|
5134
4733
|
borderStyle: "round",
|
|
@@ -5136,12 +4735,12 @@ var ModelSelector = ({
|
|
|
5136
4735
|
padding: 1,
|
|
5137
4736
|
width: 60
|
|
5138
4737
|
},
|
|
5139
|
-
/* @__PURE__ */
|
|
5140
|
-
/* @__PURE__ */
|
|
4738
|
+
/* @__PURE__ */ React10.createElement(Text8, { color: "red", bold: true }, "No models available"),
|
|
4739
|
+
/* @__PURE__ */ React10.createElement(Text8, { dimColor: true }, "Press Esc to close")
|
|
5141
4740
|
);
|
|
5142
4741
|
}
|
|
5143
|
-
return /* @__PURE__ */
|
|
5144
|
-
|
|
4742
|
+
return /* @__PURE__ */ React10.createElement(
|
|
4743
|
+
Box7,
|
|
5145
4744
|
{
|
|
5146
4745
|
flexDirection: "column",
|
|
5147
4746
|
borderStyle: "round",
|
|
@@ -5149,8 +4748,8 @@ var ModelSelector = ({
|
|
|
5149
4748
|
padding: 1,
|
|
5150
4749
|
width: 70
|
|
5151
4750
|
},
|
|
5152
|
-
/* @__PURE__ */
|
|
5153
|
-
/* @__PURE__ */
|
|
4751
|
+
/* @__PURE__ */ React10.createElement(Box7, { marginBottom: 1 }, /* @__PURE__ */ React10.createElement(Text8, { bold: true, color: "cyan" }, "\u2699\uFE0F Select Model")),
|
|
4752
|
+
/* @__PURE__ */ React10.createElement(Box7, { flexDirection: "column", marginBottom: 1 }, allowedModels.map((model, i) => {
|
|
5154
4753
|
const isSelected = i === selectedIndex;
|
|
5155
4754
|
const isCurrent = model.id === currentModel;
|
|
5156
4755
|
const icon = isSelected ? "\u25CF" : "\u25CB";
|
|
@@ -5158,8 +4757,8 @@ var ModelSelector = ({
|
|
|
5158
4757
|
if (model.dailyLimit !== void 0 && model.usedToday !== void 0) {
|
|
5159
4758
|
usageText = ` (${model.usedToday}/${model.dailyLimit})`;
|
|
5160
4759
|
}
|
|
5161
|
-
return /* @__PURE__ */
|
|
5162
|
-
|
|
4760
|
+
return /* @__PURE__ */ React10.createElement(Box7, { key: model.id, marginY: 0 }, /* @__PURE__ */ React10.createElement(
|
|
4761
|
+
Text8,
|
|
5163
4762
|
{
|
|
5164
4763
|
backgroundColor: isSelected ? "cyan" : void 0,
|
|
5165
4764
|
color: isSelected ? "black" : "white"
|
|
@@ -5172,7 +4771,7 @@ var ModelSelector = ({
|
|
|
5172
4771
|
usageText
|
|
5173
4772
|
));
|
|
5174
4773
|
})),
|
|
5175
|
-
/* @__PURE__ */
|
|
4774
|
+
/* @__PURE__ */ React10.createElement(Box7, { borderStyle: "single", borderColor: "gray", paddingX: 1 }, /* @__PURE__ */ React10.createElement(Text8, { dimColor: true }, "[\u2191\u2193] Navigate [Enter] Select [Esc] Cancel"))
|
|
5176
4775
|
);
|
|
5177
4776
|
};
|
|
5178
4777
|
|
|
@@ -5183,17 +4782,17 @@ var SLASH_COMMANDS = [
|
|
|
5183
4782
|
{ name: "quit", description: "Exit the chat", aliases: ["q", "exit"] }
|
|
5184
4783
|
];
|
|
5185
4784
|
var ChatApp = ({ service, initialModel }) => {
|
|
5186
|
-
const { exit } =
|
|
4785
|
+
const { exit } = useApp3();
|
|
5187
4786
|
const { stdout } = useStdout();
|
|
5188
4787
|
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] =
|
|
4788
|
+
const [currentView, setCurrentView] = useState6("loading");
|
|
4789
|
+
const [showSlashMenu, setShowSlashMenu] = useState6(false);
|
|
4790
|
+
const [slashMenuIndex, setSlashMenuIndex] = useState6(0);
|
|
4791
|
+
const [inputValue, setInputValue] = useState6("");
|
|
4792
|
+
const [selectedModel, setSelectedModel] = useState6("");
|
|
5194
4793
|
const { models, loading, error, refetch } = useLlmApi(service);
|
|
5195
4794
|
const { messages, isStreaming, sendMessage } = useChat(service);
|
|
5196
|
-
|
|
4795
|
+
useEffect4(() => {
|
|
5197
4796
|
if (error && !loading) {
|
|
5198
4797
|
setCurrentView("error");
|
|
5199
4798
|
return;
|
|
@@ -5236,7 +4835,7 @@ var ChatApp = ({ service, initialModel }) => {
|
|
|
5236
4835
|
}
|
|
5237
4836
|
return false;
|
|
5238
4837
|
}, [refetch, exit]);
|
|
5239
|
-
|
|
4838
|
+
useInput4((input5, key) => {
|
|
5240
4839
|
if (showSlashMenu) {
|
|
5241
4840
|
if (key.upArrow) {
|
|
5242
4841
|
setSlashMenuIndex((i) => Math.max(0, i - 1));
|
|
@@ -5297,16 +4896,16 @@ var ChatApp = ({ service, initialModel }) => {
|
|
|
5297
4896
|
}, []);
|
|
5298
4897
|
const statsView = useMemo3(() => {
|
|
5299
4898
|
const allowed = models.filter((m) => m.allowed);
|
|
5300
|
-
return /* @__PURE__ */
|
|
4899
|
+
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
4900
|
const limit = m.dailyLimit ?? 0;
|
|
5302
4901
|
const used = m.usedToday ?? 0;
|
|
5303
4902
|
const pct = limit > 0 ? Math.round(used / limit * 100) : 0;
|
|
5304
4903
|
const bar = "\u2588".repeat(Math.round(pct / 5)) + "\u2591".repeat(20 - Math.round(pct / 5));
|
|
5305
|
-
return /* @__PURE__ */
|
|
5306
|
-
}), /* @__PURE__ */
|
|
4904
|
+
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: pct > 80 ? "red" : pct > 50 ? "yellow" : "green" }, " ", bar, " ", /* @__PURE__ */ React11.createElement(Text9, { dimColor: true }, used, "/", limit)));
|
|
4905
|
+
}), /* @__PURE__ */ React11.createElement(Text9, { dimColor: true }, "[Esc] Back"));
|
|
5307
4906
|
}, [models, selectedModel]);
|
|
5308
4907
|
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__ */
|
|
4908
|
+
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
4909
|
ModelSelector,
|
|
5311
4910
|
{
|
|
5312
4911
|
models,
|
|
@@ -5314,7 +4913,7 @@ var ChatApp = ({ service, initialModel }) => {
|
|
|
5314
4913
|
onSelect: onSelectModel,
|
|
5315
4914
|
onCancel: () => setCurrentView("chat")
|
|
5316
4915
|
}
|
|
5317
|
-
)) : currentView === "stats" ? /* @__PURE__ */
|
|
4916
|
+
)) : currentView === "stats" ? /* @__PURE__ */ React11.createElement(Box8, { padding: 1, minHeight: contentHeight.current, justifyContent: "center", alignItems: "center" }, statsView) : /* @__PURE__ */ React11.createElement(
|
|
5318
4917
|
ChatPanel,
|
|
5319
4918
|
{
|
|
5320
4919
|
messages,
|
|
@@ -5328,7 +4927,7 @@ var ChatApp = ({ service, initialModel }) => {
|
|
|
5328
4927
|
slashMenuIndex,
|
|
5329
4928
|
minHeight: contentHeight.current
|
|
5330
4929
|
}
|
|
5331
|
-
), /* @__PURE__ */
|
|
4930
|
+
), /* @__PURE__ */ React11.createElement(Box8, { borderStyle: "single", borderColor: "gray", paddingX: 1 }, /* @__PURE__ */ React11.createElement(Text9, { dimColor: true }, footer)));
|
|
5332
4931
|
};
|
|
5333
4932
|
|
|
5334
4933
|
// src/server/web-chat-server.ts
|
|
@@ -6232,8 +5831,8 @@ async function handleTerminalChat(options) {
|
|
|
6232
5831
|
throw new ValidationError('Not initialized. Run "jai1 auth" first.');
|
|
6233
5832
|
}
|
|
6234
5833
|
const service = new LlmProxyService(config);
|
|
6235
|
-
const { waitUntilExit, clear } =
|
|
6236
|
-
|
|
5834
|
+
const { waitUntilExit, clear } = render3(
|
|
5835
|
+
React12.createElement(ChatApp, {
|
|
6237
5836
|
service,
|
|
6238
5837
|
initialModel: options.model
|
|
6239
5838
|
}),
|
|
@@ -6305,7 +5904,7 @@ function createChatCommand() {
|
|
|
6305
5904
|
|
|
6306
5905
|
// src/commands/openai-keys.ts
|
|
6307
5906
|
import { Command as Command15 } from "commander";
|
|
6308
|
-
import
|
|
5907
|
+
import chalk10 from "chalk";
|
|
6309
5908
|
import boxen3 from "boxen";
|
|
6310
5909
|
function maskKey2(key) {
|
|
6311
5910
|
if (key.length <= 8) return "****";
|
|
@@ -6319,17 +5918,17 @@ async function handleOpenAiKeysCommand(options) {
|
|
|
6319
5918
|
}
|
|
6320
5919
|
const service = new LlmProxyService(config);
|
|
6321
5920
|
console.log(
|
|
6322
|
-
boxen3(
|
|
5921
|
+
boxen3(chalk10.cyan.bold("\u{1F4E1} Jai1 LLM Proxy - OpenAI Compatible API"), {
|
|
6323
5922
|
padding: { top: 0, bottom: 0, left: 1, right: 1 },
|
|
6324
5923
|
borderStyle: "round",
|
|
6325
5924
|
borderColor: "cyan"
|
|
6326
5925
|
})
|
|
6327
5926
|
);
|
|
6328
5927
|
console.log();
|
|
6329
|
-
console.log(
|
|
6330
|
-
console.log(` ${
|
|
5928
|
+
console.log(chalk10.bold("\u{1F511} API Credentials"));
|
|
5929
|
+
console.log(` ${chalk10.dim("BASE_URL:")} ${chalk10.white(service.getBaseUrl())}`);
|
|
6331
5930
|
console.log(
|
|
6332
|
-
` ${
|
|
5931
|
+
` ${chalk10.dim("API_KEY:")} ${options.full ? chalk10.green(service.getApiKey()) : chalk10.yellow(maskKey2(service.getApiKey()))}`
|
|
6333
5932
|
);
|
|
6334
5933
|
console.log();
|
|
6335
5934
|
try {
|
|
@@ -6338,39 +5937,39 @@ async function handleOpenAiKeysCommand(options) {
|
|
|
6338
5937
|
service.getLimits()
|
|
6339
5938
|
]);
|
|
6340
5939
|
const allowedModels = models.filter((m) => m.allowed);
|
|
6341
|
-
console.log(
|
|
5940
|
+
console.log(chalk10.bold("\u{1F4E6} Available Models"));
|
|
6342
5941
|
if (allowedModels.length === 0) {
|
|
6343
|
-
console.log(
|
|
5942
|
+
console.log(chalk10.dim(" Kh\xF4ng c\xF3 models kh\u1EA3 d\u1EE5ng"));
|
|
6344
5943
|
} else {
|
|
6345
5944
|
for (const model of allowedModels) {
|
|
6346
|
-
const usageText = model.dailyLimit !== void 0 && model.usedToday !== void 0 ?
|
|
6347
|
-
console.log(` ${
|
|
5945
|
+
const usageText = model.dailyLimit !== void 0 && model.usedToday !== void 0 ? chalk10.dim(` (${model.usedToday}/${model.dailyLimit} h\xF4m nay)`) : "";
|
|
5946
|
+
console.log(` ${chalk10.green("\u2713")} ${chalk10.white(model.id)}${usageText}`);
|
|
6348
5947
|
}
|
|
6349
5948
|
}
|
|
6350
5949
|
console.log();
|
|
6351
5950
|
const defaultModel = allowedModels[0]?.id || "gpt-4o";
|
|
6352
|
-
console.log(
|
|
5951
|
+
console.log(chalk10.bold("\u{1F4DD} Sample cURL"));
|
|
6353
5952
|
console.log();
|
|
6354
5953
|
const curlSample = options.full ? service.generateFullCurlSample(defaultModel) : service.generateCurlSample(defaultModel);
|
|
6355
5954
|
const curlLines = curlSample.split("\n");
|
|
6356
5955
|
for (const line of curlLines) {
|
|
6357
|
-
console.log(
|
|
5956
|
+
console.log(chalk10.dim(` ${line}`));
|
|
6358
5957
|
}
|
|
6359
5958
|
console.log();
|
|
6360
|
-
console.log(
|
|
6361
|
-
console.log(
|
|
6362
|
-
console.log(
|
|
6363
|
-
console.log(
|
|
5959
|
+
console.log(chalk10.bold("\u{1F4A1} C\xE1ch s\u1EED d\u1EE5ng"));
|
|
5960
|
+
console.log(chalk10.dim(" - Thay th\u1EBF OpenAI API URL v\xE0 API Key"));
|
|
5961
|
+
console.log(chalk10.dim(" - T\u01B0\u01A1ng th\xEDch: OpenAI SDK, LangChain, LlamaIndex, v.v."));
|
|
5962
|
+
console.log(chalk10.dim(' - Ch\u1EA1y "jai1 chat" \u0111\u1EC3 chat tr\u1EF1c ti\u1EBFp'));
|
|
6364
5963
|
if (!options.full) {
|
|
6365
|
-
console.log(
|
|
5964
|
+
console.log(chalk10.dim(' - Ch\u1EA1y "jai1 openai-keys --full" \u0111\u1EC3 hi\u1EC3n th\u1ECB API key \u0111\u1EA7y \u0111\u1EE7'));
|
|
6366
5965
|
}
|
|
6367
5966
|
} catch (error) {
|
|
6368
5967
|
console.log();
|
|
6369
5968
|
console.log(
|
|
6370
|
-
|
|
6371
|
-
|
|
5969
|
+
chalk10.red("\u274C L\u1ED7i khi l\u1EA5y th\xF4ng tin API:"),
|
|
5970
|
+
chalk10.dim(error instanceof Error ? error.message : String(error))
|
|
6372
5971
|
);
|
|
6373
|
-
console.log(
|
|
5972
|
+
console.log(chalk10.dim('\n\u{1F4A1} Ki\u1EC3m tra API URL v\xE0 access key v\u1EDBi "jai1 status"'));
|
|
6374
5973
|
}
|
|
6375
5974
|
}
|
|
6376
5975
|
function createOpenAiKeysCommand() {
|
|
@@ -6383,7 +5982,7 @@ function createOpenAiKeysCommand() {
|
|
|
6383
5982
|
// src/commands/stats.ts
|
|
6384
5983
|
import { Command as Command16 } from "commander";
|
|
6385
5984
|
import Table2 from "cli-table3";
|
|
6386
|
-
import
|
|
5985
|
+
import chalk11 from "chalk";
|
|
6387
5986
|
async function handleStatsCommand() {
|
|
6388
5987
|
const configService = new ConfigService();
|
|
6389
5988
|
const config = await configService.load();
|
|
@@ -6393,8 +5992,8 @@ async function handleStatsCommand() {
|
|
|
6393
5992
|
);
|
|
6394
5993
|
}
|
|
6395
5994
|
const service = new LlmProxyService(config);
|
|
6396
|
-
console.log(
|
|
6397
|
-
console.log(
|
|
5995
|
+
console.log(chalk11.bold("\n\u{1F4CA} Th\u1ED1ng K\xEA S\u1EED D\u1EE5ng LLM"));
|
|
5996
|
+
console.log(chalk11.dim("\u2500".repeat(45)));
|
|
6398
5997
|
try {
|
|
6399
5998
|
const [limits, usage7Days, usageToday] = await Promise.all([
|
|
6400
5999
|
service.getLimits(),
|
|
@@ -6404,7 +6003,7 @@ async function handleStatsCommand() {
|
|
|
6404
6003
|
const today = (/* @__PURE__ */ new Date()).toLocaleDateString("en-CA", {
|
|
6405
6004
|
timeZone: "Asia/Ho_Chi_Minh"
|
|
6406
6005
|
});
|
|
6407
|
-
console.log(
|
|
6006
|
+
console.log(chalk11.cyan("\n\u{1F4C5} Kho\u1EA3ng th\u1EDDi gian: 7 ng\xE0y qua\n"));
|
|
6408
6007
|
const usageByModel = /* @__PURE__ */ new Map();
|
|
6409
6008
|
let total7DaysRequests = 0;
|
|
6410
6009
|
usage7Days.data?.forEach((record) => {
|
|
@@ -6424,16 +6023,16 @@ async function handleStatsCommand() {
|
|
|
6424
6023
|
modelData.today = record.count;
|
|
6425
6024
|
}
|
|
6426
6025
|
});
|
|
6427
|
-
console.log(
|
|
6428
|
-
console.log(` T\u1ED5ng s\u1ED1 y\xEAu c\u1EA7u (7 ng\xE0y): ${
|
|
6026
|
+
console.log(chalk11.bold("\u{1F4C8} T\u1ED5ng quan s\u1EED d\u1EE5ng"));
|
|
6027
|
+
console.log(` T\u1ED5ng s\u1ED1 y\xEAu c\u1EA7u (7 ng\xE0y): ${chalk11.green(total7DaysRequests)}
|
|
6429
6028
|
`);
|
|
6430
|
-
console.log(
|
|
6029
|
+
console.log(chalk11.bold("\u{1F4E6} Th\u1ED1ng k\xEA theo model\n"));
|
|
6431
6030
|
const table = new Table2({
|
|
6432
6031
|
head: [
|
|
6433
|
-
|
|
6434
|
-
|
|
6435
|
-
|
|
6436
|
-
|
|
6032
|
+
chalk11.bold("Model"),
|
|
6033
|
+
chalk11.bold("H\xF4m nay"),
|
|
6034
|
+
chalk11.bold("Gi\u1EDBi h\u1EA1n"),
|
|
6035
|
+
chalk11.bold("T\u1ED5ng 7 ng\xE0y")
|
|
6437
6036
|
],
|
|
6438
6037
|
style: {
|
|
6439
6038
|
head: ["cyan"],
|
|
@@ -6445,7 +6044,7 @@ async function handleStatsCommand() {
|
|
|
6445
6044
|
const rateLimits = limits.effectiveRateLimits || {};
|
|
6446
6045
|
if (allowedModels.length === 0) {
|
|
6447
6046
|
table.push([
|
|
6448
|
-
{ colSpan: 4, content:
|
|
6047
|
+
{ colSpan: 4, content: chalk11.yellow("Kh\xF4ng c\xF3 model n\xE0o kh\u1EA3 d\u1EE5ng") }
|
|
6449
6048
|
]);
|
|
6450
6049
|
} else {
|
|
6451
6050
|
allowedModels.forEach((modelId) => {
|
|
@@ -6454,25 +6053,25 @@ async function handleStatsCommand() {
|
|
|
6454
6053
|
const usagePercent = limit > 0 ? usage.today / limit : 0;
|
|
6455
6054
|
let todayDisplay = `${usage.today}/${limit}`;
|
|
6456
6055
|
if (usagePercent >= 0.9) {
|
|
6457
|
-
todayDisplay =
|
|
6056
|
+
todayDisplay = chalk11.red(todayDisplay);
|
|
6458
6057
|
} else if (usagePercent >= 0.7) {
|
|
6459
|
-
todayDisplay =
|
|
6058
|
+
todayDisplay = chalk11.yellow(todayDisplay);
|
|
6460
6059
|
} else {
|
|
6461
|
-
todayDisplay =
|
|
6060
|
+
todayDisplay = chalk11.green(todayDisplay);
|
|
6462
6061
|
}
|
|
6463
6062
|
table.push([modelId, todayDisplay, `${limit}/ng\xE0y`, String(usage.total7Days)]);
|
|
6464
6063
|
});
|
|
6465
6064
|
}
|
|
6466
6065
|
console.log(table.toString());
|
|
6467
6066
|
console.log(
|
|
6468
|
-
|
|
6067
|
+
chalk11.dim('\n\u{1F4A1} M\u1EB9o: Ch\u1EA1y "jai1 openai-keys" \u0111\u1EC3 xem danh s\xE1ch model kh\u1EA3 d\u1EE5ng')
|
|
6469
6068
|
);
|
|
6470
6069
|
} catch (error) {
|
|
6471
6070
|
console.error(
|
|
6472
|
-
|
|
6071
|
+
chalk11.red("\n\u274C Kh\xF4ng th\u1EC3 l\u1EA5y th\u1ED1ng k\xEA:"),
|
|
6473
6072
|
error instanceof Error ? error.message : String(error)
|
|
6474
6073
|
);
|
|
6475
|
-
console.log(
|
|
6074
|
+
console.log(chalk11.dim('\n\u{1F4A1} Ki\u1EC3m tra k\u1EBFt n\u1ED1i API v\u1EDBi "jai1 status"'));
|
|
6476
6075
|
}
|
|
6477
6076
|
}
|
|
6478
6077
|
function createStatsCommand() {
|
|
@@ -6839,7 +6438,7 @@ function createTranslateCommand() {
|
|
|
6839
6438
|
|
|
6840
6439
|
// src/commands/image/index.ts
|
|
6841
6440
|
import { Command as Command22 } from "commander";
|
|
6842
|
-
import
|
|
6441
|
+
import chalk12 from "chalk";
|
|
6843
6442
|
|
|
6844
6443
|
// src/commands/image/gen.ts
|
|
6845
6444
|
import { Command as Command18 } from "commander";
|
|
@@ -7114,22 +6713,22 @@ function createImageDeleteCommand() {
|
|
|
7114
6713
|
|
|
7115
6714
|
// src/commands/image/index.ts
|
|
7116
6715
|
function showImageHelp() {
|
|
7117
|
-
console.log(
|
|
6716
|
+
console.log(chalk12.bold.cyan("\u{1F3A8} jai1 image") + chalk12.dim(" - Image generation commands"));
|
|
7118
6717
|
console.log();
|
|
7119
|
-
console.log(
|
|
6718
|
+
console.log(chalk12.yellow("\u26A0\uFE0F Coming Soon - T\xEDnh n\u0103ng \u0111ang ph\xE1t tri\u1EC3n"));
|
|
7120
6719
|
console.log();
|
|
7121
|
-
console.log(
|
|
7122
|
-
console.log(` ${
|
|
7123
|
-
console.log(` ${
|
|
7124
|
-
console.log(` ${
|
|
7125
|
-
console.log(` ${
|
|
6720
|
+
console.log(chalk12.bold("C\xE1c l\u1EC7nh:"));
|
|
6721
|
+
console.log(` ${chalk12.cyan("gen")} T\u1EA1o \u1EA3nh t\u1EEB prompt`);
|
|
6722
|
+
console.log(` ${chalk12.cyan("list")} Li\u1EC7t k\xEA c\xE1c \u1EA3nh \u0111\xE3 t\u1EA1o`);
|
|
6723
|
+
console.log(` ${chalk12.cyan("info")} Xem th\xF4ng tin \u1EA3nh`);
|
|
6724
|
+
console.log(` ${chalk12.cyan("delete")} X\xF3a \u1EA3nh`);
|
|
7126
6725
|
console.log();
|
|
7127
|
-
console.log(
|
|
7128
|
-
console.log(
|
|
7129
|
-
console.log(
|
|
7130
|
-
console.log(
|
|
6726
|
+
console.log(chalk12.bold("V\xED d\u1EE5:"));
|
|
6727
|
+
console.log(chalk12.dim(' $ jai1 image gen "a cute cat"'));
|
|
6728
|
+
console.log(chalk12.dim(" $ jai1 image list"));
|
|
6729
|
+
console.log(chalk12.dim(" $ jai1 image info <image-id>"));
|
|
7131
6730
|
console.log();
|
|
7132
|
-
console.log(
|
|
6731
|
+
console.log(chalk12.dim('Ch\u1EA1y "jai1 image <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt'));
|
|
7133
6732
|
}
|
|
7134
6733
|
function createImageCommand() {
|
|
7135
6734
|
const cmd = new Command22("image").description("Image generation commands (Coming Soon)").action(() => {
|
|
@@ -7630,11 +7229,11 @@ async function confirmSubmit(summary, jsonMode) {
|
|
|
7630
7229
|
|
|
7631
7230
|
// src/commands/errors/index.ts
|
|
7632
7231
|
import { Command as Command28 } from "commander";
|
|
7633
|
-
import
|
|
7232
|
+
import chalk14 from "chalk";
|
|
7634
7233
|
|
|
7635
7234
|
// src/commands/errors/list.ts
|
|
7636
7235
|
import { Command as Command25 } from "commander";
|
|
7637
|
-
import
|
|
7236
|
+
import chalk13 from "chalk";
|
|
7638
7237
|
import Table3 from "cli-table3";
|
|
7639
7238
|
function createErrorsListSubcommand() {
|
|
7640
7239
|
return new Command25("list").description("Danh s\xE1ch error logs").option("--json", "Output JSON format").action(async (options) => {
|
|
@@ -7671,7 +7270,7 @@ function createErrorsListSubcommand() {
|
|
|
7671
7270
|
});
|
|
7672
7271
|
for (const log of logs) {
|
|
7673
7272
|
table.push([
|
|
7674
|
-
|
|
7273
|
+
chalk13.cyan(log.id),
|
|
7675
7274
|
log.timestamp || "-",
|
|
7676
7275
|
log.command || "-",
|
|
7677
7276
|
log.message || "-"
|
|
@@ -7750,19 +7349,19 @@ function createErrorsClearSubcommand() {
|
|
|
7750
7349
|
|
|
7751
7350
|
// src/commands/errors/index.ts
|
|
7752
7351
|
function showErrorsHelp() {
|
|
7753
|
-
console.log(
|
|
7352
|
+
console.log(chalk14.bold.cyan("\u{1F9FE} jai1 errors") + chalk14.dim(" - Qu\u1EA3n l\xFD error logs c\u1EE5c b\u1ED9"));
|
|
7754
7353
|
console.log();
|
|
7755
|
-
console.log(
|
|
7756
|
-
console.log(` ${
|
|
7757
|
-
console.log(` ${
|
|
7758
|
-
console.log(` ${
|
|
7354
|
+
console.log(chalk14.bold("C\xE1c l\u1EC7nh:"));
|
|
7355
|
+
console.log(` ${chalk14.cyan("list")} Danh s\xE1ch error logs`);
|
|
7356
|
+
console.log(` ${chalk14.cyan("show")} Xem chi ti\u1EBFt error log`);
|
|
7357
|
+
console.log(` ${chalk14.cyan("clear")} Xo\xE1 error logs`);
|
|
7759
7358
|
console.log();
|
|
7760
|
-
console.log(
|
|
7761
|
-
console.log(
|
|
7762
|
-
console.log(
|
|
7763
|
-
console.log(
|
|
7359
|
+
console.log(chalk14.bold("V\xED d\u1EE5:"));
|
|
7360
|
+
console.log(chalk14.dim(" $ jai1 errors list"));
|
|
7361
|
+
console.log(chalk14.dim(" $ jai1 errors show <id>"));
|
|
7362
|
+
console.log(chalk14.dim(" $ jai1 errors clear --all"));
|
|
7764
7363
|
console.log();
|
|
7765
|
-
console.log(
|
|
7364
|
+
console.log(chalk14.dim('Ch\u1EA1y "jai1 errors <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt'));
|
|
7766
7365
|
}
|
|
7767
7366
|
function createErrorsCommand() {
|
|
7768
7367
|
const errorsCommand = new Command28("errors").description("Manage local error logs").action(() => {
|
|
@@ -7776,7 +7375,7 @@ function createErrorsCommand() {
|
|
|
7776
7375
|
|
|
7777
7376
|
// src/commands/utils/index.ts
|
|
7778
7377
|
import { Command as Command42 } from "commander";
|
|
7779
|
-
import
|
|
7378
|
+
import chalk15 from "chalk";
|
|
7780
7379
|
|
|
7781
7380
|
// src/commands/utils/password.ts
|
|
7782
7381
|
import { Command as Command29 } from "commander";
|
|
@@ -8698,28 +8297,28 @@ Examples:
|
|
|
8698
8297
|
}
|
|
8699
8298
|
|
|
8700
8299
|
// src/commands/utils/interactive.ts
|
|
8701
|
-
import
|
|
8702
|
-
import { render as
|
|
8300
|
+
import React25 from "react";
|
|
8301
|
+
import { render as render4 } from "ink";
|
|
8703
8302
|
|
|
8704
8303
|
// src/ui/utils/UtilsApp.tsx
|
|
8705
|
-
import
|
|
8706
|
-
import { Box as
|
|
8304
|
+
import React24, { useState as useState18 } from "react";
|
|
8305
|
+
import { Box as Box20, Text as Text21, useInput as useInput16, useApp as useApp4 } from "ink";
|
|
8707
8306
|
|
|
8708
8307
|
// src/ui/utils/views/PasswordView.tsx
|
|
8709
|
-
import
|
|
8710
|
-
import { Box as
|
|
8308
|
+
import React13, { useState as useState7 } from "react";
|
|
8309
|
+
import { Box as Box9, Text as Text10, useInput as useInput5 } from "ink";
|
|
8711
8310
|
import TextInput4 from "ink-text-input";
|
|
8712
8311
|
var PasswordView = () => {
|
|
8713
|
-
const [length, setLength] =
|
|
8714
|
-
const [count, setCount] =
|
|
8715
|
-
const [passwords, setPasswords] =
|
|
8716
|
-
const [focusedField, setFocusedField] =
|
|
8717
|
-
const [copiedIndex, setCopiedIndex] =
|
|
8312
|
+
const [length, setLength] = useState7("16");
|
|
8313
|
+
const [count, setCount] = useState7("1");
|
|
8314
|
+
const [passwords, setPasswords] = useState7([]);
|
|
8315
|
+
const [focusedField, setFocusedField] = useState7("length");
|
|
8316
|
+
const [copiedIndex, setCopiedIndex] = useState7(null);
|
|
8718
8317
|
const service = new UtilsService();
|
|
8719
|
-
|
|
8318
|
+
React13.useEffect(() => {
|
|
8720
8319
|
handleGenerate();
|
|
8721
8320
|
}, []);
|
|
8722
|
-
|
|
8321
|
+
useInput5((input5, key) => {
|
|
8723
8322
|
if (key.tab) {
|
|
8724
8323
|
if (focusedField === "length") setFocusedField("count");
|
|
8725
8324
|
else if (focusedField === "count") setFocusedField("generate");
|
|
@@ -8757,8 +8356,8 @@ var PasswordView = () => {
|
|
|
8757
8356
|
} catch (error) {
|
|
8758
8357
|
}
|
|
8759
8358
|
};
|
|
8760
|
-
return /* @__PURE__ */
|
|
8761
|
-
|
|
8359
|
+
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(
|
|
8360
|
+
Box9,
|
|
8762
8361
|
{
|
|
8763
8362
|
flexDirection: "column",
|
|
8764
8363
|
borderStyle: "single",
|
|
@@ -8767,11 +8366,11 @@ var PasswordView = () => {
|
|
|
8767
8366
|
paddingY: 1,
|
|
8768
8367
|
marginBottom: 1
|
|
8769
8368
|
},
|
|
8770
|
-
/* @__PURE__ */
|
|
8771
|
-
/* @__PURE__ */
|
|
8772
|
-
/* @__PURE__ */
|
|
8773
|
-
/* @__PURE__ */
|
|
8774
|
-
|
|
8369
|
+
/* @__PURE__ */ React13.createElement(Text10, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
|
|
8370
|
+
/* @__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)")),
|
|
8371
|
+
/* @__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)")),
|
|
8372
|
+
/* @__PURE__ */ React13.createElement(Box9, { marginTop: 1 }, /* @__PURE__ */ React13.createElement(
|
|
8373
|
+
Text10,
|
|
8775
8374
|
{
|
|
8776
8375
|
bold: true,
|
|
8777
8376
|
backgroundColor: focusedField === "generate" ? "green" : void 0,
|
|
@@ -8780,8 +8379,8 @@ var PasswordView = () => {
|
|
|
8780
8379
|
focusedField === "generate" ? "\u25B6 " : " ",
|
|
8781
8380
|
"[ Generate Passwords ]"
|
|
8782
8381
|
))
|
|
8783
|
-
), passwords.length > 0 && /* @__PURE__ */
|
|
8784
|
-
|
|
8382
|
+
), passwords.length > 0 && /* @__PURE__ */ React13.createElement(
|
|
8383
|
+
Box9,
|
|
8785
8384
|
{
|
|
8786
8385
|
flexDirection: "column",
|
|
8787
8386
|
borderStyle: "single",
|
|
@@ -8789,27 +8388,27 @@ var PasswordView = () => {
|
|
|
8789
8388
|
paddingX: 2,
|
|
8790
8389
|
paddingY: 1
|
|
8791
8390
|
},
|
|
8792
|
-
/* @__PURE__ */
|
|
8793
|
-
passwords.map((password, index) => /* @__PURE__ */
|
|
8794
|
-
), /* @__PURE__ */
|
|
8391
|
+
/* @__PURE__ */ React13.createElement(Text10, { bold: true, color: "green", marginBottom: 1 }, "\u2713 Generated Passwords:"),
|
|
8392
|
+
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!")))
|
|
8393
|
+
), /* @__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
8394
|
};
|
|
8796
8395
|
|
|
8797
8396
|
// src/ui/utils/views/UuidView.tsx
|
|
8798
|
-
import
|
|
8799
|
-
import { Box as
|
|
8397
|
+
import React14, { useState as useState8 } from "react";
|
|
8398
|
+
import { Box as Box10, Text as Text11, useInput as useInput6 } from "ink";
|
|
8800
8399
|
import TextInput5 from "ink-text-input";
|
|
8801
8400
|
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] =
|
|
8401
|
+
const [count, setCount] = useState8("1");
|
|
8402
|
+
const [uppercase, setUppercase] = useState8(false);
|
|
8403
|
+
const [noHyphens, setNoHyphens] = useState8(false);
|
|
8404
|
+
const [uuids, setUuids] = useState8([]);
|
|
8405
|
+
const [focusedField, setFocusedField] = useState8("count");
|
|
8406
|
+
const [copiedIndex, setCopiedIndex] = useState8(null);
|
|
8808
8407
|
const service = new UtilsService();
|
|
8809
|
-
|
|
8408
|
+
React14.useEffect(() => {
|
|
8810
8409
|
handleGenerate();
|
|
8811
8410
|
}, []);
|
|
8812
|
-
|
|
8411
|
+
useInput6((input5, key) => {
|
|
8813
8412
|
if (key.tab) {
|
|
8814
8413
|
const fields = ["count", "uppercase", "hyphens", "generate"];
|
|
8815
8414
|
const currentIndex = fields.indexOf(focusedField);
|
|
@@ -8844,8 +8443,8 @@ var UuidView = () => {
|
|
|
8844
8443
|
} catch (error) {
|
|
8845
8444
|
}
|
|
8846
8445
|
};
|
|
8847
|
-
return /* @__PURE__ */
|
|
8848
|
-
|
|
8446
|
+
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(
|
|
8447
|
+
Box10,
|
|
8849
8448
|
{
|
|
8850
8449
|
flexDirection: "column",
|
|
8851
8450
|
borderStyle: "single",
|
|
@@ -8854,12 +8453,12 @@ var UuidView = () => {
|
|
|
8854
8453
|
paddingY: 1,
|
|
8855
8454
|
marginBottom: 1
|
|
8856
8455
|
},
|
|
8857
|
-
/* @__PURE__ */
|
|
8858
|
-
/* @__PURE__ */
|
|
8859
|
-
/* @__PURE__ */
|
|
8860
|
-
/* @__PURE__ */
|
|
8861
|
-
/* @__PURE__ */
|
|
8862
|
-
|
|
8456
|
+
/* @__PURE__ */ React14.createElement(Text11, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
|
|
8457
|
+
/* @__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))),
|
|
8458
|
+
/* @__PURE__ */ React14.createElement(Box10, { marginBottom: 1 }, /* @__PURE__ */ React14.createElement(Text11, { color: focusedField === "uppercase" ? "green" : void 0 }, focusedField === "uppercase" ? "\u25B6 " : " ", "[", uppercase ? "\u2713" : " ", "] Uppercase")),
|
|
8459
|
+
/* @__PURE__ */ React14.createElement(Box10, { marginBottom: 1 }, /* @__PURE__ */ React14.createElement(Text11, { color: focusedField === "hyphens" ? "green" : void 0 }, focusedField === "hyphens" ? "\u25B6 " : " ", "[", noHyphens ? "\u2713" : " ", "] No Hyphens")),
|
|
8460
|
+
/* @__PURE__ */ React14.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React14.createElement(
|
|
8461
|
+
Text11,
|
|
8863
8462
|
{
|
|
8864
8463
|
bold: true,
|
|
8865
8464
|
backgroundColor: focusedField === "generate" ? "green" : void 0,
|
|
@@ -8868,8 +8467,8 @@ var UuidView = () => {
|
|
|
8868
8467
|
focusedField === "generate" ? "\u25B6 " : " ",
|
|
8869
8468
|
"[ Generate UUIDs ]"
|
|
8870
8469
|
))
|
|
8871
|
-
), uuids.length > 0 && /* @__PURE__ */
|
|
8872
|
-
|
|
8470
|
+
), uuids.length > 0 && /* @__PURE__ */ React14.createElement(
|
|
8471
|
+
Box10,
|
|
8873
8472
|
{
|
|
8874
8473
|
flexDirection: "column",
|
|
8875
8474
|
borderStyle: "single",
|
|
@@ -8877,27 +8476,27 @@ var UuidView = () => {
|
|
|
8877
8476
|
paddingX: 2,
|
|
8878
8477
|
paddingY: 1
|
|
8879
8478
|
},
|
|
8880
|
-
/* @__PURE__ */
|
|
8881
|
-
uuids.map((uuid, index) => /* @__PURE__ */
|
|
8882
|
-
), /* @__PURE__ */
|
|
8479
|
+
/* @__PURE__ */ React14.createElement(Text11, { bold: true, color: "green", marginBottom: 1 }, "\u2713 Generated UUIDs:"),
|
|
8480
|
+
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!")))
|
|
8481
|
+
), /* @__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
8482
|
};
|
|
8884
8483
|
|
|
8885
8484
|
// src/ui/utils/views/HashView.tsx
|
|
8886
|
-
import
|
|
8887
|
-
import { Box as
|
|
8485
|
+
import React15, { useState as useState9 } from "react";
|
|
8486
|
+
import { Box as Box11, Text as Text12, useInput as useInput7 } from "ink";
|
|
8888
8487
|
import TextInput6 from "ink-text-input";
|
|
8889
8488
|
var ALGORITHMS = ["sha256", "sha512", "sha1", "md5", "bcrypt"];
|
|
8890
8489
|
var HashView = () => {
|
|
8891
|
-
const [text, setText] =
|
|
8892
|
-
const [algorithm, setAlgorithm] =
|
|
8893
|
-
const [hash, setHash] =
|
|
8894
|
-
const [focusedField, setFocusedField] =
|
|
8895
|
-
const [copied, setCopied] =
|
|
8490
|
+
const [text, setText] = useState9("hello world");
|
|
8491
|
+
const [algorithm, setAlgorithm] = useState9("sha256");
|
|
8492
|
+
const [hash, setHash] = useState9("");
|
|
8493
|
+
const [focusedField, setFocusedField] = useState9("text");
|
|
8494
|
+
const [copied, setCopied] = useState9(false);
|
|
8896
8495
|
const service = new UtilsService();
|
|
8897
|
-
|
|
8496
|
+
React15.useEffect(() => {
|
|
8898
8497
|
handleGenerate();
|
|
8899
8498
|
}, []);
|
|
8900
|
-
|
|
8499
|
+
useInput7((input5, key) => {
|
|
8901
8500
|
if (key.tab) {
|
|
8902
8501
|
const fields = ["text", "algorithm", "generate"];
|
|
8903
8502
|
const currentIndex = fields.indexOf(focusedField);
|
|
@@ -8934,8 +8533,8 @@ var HashView = () => {
|
|
|
8934
8533
|
} catch (error) {
|
|
8935
8534
|
}
|
|
8936
8535
|
};
|
|
8937
|
-
return /* @__PURE__ */
|
|
8938
|
-
|
|
8536
|
+
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(
|
|
8537
|
+
Box11,
|
|
8939
8538
|
{
|
|
8940
8539
|
flexDirection: "column",
|
|
8941
8540
|
borderStyle: "single",
|
|
@@ -8944,11 +8543,11 @@ var HashView = () => {
|
|
|
8944
8543
|
paddingY: 1,
|
|
8945
8544
|
marginBottom: 1
|
|
8946
8545
|
},
|
|
8947
|
-
/* @__PURE__ */
|
|
8948
|
-
/* @__PURE__ */
|
|
8949
|
-
/* @__PURE__ */
|
|
8950
|
-
/* @__PURE__ */
|
|
8951
|
-
|
|
8546
|
+
/* @__PURE__ */ React15.createElement(Text12, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
|
|
8547
|
+
/* @__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)"))),
|
|
8548
|
+
/* @__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)")),
|
|
8549
|
+
/* @__PURE__ */ React15.createElement(Box11, { marginTop: 1 }, /* @__PURE__ */ React15.createElement(
|
|
8550
|
+
Text12,
|
|
8952
8551
|
{
|
|
8953
8552
|
bold: true,
|
|
8954
8553
|
backgroundColor: focusedField === "generate" ? "green" : void 0,
|
|
@@ -8957,8 +8556,8 @@ var HashView = () => {
|
|
|
8957
8556
|
focusedField === "generate" ? "\u25B6 " : " ",
|
|
8958
8557
|
"[ Generate Hash ]"
|
|
8959
8558
|
))
|
|
8960
|
-
), hash && /* @__PURE__ */
|
|
8961
|
-
|
|
8559
|
+
), hash && /* @__PURE__ */ React15.createElement(
|
|
8560
|
+
Box11,
|
|
8962
8561
|
{
|
|
8963
8562
|
flexDirection: "column",
|
|
8964
8563
|
borderStyle: "single",
|
|
@@ -8966,25 +8565,25 @@ var HashView = () => {
|
|
|
8966
8565
|
paddingX: 2,
|
|
8967
8566
|
paddingY: 1
|
|
8968
8567
|
},
|
|
8969
|
-
/* @__PURE__ */
|
|
8970
|
-
/* @__PURE__ */
|
|
8971
|
-
), /* @__PURE__ */
|
|
8568
|
+
/* @__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!"))),
|
|
8569
|
+
/* @__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)))
|
|
8570
|
+
), /* @__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
8571
|
};
|
|
8973
8572
|
|
|
8974
8573
|
// src/ui/utils/views/Base64View.tsx
|
|
8975
|
-
import
|
|
8976
|
-
import { Box as
|
|
8574
|
+
import React16, { useState as useState10 } from "react";
|
|
8575
|
+
import { Box as Box12, Text as Text13, useInput as useInput8 } from "ink";
|
|
8977
8576
|
import TextInput7 from "ink-text-input";
|
|
8978
8577
|
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] =
|
|
8578
|
+
const [input5, setInput] = useState10("");
|
|
8579
|
+
const [mode, setMode] = useState10("encode");
|
|
8580
|
+
const [urlSafe, setUrlSafe] = useState10(false);
|
|
8581
|
+
const [result, setResult] = useState10("");
|
|
8582
|
+
const [error, setError] = useState10("");
|
|
8583
|
+
const [focusedField, setFocusedField] = useState10("input");
|
|
8584
|
+
const [copied, setCopied] = useState10(false);
|
|
8986
8585
|
const service = new UtilsService();
|
|
8987
|
-
|
|
8586
|
+
useInput8((input6, key) => {
|
|
8988
8587
|
if (key.tab) {
|
|
8989
8588
|
const fields = ["input", "mode", "urlsafe", "convert"];
|
|
8990
8589
|
const currentIndex = fields.indexOf(focusedField);
|
|
@@ -9032,8 +8631,8 @@ var Base64View = () => {
|
|
|
9032
8631
|
} catch (error2) {
|
|
9033
8632
|
}
|
|
9034
8633
|
};
|
|
9035
|
-
return /* @__PURE__ */
|
|
9036
|
-
|
|
8634
|
+
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(
|
|
8635
|
+
Box12,
|
|
9037
8636
|
{
|
|
9038
8637
|
flexDirection: "column",
|
|
9039
8638
|
borderStyle: "single",
|
|
@@ -9042,12 +8641,12 @@ var Base64View = () => {
|
|
|
9042
8641
|
paddingY: 1,
|
|
9043
8642
|
marginBottom: 1
|
|
9044
8643
|
},
|
|
9045
|
-
/* @__PURE__ */
|
|
9046
|
-
/* @__PURE__ */
|
|
9047
|
-
/* @__PURE__ */
|
|
9048
|
-
mode === "encode" && /* @__PURE__ */
|
|
9049
|
-
/* @__PURE__ */
|
|
9050
|
-
|
|
8644
|
+
/* @__PURE__ */ React16.createElement(Text13, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
|
|
8645
|
+
/* @__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)"))),
|
|
8646
|
+
/* @__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)")),
|
|
8647
|
+
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 _)")),
|
|
8648
|
+
/* @__PURE__ */ React16.createElement(Box12, { marginTop: 1 }, /* @__PURE__ */ React16.createElement(
|
|
8649
|
+
Text13,
|
|
9051
8650
|
{
|
|
9052
8651
|
bold: true,
|
|
9053
8652
|
backgroundColor: focusedField === "convert" ? "green" : void 0,
|
|
@@ -9058,8 +8657,8 @@ var Base64View = () => {
|
|
|
9058
8657
|
mode === "encode" ? "Encode" : "Decode",
|
|
9059
8658
|
" ]"
|
|
9060
8659
|
))
|
|
9061
|
-
), error && /* @__PURE__ */
|
|
9062
|
-
|
|
8660
|
+
), error && /* @__PURE__ */ React16.createElement(
|
|
8661
|
+
Box12,
|
|
9063
8662
|
{
|
|
9064
8663
|
flexDirection: "column",
|
|
9065
8664
|
borderStyle: "single",
|
|
@@ -9068,9 +8667,9 @@ var Base64View = () => {
|
|
|
9068
8667
|
paddingY: 1,
|
|
9069
8668
|
marginBottom: 1
|
|
9070
8669
|
},
|
|
9071
|
-
/* @__PURE__ */
|
|
9072
|
-
), result && /* @__PURE__ */
|
|
9073
|
-
|
|
8670
|
+
/* @__PURE__ */ React16.createElement(Text13, { color: "red" }, "\u2717 Error: ", error)
|
|
8671
|
+
), result && /* @__PURE__ */ React16.createElement(
|
|
8672
|
+
Box12,
|
|
9074
8673
|
{
|
|
9075
8674
|
flexDirection: "column",
|
|
9076
8675
|
borderStyle: "single",
|
|
@@ -9078,24 +8677,24 @@ var Base64View = () => {
|
|
|
9078
8677
|
paddingX: 2,
|
|
9079
8678
|
paddingY: 1
|
|
9080
8679
|
},
|
|
9081
|
-
/* @__PURE__ */
|
|
9082
|
-
/* @__PURE__ */
|
|
9083
|
-
), /* @__PURE__ */
|
|
8680
|
+
/* @__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!"))),
|
|
8681
|
+
/* @__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)))
|
|
8682
|
+
), /* @__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
8683
|
};
|
|
9085
8684
|
|
|
9086
8685
|
// src/ui/utils/views/UrlView.tsx
|
|
9087
|
-
import
|
|
9088
|
-
import { Box as
|
|
8686
|
+
import React17, { useState as useState11 } from "react";
|
|
8687
|
+
import { Box as Box13, Text as Text14, useInput as useInput9 } from "ink";
|
|
9089
8688
|
import TextInput8 from "ink-text-input";
|
|
9090
8689
|
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] =
|
|
8690
|
+
const [input5, setInput] = useState11("");
|
|
8691
|
+
const [mode, setMode] = useState11("encode");
|
|
8692
|
+
const [fullUrl, setFullUrl] = useState11(false);
|
|
8693
|
+
const [result, setResult] = useState11("");
|
|
8694
|
+
const [focusedField, setFocusedField] = useState11("input");
|
|
8695
|
+
const [copied, setCopied] = useState11(false);
|
|
9097
8696
|
const service = new UtilsService();
|
|
9098
|
-
|
|
8697
|
+
useInput9((input6, key) => {
|
|
9099
8698
|
if (key.tab) {
|
|
9100
8699
|
const fields = ["input", "mode", "full", "convert"];
|
|
9101
8700
|
const currentIndex = fields.indexOf(focusedField);
|
|
@@ -9133,8 +8732,8 @@ var UrlView = () => {
|
|
|
9133
8732
|
} catch (error) {
|
|
9134
8733
|
}
|
|
9135
8734
|
};
|
|
9136
|
-
return /* @__PURE__ */
|
|
9137
|
-
|
|
8735
|
+
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(
|
|
8736
|
+
Box13,
|
|
9138
8737
|
{
|
|
9139
8738
|
flexDirection: "column",
|
|
9140
8739
|
borderStyle: "single",
|
|
@@ -9143,12 +8742,12 @@ var UrlView = () => {
|
|
|
9143
8742
|
paddingY: 1,
|
|
9144
8743
|
marginBottom: 1
|
|
9145
8744
|
},
|
|
9146
|
-
/* @__PURE__ */
|
|
9147
|
-
/* @__PURE__ */
|
|
9148
|
-
/* @__PURE__ */
|
|
9149
|
-
/* @__PURE__ */
|
|
9150
|
-
/* @__PURE__ */
|
|
9151
|
-
|
|
8745
|
+
/* @__PURE__ */ React17.createElement(Text14, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
|
|
8746
|
+
/* @__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)"))),
|
|
8747
|
+
/* @__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)")),
|
|
8748
|
+
/* @__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)")),
|
|
8749
|
+
/* @__PURE__ */ React17.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React17.createElement(
|
|
8750
|
+
Text14,
|
|
9152
8751
|
{
|
|
9153
8752
|
bold: true,
|
|
9154
8753
|
backgroundColor: focusedField === "convert" ? "green" : void 0,
|
|
@@ -9159,8 +8758,8 @@ var UrlView = () => {
|
|
|
9159
8758
|
mode === "encode" ? "Encode" : "Decode",
|
|
9160
8759
|
" ]"
|
|
9161
8760
|
))
|
|
9162
|
-
), result && /* @__PURE__ */
|
|
9163
|
-
|
|
8761
|
+
), result && /* @__PURE__ */ React17.createElement(
|
|
8762
|
+
Box13,
|
|
9164
8763
|
{
|
|
9165
8764
|
flexDirection: "column",
|
|
9166
8765
|
borderStyle: "single",
|
|
@@ -9168,26 +8767,26 @@ var UrlView = () => {
|
|
|
9168
8767
|
paddingX: 2,
|
|
9169
8768
|
paddingY: 1
|
|
9170
8769
|
},
|
|
9171
|
-
/* @__PURE__ */
|
|
9172
|
-
/* @__PURE__ */
|
|
9173
|
-
), /* @__PURE__ */
|
|
8770
|
+
/* @__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!"))),
|
|
8771
|
+
/* @__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)))
|
|
8772
|
+
), /* @__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
8773
|
};
|
|
9175
8774
|
|
|
9176
8775
|
// src/ui/utils/views/UnixTimeView.tsx
|
|
9177
|
-
import
|
|
9178
|
-
import { Box as
|
|
8776
|
+
import React18, { useState as useState12 } from "react";
|
|
8777
|
+
import { Box as Box14, Text as Text15, useInput as useInput10 } from "ink";
|
|
9179
8778
|
import TextInput9 from "ink-text-input";
|
|
9180
8779
|
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] =
|
|
8780
|
+
const [input5, setInput] = useState12("");
|
|
8781
|
+
const [mode, setMode] = useState12("now");
|
|
8782
|
+
const [format, setFormat] = useState12("iso");
|
|
8783
|
+
const [useMs, setUseMs] = useState12(false);
|
|
8784
|
+
const [result, setResult] = useState12("");
|
|
8785
|
+
const [error, setError] = useState12("");
|
|
8786
|
+
const [focusedField, setFocusedField] = useState12("mode");
|
|
8787
|
+
const [copied, setCopied] = useState12(false);
|
|
9189
8788
|
const service = new UtilsService();
|
|
9190
|
-
|
|
8789
|
+
useInput10((input6, key) => {
|
|
9191
8790
|
if (key.tab) {
|
|
9192
8791
|
const fields = mode === "now" ? ["mode", "ms", "convert"] : mode === "to-human" ? ["mode", "input", "format", "convert"] : ["mode", "input", "convert"];
|
|
9193
8792
|
const currentIndex = fields.indexOf(focusedField);
|
|
@@ -9248,8 +8847,8 @@ var UnixTimeView = () => {
|
|
|
9248
8847
|
} catch (error2) {
|
|
9249
8848
|
}
|
|
9250
8849
|
};
|
|
9251
|
-
return /* @__PURE__ */
|
|
9252
|
-
|
|
8850
|
+
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(
|
|
8851
|
+
Box14,
|
|
9253
8852
|
{
|
|
9254
8853
|
flexDirection: "column",
|
|
9255
8854
|
borderStyle: "single",
|
|
@@ -9258,20 +8857,20 @@ var UnixTimeView = () => {
|
|
|
9258
8857
|
paddingY: 1,
|
|
9259
8858
|
marginBottom: 1
|
|
9260
8859
|
},
|
|
9261
|
-
/* @__PURE__ */
|
|
9262
|
-
/* @__PURE__ */
|
|
9263
|
-
mode !== "now" && /* @__PURE__ */
|
|
8860
|
+
/* @__PURE__ */ React18.createElement(Text15, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
|
|
8861
|
+
/* @__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)")),
|
|
8862
|
+
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
8863
|
TextInput9,
|
|
9265
8864
|
{
|
|
9266
8865
|
value: input5,
|
|
9267
8866
|
onChange: setInput,
|
|
9268
8867
|
placeholder: mode === "to-human" ? "1702550400" : "2024-01-15 10:30:00"
|
|
9269
8868
|
}
|
|
9270
|
-
) : /* @__PURE__ */
|
|
9271
|
-
mode === "to-human" && /* @__PURE__ */
|
|
9272
|
-
mode === "now" && /* @__PURE__ */
|
|
9273
|
-
/* @__PURE__ */
|
|
9274
|
-
|
|
8869
|
+
) : /* @__PURE__ */ React18.createElement(Text15, { dimColor: !input5 }, input5 || "(empty)"))),
|
|
8870
|
+
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)")),
|
|
8871
|
+
mode === "now" && /* @__PURE__ */ React18.createElement(Box14, { marginBottom: 1 }, /* @__PURE__ */ React18.createElement(Text15, { color: focusedField === "ms" ? "green" : void 0 }, focusedField === "ms" ? "\u25B6 " : " ", "[", useMs ? "\u2713" : " ", "] Milliseconds")),
|
|
8872
|
+
/* @__PURE__ */ React18.createElement(Box14, { marginTop: 1 }, /* @__PURE__ */ React18.createElement(
|
|
8873
|
+
Text15,
|
|
9275
8874
|
{
|
|
9276
8875
|
bold: true,
|
|
9277
8876
|
backgroundColor: focusedField === "convert" ? "green" : void 0,
|
|
@@ -9282,8 +8881,8 @@ var UnixTimeView = () => {
|
|
|
9282
8881
|
mode === "now" ? "Get Current" : "Convert",
|
|
9283
8882
|
" ]"
|
|
9284
8883
|
))
|
|
9285
|
-
), error && /* @__PURE__ */
|
|
9286
|
-
|
|
8884
|
+
), error && /* @__PURE__ */ React18.createElement(
|
|
8885
|
+
Box14,
|
|
9287
8886
|
{
|
|
9288
8887
|
flexDirection: "column",
|
|
9289
8888
|
borderStyle: "single",
|
|
@@ -9292,9 +8891,9 @@ var UnixTimeView = () => {
|
|
|
9292
8891
|
paddingY: 1,
|
|
9293
8892
|
marginBottom: 1
|
|
9294
8893
|
},
|
|
9295
|
-
/* @__PURE__ */
|
|
9296
|
-
), result && /* @__PURE__ */
|
|
9297
|
-
|
|
8894
|
+
/* @__PURE__ */ React18.createElement(Text15, { color: "red" }, "\u2717 Error: ", error)
|
|
8895
|
+
), result && /* @__PURE__ */ React18.createElement(
|
|
8896
|
+
Box14,
|
|
9298
8897
|
{
|
|
9299
8898
|
flexDirection: "column",
|
|
9300
8899
|
borderStyle: "single",
|
|
@@ -9302,26 +8901,26 @@ var UnixTimeView = () => {
|
|
|
9302
8901
|
paddingX: 2,
|
|
9303
8902
|
paddingY: 1
|
|
9304
8903
|
},
|
|
9305
|
-
/* @__PURE__ */
|
|
9306
|
-
/* @__PURE__ */
|
|
9307
|
-
), /* @__PURE__ */
|
|
8904
|
+
/* @__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!"))),
|
|
8905
|
+
/* @__PURE__ */ React18.createElement(Box14, { flexDirection: "column" }, /* @__PURE__ */ React18.createElement(Box14, { marginTop: 1 }, /* @__PURE__ */ React18.createElement(Text15, { wrap: "wrap" }, result)))
|
|
8906
|
+
), /* @__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
8907
|
};
|
|
9309
8908
|
|
|
9310
8909
|
// src/ui/utils/views/JwtView.tsx
|
|
9311
|
-
import
|
|
9312
|
-
import { Box as
|
|
8910
|
+
import React19, { useState as useState13 } from "react";
|
|
8911
|
+
import { Box as Box15, Text as Text16, useInput as useInput11 } from "ink";
|
|
9313
8912
|
import TextInput10 from "ink-text-input";
|
|
9314
8913
|
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] =
|
|
8914
|
+
const [mode, setMode] = useState13("decode");
|
|
8915
|
+
const [token, setToken] = useState13("");
|
|
8916
|
+
const [payload, setPayload] = useState13("");
|
|
8917
|
+
const [secret, setSecret] = useState13("");
|
|
8918
|
+
const [result, setResult] = useState13({});
|
|
8919
|
+
const [error, setError] = useState13("");
|
|
8920
|
+
const [focusedField, setFocusedField] = useState13("mode");
|
|
8921
|
+
const [copied, setCopied] = useState13(false);
|
|
9323
8922
|
const service = new UtilsService();
|
|
9324
|
-
|
|
8923
|
+
useInput11((input5, key) => {
|
|
9325
8924
|
if (key.tab) {
|
|
9326
8925
|
const fields = mode === "decode" ? ["mode", "token", "process"] : ["mode", "payload", "secret", "process"];
|
|
9327
8926
|
const currentIndex = fields.indexOf(focusedField);
|
|
@@ -9376,8 +8975,8 @@ var JwtView = () => {
|
|
|
9376
8975
|
} catch (error2) {
|
|
9377
8976
|
}
|
|
9378
8977
|
};
|
|
9379
|
-
return /* @__PURE__ */
|
|
9380
|
-
|
|
8978
|
+
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(
|
|
8979
|
+
Box15,
|
|
9381
8980
|
{
|
|
9382
8981
|
flexDirection: "column",
|
|
9383
8982
|
borderStyle: "single",
|
|
@@ -9386,23 +8985,23 @@ var JwtView = () => {
|
|
|
9386
8985
|
paddingY: 1,
|
|
9387
8986
|
marginBottom: 1
|
|
9388
8987
|
},
|
|
9389
|
-
/* @__PURE__ */
|
|
9390
|
-
/* @__PURE__ */
|
|
9391
|
-
mode === "decode" ? /* @__PURE__ */
|
|
8988
|
+
/* @__PURE__ */ React19.createElement(Text16, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
|
|
8989
|
+
/* @__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)")),
|
|
8990
|
+
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
8991
|
TextInput10,
|
|
9393
8992
|
{
|
|
9394
8993
|
value: token,
|
|
9395
8994
|
onChange: setToken,
|
|
9396
8995
|
placeholder: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
|
9397
8996
|
}
|
|
9398
|
-
) : /* @__PURE__ */
|
|
8997
|
+
) : /* @__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
8998
|
TextInput10,
|
|
9400
8999
|
{
|
|
9401
9000
|
value: payload,
|
|
9402
9001
|
onChange: setPayload,
|
|
9403
9002
|
placeholder: '{"sub":"123","name":"John"}'
|
|
9404
9003
|
}
|
|
9405
|
-
) : /* @__PURE__ */
|
|
9004
|
+
) : /* @__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
9005
|
TextInput10,
|
|
9407
9006
|
{
|
|
9408
9007
|
value: secret,
|
|
@@ -9410,9 +9009,9 @@ var JwtView = () => {
|
|
|
9410
9009
|
placeholder: "your-secret-key",
|
|
9411
9010
|
mask: "*"
|
|
9412
9011
|
}
|
|
9413
|
-
) : /* @__PURE__ */
|
|
9414
|
-
/* @__PURE__ */
|
|
9415
|
-
|
|
9012
|
+
) : /* @__PURE__ */ React19.createElement(Text16, { dimColor: !secret }, secret ? "*".repeat(secret.length) : "(empty)")))),
|
|
9013
|
+
/* @__PURE__ */ React19.createElement(Box15, { marginTop: 1 }, /* @__PURE__ */ React19.createElement(
|
|
9014
|
+
Text16,
|
|
9416
9015
|
{
|
|
9417
9016
|
bold: true,
|
|
9418
9017
|
backgroundColor: focusedField === "process" ? "green" : void 0,
|
|
@@ -9423,8 +9022,8 @@ var JwtView = () => {
|
|
|
9423
9022
|
mode === "decode" ? "Decode" : "Encode",
|
|
9424
9023
|
" ]"
|
|
9425
9024
|
))
|
|
9426
|
-
), error && /* @__PURE__ */
|
|
9427
|
-
|
|
9025
|
+
), error && /* @__PURE__ */ React19.createElement(
|
|
9026
|
+
Box15,
|
|
9428
9027
|
{
|
|
9429
9028
|
flexDirection: "column",
|
|
9430
9029
|
borderStyle: "single",
|
|
@@ -9433,9 +9032,9 @@ var JwtView = () => {
|
|
|
9433
9032
|
paddingY: 1,
|
|
9434
9033
|
marginBottom: 1
|
|
9435
9034
|
},
|
|
9436
|
-
/* @__PURE__ */
|
|
9437
|
-
), (result.header || result.token) && /* @__PURE__ */
|
|
9438
|
-
|
|
9035
|
+
/* @__PURE__ */ React19.createElement(Text16, { color: "red" }, "\u2717 Error: ", error)
|
|
9036
|
+
), (result.header || result.token) && /* @__PURE__ */ React19.createElement(
|
|
9037
|
+
Box15,
|
|
9439
9038
|
{
|
|
9440
9039
|
flexDirection: "column",
|
|
9441
9040
|
borderStyle: "single",
|
|
@@ -9443,23 +9042,23 @@ var JwtView = () => {
|
|
|
9443
9042
|
paddingX: 2,
|
|
9444
9043
|
paddingY: 1
|
|
9445
9044
|
},
|
|
9446
|
-
/* @__PURE__ */
|
|
9447
|
-
/* @__PURE__ */
|
|
9448
|
-
), /* @__PURE__ */
|
|
9045
|
+
/* @__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!"))),
|
|
9046
|
+
/* @__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)))
|
|
9047
|
+
), /* @__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
9048
|
};
|
|
9450
9049
|
|
|
9451
9050
|
// src/ui/utils/views/CronView.tsx
|
|
9452
|
-
import
|
|
9453
|
-
import { Box as
|
|
9051
|
+
import React20, { useState as useState14 } from "react";
|
|
9052
|
+
import { Box as Box16, Text as Text17, useInput as useInput12 } from "ink";
|
|
9454
9053
|
import TextInput11 from "ink-text-input";
|
|
9455
9054
|
var CronView = () => {
|
|
9456
|
-
const [expression, setExpression] =
|
|
9457
|
-
const [result, setResult] =
|
|
9458
|
-
const [error, setError] =
|
|
9459
|
-
const [focusedField, setFocusedField] =
|
|
9460
|
-
const [copied, setCopied] =
|
|
9055
|
+
const [expression, setExpression] = useState14("");
|
|
9056
|
+
const [result, setResult] = useState14(null);
|
|
9057
|
+
const [error, setError] = useState14("");
|
|
9058
|
+
const [focusedField, setFocusedField] = useState14("expression");
|
|
9059
|
+
const [copied, setCopied] = useState14(false);
|
|
9461
9060
|
const service = new UtilsService();
|
|
9462
|
-
|
|
9061
|
+
useInput12((input5, key) => {
|
|
9463
9062
|
if (key.tab) {
|
|
9464
9063
|
setFocusedField(focusedField === "expression" ? "parse" : "expression");
|
|
9465
9064
|
} else if (key.return) {
|
|
@@ -9497,8 +9096,8 @@ ${result.nextRuns.join("\n")}`;
|
|
|
9497
9096
|
} catch (error2) {
|
|
9498
9097
|
}
|
|
9499
9098
|
};
|
|
9500
|
-
return /* @__PURE__ */
|
|
9501
|
-
|
|
9099
|
+
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(
|
|
9100
|
+
Box16,
|
|
9502
9101
|
{
|
|
9503
9102
|
flexDirection: "column",
|
|
9504
9103
|
borderStyle: "single",
|
|
@@ -9507,18 +9106,18 @@ ${result.nextRuns.join("\n")}`;
|
|
|
9507
9106
|
paddingY: 1,
|
|
9508
9107
|
marginBottom: 1
|
|
9509
9108
|
},
|
|
9510
|
-
/* @__PURE__ */
|
|
9511
|
-
/* @__PURE__ */
|
|
9109
|
+
/* @__PURE__ */ React20.createElement(Text17, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
|
|
9110
|
+
/* @__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
9111
|
TextInput11,
|
|
9513
9112
|
{
|
|
9514
9113
|
value: expression,
|
|
9515
9114
|
onChange: setExpression,
|
|
9516
9115
|
placeholder: "0 5 * * * (5-field or 6-field)"
|
|
9517
9116
|
}
|
|
9518
|
-
) : /* @__PURE__ */
|
|
9519
|
-
/* @__PURE__ */
|
|
9520
|
-
/* @__PURE__ */
|
|
9521
|
-
|
|
9117
|
+
) : /* @__PURE__ */ React20.createElement(Text17, { dimColor: !expression }, expression || "(empty)"))),
|
|
9118
|
+
/* @__PURE__ */ React20.createElement(Box16, { marginTop: 1, marginBottom: 1 }, /* @__PURE__ */ React20.createElement(Text17, { dimColor: true }, 'Examples: "0 5 * * *" (daily at 5am), "*/15 * * * *" (every 15 min)')),
|
|
9119
|
+
/* @__PURE__ */ React20.createElement(Box16, { marginTop: 1 }, /* @__PURE__ */ React20.createElement(
|
|
9120
|
+
Text17,
|
|
9522
9121
|
{
|
|
9523
9122
|
bold: true,
|
|
9524
9123
|
backgroundColor: focusedField === "parse" ? "green" : void 0,
|
|
@@ -9527,8 +9126,8 @@ ${result.nextRuns.join("\n")}`;
|
|
|
9527
9126
|
focusedField === "parse" ? "\u25B6 " : " ",
|
|
9528
9127
|
"[ Parse Expression ]"
|
|
9529
9128
|
))
|
|
9530
|
-
), error && /* @__PURE__ */
|
|
9531
|
-
|
|
9129
|
+
), error && /* @__PURE__ */ React20.createElement(
|
|
9130
|
+
Box16,
|
|
9532
9131
|
{
|
|
9533
9132
|
flexDirection: "column",
|
|
9534
9133
|
borderStyle: "single",
|
|
@@ -9537,9 +9136,9 @@ ${result.nextRuns.join("\n")}`;
|
|
|
9537
9136
|
paddingY: 1,
|
|
9538
9137
|
marginBottom: 1
|
|
9539
9138
|
},
|
|
9540
|
-
/* @__PURE__ */
|
|
9541
|
-
), result && /* @__PURE__ */
|
|
9542
|
-
|
|
9139
|
+
/* @__PURE__ */ React20.createElement(Text17, { color: "red" }, "\u2717 Error: ", error)
|
|
9140
|
+
), result && /* @__PURE__ */ React20.createElement(
|
|
9141
|
+
Box16,
|
|
9543
9142
|
{
|
|
9544
9143
|
flexDirection: "column",
|
|
9545
9144
|
borderStyle: "single",
|
|
@@ -9547,25 +9146,25 @@ ${result.nextRuns.join("\n")}`;
|
|
|
9547
9146
|
paddingX: 2,
|
|
9548
9147
|
paddingY: 1
|
|
9549
9148
|
},
|
|
9550
|
-
/* @__PURE__ */
|
|
9551
|
-
/* @__PURE__ */
|
|
9552
|
-
), /* @__PURE__ */
|
|
9149
|
+
/* @__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!"))),
|
|
9150
|
+
/* @__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)))
|
|
9151
|
+
), /* @__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
9152
|
};
|
|
9554
9153
|
|
|
9555
9154
|
// src/ui/utils/views/TimezoneView.tsx
|
|
9556
|
-
import
|
|
9557
|
-
import { Box as
|
|
9155
|
+
import React21, { useState as useState15 } from "react";
|
|
9156
|
+
import { Box as Box17, Text as Text18, useInput as useInput13 } from "ink";
|
|
9558
9157
|
import TextInput12 from "ink-text-input";
|
|
9559
9158
|
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] =
|
|
9159
|
+
const [time, setTime] = useState15("");
|
|
9160
|
+
const [fromTz, setFromTz] = useState15("UTC");
|
|
9161
|
+
const [toTz, setToTz] = useState15("America/New_York");
|
|
9162
|
+
const [result, setResult] = useState15("");
|
|
9163
|
+
const [error, setError] = useState15("");
|
|
9164
|
+
const [focusedField, setFocusedField] = useState15("time");
|
|
9165
|
+
const [copied, setCopied] = useState15(false);
|
|
9567
9166
|
const service = new UtilsService();
|
|
9568
|
-
|
|
9167
|
+
useInput13((input5, key) => {
|
|
9569
9168
|
if (key.tab) {
|
|
9570
9169
|
const fields = ["time", "from", "to", "convert"];
|
|
9571
9170
|
const currentIndex = fields.indexOf(focusedField);
|
|
@@ -9604,8 +9203,8 @@ var TimezoneView = () => {
|
|
|
9604
9203
|
} catch (error2) {
|
|
9605
9204
|
}
|
|
9606
9205
|
};
|
|
9607
|
-
return /* @__PURE__ */
|
|
9608
|
-
|
|
9206
|
+
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(
|
|
9207
|
+
Box17,
|
|
9609
9208
|
{
|
|
9610
9209
|
flexDirection: "column",
|
|
9611
9210
|
borderStyle: "single",
|
|
@@ -9614,34 +9213,34 @@ var TimezoneView = () => {
|
|
|
9614
9213
|
paddingY: 1,
|
|
9615
9214
|
marginBottom: 1
|
|
9616
9215
|
},
|
|
9617
|
-
/* @__PURE__ */
|
|
9618
|
-
/* @__PURE__ */
|
|
9216
|
+
/* @__PURE__ */ React21.createElement(Text18, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
|
|
9217
|
+
/* @__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
9218
|
TextInput12,
|
|
9620
9219
|
{
|
|
9621
9220
|
value: time,
|
|
9622
9221
|
onChange: setTime,
|
|
9623
9222
|
placeholder: "2024-01-15 10:00:00"
|
|
9624
9223
|
}
|
|
9625
|
-
) : /* @__PURE__ */
|
|
9626
|
-
/* @__PURE__ */
|
|
9224
|
+
) : /* @__PURE__ */ React21.createElement(Text18, { dimColor: !time }, time || "(empty)"))),
|
|
9225
|
+
/* @__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
9226
|
TextInput12,
|
|
9628
9227
|
{
|
|
9629
9228
|
value: fromTz,
|
|
9630
9229
|
onChange: setFromTz,
|
|
9631
9230
|
placeholder: "UTC or America/New_York"
|
|
9632
9231
|
}
|
|
9633
|
-
) : /* @__PURE__ */
|
|
9634
|
-
/* @__PURE__ */
|
|
9232
|
+
) : /* @__PURE__ */ React21.createElement(Text18, { dimColor: !fromTz }, fromTz || "(empty)"))),
|
|
9233
|
+
/* @__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
9234
|
TextInput12,
|
|
9636
9235
|
{
|
|
9637
9236
|
value: toTz,
|
|
9638
9237
|
onChange: setToTz,
|
|
9639
9238
|
placeholder: "Asia/Tokyo or Europe/London"
|
|
9640
9239
|
}
|
|
9641
|
-
) : /* @__PURE__ */
|
|
9642
|
-
/* @__PURE__ */
|
|
9643
|
-
/* @__PURE__ */
|
|
9644
|
-
|
|
9240
|
+
) : /* @__PURE__ */ React21.createElement(Text18, { dimColor: !toTz }, toTz || "(empty)"))),
|
|
9241
|
+
/* @__PURE__ */ React21.createElement(Box17, { marginBottom: 1 }, /* @__PURE__ */ React21.createElement(Text18, { dimColor: true }, "Common: UTC, America/New_York, Europe/London, Asia/Tokyo")),
|
|
9242
|
+
/* @__PURE__ */ React21.createElement(Box17, { marginTop: 1 }, /* @__PURE__ */ React21.createElement(
|
|
9243
|
+
Text18,
|
|
9645
9244
|
{
|
|
9646
9245
|
bold: true,
|
|
9647
9246
|
backgroundColor: focusedField === "convert" ? "green" : void 0,
|
|
@@ -9650,8 +9249,8 @@ var TimezoneView = () => {
|
|
|
9650
9249
|
focusedField === "convert" ? "\u25B6 " : " ",
|
|
9651
9250
|
"[ Convert ]"
|
|
9652
9251
|
))
|
|
9653
|
-
), error && /* @__PURE__ */
|
|
9654
|
-
|
|
9252
|
+
), error && /* @__PURE__ */ React21.createElement(
|
|
9253
|
+
Box17,
|
|
9655
9254
|
{
|
|
9656
9255
|
flexDirection: "column",
|
|
9657
9256
|
borderStyle: "single",
|
|
@@ -9660,9 +9259,9 @@ var TimezoneView = () => {
|
|
|
9660
9259
|
paddingY: 1,
|
|
9661
9260
|
marginBottom: 1
|
|
9662
9261
|
},
|
|
9663
|
-
/* @__PURE__ */
|
|
9664
|
-
), result && /* @__PURE__ */
|
|
9665
|
-
|
|
9262
|
+
/* @__PURE__ */ React21.createElement(Text18, { color: "red" }, "\u2717 Error: ", error)
|
|
9263
|
+
), result && /* @__PURE__ */ React21.createElement(
|
|
9264
|
+
Box17,
|
|
9666
9265
|
{
|
|
9667
9266
|
flexDirection: "column",
|
|
9668
9267
|
borderStyle: "single",
|
|
@@ -9670,28 +9269,28 @@ var TimezoneView = () => {
|
|
|
9670
9269
|
paddingX: 2,
|
|
9671
9270
|
paddingY: 1
|
|
9672
9271
|
},
|
|
9673
|
-
/* @__PURE__ */
|
|
9674
|
-
/* @__PURE__ */
|
|
9675
|
-
), /* @__PURE__ */
|
|
9272
|
+
/* @__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!"))),
|
|
9273
|
+
/* @__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)))
|
|
9274
|
+
), /* @__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
9275
|
};
|
|
9677
9276
|
|
|
9678
9277
|
// src/ui/utils/views/HttpView.tsx
|
|
9679
|
-
import
|
|
9680
|
-
import { Box as
|
|
9278
|
+
import React22, { useState as useState16 } from "react";
|
|
9279
|
+
import { Box as Box18, Text as Text19, useInput as useInput14 } from "ink";
|
|
9681
9280
|
import TextInput13 from "ink-text-input";
|
|
9682
9281
|
var METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE"];
|
|
9683
9282
|
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] =
|
|
9283
|
+
const [url, setUrl] = useState16("");
|
|
9284
|
+
const [method, setMethod] = useState16("GET");
|
|
9285
|
+
const [headers, setHeaders] = useState16("");
|
|
9286
|
+
const [body, setBody] = useState16("");
|
|
9287
|
+
const [response, setResponse] = useState16(null);
|
|
9288
|
+
const [error, setError] = useState16("");
|
|
9289
|
+
const [loading, setLoading] = useState16(false);
|
|
9290
|
+
const [focusedField, setFocusedField] = useState16("url");
|
|
9291
|
+
const [copied, setCopied] = useState16(false);
|
|
9693
9292
|
const service = new UtilsService();
|
|
9694
|
-
|
|
9293
|
+
useInput14((input5, key) => {
|
|
9695
9294
|
if (loading) return;
|
|
9696
9295
|
if (key.tab) {
|
|
9697
9296
|
const fields = ["url", "method", "headers", "body", "send"];
|
|
@@ -9752,8 +9351,8 @@ var HttpView = () => {
|
|
|
9752
9351
|
} catch (error2) {
|
|
9753
9352
|
}
|
|
9754
9353
|
};
|
|
9755
|
-
return /* @__PURE__ */
|
|
9756
|
-
|
|
9354
|
+
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(
|
|
9355
|
+
Box18,
|
|
9757
9356
|
{
|
|
9758
9357
|
flexDirection: "column",
|
|
9759
9358
|
borderStyle: "single",
|
|
@@ -9762,34 +9361,34 @@ var HttpView = () => {
|
|
|
9762
9361
|
paddingY: 1,
|
|
9763
9362
|
marginBottom: 1
|
|
9764
9363
|
},
|
|
9765
|
-
/* @__PURE__ */
|
|
9766
|
-
/* @__PURE__ */
|
|
9364
|
+
/* @__PURE__ */ React22.createElement(Text19, { bold: true, color: "yellow", marginBottom: 1 }, "Request:"),
|
|
9365
|
+
/* @__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
9366
|
TextInput13,
|
|
9768
9367
|
{
|
|
9769
9368
|
value: url,
|
|
9770
9369
|
onChange: setUrl,
|
|
9771
9370
|
placeholder: "https://api.example.com/endpoint"
|
|
9772
9371
|
}
|
|
9773
|
-
) : /* @__PURE__ */
|
|
9774
|
-
/* @__PURE__ */
|
|
9775
|
-
/* @__PURE__ */
|
|
9372
|
+
) : /* @__PURE__ */ React22.createElement(Text19, { dimColor: !url }, url || "(empty)"))),
|
|
9373
|
+
/* @__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)")),
|
|
9374
|
+
/* @__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
9375
|
TextInput13,
|
|
9777
9376
|
{
|
|
9778
9377
|
value: headers,
|
|
9779
9378
|
onChange: setHeaders,
|
|
9780
9379
|
placeholder: "Authorization: Bearer token"
|
|
9781
9380
|
}
|
|
9782
|
-
) : /* @__PURE__ */
|
|
9783
|
-
(method === "POST" || method === "PUT" || method === "PATCH") && /* @__PURE__ */
|
|
9381
|
+
) : /* @__PURE__ */ React22.createElement(Text19, { dimColor: !headers }, headers || "(none)"))),
|
|
9382
|
+
(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
9383
|
TextInput13,
|
|
9785
9384
|
{
|
|
9786
9385
|
value: body,
|
|
9787
9386
|
onChange: setBody,
|
|
9788
9387
|
placeholder: '{"key":"value"}'
|
|
9789
9388
|
}
|
|
9790
|
-
) : /* @__PURE__ */
|
|
9791
|
-
/* @__PURE__ */
|
|
9792
|
-
|
|
9389
|
+
) : /* @__PURE__ */ React22.createElement(Text19, { dimColor: !body }, body || "(empty)"))),
|
|
9390
|
+
/* @__PURE__ */ React22.createElement(Box18, { marginTop: 1 }, /* @__PURE__ */ React22.createElement(
|
|
9391
|
+
Text19,
|
|
9793
9392
|
{
|
|
9794
9393
|
bold: true,
|
|
9795
9394
|
backgroundColor: focusedField === "send" ? "green" : void 0,
|
|
@@ -9800,8 +9399,8 @@ var HttpView = () => {
|
|
|
9800
9399
|
loading ? "Sending..." : "Send Request",
|
|
9801
9400
|
" ]"
|
|
9802
9401
|
))
|
|
9803
|
-
), error && /* @__PURE__ */
|
|
9804
|
-
|
|
9402
|
+
), error && /* @__PURE__ */ React22.createElement(
|
|
9403
|
+
Box18,
|
|
9805
9404
|
{
|
|
9806
9405
|
flexDirection: "column",
|
|
9807
9406
|
borderStyle: "single",
|
|
@@ -9810,9 +9409,9 @@ var HttpView = () => {
|
|
|
9810
9409
|
paddingY: 1,
|
|
9811
9410
|
marginBottom: 1
|
|
9812
9411
|
},
|
|
9813
|
-
/* @__PURE__ */
|
|
9814
|
-
), response && /* @__PURE__ */
|
|
9815
|
-
|
|
9412
|
+
/* @__PURE__ */ React22.createElement(Text19, { color: "red" }, "\u2717 Error: ", error)
|
|
9413
|
+
), response && /* @__PURE__ */ React22.createElement(
|
|
9414
|
+
Box18,
|
|
9816
9415
|
{
|
|
9817
9416
|
flexDirection: "column",
|
|
9818
9417
|
borderStyle: "single",
|
|
@@ -9820,23 +9419,23 @@ var HttpView = () => {
|
|
|
9820
9419
|
paddingX: 2,
|
|
9821
9420
|
paddingY: 1
|
|
9822
9421
|
},
|
|
9823
|
-
/* @__PURE__ */
|
|
9824
|
-
/* @__PURE__ */
|
|
9825
|
-
), /* @__PURE__ */
|
|
9422
|
+
/* @__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!"))),
|
|
9423
|
+
/* @__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)))
|
|
9424
|
+
), /* @__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
9425
|
};
|
|
9827
9426
|
|
|
9828
9427
|
// src/ui/utils/views/MarkdownView.tsx
|
|
9829
|
-
import
|
|
9830
|
-
import { Box as
|
|
9428
|
+
import React23, { useState as useState17 } from "react";
|
|
9429
|
+
import { Box as Box19, Text as Text20, useInput as useInput15 } from "ink";
|
|
9831
9430
|
import TextInput14 from "ink-text-input";
|
|
9832
9431
|
import * as fs15 from "fs";
|
|
9833
9432
|
import * as path7 from "path";
|
|
9834
9433
|
var MarkdownView = () => {
|
|
9835
|
-
const [filePath, setFilePath] =
|
|
9836
|
-
const [content, setContent] =
|
|
9837
|
-
const [error, setError] =
|
|
9838
|
-
const [focusedField, setFocusedField] =
|
|
9839
|
-
|
|
9434
|
+
const [filePath, setFilePath] = useState17("");
|
|
9435
|
+
const [content, setContent] = useState17("");
|
|
9436
|
+
const [error, setError] = useState17("");
|
|
9437
|
+
const [focusedField, setFocusedField] = useState17("file");
|
|
9438
|
+
useInput15((input5, key) => {
|
|
9840
9439
|
if (key.tab) {
|
|
9841
9440
|
setFocusedField(focusedField === "file" ? "preview" : "file");
|
|
9842
9441
|
} else if (key.return) {
|
|
@@ -9877,8 +9476,8 @@ ${code.trim()}
|
|
|
9877
9476
|
setContent("");
|
|
9878
9477
|
}
|
|
9879
9478
|
};
|
|
9880
|
-
return /* @__PURE__ */
|
|
9881
|
-
|
|
9479
|
+
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(
|
|
9480
|
+
Box19,
|
|
9882
9481
|
{
|
|
9883
9482
|
flexDirection: "column",
|
|
9884
9483
|
borderStyle: "single",
|
|
@@ -9887,17 +9486,17 @@ ${code.trim()}
|
|
|
9887
9486
|
paddingY: 1,
|
|
9888
9487
|
marginBottom: 1
|
|
9889
9488
|
},
|
|
9890
|
-
/* @__PURE__ */
|
|
9891
|
-
/* @__PURE__ */
|
|
9489
|
+
/* @__PURE__ */ React23.createElement(Text20, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
|
|
9490
|
+
/* @__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
9491
|
TextInput14,
|
|
9893
9492
|
{
|
|
9894
9493
|
value: filePath,
|
|
9895
9494
|
onChange: setFilePath,
|
|
9896
9495
|
placeholder: "./README.md or /path/to/file.md"
|
|
9897
9496
|
}
|
|
9898
|
-
) : /* @__PURE__ */
|
|
9899
|
-
/* @__PURE__ */
|
|
9900
|
-
|
|
9497
|
+
) : /* @__PURE__ */ React23.createElement(Text20, { dimColor: !filePath }, filePath || "(empty)"))),
|
|
9498
|
+
/* @__PURE__ */ React23.createElement(Box19, { marginTop: 1 }, /* @__PURE__ */ React23.createElement(
|
|
9499
|
+
Text20,
|
|
9901
9500
|
{
|
|
9902
9501
|
bold: true,
|
|
9903
9502
|
backgroundColor: focusedField === "preview" ? "green" : void 0,
|
|
@@ -9906,8 +9505,8 @@ ${code.trim()}
|
|
|
9906
9505
|
focusedField === "preview" ? "\u25B6 " : " ",
|
|
9907
9506
|
"[ Preview File ]"
|
|
9908
9507
|
))
|
|
9909
|
-
), error && /* @__PURE__ */
|
|
9910
|
-
|
|
9508
|
+
), error && /* @__PURE__ */ React23.createElement(
|
|
9509
|
+
Box19,
|
|
9911
9510
|
{
|
|
9912
9511
|
flexDirection: "column",
|
|
9913
9512
|
borderStyle: "single",
|
|
@@ -9916,9 +9515,9 @@ ${code.trim()}
|
|
|
9916
9515
|
paddingY: 1,
|
|
9917
9516
|
marginBottom: 1
|
|
9918
9517
|
},
|
|
9919
|
-
/* @__PURE__ */
|
|
9920
|
-
), content && /* @__PURE__ */
|
|
9921
|
-
|
|
9518
|
+
/* @__PURE__ */ React23.createElement(Text20, { color: "red" }, "\u2717 Error: ", error)
|
|
9519
|
+
), content && /* @__PURE__ */ React23.createElement(
|
|
9520
|
+
Box19,
|
|
9922
9521
|
{
|
|
9923
9522
|
flexDirection: "column",
|
|
9924
9523
|
borderStyle: "single",
|
|
@@ -9926,9 +9525,9 @@ ${code.trim()}
|
|
|
9926
9525
|
paddingX: 2,
|
|
9927
9526
|
paddingY: 1
|
|
9928
9527
|
},
|
|
9929
|
-
/* @__PURE__ */
|
|
9930
|
-
/* @__PURE__ */
|
|
9931
|
-
), /* @__PURE__ */
|
|
9528
|
+
/* @__PURE__ */ React23.createElement(Box19, { marginBottom: 1 }, /* @__PURE__ */ React23.createElement(Text20, { bold: true, color: "green" }, "\u2713 Preview:")),
|
|
9529
|
+
/* @__PURE__ */ React23.createElement(Box19, { flexDirection: "column" }, /* @__PURE__ */ React23.createElement(Text20, null, content))
|
|
9530
|
+
), /* @__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
9531
|
};
|
|
9933
9532
|
|
|
9934
9533
|
// src/ui/utils/UtilsApp.tsx
|
|
@@ -9948,10 +9547,10 @@ var MENU_ITEMS = [
|
|
|
9948
9547
|
{ id: "markdown", icon: "\u{1F4C4}", label: "Markdown", description: "Preview markdown" }
|
|
9949
9548
|
];
|
|
9950
9549
|
var UtilsApp = ({ onExit }) => {
|
|
9951
|
-
const [selectedIndex, setSelectedIndex] =
|
|
9952
|
-
const [activeView, setActiveView] =
|
|
9953
|
-
const { exit } =
|
|
9954
|
-
|
|
9550
|
+
const [selectedIndex, setSelectedIndex] = useState18(0);
|
|
9551
|
+
const [activeView, setActiveView] = useState18(null);
|
|
9552
|
+
const { exit } = useApp4();
|
|
9553
|
+
useInput16((input5, key) => {
|
|
9955
9554
|
if (activeView) {
|
|
9956
9555
|
if (key.escape) {
|
|
9957
9556
|
setActiveView(null);
|
|
@@ -9969,8 +9568,8 @@ var UtilsApp = ({ onExit }) => {
|
|
|
9969
9568
|
exit();
|
|
9970
9569
|
}
|
|
9971
9570
|
});
|
|
9972
|
-
return /* @__PURE__ */
|
|
9973
|
-
|
|
9571
|
+
return /* @__PURE__ */ React24.createElement(Box20, { flexDirection: "column", width: "100%", height: "100%" }, /* @__PURE__ */ React24.createElement(
|
|
9572
|
+
Box20,
|
|
9974
9573
|
{
|
|
9975
9574
|
borderStyle: "single",
|
|
9976
9575
|
borderColor: "cyan",
|
|
@@ -9978,10 +9577,10 @@ var UtilsApp = ({ onExit }) => {
|
|
|
9978
9577
|
paddingY: 0,
|
|
9979
9578
|
marginBottom: 1
|
|
9980
9579
|
},
|
|
9981
|
-
/* @__PURE__ */
|
|
9982
|
-
/* @__PURE__ */
|
|
9983
|
-
), /* @__PURE__ */
|
|
9984
|
-
|
|
9580
|
+
/* @__PURE__ */ React24.createElement(Text21, { bold: true, color: "cyan" }, "\u{1F6E0}\uFE0F Developer Utilities - Interactive Mode"),
|
|
9581
|
+
/* @__PURE__ */ React24.createElement(Box20, { marginLeft: "auto" }, /* @__PURE__ */ React24.createElement(Text21, { dimColor: true }, "Press Ctrl+Q to quit"))
|
|
9582
|
+
), /* @__PURE__ */ React24.createElement(Box20, { flexGrow: 1 }, /* @__PURE__ */ React24.createElement(
|
|
9583
|
+
Box20,
|
|
9985
9584
|
{
|
|
9986
9585
|
flexDirection: "column",
|
|
9987
9586
|
width: 30,
|
|
@@ -9991,9 +9590,9 @@ var UtilsApp = ({ onExit }) => {
|
|
|
9991
9590
|
paddingY: 1,
|
|
9992
9591
|
marginRight: 1
|
|
9993
9592
|
},
|
|
9994
|
-
/* @__PURE__ */
|
|
9995
|
-
MENU_ITEMS.map((item, index) => /* @__PURE__ */
|
|
9996
|
-
|
|
9593
|
+
/* @__PURE__ */ React24.createElement(Box20, { marginBottom: 1 }, /* @__PURE__ */ React24.createElement(Text21, { bold: true, color: "yellow" }, "Select Utility:")),
|
|
9594
|
+
MENU_ITEMS.map((item, index) => /* @__PURE__ */ React24.createElement(Box20, { key: item.id, marginBottom: 0 }, /* @__PURE__ */ React24.createElement(
|
|
9595
|
+
Text21,
|
|
9997
9596
|
{
|
|
9998
9597
|
color: selectedIndex === index && !activeView ? "green" : void 0,
|
|
9999
9598
|
bold: selectedIndex === index && !activeView,
|
|
@@ -10004,9 +9603,9 @@ var UtilsApp = ({ onExit }) => {
|
|
|
10004
9603
|
" ",
|
|
10005
9604
|
item.label
|
|
10006
9605
|
))),
|
|
10007
|
-
/* @__PURE__ */
|
|
10008
|
-
), /* @__PURE__ */
|
|
10009
|
-
|
|
9606
|
+
/* @__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"))
|
|
9607
|
+
), /* @__PURE__ */ React24.createElement(
|
|
9608
|
+
Box20,
|
|
10010
9609
|
{
|
|
10011
9610
|
flexDirection: "column",
|
|
10012
9611
|
flexGrow: 1,
|
|
@@ -10015,21 +9614,21 @@ var UtilsApp = ({ onExit }) => {
|
|
|
10015
9614
|
paddingX: 2,
|
|
10016
9615
|
paddingY: 1
|
|
10017
9616
|
},
|
|
10018
|
-
activeView ? /* @__PURE__ */
|
|
10019
|
-
)), /* @__PURE__ */
|
|
10020
|
-
|
|
9617
|
+
activeView ? /* @__PURE__ */ React24.createElement(ActiveUtilityView, { utilityType: activeView }) : /* @__PURE__ */ React24.createElement(WelcomeView, { selectedItem: MENU_ITEMS[selectedIndex] })
|
|
9618
|
+
)), /* @__PURE__ */ React24.createElement(
|
|
9619
|
+
Box20,
|
|
10021
9620
|
{
|
|
10022
9621
|
borderStyle: "single",
|
|
10023
9622
|
borderColor: "gray",
|
|
10024
9623
|
paddingX: 2,
|
|
10025
9624
|
marginTop: 1
|
|
10026
9625
|
},
|
|
10027
|
-
/* @__PURE__ */
|
|
9626
|
+
/* @__PURE__ */ React24.createElement(Text21, { dimColor: true }, "jai1-cli | Use arrow keys or j/k to navigate")
|
|
10028
9627
|
));
|
|
10029
9628
|
};
|
|
10030
9629
|
var WelcomeView = ({ selectedItem }) => {
|
|
10031
|
-
return /* @__PURE__ */
|
|
10032
|
-
|
|
9630
|
+
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(
|
|
9631
|
+
Box20,
|
|
10033
9632
|
{
|
|
10034
9633
|
borderStyle: "single",
|
|
10035
9634
|
borderColor: "yellow",
|
|
@@ -10037,49 +9636,49 @@ var WelcomeView = ({ selectedItem }) => {
|
|
|
10037
9636
|
paddingY: 1,
|
|
10038
9637
|
marginBottom: 2
|
|
10039
9638
|
},
|
|
10040
|
-
/* @__PURE__ */
|
|
10041
|
-
), /* @__PURE__ */
|
|
9639
|
+
/* @__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))
|
|
9640
|
+
), /* @__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
9641
|
};
|
|
10043
9642
|
var ActiveUtilityView = ({ utilityType }) => {
|
|
10044
9643
|
switch (utilityType) {
|
|
10045
9644
|
case "password":
|
|
10046
|
-
return /* @__PURE__ */
|
|
9645
|
+
return /* @__PURE__ */ React24.createElement(PasswordView, null);
|
|
10047
9646
|
case "uuid":
|
|
10048
|
-
return /* @__PURE__ */
|
|
9647
|
+
return /* @__PURE__ */ React24.createElement(UuidView, null);
|
|
10049
9648
|
case "hash":
|
|
10050
|
-
return /* @__PURE__ */
|
|
9649
|
+
return /* @__PURE__ */ React24.createElement(HashView, null);
|
|
10051
9650
|
case "base64-encode":
|
|
10052
9651
|
case "base64-decode":
|
|
10053
|
-
return /* @__PURE__ */
|
|
9652
|
+
return /* @__PURE__ */ React24.createElement(Base64View, null);
|
|
10054
9653
|
case "url-encode":
|
|
10055
9654
|
case "url-decode":
|
|
10056
|
-
return /* @__PURE__ */
|
|
9655
|
+
return /* @__PURE__ */ React24.createElement(UrlView, null);
|
|
10057
9656
|
case "unix-time":
|
|
10058
|
-
return /* @__PURE__ */
|
|
9657
|
+
return /* @__PURE__ */ React24.createElement(UnixTimeView, null);
|
|
10059
9658
|
case "jwt":
|
|
10060
|
-
return /* @__PURE__ */
|
|
9659
|
+
return /* @__PURE__ */ React24.createElement(JwtView, null);
|
|
10061
9660
|
case "cron":
|
|
10062
|
-
return /* @__PURE__ */
|
|
9661
|
+
return /* @__PURE__ */ React24.createElement(CronView, null);
|
|
10063
9662
|
case "timezone":
|
|
10064
|
-
return /* @__PURE__ */
|
|
9663
|
+
return /* @__PURE__ */ React24.createElement(TimezoneView, null);
|
|
10065
9664
|
case "http":
|
|
10066
|
-
return /* @__PURE__ */
|
|
9665
|
+
return /* @__PURE__ */ React24.createElement(HttpView, null);
|
|
10067
9666
|
case "markdown":
|
|
10068
|
-
return /* @__PURE__ */
|
|
9667
|
+
return /* @__PURE__ */ React24.createElement(MarkdownView, null);
|
|
10069
9668
|
default:
|
|
10070
|
-
return /* @__PURE__ */
|
|
9669
|
+
return /* @__PURE__ */ React24.createElement(PlaceholderView, { utilityType });
|
|
10071
9670
|
}
|
|
10072
9671
|
};
|
|
10073
9672
|
var PlaceholderView = ({ utilityType }) => {
|
|
10074
9673
|
const item = MENU_ITEMS.find((m) => m.id === utilityType);
|
|
10075
|
-
return /* @__PURE__ */
|
|
9674
|
+
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
9675
|
};
|
|
10077
9676
|
|
|
10078
9677
|
// src/commands/utils/interactive.ts
|
|
10079
9678
|
async function runInteractiveMode() {
|
|
10080
9679
|
return new Promise((resolve4) => {
|
|
10081
|
-
const { unmount, waitUntilExit } =
|
|
10082
|
-
|
|
9680
|
+
const { unmount, waitUntilExit } = render4(
|
|
9681
|
+
React25.createElement(UtilsApp, {
|
|
10083
9682
|
onExit: () => {
|
|
10084
9683
|
unmount();
|
|
10085
9684
|
resolve4();
|
|
@@ -10094,40 +9693,40 @@ async function runInteractiveMode() {
|
|
|
10094
9693
|
|
|
10095
9694
|
// src/commands/utils/index.ts
|
|
10096
9695
|
function showUtilsHelp() {
|
|
10097
|
-
console.log(
|
|
9696
|
+
console.log(chalk15.bold.cyan("\u{1F6E0}\uFE0F jai1 utils") + chalk15.dim(" - Developer utilities"));
|
|
10098
9697
|
console.log();
|
|
10099
|
-
console.log(
|
|
10100
|
-
console.log(` ${
|
|
10101
|
-
console.log(` ${
|
|
10102
|
-
console.log(` ${
|
|
10103
|
-
console.log(` ${
|
|
9698
|
+
console.log(chalk15.bold("M\xE3 h\xF3a & B\u1EA3o m\u1EADt:"));
|
|
9699
|
+
console.log(` ${chalk15.cyan("password")} T\u1EA1o m\u1EADt kh\u1EA9u ng\u1EABu nhi\xEAn`);
|
|
9700
|
+
console.log(` ${chalk15.cyan("uuid")} T\u1EA1o UUID v4`);
|
|
9701
|
+
console.log(` ${chalk15.cyan("hash")} Hash text (MD5/SHA/bcrypt)`);
|
|
9702
|
+
console.log(` ${chalk15.cyan("jwt")} Decode/encode JWT tokens`);
|
|
10104
9703
|
console.log();
|
|
10105
|
-
console.log(
|
|
10106
|
-
console.log(` ${
|
|
10107
|
-
console.log(` ${
|
|
10108
|
-
console.log(` ${
|
|
10109
|
-
console.log(` ${
|
|
9704
|
+
console.log(chalk15.bold("Encoding:"));
|
|
9705
|
+
console.log(` ${chalk15.cyan("base64-encode")} Encode sang Base64`);
|
|
9706
|
+
console.log(` ${chalk15.cyan("base64-decode")} Decode t\u1EEB Base64`);
|
|
9707
|
+
console.log(` ${chalk15.cyan("url-encode")} Encode URL components`);
|
|
9708
|
+
console.log(` ${chalk15.cyan("url-decode")} Decode URL components`);
|
|
10110
9709
|
console.log();
|
|
10111
|
-
console.log(
|
|
10112
|
-
console.log(` ${
|
|
10113
|
-
console.log(` ${
|
|
10114
|
-
console.log(` ${
|
|
9710
|
+
console.log(chalk15.bold("Th\u1EDDi gian:"));
|
|
9711
|
+
console.log(` ${chalk15.cyan("unix-time")} Chuy\u1EC3n \u0111\u1ED5i unix timestamp`);
|
|
9712
|
+
console.log(` ${chalk15.cyan("timezone")} Chuy\u1EC3n \u0111\u1ED5i m\xFAi gi\u1EDD`);
|
|
9713
|
+
console.log(` ${chalk15.cyan("cron")} Parse cron expressions`);
|
|
10115
9714
|
console.log();
|
|
10116
|
-
console.log(
|
|
10117
|
-
console.log(` ${
|
|
10118
|
-
console.log(` ${
|
|
9715
|
+
console.log(chalk15.bold("Kh\xE1c:"));
|
|
9716
|
+
console.log(` ${chalk15.cyan("http")} G\u1EEDi HTTP requests`);
|
|
9717
|
+
console.log(` ${chalk15.cyan("markdown-preview")} Xem tr\u01B0\u1EDBc file markdown`);
|
|
10119
9718
|
console.log();
|
|
10120
|
-
console.log(
|
|
10121
|
-
console.log(
|
|
10122
|
-
console.log(
|
|
9719
|
+
console.log(chalk15.bold("Ch\u1EBF \u0111\u1ED9 Interactive:"));
|
|
9720
|
+
console.log(chalk15.dim(" $ jai1 utils -i"));
|
|
9721
|
+
console.log(chalk15.dim(" $ jai1 utils --interactive"));
|
|
10123
9722
|
console.log();
|
|
10124
|
-
console.log(
|
|
10125
|
-
console.log(
|
|
10126
|
-
console.log(
|
|
10127
|
-
console.log(
|
|
10128
|
-
console.log(
|
|
9723
|
+
console.log(chalk15.bold("V\xED d\u1EE5:"));
|
|
9724
|
+
console.log(chalk15.dim(" $ jai1 utils password --length 24"));
|
|
9725
|
+
console.log(chalk15.dim(" $ jai1 utils uuid --count 5"));
|
|
9726
|
+
console.log(chalk15.dim(' $ jai1 utils hash "text" --algorithm sha256'));
|
|
9727
|
+
console.log(chalk15.dim(" $ jai1 utils http https://api.example.com"));
|
|
10129
9728
|
console.log();
|
|
10130
|
-
console.log(
|
|
9729
|
+
console.log(chalk15.dim('Ch\u1EA1y "jai1 utils <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt'));
|
|
10131
9730
|
}
|
|
10132
9731
|
function createUtilsCommand() {
|
|
10133
9732
|
const utilsCommand = new Command42("utils").description("Developer utilities for common tasks").option("-i, --interactive", "Run in interactive mode");
|
|
@@ -10156,11 +9755,11 @@ function createUtilsCommand() {
|
|
|
10156
9755
|
|
|
10157
9756
|
// src/commands/deps/index.ts
|
|
10158
9757
|
import { Command as Command45 } from "commander";
|
|
10159
|
-
import
|
|
9758
|
+
import chalk18 from "chalk";
|
|
10160
9759
|
|
|
10161
9760
|
// src/commands/deps/check.ts
|
|
10162
9761
|
import { Command as Command43 } from "commander";
|
|
10163
|
-
import
|
|
9762
|
+
import chalk16 from "chalk";
|
|
10164
9763
|
import Table4 from "cli-table3";
|
|
10165
9764
|
import ora from "ora";
|
|
10166
9765
|
|
|
@@ -10763,7 +10362,7 @@ function createDepsCheckCommand() {
|
|
|
10763
10362
|
if (projects.length === 0) {
|
|
10764
10363
|
spinner.fail("Kh\xF4ng t\xECm th\u1EA5y project n\xE0o \u0111\u01B0\u1EE3c h\u1ED7 tr\u1EE3");
|
|
10765
10364
|
console.log();
|
|
10766
|
-
console.log(
|
|
10365
|
+
console.log(chalk16.dim("H\u1ED7 tr\u1EE3: Node.js (package.json), PHP (composer.json), Python (requirements.txt/Pipfile)"));
|
|
10767
10366
|
process.exit(1);
|
|
10768
10367
|
}
|
|
10769
10368
|
spinner.succeed(`Ph\xE1t hi\u1EC7n ${projects.length} project:`);
|
|
@@ -10777,7 +10376,7 @@ function createDepsCheckCommand() {
|
|
|
10777
10376
|
await checkEcosystem(project.ecosystem, project.manager, cwd);
|
|
10778
10377
|
}
|
|
10779
10378
|
console.log();
|
|
10780
|
-
console.log(
|
|
10379
|
+
console.log(chalk16.dim('\u{1F4A1} Ch\u1EA1y "jai1 deps upgrade" \u0111\u1EC3 n\xE2ng c\u1EA5p packages.'));
|
|
10781
10380
|
});
|
|
10782
10381
|
return checkCommand;
|
|
10783
10382
|
}
|
|
@@ -10810,7 +10409,7 @@ async function checkEcosystem(ecosystem, manager, cwd) {
|
|
|
10810
10409
|
});
|
|
10811
10410
|
} catch (error) {
|
|
10812
10411
|
spinner.fail(`L\u1ED7i ki\u1EC3m tra ${label}`);
|
|
10813
|
-
console.log(
|
|
10412
|
+
console.log(chalk16.red(error.message));
|
|
10814
10413
|
console.log();
|
|
10815
10414
|
return;
|
|
10816
10415
|
}
|
|
@@ -10823,10 +10422,10 @@ async function checkEcosystem(ecosystem, manager, cwd) {
|
|
|
10823
10422
|
console.log();
|
|
10824
10423
|
const table = new Table4({
|
|
10825
10424
|
head: [
|
|
10826
|
-
|
|
10827
|
-
|
|
10828
|
-
|
|
10829
|
-
|
|
10425
|
+
chalk16.cyan("Package"),
|
|
10426
|
+
chalk16.cyan("Hi\u1EC7n t\u1EA1i"),
|
|
10427
|
+
chalk16.cyan("M\u1EDBi nh\u1EA5t"),
|
|
10428
|
+
chalk16.cyan("Lo\u1EA1i")
|
|
10830
10429
|
],
|
|
10831
10430
|
style: {
|
|
10832
10431
|
head: [],
|
|
@@ -10837,9 +10436,9 @@ async function checkEcosystem(ecosystem, manager, cwd) {
|
|
|
10837
10436
|
const upgradeIcon = pkg.upgradeType === "major" ? "\u{1F534}" : pkg.upgradeType === "minor" ? "\u{1F7E1}" : "\u{1F7E2}";
|
|
10838
10437
|
table.push([
|
|
10839
10438
|
`${upgradeIcon} ${pkg.name}`,
|
|
10840
|
-
|
|
10841
|
-
|
|
10842
|
-
pkg.type === "dev" ?
|
|
10439
|
+
chalk16.dim(pkg.current),
|
|
10440
|
+
chalk16.green(pkg.latest),
|
|
10441
|
+
pkg.type === "dev" ? chalk16.dim("dev") : "dep"
|
|
10843
10442
|
]);
|
|
10844
10443
|
}
|
|
10845
10444
|
console.log(table.toString());
|
|
@@ -10847,13 +10446,13 @@ async function checkEcosystem(ecosystem, manager, cwd) {
|
|
|
10847
10446
|
if (result.isLaravel) {
|
|
10848
10447
|
const blockedPackages = result.packages.filter((p) => p.blockedReason);
|
|
10849
10448
|
if (blockedPackages.length > 0) {
|
|
10850
|
-
console.log(
|
|
10449
|
+
console.log(chalk16.yellow("\u26A0\uFE0F Laravel major version upgrades blocked (nguy hi\u1EC3m):"));
|
|
10851
10450
|
for (const pkg of blockedPackages) {
|
|
10852
|
-
console.log(
|
|
10451
|
+
console.log(chalk16.dim(` - ${pkg.name}: ${pkg.current} \u2192 ${pkg.latest}`));
|
|
10853
10452
|
}
|
|
10854
10453
|
console.log();
|
|
10855
|
-
console.log(
|
|
10856
|
-
console.log(
|
|
10454
|
+
console.log(chalk16.dim("\u{1F4A1} \u0110\u1EC3 n\xE2ng c\u1EA5p Laravel major version, ch\u1EA1y th\u1EE7 c\xF4ng:"));
|
|
10455
|
+
console.log(chalk16.dim(` composer require ${blockedPackages[0].name}:^${blockedPackages[0].latest}`));
|
|
10857
10456
|
console.log();
|
|
10858
10457
|
}
|
|
10859
10458
|
}
|
|
@@ -10862,7 +10461,7 @@ async function checkEcosystem(ecosystem, manager, cwd) {
|
|
|
10862
10461
|
// src/commands/deps/upgrade.ts
|
|
10863
10462
|
import { Command as Command44 } from "commander";
|
|
10864
10463
|
import { checkbox as checkbox3, confirm as confirm8 } from "@inquirer/prompts";
|
|
10865
|
-
import
|
|
10464
|
+
import chalk17 from "chalk";
|
|
10866
10465
|
import ora2 from "ora";
|
|
10867
10466
|
import Table5 from "cli-table3";
|
|
10868
10467
|
function createDepsUpgradeCommand() {
|
|
@@ -10879,7 +10478,7 @@ async function handleDepsUpgrade(options) {
|
|
|
10879
10478
|
if (projects.length === 0) {
|
|
10880
10479
|
spinner.fail("Kh\xF4ng t\xECm th\u1EA5y project n\xE0o \u0111\u01B0\u1EE3c h\u1ED7 tr\u1EE3");
|
|
10881
10480
|
console.log();
|
|
10882
|
-
console.log(
|
|
10481
|
+
console.log(chalk17.dim("H\u1ED7 tr\u1EE3: Node.js (package.json), PHP (composer.json), Python (requirements.txt/Pipfile)"));
|
|
10883
10482
|
process.exit(1);
|
|
10884
10483
|
}
|
|
10885
10484
|
spinner.succeed(`Ph\xE1t hi\u1EC7n ${projects.length} project:`);
|
|
@@ -10893,9 +10492,9 @@ async function handleDepsUpgrade(options) {
|
|
|
10893
10492
|
await upgradeEcosystem(project, cwd, options);
|
|
10894
10493
|
}
|
|
10895
10494
|
console.log();
|
|
10896
|
-
console.log(
|
|
10495
|
+
console.log(chalk17.green("\u2705 Ho\xE0n th\xE0nh!"));
|
|
10897
10496
|
} catch (error) {
|
|
10898
|
-
console.error(
|
|
10497
|
+
console.error(chalk17.red(`
|
|
10899
10498
|
\u274C ${error.message}
|
|
10900
10499
|
`));
|
|
10901
10500
|
process.exit(1);
|
|
@@ -10904,10 +10503,10 @@ async function handleDepsUpgrade(options) {
|
|
|
10904
10503
|
async function upgradeEcosystem(project, cwd, options) {
|
|
10905
10504
|
const service = getService(project.ecosystem);
|
|
10906
10505
|
const label = `${getEcosystemIcon(project.ecosystem)} ${getEcosystemLabel(project.ecosystem)}`;
|
|
10907
|
-
console.log(
|
|
10506
|
+
console.log(chalk17.bold.cyan(`
|
|
10908
10507
|
${"\u2501".repeat(80)}`));
|
|
10909
|
-
console.log(
|
|
10910
|
-
console.log(
|
|
10508
|
+
console.log(chalk17.bold.cyan(`${label}`));
|
|
10509
|
+
console.log(chalk17.bold.cyan("\u2501".repeat(80)));
|
|
10911
10510
|
console.log();
|
|
10912
10511
|
const spinner = ora2("\u0110ang ki\u1EC3m tra packages...").start();
|
|
10913
10512
|
let packages;
|
|
@@ -10918,7 +10517,7 @@ ${"\u2501".repeat(80)}`));
|
|
|
10918
10517
|
packages = result.packages;
|
|
10919
10518
|
} catch (error) {
|
|
10920
10519
|
spinner.fail("L\u1ED7i ki\u1EC3m tra packages");
|
|
10921
|
-
console.log(
|
|
10520
|
+
console.log(chalk17.red(error.message));
|
|
10922
10521
|
return;
|
|
10923
10522
|
}
|
|
10924
10523
|
if (packages.length === 0) {
|
|
@@ -10931,7 +10530,7 @@ ${"\u2501".repeat(80)}`));
|
|
|
10931
10530
|
let selectedPackages;
|
|
10932
10531
|
if (options.all) {
|
|
10933
10532
|
selectedPackages = packages;
|
|
10934
|
-
console.log(
|
|
10533
|
+
console.log(chalk17.cyan(`\u{1F4CB} \u0110\xE3 ch\u1ECDn t\u1EA5t c\u1EA3 ${selectedPackages.length} packages
|
|
10935
10534
|
`));
|
|
10936
10535
|
} else {
|
|
10937
10536
|
try {
|
|
@@ -10949,12 +10548,12 @@ ${"\u2501".repeat(80)}`));
|
|
|
10949
10548
|
theme: checkboxTheme
|
|
10950
10549
|
});
|
|
10951
10550
|
if (selected.length === 0) {
|
|
10952
|
-
console.log(
|
|
10551
|
+
console.log(chalk17.yellow("\u23F8\uFE0F Kh\xF4ng c\xF3 packages n\xE0o \u0111\u01B0\u1EE3c ch\u1ECDn\n"));
|
|
10953
10552
|
return;
|
|
10954
10553
|
}
|
|
10955
10554
|
selectedPackages = packages.filter((p) => selected.includes(p.name));
|
|
10956
10555
|
} catch {
|
|
10957
|
-
console.log(
|
|
10556
|
+
console.log(chalk17.yellow("\n\u23F8\uFE0F \u0110\xE3 h\u1EE7y\n"));
|
|
10958
10557
|
return;
|
|
10959
10558
|
}
|
|
10960
10559
|
}
|
|
@@ -10965,35 +10564,35 @@ ${"\u2501".repeat(80)}`));
|
|
|
10965
10564
|
default: true
|
|
10966
10565
|
});
|
|
10967
10566
|
} catch {
|
|
10968
|
-
console.log(
|
|
10567
|
+
console.log(chalk17.yellow("\n\u23F8\uFE0F \u0110\xE3 h\u1EE7y\n"));
|
|
10969
10568
|
return;
|
|
10970
10569
|
}
|
|
10971
10570
|
if (!shouldProceed) {
|
|
10972
|
-
console.log(
|
|
10571
|
+
console.log(chalk17.yellow("\u23F8\uFE0F Upgrade \u0111\xE3 h\u1EE7y\n"));
|
|
10973
10572
|
return;
|
|
10974
10573
|
}
|
|
10975
10574
|
console.log();
|
|
10976
|
-
console.log(
|
|
10977
|
-
console.log(
|
|
10575
|
+
console.log(chalk17.cyan(`\u{1F527} Package manager: ${project.manager}`));
|
|
10576
|
+
console.log(chalk17.cyan("\u{1F4E5} \u0110ang upgrade...\n"));
|
|
10978
10577
|
const commands = service.getUpgradeCommands(selectedPackages);
|
|
10979
10578
|
try {
|
|
10980
10579
|
if (commands.deps) {
|
|
10981
|
-
console.log(
|
|
10580
|
+
console.log(chalk17.dim(`$ ${commands.deps}
|
|
10982
10581
|
`));
|
|
10983
10582
|
}
|
|
10984
10583
|
if (commands.devDeps) {
|
|
10985
|
-
console.log(
|
|
10584
|
+
console.log(chalk17.dim(`$ ${commands.devDeps}
|
|
10986
10585
|
`));
|
|
10987
10586
|
}
|
|
10988
10587
|
await service.upgrade(cwd, { packages: selectedPackages });
|
|
10989
|
-
console.log(
|
|
10588
|
+
console.log(chalk17.green(`
|
|
10990
10589
|
\u2705 \u0110\xE3 upgrade ${selectedPackages.length} packages th\xE0nh c\xF4ng!`));
|
|
10991
10590
|
} catch (error) {
|
|
10992
|
-
console.error(
|
|
10993
|
-
console.error(
|
|
10994
|
-
console.log(
|
|
10995
|
-
if (commands.deps) console.log(
|
|
10996
|
-
if (commands.devDeps) console.log(
|
|
10591
|
+
console.error(chalk17.red("\n\u274C L\u1ED7i khi upgrade:"));
|
|
10592
|
+
console.error(chalk17.red(error.message));
|
|
10593
|
+
console.log(chalk17.yellow("\n\u{1F4A1} B\u1EA1n c\xF3 th\u1EC3 th\u1EED upgrade th\u1EE7 c\xF4ng:"));
|
|
10594
|
+
if (commands.deps) console.log(chalk17.cyan(` ${commands.deps}`));
|
|
10595
|
+
if (commands.devDeps) console.log(chalk17.cyan(` ${commands.devDeps}`));
|
|
10997
10596
|
console.log();
|
|
10998
10597
|
throw error;
|
|
10999
10598
|
}
|
|
@@ -11001,10 +10600,10 @@ ${"\u2501".repeat(80)}`));
|
|
|
11001
10600
|
function displayUpgradeTable(packages) {
|
|
11002
10601
|
const table = new Table5({
|
|
11003
10602
|
head: [
|
|
11004
|
-
|
|
11005
|
-
|
|
11006
|
-
|
|
11007
|
-
|
|
10603
|
+
chalk17.cyan("Package"),
|
|
10604
|
+
chalk17.cyan("Hi\u1EC7n t\u1EA1i"),
|
|
10605
|
+
chalk17.cyan("M\u1EDBi nh\u1EA5t"),
|
|
10606
|
+
chalk17.cyan("Lo\u1EA1i")
|
|
11008
10607
|
],
|
|
11009
10608
|
style: {
|
|
11010
10609
|
head: [],
|
|
@@ -11015,9 +10614,9 @@ function displayUpgradeTable(packages) {
|
|
|
11015
10614
|
const upgradeIcon = pkg.upgradeType === "major" ? "\u{1F534}" : pkg.upgradeType === "minor" ? "\u{1F7E1}" : "\u{1F7E2}";
|
|
11016
10615
|
table.push([
|
|
11017
10616
|
`${upgradeIcon} ${pkg.name}`,
|
|
11018
|
-
|
|
11019
|
-
|
|
11020
|
-
pkg.type === "dev" ?
|
|
10617
|
+
chalk17.dim(pkg.current),
|
|
10618
|
+
chalk17.green(pkg.latest),
|
|
10619
|
+
pkg.type === "dev" ? chalk17.dim("dev") : "dep"
|
|
11021
10620
|
]);
|
|
11022
10621
|
}
|
|
11023
10622
|
console.log(table.toString());
|
|
@@ -11060,23 +10659,23 @@ function getEcosystemLabel(ecosystem) {
|
|
|
11060
10659
|
|
|
11061
10660
|
// src/commands/deps/index.ts
|
|
11062
10661
|
function showDepsHelp() {
|
|
11063
|
-
console.log(
|
|
10662
|
+
console.log(chalk18.bold.cyan("\u{1F4E6} jai1 deps") + chalk18.dim(" - Qu\u1EA3n l\xFD dependencies trong project"));
|
|
11064
10663
|
console.log();
|
|
11065
|
-
console.log(
|
|
11066
|
-
console.log(` ${
|
|
11067
|
-
console.log(` ${
|
|
10664
|
+
console.log(chalk18.bold("C\xE1c l\u1EC7nh:"));
|
|
10665
|
+
console.log(` ${chalk18.cyan("check")} Ki\u1EC3m tra c\xE1c packages c\u1EA7n upgrade`);
|
|
10666
|
+
console.log(` ${chalk18.cyan("upgrade")} N\xE2ng c\u1EA5p dependencies l\xEAn phi\xEAn b\u1EA3n m\u1EDBi nh\u1EA5t`);
|
|
11068
10667
|
console.log();
|
|
11069
|
-
console.log(
|
|
11070
|
-
console.log(
|
|
11071
|
-
console.log(
|
|
11072
|
-
console.log(
|
|
10668
|
+
console.log(chalk18.bold("H\u1ED7 tr\u1EE3:"));
|
|
10669
|
+
console.log(chalk18.dim(" \u2022 Node.js (npm, pnpm, yarn, bun)"));
|
|
10670
|
+
console.log(chalk18.dim(" \u2022 PHP/Composer (v\u1EDBi b\u1EA3o v\u1EC7 Laravel major version)"));
|
|
10671
|
+
console.log(chalk18.dim(" \u2022 Python (pip, pipenv)"));
|
|
11073
10672
|
console.log();
|
|
11074
|
-
console.log(
|
|
11075
|
-
console.log(
|
|
11076
|
-
console.log(
|
|
11077
|
-
console.log(
|
|
10673
|
+
console.log(chalk18.bold("V\xED d\u1EE5:"));
|
|
10674
|
+
console.log(chalk18.dim(" $ jai1 deps check"));
|
|
10675
|
+
console.log(chalk18.dim(" $ jai1 deps upgrade"));
|
|
10676
|
+
console.log(chalk18.dim(" $ jai1 deps upgrade --all"));
|
|
11078
10677
|
console.log();
|
|
11079
|
-
console.log(
|
|
10678
|
+
console.log(chalk18.dim('Ch\u1EA1y "jai1 deps <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt'));
|
|
11080
10679
|
}
|
|
11081
10680
|
function createDepsCommand() {
|
|
11082
10681
|
const depsCommand = new Command45("deps").description("Qu\u1EA3n l\xFD dependencies trong project").action(() => {
|
|
@@ -11092,13 +10691,13 @@ import { Command as Command56 } from "commander";
|
|
|
11092
10691
|
|
|
11093
10692
|
// src/commands/tasks/add.ts
|
|
11094
10693
|
import { Command as Command46 } from "commander";
|
|
11095
|
-
import
|
|
10694
|
+
import chalk19 from "chalk";
|
|
11096
10695
|
function createTaskAddCommand() {
|
|
11097
10696
|
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
10697
|
const service = new TaskService();
|
|
11099
10698
|
const priority = Number(options.priority ?? 2);
|
|
11100
10699
|
if (priority < 0 || priority > 3) {
|
|
11101
|
-
console.error(
|
|
10700
|
+
console.error(chalk19.red("\u274C Priority must be 0-3"));
|
|
11102
10701
|
process.exit(1);
|
|
11103
10702
|
}
|
|
11104
10703
|
const tags = options.tags ? options.tags.split(",").map((t) => t.trim()) : [];
|
|
@@ -11114,21 +10713,21 @@ function createTaskAddCommand() {
|
|
|
11114
10713
|
}
|
|
11115
10714
|
const icon = PRIORITY_ICONS[task.priority] || "\u{1F7E1}";
|
|
11116
10715
|
const label = PRIORITY_LABELS[task.priority] || "Medium";
|
|
11117
|
-
console.log(
|
|
11118
|
-
console.log(` ${
|
|
11119
|
-
console.log(` ${
|
|
10716
|
+
console.log(chalk19.green(`\u2705 Task added: ${chalk19.bold(task.id)}`));
|
|
10717
|
+
console.log(` ${chalk19.dim("Title:")} ${task.title}`);
|
|
10718
|
+
console.log(` ${chalk19.dim("Priority:")} ${icon} ${label}`);
|
|
11120
10719
|
if (task.parent) {
|
|
11121
|
-
console.log(` ${
|
|
10720
|
+
console.log(` ${chalk19.dim("Parent:")} ${task.parent}`);
|
|
11122
10721
|
}
|
|
11123
10722
|
if (task.tags.length > 0) {
|
|
11124
|
-
console.log(` ${
|
|
10723
|
+
console.log(` ${chalk19.dim("Tags:")} ${task.tags.join(", ")}`);
|
|
11125
10724
|
}
|
|
11126
10725
|
});
|
|
11127
10726
|
}
|
|
11128
10727
|
|
|
11129
10728
|
// src/commands/tasks/list.ts
|
|
11130
10729
|
import { Command as Command47 } from "commander";
|
|
11131
|
-
import
|
|
10730
|
+
import chalk20 from "chalk";
|
|
11132
10731
|
function createTaskListCommand() {
|
|
11133
10732
|
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
10733
|
await handleTaskList(options);
|
|
@@ -11149,12 +10748,12 @@ async function handleTaskList(options) {
|
|
|
11149
10748
|
return;
|
|
11150
10749
|
}
|
|
11151
10750
|
if (tasks.length === 0) {
|
|
11152
|
-
console.log(
|
|
10751
|
+
console.log(chalk20.dim("No tasks found."));
|
|
11153
10752
|
return;
|
|
11154
10753
|
}
|
|
11155
10754
|
const doneIds = new Set(allTasks.filter((t) => t.status === "done").map((t) => t.id));
|
|
11156
10755
|
const header = options.parent ? `\u{1F4CB} ${options.parent} (${tasks.length} tasks)` : `\u{1F4CB} All tasks (${tasks.length})`;
|
|
11157
|
-
console.log(
|
|
10756
|
+
console.log(chalk20.bold(header));
|
|
11158
10757
|
console.log();
|
|
11159
10758
|
for (const task of tasks) {
|
|
11160
10759
|
printTaskLine(task, doneIds);
|
|
@@ -11164,23 +10763,23 @@ function printTaskLine(task, doneIds) {
|
|
|
11164
10763
|
const isBlocked = task.status === "todo" && task.depends_on.length > 0 && !task.depends_on.every((id) => doneIds.has(id));
|
|
11165
10764
|
const statusIcon = isBlocked ? BLOCKED_ICON : STATUS_ICONS[task.status] || "\u{1F4CB}";
|
|
11166
10765
|
const priorityIcon = PRIORITY_ICONS[task.priority] || "\u{1F7E1}";
|
|
11167
|
-
let line = ` ${statusIcon} ${
|
|
10766
|
+
let line = ` ${statusIcon} ${chalk20.dim(task.id)} P${task.priority}${priorityIcon} ${task.title}`;
|
|
11168
10767
|
if (task.status === "in_progress" && task.assigned_to) {
|
|
11169
|
-
line +=
|
|
10768
|
+
line += chalk20.cyan(` @${task.assigned_to}`);
|
|
11170
10769
|
}
|
|
11171
10770
|
if (isBlocked) {
|
|
11172
10771
|
const blockedBy = task.depends_on.filter((id) => !doneIds.has(id));
|
|
11173
|
-
line +=
|
|
10772
|
+
line += chalk20.red(` (blocked: ${blockedBy.join(", ")})`);
|
|
11174
10773
|
}
|
|
11175
10774
|
if (task.parent) {
|
|
11176
|
-
line +=
|
|
10775
|
+
line += chalk20.dim(` [${task.parent}]`);
|
|
11177
10776
|
}
|
|
11178
10777
|
console.log(line);
|
|
11179
10778
|
}
|
|
11180
10779
|
|
|
11181
10780
|
// src/commands/tasks/ready.ts
|
|
11182
10781
|
import { Command as Command48 } from "commander";
|
|
11183
|
-
import
|
|
10782
|
+
import chalk21 from "chalk";
|
|
11184
10783
|
function createTaskReadyCommand() {
|
|
11185
10784
|
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
10785
|
const service = new TaskService();
|
|
@@ -11190,33 +10789,33 @@ function createTaskReadyCommand() {
|
|
|
11190
10789
|
return;
|
|
11191
10790
|
}
|
|
11192
10791
|
if (tasks.length === 0) {
|
|
11193
|
-
console.log(
|
|
11194
|
-
console.log(
|
|
10792
|
+
console.log(chalk21.dim("No tasks ready to pick."));
|
|
10793
|
+
console.log(chalk21.dim("\u{1F4A1} Check blocked tasks: jai1 t list -s todo"));
|
|
11195
10794
|
return;
|
|
11196
10795
|
}
|
|
11197
|
-
console.log(
|
|
10796
|
+
console.log(chalk21.bold(`\u{1F4CB} Ready to pick (${tasks.length} tasks):`));
|
|
11198
10797
|
console.log();
|
|
11199
10798
|
for (const task of tasks) {
|
|
11200
10799
|
const icon = PRIORITY_ICONS[task.priority] || "\u{1F7E1}";
|
|
11201
|
-
let line = ` P${task.priority}${icon} ${
|
|
10800
|
+
let line = ` P${task.priority}${icon} ${chalk21.dim(task.id)} ${task.title}`;
|
|
11202
10801
|
if (task.parent) {
|
|
11203
|
-
line +=
|
|
10802
|
+
line += chalk21.dim(` [${task.parent}]`);
|
|
11204
10803
|
}
|
|
11205
10804
|
console.log(line);
|
|
11206
10805
|
}
|
|
11207
10806
|
console.log();
|
|
11208
|
-
console.log(
|
|
10807
|
+
console.log(chalk21.dim("\u{1F4A1} Run: jai1 t pick"));
|
|
11209
10808
|
});
|
|
11210
10809
|
}
|
|
11211
10810
|
|
|
11212
10811
|
// src/commands/tasks/update.ts
|
|
11213
10812
|
import { Command as Command49 } from "commander";
|
|
11214
|
-
import
|
|
10813
|
+
import chalk22 from "chalk";
|
|
11215
10814
|
var VALID_STATUSES = ["todo", "in_progress", "done", "cancelled"];
|
|
11216
10815
|
function createTaskUpdateCommand() {
|
|
11217
10816
|
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
10817
|
if (!VALID_STATUSES.includes(options.status)) {
|
|
11219
|
-
console.error(
|
|
10818
|
+
console.error(chalk22.red(`\u274C Invalid status. Must be: ${VALID_STATUSES.join(", ")}`));
|
|
11220
10819
|
process.exit(1);
|
|
11221
10820
|
}
|
|
11222
10821
|
const service = new TaskService();
|
|
@@ -11227,9 +10826,9 @@ function createTaskUpdateCommand() {
|
|
|
11227
10826
|
return;
|
|
11228
10827
|
}
|
|
11229
10828
|
const icon = STATUS_ICONS[task.status] || "\u{1F4CB}";
|
|
11230
|
-
console.log(
|
|
10829
|
+
console.log(chalk22.green(`\u2705 ${task.id} \u2192 ${icon} ${task.status}`));
|
|
11231
10830
|
} catch (error) {
|
|
11232
|
-
console.error(
|
|
10831
|
+
console.error(chalk22.red(`\u274C ${error instanceof Error ? error.message : String(error)}`));
|
|
11233
10832
|
process.exit(1);
|
|
11234
10833
|
}
|
|
11235
10834
|
});
|
|
@@ -11237,14 +10836,14 @@ function createTaskUpdateCommand() {
|
|
|
11237
10836
|
|
|
11238
10837
|
// src/commands/tasks/show.ts
|
|
11239
10838
|
import { Command as Command50 } from "commander";
|
|
11240
|
-
import
|
|
10839
|
+
import chalk23 from "chalk";
|
|
11241
10840
|
function createTaskShowCommand() {
|
|
11242
10841
|
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
10842
|
const service = new TaskService();
|
|
11244
10843
|
if (query.startsWith("T-")) {
|
|
11245
10844
|
const task = await service.findById(query);
|
|
11246
10845
|
if (!task) {
|
|
11247
|
-
console.error(
|
|
10846
|
+
console.error(chalk23.red(`\u274C Task ${query} not found`));
|
|
11248
10847
|
process.exit(1);
|
|
11249
10848
|
}
|
|
11250
10849
|
if (options.json) {
|
|
@@ -11255,34 +10854,34 @@ function createTaskShowCommand() {
|
|
|
11255
10854
|
const statusIcon = blocked ? BLOCKED_ICON : STATUS_ICONS[task.status] || "\u{1F4CB}";
|
|
11256
10855
|
const priIcon = PRIORITY_ICONS[task.priority] || "\u{1F7E1}";
|
|
11257
10856
|
const priLabel = PRIORITY_LABELS[task.priority] || "Medium";
|
|
11258
|
-
console.log(
|
|
10857
|
+
console.log(chalk23.bold(`
|
|
11259
10858
|
\u{1F4CC} ${task.id}: ${task.title}
|
|
11260
10859
|
`));
|
|
11261
|
-
console.log(` ${
|
|
11262
|
-
console.log(` ${
|
|
10860
|
+
console.log(` ${chalk23.dim("Status:")} ${statusIcon} ${task.status}${blocked ? chalk23.red(" (BLOCKED)") : ""}`);
|
|
10861
|
+
console.log(` ${chalk23.dim("Priority:")} ${priIcon} P${task.priority} ${priLabel}`);
|
|
11263
10862
|
if (task.parent) {
|
|
11264
|
-
console.log(` ${
|
|
10863
|
+
console.log(` ${chalk23.dim("Parent:")} ${task.parent}`);
|
|
11265
10864
|
}
|
|
11266
10865
|
if (task.assigned_to) {
|
|
11267
|
-
console.log(` ${
|
|
10866
|
+
console.log(` ${chalk23.dim("Assigned:")} @${task.assigned_to} (${task.claimed_at})`);
|
|
11268
10867
|
}
|
|
11269
10868
|
if (task.depends_on.length > 0) {
|
|
11270
|
-
console.log(` ${
|
|
10869
|
+
console.log(` ${chalk23.dim("Depends on:")} ${task.depends_on.join(", ")}`);
|
|
11271
10870
|
if (blocked) {
|
|
11272
|
-
console.log(` ${
|
|
10871
|
+
console.log(` ${chalk23.dim("Blocked by:")} ${chalk23.red(blockedBy.join(", "))}`);
|
|
11273
10872
|
}
|
|
11274
10873
|
}
|
|
11275
10874
|
if (task.tags.length > 0) {
|
|
11276
|
-
console.log(` ${
|
|
10875
|
+
console.log(` ${chalk23.dim("Tags:")} ${task.tags.join(", ")}`);
|
|
11277
10876
|
}
|
|
11278
10877
|
if (task.branch) {
|
|
11279
|
-
console.log(` ${
|
|
10878
|
+
console.log(` ${chalk23.dim("Branch:")} ${task.branch}`);
|
|
11280
10879
|
}
|
|
11281
10880
|
if (task.notes) {
|
|
11282
|
-
console.log(` ${
|
|
10881
|
+
console.log(` ${chalk23.dim("Notes:")} ${task.notes}`);
|
|
11283
10882
|
}
|
|
11284
|
-
console.log(` ${
|
|
11285
|
-
console.log(` ${
|
|
10883
|
+
console.log(` ${chalk23.dim("Created:")} ${task.created}`);
|
|
10884
|
+
console.log(` ${chalk23.dim("Updated:")} ${task.updated}`);
|
|
11286
10885
|
console.log();
|
|
11287
10886
|
} else {
|
|
11288
10887
|
const tasks = await service.filter({ parent: query });
|
|
@@ -11291,10 +10890,10 @@ function createTaskShowCommand() {
|
|
|
11291
10890
|
return;
|
|
11292
10891
|
}
|
|
11293
10892
|
if (tasks.length === 0) {
|
|
11294
|
-
console.log(
|
|
10893
|
+
console.log(chalk23.dim(`No tasks for parent: ${query}`));
|
|
11295
10894
|
return;
|
|
11296
10895
|
}
|
|
11297
|
-
console.log(
|
|
10896
|
+
console.log(chalk23.bold(`
|
|
11298
10897
|
\u{1F4CB} ${query} (${tasks.length} tasks)
|
|
11299
10898
|
`));
|
|
11300
10899
|
const allTasks = await service.readAll();
|
|
@@ -11302,11 +10901,11 @@ function createTaskShowCommand() {
|
|
|
11302
10901
|
for (const task of tasks) {
|
|
11303
10902
|
const isBlocked = task.status === "todo" && task.depends_on.length > 0 && !task.depends_on.every((id) => doneIds.has(id));
|
|
11304
10903
|
const icon = isBlocked ? BLOCKED_ICON : STATUS_ICONS[task.status] || "\u{1F4CB}";
|
|
11305
|
-
let line = ` ${icon} ${
|
|
11306
|
-
if (task.assigned_to) line +=
|
|
10904
|
+
let line = ` ${icon} ${chalk23.dim(task.id)} P${task.priority} ${task.title}`;
|
|
10905
|
+
if (task.assigned_to) line += chalk23.cyan(` @${task.assigned_to}`);
|
|
11307
10906
|
if (isBlocked) {
|
|
11308
10907
|
const bb = task.depends_on.filter((id) => !doneIds.has(id));
|
|
11309
|
-
line +=
|
|
10908
|
+
line += chalk23.red(` (blocked: ${bb.join(", ")})`);
|
|
11310
10909
|
}
|
|
11311
10910
|
console.log(line);
|
|
11312
10911
|
}
|
|
@@ -11317,7 +10916,7 @@ function createTaskShowCommand() {
|
|
|
11317
10916
|
|
|
11318
10917
|
// src/commands/tasks/pick.ts
|
|
11319
10918
|
import { Command as Command51 } from "commander";
|
|
11320
|
-
import
|
|
10919
|
+
import chalk24 from "chalk";
|
|
11321
10920
|
import { confirm as confirm9 } from "@inquirer/prompts";
|
|
11322
10921
|
function createTaskPickCommand() {
|
|
11323
10922
|
return new Command51("pick").description("Claim the next available task").option("-j, --json", "Output JSON").action(async (options) => {
|
|
@@ -11328,8 +10927,8 @@ function createTaskPickCommand() {
|
|
|
11328
10927
|
console.log(JSON.stringify({ picked: null, message: "No tasks ready" }));
|
|
11329
10928
|
return;
|
|
11330
10929
|
}
|
|
11331
|
-
console.log(
|
|
11332
|
-
console.log(
|
|
10930
|
+
console.log(chalk24.dim("No tasks ready to pick."));
|
|
10931
|
+
console.log(chalk24.dim('\u{1F4A1} Add tasks first: jai1 t add "..."'));
|
|
11333
10932
|
return;
|
|
11334
10933
|
}
|
|
11335
10934
|
const top = ready[0];
|
|
@@ -11339,13 +10938,13 @@ function createTaskPickCommand() {
|
|
|
11339
10938
|
console.log(JSON.stringify(picked2, null, 2));
|
|
11340
10939
|
return;
|
|
11341
10940
|
}
|
|
11342
|
-
console.log(
|
|
11343
|
-
console.log(` ${
|
|
10941
|
+
console.log(chalk24.bold("\n\u{1F4CC} Next available task:"));
|
|
10942
|
+
console.log(` ${chalk24.bold(top.id)} P${top.priority}${icon} ${top.title}`);
|
|
11344
10943
|
if (top.parent) {
|
|
11345
|
-
console.log(` ${
|
|
10944
|
+
console.log(` ${chalk24.dim("Parent:")} ${top.parent}`);
|
|
11346
10945
|
}
|
|
11347
10946
|
if (ready.length > 1) {
|
|
11348
|
-
console.log(
|
|
10947
|
+
console.log(chalk24.dim(`
|
|
11349
10948
|
+${ready.length - 1} more tasks ready`));
|
|
11350
10949
|
}
|
|
11351
10950
|
const proceed = await confirm9({
|
|
@@ -11353,18 +10952,18 @@ function createTaskPickCommand() {
|
|
|
11353
10952
|
default: true
|
|
11354
10953
|
});
|
|
11355
10954
|
if (!proceed) {
|
|
11356
|
-
console.log(
|
|
10955
|
+
console.log(chalk24.dim("\nCancelled."));
|
|
11357
10956
|
return;
|
|
11358
10957
|
}
|
|
11359
10958
|
const picked = await service.pick(top.id);
|
|
11360
|
-
console.log(
|
|
10959
|
+
console.log(chalk24.green(`
|
|
11361
10960
|
\u2705 ${picked.id} assigned to @${picked.assigned_to}, status \u2192 in_progress`));
|
|
11362
10961
|
});
|
|
11363
10962
|
}
|
|
11364
10963
|
|
|
11365
10964
|
// src/commands/tasks/done.ts
|
|
11366
10965
|
import { Command as Command52 } from "commander";
|
|
11367
|
-
import
|
|
10966
|
+
import chalk25 from "chalk";
|
|
11368
10967
|
function createTaskDoneCommand() {
|
|
11369
10968
|
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
10969
|
const service = new TaskService();
|
|
@@ -11374,9 +10973,9 @@ function createTaskDoneCommand() {
|
|
|
11374
10973
|
console.log(JSON.stringify(task, null, 2));
|
|
11375
10974
|
return;
|
|
11376
10975
|
}
|
|
11377
|
-
console.log(
|
|
10976
|
+
console.log(chalk25.green(`\u2705 ${task.id}: ${task.title} \u2192 done`));
|
|
11378
10977
|
} catch (error) {
|
|
11379
|
-
console.error(
|
|
10978
|
+
console.error(chalk25.red(`\u274C ${error instanceof Error ? error.message : String(error)}`));
|
|
11380
10979
|
process.exit(1);
|
|
11381
10980
|
}
|
|
11382
10981
|
});
|
|
@@ -11384,7 +10983,7 @@ function createTaskDoneCommand() {
|
|
|
11384
10983
|
|
|
11385
10984
|
// src/commands/tasks/dep.ts
|
|
11386
10985
|
import { Command as Command53 } from "commander";
|
|
11387
|
-
import
|
|
10986
|
+
import chalk26 from "chalk";
|
|
11388
10987
|
function createTaskDepCommand() {
|
|
11389
10988
|
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
10989
|
const service = new TaskService();
|
|
@@ -11394,10 +10993,10 @@ function createTaskDepCommand() {
|
|
|
11394
10993
|
console.log(JSON.stringify(task, null, 2));
|
|
11395
10994
|
return;
|
|
11396
10995
|
}
|
|
11397
|
-
console.log(
|
|
11398
|
-
console.log(
|
|
10996
|
+
console.log(chalk26.green(`\u2705 ${childId} now depends on ${parentId}`));
|
|
10997
|
+
console.log(chalk26.dim(` ${task.title} \u2192 waits for ${parentId}`));
|
|
11399
10998
|
} catch (error) {
|
|
11400
|
-
console.error(
|
|
10999
|
+
console.error(chalk26.red(`\u274C ${error instanceof Error ? error.message : String(error)}`));
|
|
11401
11000
|
process.exit(1);
|
|
11402
11001
|
}
|
|
11403
11002
|
});
|
|
@@ -11405,27 +11004,27 @@ function createTaskDepCommand() {
|
|
|
11405
11004
|
|
|
11406
11005
|
// src/commands/tasks/sync.ts
|
|
11407
11006
|
import { Command as Command54 } from "commander";
|
|
11408
|
-
import
|
|
11007
|
+
import chalk27 from "chalk";
|
|
11409
11008
|
function createTaskSyncCommand() {
|
|
11410
11009
|
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
11010
|
const service = new TaskService();
|
|
11412
11011
|
if (options.pull) {
|
|
11413
|
-
console.log(
|
|
11012
|
+
console.log(chalk27.dim("\u23F3 Pulling tasks from origin/main..."));
|
|
11414
11013
|
try {
|
|
11415
11014
|
const result = await service.syncPull();
|
|
11416
|
-
console.log(
|
|
11015
|
+
console.log(chalk27.green(`\u2705 Sync pull complete: ${result.merged} tasks merged`));
|
|
11417
11016
|
} catch (error) {
|
|
11418
|
-
console.error(
|
|
11017
|
+
console.error(chalk27.red(`\u274C ${error instanceof Error ? error.message : String(error)}`));
|
|
11419
11018
|
process.exit(1);
|
|
11420
11019
|
}
|
|
11421
11020
|
return;
|
|
11422
11021
|
}
|
|
11423
|
-
console.log(
|
|
11022
|
+
console.log(chalk27.dim("\u23F3 Syncing tasks to git..."));
|
|
11424
11023
|
try {
|
|
11425
11024
|
await service.syncPush();
|
|
11426
|
-
console.log(
|
|
11025
|
+
console.log(chalk27.green("\u2705 Tasks synced to git"));
|
|
11427
11026
|
} catch (error) {
|
|
11428
|
-
console.error(
|
|
11027
|
+
console.error(chalk27.red(`\u274C ${error instanceof Error ? error.message : String(error)}`));
|
|
11429
11028
|
process.exit(1);
|
|
11430
11029
|
}
|
|
11431
11030
|
});
|
|
@@ -11433,107 +11032,107 @@ function createTaskSyncCommand() {
|
|
|
11433
11032
|
|
|
11434
11033
|
// src/commands/tasks/guide.ts
|
|
11435
11034
|
import { Command as Command55 } from "commander";
|
|
11436
|
-
import
|
|
11035
|
+
import chalk28 from "chalk";
|
|
11437
11036
|
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. ${
|
|
11037
|
+
${chalk28.cyan.bold("\u{1F4D6} Jai1 Task Management Guide")}
|
|
11038
|
+
|
|
11039
|
+
${chalk28.bold("\u2501\u2501\u2501 STATUSES \u2501\u2501\u2501")}
|
|
11040
|
+
${chalk28.dim("todo")} \u{1F4CB} Ch\u01B0a b\u1EAFt \u0111\u1EA7u
|
|
11041
|
+
${chalk28.dim("in_progress")} \u{1F535} \u0110ang l\xE0m (bao g\u1ED3m review)
|
|
11042
|
+
${chalk28.dim("done")} \u2705 Ho\xE0n th\xE0nh
|
|
11043
|
+
${chalk28.dim("cancelled")} \u26AB Hu\u1EF7
|
|
11044
|
+
${chalk28.dim("(blocked)")} \u{1F534} Computed: depends_on ch\u01B0a done
|
|
11045
|
+
|
|
11046
|
+
${chalk28.bold("\u2501\u2501\u2501 PRIORITY \u2501\u2501\u2501")}
|
|
11047
|
+
${chalk28.dim("0")} = \u{1F525} Critical \u2014 Prod down, security, block c\u1EA3 team
|
|
11048
|
+
${chalk28.dim("1")} = \u{1F534} High \u2014 Feature ch\xEDnh, deadline g\u1EA7n
|
|
11049
|
+
${chalk28.dim("2")} = \u{1F7E1} Medium \u2014 B\xECnh th\u01B0\u1EDDng (default)
|
|
11050
|
+
${chalk28.dim("3")} = \u{1F7E2} Low \u2014 Nice-to-have, docs, refactor
|
|
11051
|
+
|
|
11052
|
+
${chalk28.bold("\u2501\u2501\u2501 QUICK START \u2501\u2501\u2501")}
|
|
11053
|
+
${chalk28.cyan("jai1 t add")} "Fix login bug" -p 1 -P bug/login
|
|
11054
|
+
${chalk28.cyan("jai1 t ready")} Show tasks s\u1EB5n s\xE0ng
|
|
11055
|
+
${chalk28.cyan("jai1 t pick")} Claim & start working
|
|
11056
|
+
${chalk28.cyan("jai1 t done")} T-003 Mark complete
|
|
11057
|
+
|
|
11058
|
+
${chalk28.bold("\u2501\u2501\u2501 DAILY WORKFLOW \u2501\u2501\u2501")}
|
|
11059
|
+
${chalk28.cyan("jai1 t sync --pull")} Pull latest tasks
|
|
11060
|
+
${chalk28.cyan("jai1 t summary")} Dashboard t\u1ED5ng quan
|
|
11061
|
+
${chalk28.cyan("jai1 t ready")} Xem tasks s\u1EB5n s\xE0ng
|
|
11062
|
+
${chalk28.cyan("jai1 t pick")} Claim task m\u1EDBi
|
|
11063
|
+
${chalk28.cyan("jai1 t done")} T-xxx Ho\xE0n th\xE0nh task
|
|
11064
|
+
${chalk28.cyan("jai1 t sync --push")} Push l\xEAn git
|
|
11065
|
+
|
|
11066
|
+
${chalk28.bold("\u2501\u2501\u2501 ADDING TASKS \u2501\u2501\u2501")}
|
|
11067
|
+
${chalk28.yellow("\u26A0 Lu\xF4n ki\u1EC3m tra duplicate tr\u01B0\u1EDBc khi add:")}
|
|
11068
|
+
${chalk28.cyan("jai1 t list -P")} feature/xxx
|
|
11069
|
+
|
|
11070
|
+
${chalk28.dim("Add cho feature:")}
|
|
11071
|
+
${chalk28.cyan("jai1 t add")} "Setup DB schema" -p 1 -P feature/xxx
|
|
11072
|
+
${chalk28.cyan("jai1 t add")} "Create API" -p 1 -P feature/xxx
|
|
11073
|
+
${chalk28.cyan("jai1 t add")} "Build UI" -p 2 -P feature/xxx
|
|
11074
|
+
|
|
11075
|
+
${chalk28.dim("Add cho plan:")}
|
|
11076
|
+
${chalk28.cyan("jai1 t add")} "Refactor middleware" -p 2 -P plan/xxx
|
|
11077
|
+
|
|
11078
|
+
${chalk28.dim("Add standalone:")}
|
|
11079
|
+
${chalk28.cyan("jai1 t add")} "Fix README typo" -p 3
|
|
11080
|
+
|
|
11081
|
+
${chalk28.dim("Add bug fix:")}
|
|
11082
|
+
${chalk28.cyan("jai1 t add")} "Fix login redirect" -p 1 -P bug/xxx
|
|
11083
|
+
|
|
11084
|
+
${chalk28.bold("\u2501\u2501\u2501 DEPENDENCY \u2501\u2501\u2501")}
|
|
11085
|
+
${chalk28.dim("Task dependency:")}
|
|
11086
|
+
${chalk28.cyan("jai1 t dep")} T-002 T-001 T-002 ch\u1EDD T-001 done
|
|
11087
|
+
${chalk28.cyan("jai1 t dep")} T-003 T-002 T-003 ch\u1EDD T-002 done
|
|
11088
|
+
|
|
11089
|
+
${chalk28.dim("Feature-level dependency:")}
|
|
11090
|
+
${chalk28.dim("# N\u1EBFu feature/auth ph\u1EE5 thu\u1ED9c feature/user-model:")}
|
|
11091
|
+
${chalk28.cyan("jai1 t add")} "[DEP] Wait for feature/user-model" -p 1 -P feature/auth
|
|
11092
|
+
${chalk28.dim("# R\u1ED3i dep n\xF3 v\u1EDBi tasks cu\u1ED1i c\u1EE7a user-model")}
|
|
11093
|
+
|
|
11094
|
+
${chalk28.dim("View deps:")}
|
|
11095
|
+
${chalk28.cyan("jai1 t show")} T-002 Hi\u1EC7n depends_on
|
|
11096
|
+
|
|
11097
|
+
${chalk28.bold("\u2501\u2501\u2501 TEAM COLLABORATION \u2501\u2501\u2501")}
|
|
11098
|
+
${chalk28.yellow("\u26A0 Assignment ch\u1EC9 qua pick \u2014 kh\xF4ng set th\u1EE7 c\xF4ng.")}
|
|
11099
|
+
${chalk28.dim("Khi b\u1EA1n pick \u2192 team th\u1EA5y task \u0111\xE3 c\xF3 ng\u01B0\u1EDDi nh\u1EADn.")}
|
|
11100
|
+
|
|
11101
|
+
${chalk28.dim("Sync morning:")} ${chalk28.cyan("jai1 t sync --pull")}
|
|
11102
|
+
${chalk28.dim("Sync evening:")} ${chalk28.cyan("jai1 t sync --push")}
|
|
11103
|
+
|
|
11104
|
+
${chalk28.bold("\u2501\u2501\u2501 FOR AI AGENTS (Workflow Integration) \u2501\u2501\u2501")}
|
|
11105
|
+
${chalk28.dim("Khi t\u1EA1o tasks t\u1EEB feature/plan:")}
|
|
11106
|
+
1. ${chalk28.cyan("jai1 t list -P")} <parent> Check existing (tr\xE1nh duplicate)
|
|
11107
|
+
2. ${chalk28.cyan("jai1 t add")} "..." -p <0-3> -P <parent> Add t\u1EEBng task
|
|
11108
|
+
3. ${chalk28.cyan("jai1 t dep")} <child> <parent> Set dependencies
|
|
11109
|
+
4. ${chalk28.cyan("jai1 t done")} <id> Mark complete
|
|
11110
|
+
|
|
11111
|
+
${chalk28.dim("Khi implement task ti\u1EBFp theo:")}
|
|
11112
|
+
1. ${chalk28.cyan("jai1 t pick")} (ho\u1EB7c ${chalk28.cyan("jai1 t ready -P")} <parent>)
|
|
11514
11113
|
2. Implement task
|
|
11515
|
-
3. ${
|
|
11114
|
+
3. ${chalk28.cyan("jai1 t done")} <id>
|
|
11516
11115
|
|
|
11517
|
-
${
|
|
11116
|
+
${chalk28.dim("Status transitions:")}
|
|
11518
11117
|
add \u2192 todo (default)
|
|
11519
11118
|
pick \u2192 in_progress (auto assign)
|
|
11520
11119
|
done \u2192 done
|
|
11521
11120
|
update -s \u2192 any valid status
|
|
11522
11121
|
|
|
11523
|
-
${
|
|
11524
|
-
${
|
|
11525
|
-
${
|
|
11526
|
-
${
|
|
11527
|
-
${
|
|
11528
|
-
${
|
|
11529
|
-
${
|
|
11530
|
-
${
|
|
11531
|
-
${
|
|
11532
|
-
${
|
|
11533
|
-
${
|
|
11534
|
-
${
|
|
11535
|
-
|
|
11536
|
-
${
|
|
11122
|
+
${chalk28.bold("\u2501\u2501\u2501 ALL COMMANDS \u2501\u2501\u2501")}
|
|
11123
|
+
${chalk28.cyan("jai1 t list")} [-s status] [-P parent] [-j]
|
|
11124
|
+
${chalk28.cyan("jai1 t ready")} [-P parent] [-j]
|
|
11125
|
+
${chalk28.cyan("jai1 t add")} <title> [-p 0-3] [-P parent] [-t tags] [-j]
|
|
11126
|
+
${chalk28.cyan("jai1 t update")} <id> -s <status> [-j]
|
|
11127
|
+
${chalk28.cyan("jai1 t show")} <id|parent> [-j]
|
|
11128
|
+
${chalk28.cyan("jai1 t pick")} [-j]
|
|
11129
|
+
${chalk28.cyan("jai1 t done")} <id> [-j]
|
|
11130
|
+
${chalk28.cyan("jai1 t dep")} <childId> <parentId> [-j]
|
|
11131
|
+
${chalk28.cyan("jai1 t sync")} [--pull] [--push]
|
|
11132
|
+
${chalk28.cyan("jai1 t summary")} [-j]
|
|
11133
|
+
${chalk28.cyan("jai1 t guide")}
|
|
11134
|
+
|
|
11135
|
+
${chalk28.dim("-j / --json available on all commands (except guide, sync)")}
|
|
11537
11136
|
`;
|
|
11538
11137
|
function createTaskGuideCommand() {
|
|
11539
11138
|
return new Command55("guide").description("Show full task management guide").action(() => {
|
|
@@ -11568,11 +11167,11 @@ function createTasksCommand() {
|
|
|
11568
11167
|
|
|
11569
11168
|
// src/commands/kit/index.ts
|
|
11570
11169
|
import { Command as Command60 } from "commander";
|
|
11571
|
-
import
|
|
11170
|
+
import chalk30 from "chalk";
|
|
11572
11171
|
|
|
11573
11172
|
// src/commands/kit/list.ts
|
|
11574
11173
|
import { Command as Command57 } from "commander";
|
|
11575
|
-
import
|
|
11174
|
+
import chalk29 from "chalk";
|
|
11576
11175
|
import Table6 from "cli-table3";
|
|
11577
11176
|
|
|
11578
11177
|
// src/services/starter-kit.service.ts
|
|
@@ -11646,7 +11245,7 @@ function createKitListCommand() {
|
|
|
11646
11245
|
if (!config) {
|
|
11647
11246
|
throw new ValidationError('Not initialized. Run "jai1 auth" first.');
|
|
11648
11247
|
}
|
|
11649
|
-
console.log(
|
|
11248
|
+
console.log(chalk29.cyan("\u{1F4E6} \u0110ang t\u1EA3i danh s\xE1ch starter kits..."));
|
|
11650
11249
|
console.log();
|
|
11651
11250
|
const kitService = new StarterKitService();
|
|
11652
11251
|
const kits = await kitService.list(config, {
|
|
@@ -11654,9 +11253,9 @@ function createKitListCommand() {
|
|
|
11654
11253
|
search: options.search
|
|
11655
11254
|
});
|
|
11656
11255
|
if (kits.length === 0) {
|
|
11657
|
-
console.log(
|
|
11256
|
+
console.log(chalk29.yellow("Kh\xF4ng t\xECm th\u1EA5y starter kits n\xE0o."));
|
|
11658
11257
|
if (options.category || options.search) {
|
|
11659
|
-
console.log(
|
|
11258
|
+
console.log(chalk29.dim("Th\u1EED b\u1ECF filter \u0111\u1EC3 xem t\u1EA5t c\u1EA3."));
|
|
11660
11259
|
}
|
|
11661
11260
|
return;
|
|
11662
11261
|
}
|
|
@@ -11680,28 +11279,28 @@ function createKitListCommand() {
|
|
|
11680
11279
|
const categoryKits = byCategory[category];
|
|
11681
11280
|
const categoryIcon = category === "frontend" ? "\u{1F3A8}" : category === "backend" ? "\u2699\uFE0F" : category === "fullstack" ? "\u{1F680}" : "\u{1F4E6}";
|
|
11682
11281
|
console.log(
|
|
11683
|
-
|
|
11282
|
+
chalk29.bold(`${categoryIcon} ${category.charAt(0).toUpperCase() + category.slice(1)}`)
|
|
11684
11283
|
);
|
|
11685
11284
|
const table = new Table6({
|
|
11686
11285
|
head: [
|
|
11687
|
-
|
|
11688
|
-
|
|
11689
|
-
|
|
11286
|
+
chalk29.cyan("Slug"),
|
|
11287
|
+
chalk29.cyan("M\xF4 t\u1EA3"),
|
|
11288
|
+
chalk29.cyan("Version")
|
|
11690
11289
|
],
|
|
11691
11290
|
style: { head: [], border: ["gray"] }
|
|
11692
11291
|
});
|
|
11693
11292
|
for (const kit of categoryKits) {
|
|
11694
11293
|
table.push([
|
|
11695
|
-
|
|
11696
|
-
|
|
11697
|
-
|
|
11294
|
+
chalk29.white(kit.slug),
|
|
11295
|
+
chalk29.dim(kit.description.slice(0, 50)),
|
|
11296
|
+
chalk29.green(`v${kit.version}`)
|
|
11698
11297
|
]);
|
|
11699
11298
|
}
|
|
11700
11299
|
console.log(table.toString());
|
|
11701
11300
|
console.log();
|
|
11702
11301
|
}
|
|
11703
|
-
console.log(
|
|
11704
|
-
console.log(
|
|
11302
|
+
console.log(chalk29.dim(`T\u1ED5ng c\u1ED9ng: ${kits.length} starter kit(s)`));
|
|
11303
|
+
console.log(chalk29.dim('\n\u{1F4A1} Ch\u1EA1y "jai1 kit create <slug>" \u0111\u1EC3 t\u1EA1o project m\u1EDBi'));
|
|
11705
11304
|
});
|
|
11706
11305
|
}
|
|
11707
11306
|
|
|
@@ -11981,20 +11580,20 @@ async function getAllFiles(dir) {
|
|
|
11981
11580
|
|
|
11982
11581
|
// src/commands/kit/index.ts
|
|
11983
11582
|
function showKitHelp() {
|
|
11984
|
-
console.log(
|
|
11583
|
+
console.log(chalk30.bold.cyan("\u{1F4E6} jai1 kit") + chalk30.dim(" - Qu\u1EA3n l\xFD starter kits"));
|
|
11985
11584
|
console.log();
|
|
11986
|
-
console.log(
|
|
11987
|
-
console.log(` ${
|
|
11988
|
-
console.log(` ${
|
|
11989
|
-
console.log(` ${
|
|
11585
|
+
console.log(chalk30.bold("C\xE1c l\u1EC7nh:"));
|
|
11586
|
+
console.log(` ${chalk30.cyan("list")} Li\u1EC7t k\xEA c\xE1c starter kits c\xF3 s\u1EB5n`);
|
|
11587
|
+
console.log(` ${chalk30.cyan("info")} Xem chi ti\u1EBFt m\u1ED9t starter kit`);
|
|
11588
|
+
console.log(` ${chalk30.cyan("create")} T\u1EA1o project m\u1EDBi t\u1EEB starter kit`);
|
|
11990
11589
|
console.log();
|
|
11991
|
-
console.log(
|
|
11992
|
-
console.log(
|
|
11993
|
-
console.log(
|
|
11994
|
-
console.log(
|
|
11995
|
-
console.log(
|
|
11590
|
+
console.log(chalk30.bold("V\xED d\u1EE5:"));
|
|
11591
|
+
console.log(chalk30.dim(" $ jai1 kit list"));
|
|
11592
|
+
console.log(chalk30.dim(" $ jai1 kit list --category frontend"));
|
|
11593
|
+
console.log(chalk30.dim(" $ jai1 kit info next-tw4-shadcn"));
|
|
11594
|
+
console.log(chalk30.dim(" $ jai1 kit create next-tw4-shadcn my-project"));
|
|
11996
11595
|
console.log();
|
|
11997
|
-
console.log(
|
|
11596
|
+
console.log(chalk30.dim('Ch\u1EA1y "jai1 kit <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt'));
|
|
11998
11597
|
}
|
|
11999
11598
|
function createKitCommand() {
|
|
12000
11599
|
const cmd = new Command60("kit").description("Manage starter kits for new projects").action(() => {
|
|
@@ -12008,11 +11607,11 @@ function createKitCommand() {
|
|
|
12008
11607
|
|
|
12009
11608
|
// src/commands/rules/index.ts
|
|
12010
11609
|
import { Command as Command67 } from "commander";
|
|
12011
|
-
import
|
|
11610
|
+
import chalk32 from "chalk";
|
|
12012
11611
|
|
|
12013
11612
|
// src/commands/rules/list.ts
|
|
12014
11613
|
import { Command as Command61 } from "commander";
|
|
12015
|
-
import
|
|
11614
|
+
import chalk31 from "chalk";
|
|
12016
11615
|
import Table7 from "cli-table3";
|
|
12017
11616
|
function createRulesListCommand() {
|
|
12018
11617
|
return new Command61("list").description("List available rule presets").option("--json", "Output as JSON").action(async (options) => {
|
|
@@ -12021,7 +11620,7 @@ function createRulesListCommand() {
|
|
|
12021
11620
|
if (!config) {
|
|
12022
11621
|
throw new ValidationError('Not initialized. Run "jai1 auth" first.');
|
|
12023
11622
|
}
|
|
12024
|
-
console.log(
|
|
11623
|
+
console.log(chalk31.cyan("\u{1F4CB} \u0110ang t\u1EA3i danh s\xE1ch rule presets..."));
|
|
12025
11624
|
console.log();
|
|
12026
11625
|
try {
|
|
12027
11626
|
const response = await fetch(`${config.apiUrl}/api/rules/presets`, {
|
|
@@ -12038,23 +11637,23 @@ function createRulesListCommand() {
|
|
|
12038
11637
|
return;
|
|
12039
11638
|
}
|
|
12040
11639
|
if (data.total === 0) {
|
|
12041
|
-
console.log(
|
|
11640
|
+
console.log(chalk31.yellow("Kh\xF4ng c\xF3 presets n\xE0o."));
|
|
12042
11641
|
return;
|
|
12043
11642
|
}
|
|
12044
11643
|
console.log(
|
|
12045
|
-
|
|
11644
|
+
chalk31.green(`\u2713 T\xECm th\u1EA5y ${chalk31.bold(data.total)} preset${data.total > 1 ? "s" : ""}`)
|
|
12046
11645
|
);
|
|
12047
11646
|
console.log();
|
|
12048
11647
|
for (const preset of data.presets) {
|
|
12049
|
-
console.log(
|
|
11648
|
+
console.log(chalk31.bold.cyan(`\u{1F4E6} ${preset.slug}`));
|
|
12050
11649
|
const table = new Table7({
|
|
12051
11650
|
style: { head: [], border: ["gray"], compact: true },
|
|
12052
11651
|
colWidths: [15, 55]
|
|
12053
11652
|
});
|
|
12054
11653
|
table.push(
|
|
12055
|
-
[
|
|
12056
|
-
[
|
|
12057
|
-
[
|
|
11654
|
+
[chalk31.dim("T\xEAn"), chalk31.white(preset.name)],
|
|
11655
|
+
[chalk31.dim("M\xF4 t\u1EA3"), chalk31.white(preset.description)],
|
|
11656
|
+
[chalk31.dim("Version"), chalk31.green(`v${preset.version}`)]
|
|
12058
11657
|
);
|
|
12059
11658
|
const stackParts = [];
|
|
12060
11659
|
if (preset.stack.frontend) stackParts.push(preset.stack.frontend);
|
|
@@ -12062,16 +11661,16 @@ function createRulesListCommand() {
|
|
|
12062
11661
|
if (preset.stack.css) stackParts.push(preset.stack.css);
|
|
12063
11662
|
if (preset.stack.database) stackParts.push(preset.stack.database);
|
|
12064
11663
|
if (stackParts.length > 0) {
|
|
12065
|
-
table.push([
|
|
11664
|
+
table.push([chalk31.dim("Stack"), chalk31.yellow(stackParts.join(" + "))]);
|
|
12066
11665
|
}
|
|
12067
11666
|
table.push(
|
|
12068
|
-
[
|
|
12069
|
-
[
|
|
11667
|
+
[chalk31.dim("Tags"), chalk31.dim(preset.tags.join(", ") || "-")],
|
|
11668
|
+
[chalk31.dim("Downloads"), chalk31.white(preset.downloads.toString())]
|
|
12070
11669
|
);
|
|
12071
11670
|
console.log(table.toString());
|
|
12072
11671
|
console.log();
|
|
12073
11672
|
}
|
|
12074
|
-
console.log(
|
|
11673
|
+
console.log(chalk31.dim('\u{1F4A1} Ch\u1EA1y "jai1 rules apply <name>" \u0111\u1EC3 \xE1p d\u1EE5ng preset'));
|
|
12075
11674
|
} catch (error) {
|
|
12076
11675
|
throw new Error(
|
|
12077
11676
|
`L\u1ED7i khi t\u1EA3i presets: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -13499,23 +13098,23 @@ async function checkIdeFilesExist(ideId, format) {
|
|
|
13499
13098
|
|
|
13500
13099
|
// src/commands/rules/index.ts
|
|
13501
13100
|
function showRulesHelp() {
|
|
13502
|
-
console.log(
|
|
13101
|
+
console.log(chalk32.bold.cyan("\u{1F4CB} jai1 rules") + chalk32.dim(" - Qu\u1EA3n l\xFD rule presets cho AI agents"));
|
|
13503
13102
|
console.log();
|
|
13504
|
-
console.log(
|
|
13505
|
-
console.log(` ${
|
|
13506
|
-
console.log(` ${
|
|
13507
|
-
console.log(` ${
|
|
13508
|
-
console.log(` ${
|
|
13509
|
-
console.log(` ${
|
|
13510
|
-
console.log(` ${
|
|
13103
|
+
console.log(chalk32.bold("C\xE1c l\u1EC7nh:"));
|
|
13104
|
+
console.log(` ${chalk32.cyan("list")} Li\u1EC7t k\xEA c\xE1c presets c\xF3 s\u1EB5n`);
|
|
13105
|
+
console.log(` ${chalk32.cyan("info")} Xem chi ti\u1EBFt m\u1ED9t preset`);
|
|
13106
|
+
console.log(` ${chalk32.cyan("init")} Kh\u1EDFi t\u1EA1o rules t\u1EEB preset`);
|
|
13107
|
+
console.log(` ${chalk32.cyan("apply")} \xC1p d\u1EE5ng preset v\xE0o project`);
|
|
13108
|
+
console.log(` ${chalk32.cyan("sync")} \u0110\u1ED3ng b\u1ED9 rules sang c\xE1c \u0111\u1ECBnh d\u1EA1ng IDE`);
|
|
13109
|
+
console.log(` ${chalk32.cyan("restore")} Kh\xF4i ph\u1EE5c rules t\u1EEB backup`);
|
|
13511
13110
|
console.log();
|
|
13512
|
-
console.log(
|
|
13513
|
-
console.log(
|
|
13514
|
-
console.log(
|
|
13515
|
-
console.log(
|
|
13516
|
-
console.log(
|
|
13111
|
+
console.log(chalk32.bold("V\xED d\u1EE5:"));
|
|
13112
|
+
console.log(chalk32.dim(" $ jai1 rules list"));
|
|
13113
|
+
console.log(chalk32.dim(" $ jai1 rules info react-typescript"));
|
|
13114
|
+
console.log(chalk32.dim(" $ jai1 rules init --preset=react-typescript"));
|
|
13115
|
+
console.log(chalk32.dim(" $ jai1 rules apply react-typescript"));
|
|
13517
13116
|
console.log();
|
|
13518
|
-
console.log(
|
|
13117
|
+
console.log(chalk32.dim('Ch\u1EA1y "jai1 rules <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt'));
|
|
13519
13118
|
}
|
|
13520
13119
|
function createRulesCommand() {
|
|
13521
13120
|
const rulesCommand = new Command67("rules").description("Manage rule presets for AI agents").action(() => {
|
|
@@ -15248,92 +14847,11 @@ async function resetSettings2(groupKeys) {
|
|
|
15248
14847
|
console.log("\u{1F4A1} M\u1EB9o: Kh\u1EDFi \u0111\u1ED9ng l\u1EA1i VSCode \u0111\u1EC3 \xE1p d\u1EE5ng c\xE1c thay \u0111\u1ED5i.");
|
|
15249
14848
|
}
|
|
15250
14849
|
|
|
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
14850
|
// src/commands/migrate-ide.ts
|
|
15333
|
-
import { Command as
|
|
14851
|
+
import { Command as Command77 } from "commander";
|
|
15334
14852
|
import { checkbox as checkbox8, confirm as confirm19 } from "@inquirer/prompts";
|
|
15335
14853
|
function createMigrateIdeCommand() {
|
|
15336
|
-
const cmd = new
|
|
14854
|
+
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
14855
|
await runMigrateIde(options);
|
|
15338
14856
|
});
|
|
15339
14857
|
return cmd;
|
|
@@ -15442,62 +14960,62 @@ async function runMigrateIde(options) {
|
|
|
15442
14960
|
|
|
15443
14961
|
// src/utils/help-formatter.ts
|
|
15444
14962
|
import boxen4 from "boxen";
|
|
15445
|
-
import
|
|
14963
|
+
import chalk33 from "chalk";
|
|
15446
14964
|
import gradient from "gradient-string";
|
|
15447
14965
|
import figlet from "figlet";
|
|
15448
14966
|
function showCustomHelp(version) {
|
|
15449
14967
|
const title = figlet.textSync("JAI1", { font: "Small" });
|
|
15450
14968
|
console.log(gradient.pastel(title));
|
|
15451
14969
|
console.log(
|
|
15452
|
-
boxen4(
|
|
14970
|
+
boxen4(chalk33.cyan(`Agentic Coding CLI v${version}`), {
|
|
15453
14971
|
padding: { left: 1, right: 1, top: 0, bottom: 0 },
|
|
15454
14972
|
borderStyle: "round",
|
|
15455
14973
|
borderColor: "cyan"
|
|
15456
14974
|
})
|
|
15457
14975
|
);
|
|
15458
|
-
console.log(
|
|
14976
|
+
console.log(chalk33.bold("\n\u{1F527} Thi\u1EBFt l\u1EADp & Th\xF4ng tin"));
|
|
15459
14977
|
console.log(" auth X\xE1c th\u1EF1c v\xE0 c\u1EA5u h\xECnh client");
|
|
15460
14978
|
console.log(" status Hi\u1EC3n th\u1ECB tr\u1EA1ng th\xE1i c\u1EA5u h\xECnh");
|
|
15461
14979
|
console.log(" client-info T\u1EA1o th\xF4ng tin client \u0111\u1EC3 g\u1EEDi \u0111\u1ED9i ph\xE1t tri\u1EC3n");
|
|
15462
14980
|
console.log(" errors Qu\u1EA3n l\xFD error logs c\u1EE5c b\u1ED9");
|
|
15463
14981
|
console.log(" guide H\u01B0\u1EDBng d\u1EABn s\u1EED d\u1EE5ng nhanh");
|
|
15464
14982
|
console.log(" doctor Chu\u1EA9n \u0111o\xE1n project hi\u1EC7n t\u1EA1i");
|
|
15465
|
-
console.log(
|
|
14983
|
+
console.log(chalk33.bold("\n\u{1F4E6} Qu\u1EA3n l\xFD Components"));
|
|
15466
14984
|
console.log(" apply C\xE0i \u0111\u1EB7t components (interactive)");
|
|
15467
14985
|
console.log(" update C\u1EADp nh\u1EADt components \u0111\xE3 c\xE0i");
|
|
15468
14986
|
console.log(" check Ki\u1EC3m tra c\u1EADp nh\u1EADt t\u1EEB server");
|
|
15469
|
-
console.log(
|
|
14987
|
+
console.log(chalk33.bold("\n\u{1F5A5}\uFE0F IDE & T\xEDch h\u1EE3p"));
|
|
15470
14988
|
console.log(" ide L\u1EC7nh c\u1EA5u h\xECnh IDE");
|
|
15471
14989
|
console.log(" chat Chat AI v\u1EDBi Jai1 LLM Proxy");
|
|
15472
14990
|
console.log(" openai-keys Th\xF4ng tin API credentials");
|
|
15473
|
-
console.log(
|
|
14991
|
+
console.log(chalk33.bold("\n\u{1F916} AI Tools"));
|
|
15474
14992
|
console.log(" translate D\u1ECBch v\u0103n b\u1EA3n/file b\u1EB1ng AI");
|
|
15475
14993
|
console.log(" image T\u1EA1o \u1EA3nh (Coming Soon)");
|
|
15476
14994
|
console.log(" stats Th\u1ED1ng k\xEA s\u1EED d\u1EE5ng LLM");
|
|
15477
14995
|
console.log(" feedback G\u1EEDi b\xE1o c\xE1o/\u0111\u1EC1 xu\u1EA5t");
|
|
15478
|
-
console.log(
|
|
14996
|
+
console.log(chalk33.bold("\n\u{1F4C1} Project"));
|
|
15479
14997
|
console.log(" kit Qu\u1EA3n l\xFD starter kits");
|
|
15480
14998
|
console.log(" rules Qu\u1EA3n l\xFD rule presets");
|
|
15481
14999
|
console.log(" deps Qu\u1EA3n l\xFD dependencies");
|
|
15482
15000
|
console.log(" redmine Redmine context sync");
|
|
15483
|
-
console.log(
|
|
15001
|
+
console.log(chalk33.bold("\n\u2699\uFE0F B\u1EA3o tr\xEC"));
|
|
15484
15002
|
console.log(" upgrade C\u1EADp nh\u1EADt CLI client");
|
|
15485
15003
|
console.log(" clean D\u1ECDn d\u1EB9p cache/backup");
|
|
15486
15004
|
console.log(" utils Developer utilities");
|
|
15487
15005
|
const name = getCliName();
|
|
15488
|
-
console.log(
|
|
15006
|
+
console.log(chalk33.dim(`
|
|
15489
15007
|
S\u1EED d\u1EE5ng: ${name} [l\u1EC7nh] --help \u0111\u1EC3 xem chi ti\u1EBFt`));
|
|
15490
15008
|
}
|
|
15491
15009
|
function showUnknownCommand(commandName) {
|
|
15492
|
-
console.error(
|
|
15010
|
+
console.error(chalk33.red(`\u274C L\u1EC7nh kh\xF4ng t\u1ED3n t\u1EA1i: ${commandName}`));
|
|
15493
15011
|
const name = getCliName();
|
|
15494
|
-
console.error(
|
|
15012
|
+
console.error(chalk33.dim(`
|
|
15495
15013
|
G\u1EE3i \xFD: Ch\u1EA1y ${name} --help \u0111\u1EC3 xem danh s\xE1ch l\u1EC7nh`));
|
|
15496
15014
|
}
|
|
15497
15015
|
|
|
15498
15016
|
// src/cli.ts
|
|
15499
15017
|
checkNodeVersion();
|
|
15500
|
-
var program = new
|
|
15018
|
+
var program = new Command78();
|
|
15501
15019
|
if (process.argv.includes("-v") || process.argv.includes("--version")) {
|
|
15502
15020
|
console.log(package_default.version);
|
|
15503
15021
|
if (!process.argv.includes("--skip-update-check")) {
|
|
@@ -15536,9 +15054,9 @@ program.addCommand(createKitCommand());
|
|
|
15536
15054
|
program.addCommand(createRulesCommand());
|
|
15537
15055
|
program.addCommand(createUpgradeCommand());
|
|
15538
15056
|
program.addCommand(createCleanCommand());
|
|
15539
|
-
var redmineCommand = new
|
|
15057
|
+
var redmineCommand = new Command78("redmine").description("Redmine context sync commands");
|
|
15540
15058
|
redmineCommand.addCommand(createRedmineCheckCommand());
|
|
15541
|
-
var syncCommand = new
|
|
15059
|
+
var syncCommand = new Command78("sync").description("Sync Redmine issues to markdown files");
|
|
15542
15060
|
syncCommand.addCommand(createSyncIssueCommand());
|
|
15543
15061
|
syncCommand.addCommand(createSyncProjectCommand());
|
|
15544
15062
|
redmineCommand.addCommand(syncCommand);
|