@jvittechs/j 1.0.13 → 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 +925 -1395
- 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,54 +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(` ${
|
|
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`);
|
|
4425
4026
|
console.log();
|
|
4426
|
-
console.log(
|
|
4427
|
-
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"));
|
|
4031
|
+
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`);
|
|
4036
|
+
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.`));
|
|
4428
4039
|
console.log();
|
|
4429
4040
|
}
|
|
4430
4041
|
|
|
4431
4042
|
// src/commands/doctor.ts
|
|
4432
4043
|
import { Command as Command13 } from "commander";
|
|
4433
|
-
import
|
|
4044
|
+
import chalk9 from "chalk";
|
|
4434
4045
|
import { promises as fs9 } from "fs";
|
|
4435
4046
|
import { join as join6 } from "path";
|
|
4436
4047
|
var CORE_FILES = [
|
|
@@ -4458,8 +4069,8 @@ async function runDoctor(options) {
|
|
|
4458
4069
|
const name = getCliName();
|
|
4459
4070
|
const results = [];
|
|
4460
4071
|
if (!options.json) {
|
|
4461
|
-
console.log(
|
|
4462
|
-
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()}
|
|
4463
4074
|
`));
|
|
4464
4075
|
}
|
|
4465
4076
|
results.push(await checkAuth(name));
|
|
@@ -4472,27 +4083,27 @@ async function runDoctor(options) {
|
|
|
4472
4083
|
return;
|
|
4473
4084
|
}
|
|
4474
4085
|
for (const result of results) {
|
|
4475
|
-
const icon = result.passed ?
|
|
4476
|
-
const label = result.passed ?
|
|
4477
|
-
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}`);
|
|
4478
4089
|
if (result.details && result.details.length > 0) {
|
|
4479
4090
|
for (const detail of result.details) {
|
|
4480
|
-
console.log(
|
|
4091
|
+
console.log(chalk9.dim(` ${detail}`));
|
|
4481
4092
|
}
|
|
4482
4093
|
}
|
|
4483
4094
|
if (!result.passed && result.suggestion) {
|
|
4484
|
-
console.log(
|
|
4095
|
+
console.log(chalk9.yellow(` \u{1F4A1} ${result.suggestion}`));
|
|
4485
4096
|
}
|
|
4486
4097
|
console.log();
|
|
4487
4098
|
}
|
|
4488
4099
|
const passed = results.filter((r) => r.passed).length;
|
|
4489
4100
|
const total = results.length;
|
|
4490
4101
|
if (passed === total) {
|
|
4491
|
-
console.log(
|
|
4102
|
+
console.log(chalk9.green.bold(` \u2705 T\u1EA5t c\u1EA3 ${total} ki\u1EC3m tra \u0111\xE3 pass!
|
|
4492
4103
|
`));
|
|
4493
4104
|
} else {
|
|
4494
4105
|
console.log(
|
|
4495
|
-
|
|
4106
|
+
chalk9.yellow(` \u26A0\uFE0F ${passed}/${total} ki\u1EC3m tra pass. Xem g\u1EE3i \xFD \u1EDF tr\xEAn \u0111\u1EC3 s\u1EEDa.
|
|
4496
4107
|
`)
|
|
4497
4108
|
);
|
|
4498
4109
|
}
|
|
@@ -4644,8 +4255,8 @@ async function checkIde(cliName) {
|
|
|
4644
4255
|
|
|
4645
4256
|
// src/commands/chat.ts
|
|
4646
4257
|
import { Command as Command14 } from "commander";
|
|
4647
|
-
import
|
|
4648
|
-
import { render as
|
|
4258
|
+
import React12 from "react";
|
|
4259
|
+
import { render as render3 } from "ink";
|
|
4649
4260
|
|
|
4650
4261
|
// src/services/llm-proxy.service.ts
|
|
4651
4262
|
var LlmProxyService = class {
|
|
@@ -4872,16 +4483,16 @@ var LlmProxyService = class {
|
|
|
4872
4483
|
};
|
|
4873
4484
|
|
|
4874
4485
|
// src/ui/llm/LlmApp.tsx
|
|
4875
|
-
import
|
|
4876
|
-
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";
|
|
4877
4488
|
import Spinner4 from "ink-spinner";
|
|
4878
4489
|
|
|
4879
4490
|
// src/ui/llm/hooks/useChat.ts
|
|
4880
|
-
import { useState as
|
|
4491
|
+
import { useState as useState3, useCallback } from "react";
|
|
4881
4492
|
function useChat(service) {
|
|
4882
|
-
const [messages, setMessages] =
|
|
4883
|
-
const [isStreaming, setIsStreaming] =
|
|
4884
|
-
const [error, setError] =
|
|
4493
|
+
const [messages, setMessages] = useState3([]);
|
|
4494
|
+
const [isStreaming, setIsStreaming] = useState3(false);
|
|
4495
|
+
const [error, setError] = useState3(null);
|
|
4885
4496
|
const sendMessage = useCallback(
|
|
4886
4497
|
async (content, model) => {
|
|
4887
4498
|
if (!content.trim() || isStreaming) return;
|
|
@@ -4950,9 +4561,9 @@ function useChat(service) {
|
|
|
4950
4561
|
}
|
|
4951
4562
|
|
|
4952
4563
|
// src/ui/llm/hooks/useLlmApi.ts
|
|
4953
|
-
import { useState as
|
|
4564
|
+
import { useState as useState4, useEffect as useEffect3, useCallback as useCallback2, useRef } from "react";
|
|
4954
4565
|
function useLlmApi(service) {
|
|
4955
|
-
const [state, setState] =
|
|
4566
|
+
const [state, setState] = useState4({
|
|
4956
4567
|
models: [],
|
|
4957
4568
|
limits: null,
|
|
4958
4569
|
usage: null,
|
|
@@ -4985,7 +4596,7 @@ function useLlmApi(service) {
|
|
|
4985
4596
|
}));
|
|
4986
4597
|
}
|
|
4987
4598
|
}, [service]);
|
|
4988
|
-
|
|
4599
|
+
useEffect3(() => {
|
|
4989
4600
|
if (!hasFetched.current) {
|
|
4990
4601
|
hasFetched.current = true;
|
|
4991
4602
|
fetchData(true);
|
|
@@ -5001,26 +4612,26 @@ function useLlmApi(service) {
|
|
|
5001
4612
|
}
|
|
5002
4613
|
|
|
5003
4614
|
// src/ui/llm/components/ChatPanel.tsx
|
|
5004
|
-
import
|
|
5005
|
-
import { Box as
|
|
4615
|
+
import React9, { memo as memo3 } from "react";
|
|
4616
|
+
import { Box as Box6, Text as Text7 } from "ink";
|
|
5006
4617
|
import Spinner3 from "ink-spinner";
|
|
5007
4618
|
|
|
5008
4619
|
// src/ui/llm/components/MessageItem.tsx
|
|
5009
|
-
import
|
|
5010
|
-
import { Box as
|
|
4620
|
+
import React7, { memo } from "react";
|
|
4621
|
+
import { Box as Box4, Text as Text5 } from "ink";
|
|
5011
4622
|
var MessageItem = memo(({ message }) => {
|
|
5012
4623
|
if (message.role === "user") {
|
|
5013
|
-
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));
|
|
5014
4625
|
}
|
|
5015
4626
|
if (message.role === "assistant") {
|
|
5016
|
-
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));
|
|
5017
4628
|
}
|
|
5018
|
-
return /* @__PURE__ */
|
|
4629
|
+
return /* @__PURE__ */ React7.createElement(Box4, { marginBottom: 1 }, /* @__PURE__ */ React7.createElement(Text5, { dimColor: true, italic: true }, message.content));
|
|
5019
4630
|
});
|
|
5020
4631
|
|
|
5021
4632
|
// src/ui/llm/components/InputBox.tsx
|
|
5022
|
-
import
|
|
5023
|
-
import { Box as
|
|
4633
|
+
import React8, { memo as memo2 } from "react";
|
|
4634
|
+
import { Box as Box5, Text as Text6 } from "ink";
|
|
5024
4635
|
import TextInput3 from "ink-text-input";
|
|
5025
4636
|
var InputBox = memo2(({
|
|
5026
4637
|
value,
|
|
@@ -5028,7 +4639,7 @@ var InputBox = memo2(({
|
|
|
5028
4639
|
onSubmit,
|
|
5029
4640
|
disabled = false,
|
|
5030
4641
|
focused = true
|
|
5031
|
-
}) => /* @__PURE__ */
|
|
4642
|
+
}) => /* @__PURE__ */ React8.createElement(Box5, { borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React8.createElement(Text6, { color: "cyan" }, "\u276F "), !disabled ? /* @__PURE__ */ React8.createElement(
|
|
5032
4643
|
TextInput3,
|
|
5033
4644
|
{
|
|
5034
4645
|
value,
|
|
@@ -5037,19 +4648,19 @@ var InputBox = memo2(({
|
|
|
5037
4648
|
placeholder: "Type your message...",
|
|
5038
4649
|
focus: focused
|
|
5039
4650
|
}
|
|
5040
|
-
) : /* @__PURE__ */
|
|
4651
|
+
) : /* @__PURE__ */ React8.createElement(Text6, { dimColor: true }, "Waiting...")));
|
|
5041
4652
|
|
|
5042
4653
|
// src/ui/llm/components/ChatPanel.tsx
|
|
5043
4654
|
var MessageList = memo3(({ messages }) => {
|
|
5044
4655
|
const visible = messages.slice(-8);
|
|
5045
4656
|
const hidden = messages.length - visible.length;
|
|
5046
4657
|
if (visible.length === 0) {
|
|
5047
|
-
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"));
|
|
5048
4659
|
}
|
|
5049
|
-
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 })));
|
|
5050
4661
|
});
|
|
5051
|
-
var SlashMenu = memo3(({ commands, index }) => /* @__PURE__ */
|
|
5052
|
-
|
|
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,
|
|
5053
4664
|
{
|
|
5054
4665
|
key: cmd.name,
|
|
5055
4666
|
backgroundColor: i === index ? "cyan" : void 0,
|
|
@@ -5074,7 +4685,7 @@ var ChatPanel = ({
|
|
|
5074
4685
|
minHeight = 15
|
|
5075
4686
|
}) => {
|
|
5076
4687
|
const messagesMinHeight = Math.max(5, minHeight - 4 - (showSlashMenu ? 5 : 0));
|
|
5077
|
-
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(
|
|
5078
4689
|
InputBox,
|
|
5079
4690
|
{
|
|
5080
4691
|
value: inputValue,
|
|
@@ -5087,8 +4698,8 @@ var ChatPanel = ({
|
|
|
5087
4698
|
};
|
|
5088
4699
|
|
|
5089
4700
|
// src/ui/llm/components/ModelSelector.tsx
|
|
5090
|
-
import
|
|
5091
|
-
import { Box as
|
|
4701
|
+
import React10, { useState as useState5 } from "react";
|
|
4702
|
+
import { Box as Box7, Text as Text8, useInput as useInput3 } from "ink";
|
|
5092
4703
|
var ModelSelector = ({
|
|
5093
4704
|
models,
|
|
5094
4705
|
currentModel,
|
|
@@ -5097,8 +4708,8 @@ var ModelSelector = ({
|
|
|
5097
4708
|
}) => {
|
|
5098
4709
|
const allowedModels = models.filter((m) => m.allowed);
|
|
5099
4710
|
const currentIndex = allowedModels.findIndex((m) => m.id === currentModel);
|
|
5100
|
-
const [selectedIndex, setSelectedIndex] =
|
|
5101
|
-
|
|
4711
|
+
const [selectedIndex, setSelectedIndex] = useState5(Math.max(0, currentIndex));
|
|
4712
|
+
useInput3((input5, key) => {
|
|
5102
4713
|
if (key.escape) {
|
|
5103
4714
|
onCancel();
|
|
5104
4715
|
return;
|
|
@@ -5115,8 +4726,8 @@ var ModelSelector = ({
|
|
|
5115
4726
|
}
|
|
5116
4727
|
});
|
|
5117
4728
|
if (allowedModels.length === 0) {
|
|
5118
|
-
return /* @__PURE__ */
|
|
5119
|
-
|
|
4729
|
+
return /* @__PURE__ */ React10.createElement(
|
|
4730
|
+
Box7,
|
|
5120
4731
|
{
|
|
5121
4732
|
flexDirection: "column",
|
|
5122
4733
|
borderStyle: "round",
|
|
@@ -5124,12 +4735,12 @@ var ModelSelector = ({
|
|
|
5124
4735
|
padding: 1,
|
|
5125
4736
|
width: 60
|
|
5126
4737
|
},
|
|
5127
|
-
/* @__PURE__ */
|
|
5128
|
-
/* @__PURE__ */
|
|
4738
|
+
/* @__PURE__ */ React10.createElement(Text8, { color: "red", bold: true }, "No models available"),
|
|
4739
|
+
/* @__PURE__ */ React10.createElement(Text8, { dimColor: true }, "Press Esc to close")
|
|
5129
4740
|
);
|
|
5130
4741
|
}
|
|
5131
|
-
return /* @__PURE__ */
|
|
5132
|
-
|
|
4742
|
+
return /* @__PURE__ */ React10.createElement(
|
|
4743
|
+
Box7,
|
|
5133
4744
|
{
|
|
5134
4745
|
flexDirection: "column",
|
|
5135
4746
|
borderStyle: "round",
|
|
@@ -5137,8 +4748,8 @@ var ModelSelector = ({
|
|
|
5137
4748
|
padding: 1,
|
|
5138
4749
|
width: 70
|
|
5139
4750
|
},
|
|
5140
|
-
/* @__PURE__ */
|
|
5141
|
-
/* @__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) => {
|
|
5142
4753
|
const isSelected = i === selectedIndex;
|
|
5143
4754
|
const isCurrent = model.id === currentModel;
|
|
5144
4755
|
const icon = isSelected ? "\u25CF" : "\u25CB";
|
|
@@ -5146,8 +4757,8 @@ var ModelSelector = ({
|
|
|
5146
4757
|
if (model.dailyLimit !== void 0 && model.usedToday !== void 0) {
|
|
5147
4758
|
usageText = ` (${model.usedToday}/${model.dailyLimit})`;
|
|
5148
4759
|
}
|
|
5149
|
-
return /* @__PURE__ */
|
|
5150
|
-
|
|
4760
|
+
return /* @__PURE__ */ React10.createElement(Box7, { key: model.id, marginY: 0 }, /* @__PURE__ */ React10.createElement(
|
|
4761
|
+
Text8,
|
|
5151
4762
|
{
|
|
5152
4763
|
backgroundColor: isSelected ? "cyan" : void 0,
|
|
5153
4764
|
color: isSelected ? "black" : "white"
|
|
@@ -5160,7 +4771,7 @@ var ModelSelector = ({
|
|
|
5160
4771
|
usageText
|
|
5161
4772
|
));
|
|
5162
4773
|
})),
|
|
5163
|
-
/* @__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"))
|
|
5164
4775
|
);
|
|
5165
4776
|
};
|
|
5166
4777
|
|
|
@@ -5171,17 +4782,17 @@ var SLASH_COMMANDS = [
|
|
|
5171
4782
|
{ name: "quit", description: "Exit the chat", aliases: ["q", "exit"] }
|
|
5172
4783
|
];
|
|
5173
4784
|
var ChatApp = ({ service, initialModel }) => {
|
|
5174
|
-
const { exit } =
|
|
4785
|
+
const { exit } = useApp3();
|
|
5175
4786
|
const { stdout } = useStdout();
|
|
5176
4787
|
const contentHeight = useRef2(Math.max(10, (stdout?.rows || 24) - 6));
|
|
5177
|
-
const [currentView, setCurrentView] =
|
|
5178
|
-
const [showSlashMenu, setShowSlashMenu] =
|
|
5179
|
-
const [slashMenuIndex, setSlashMenuIndex] =
|
|
5180
|
-
const [inputValue, setInputValue] =
|
|
5181
|
-
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("");
|
|
5182
4793
|
const { models, loading, error, refetch } = useLlmApi(service);
|
|
5183
4794
|
const { messages, isStreaming, sendMessage } = useChat(service);
|
|
5184
|
-
|
|
4795
|
+
useEffect4(() => {
|
|
5185
4796
|
if (error && !loading) {
|
|
5186
4797
|
setCurrentView("error");
|
|
5187
4798
|
return;
|
|
@@ -5224,7 +4835,7 @@ var ChatApp = ({ service, initialModel }) => {
|
|
|
5224
4835
|
}
|
|
5225
4836
|
return false;
|
|
5226
4837
|
}, [refetch, exit]);
|
|
5227
|
-
|
|
4838
|
+
useInput4((input5, key) => {
|
|
5228
4839
|
if (showSlashMenu) {
|
|
5229
4840
|
if (key.upArrow) {
|
|
5230
4841
|
setSlashMenuIndex((i) => Math.max(0, i - 1));
|
|
@@ -5285,16 +4896,16 @@ var ChatApp = ({ service, initialModel }) => {
|
|
|
5285
4896
|
}, []);
|
|
5286
4897
|
const statsView = useMemo3(() => {
|
|
5287
4898
|
const allowed = models.filter((m) => m.allowed);
|
|
5288
|
-
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) => {
|
|
5289
4900
|
const limit = m.dailyLimit ?? 0;
|
|
5290
4901
|
const used = m.usedToday ?? 0;
|
|
5291
4902
|
const pct = limit > 0 ? Math.round(used / limit * 100) : 0;
|
|
5292
4903
|
const bar = "\u2588".repeat(Math.round(pct / 5)) + "\u2591".repeat(20 - Math.round(pct / 5));
|
|
5293
|
-
return /* @__PURE__ */
|
|
5294
|
-
}), /* @__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"));
|
|
5295
4906
|
}, [models, selectedModel]);
|
|
5296
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";
|
|
5297
|
-
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(
|
|
5298
4909
|
ModelSelector,
|
|
5299
4910
|
{
|
|
5300
4911
|
models,
|
|
@@ -5302,7 +4913,7 @@ var ChatApp = ({ service, initialModel }) => {
|
|
|
5302
4913
|
onSelect: onSelectModel,
|
|
5303
4914
|
onCancel: () => setCurrentView("chat")
|
|
5304
4915
|
}
|
|
5305
|
-
)) : currentView === "stats" ? /* @__PURE__ */
|
|
4916
|
+
)) : currentView === "stats" ? /* @__PURE__ */ React11.createElement(Box8, { padding: 1, minHeight: contentHeight.current, justifyContent: "center", alignItems: "center" }, statsView) : /* @__PURE__ */ React11.createElement(
|
|
5306
4917
|
ChatPanel,
|
|
5307
4918
|
{
|
|
5308
4919
|
messages,
|
|
@@ -5316,7 +4927,7 @@ var ChatApp = ({ service, initialModel }) => {
|
|
|
5316
4927
|
slashMenuIndex,
|
|
5317
4928
|
minHeight: contentHeight.current
|
|
5318
4929
|
}
|
|
5319
|
-
), /* @__PURE__ */
|
|
4930
|
+
), /* @__PURE__ */ React11.createElement(Box8, { borderStyle: "single", borderColor: "gray", paddingX: 1 }, /* @__PURE__ */ React11.createElement(Text9, { dimColor: true }, footer)));
|
|
5320
4931
|
};
|
|
5321
4932
|
|
|
5322
4933
|
// src/server/web-chat-server.ts
|
|
@@ -6220,8 +5831,8 @@ async function handleTerminalChat(options) {
|
|
|
6220
5831
|
throw new ValidationError('Not initialized. Run "jai1 auth" first.');
|
|
6221
5832
|
}
|
|
6222
5833
|
const service = new LlmProxyService(config);
|
|
6223
|
-
const { waitUntilExit, clear } =
|
|
6224
|
-
|
|
5834
|
+
const { waitUntilExit, clear } = render3(
|
|
5835
|
+
React12.createElement(ChatApp, {
|
|
6225
5836
|
service,
|
|
6226
5837
|
initialModel: options.model
|
|
6227
5838
|
}),
|
|
@@ -6293,7 +5904,7 @@ function createChatCommand() {
|
|
|
6293
5904
|
|
|
6294
5905
|
// src/commands/openai-keys.ts
|
|
6295
5906
|
import { Command as Command15 } from "commander";
|
|
6296
|
-
import
|
|
5907
|
+
import chalk10 from "chalk";
|
|
6297
5908
|
import boxen3 from "boxen";
|
|
6298
5909
|
function maskKey2(key) {
|
|
6299
5910
|
if (key.length <= 8) return "****";
|
|
@@ -6307,17 +5918,17 @@ async function handleOpenAiKeysCommand(options) {
|
|
|
6307
5918
|
}
|
|
6308
5919
|
const service = new LlmProxyService(config);
|
|
6309
5920
|
console.log(
|
|
6310
|
-
boxen3(
|
|
5921
|
+
boxen3(chalk10.cyan.bold("\u{1F4E1} Jai1 LLM Proxy - OpenAI Compatible API"), {
|
|
6311
5922
|
padding: { top: 0, bottom: 0, left: 1, right: 1 },
|
|
6312
5923
|
borderStyle: "round",
|
|
6313
5924
|
borderColor: "cyan"
|
|
6314
5925
|
})
|
|
6315
5926
|
);
|
|
6316
5927
|
console.log();
|
|
6317
|
-
console.log(
|
|
6318
|
-
console.log(` ${
|
|
5928
|
+
console.log(chalk10.bold("\u{1F511} API Credentials"));
|
|
5929
|
+
console.log(` ${chalk10.dim("BASE_URL:")} ${chalk10.white(service.getBaseUrl())}`);
|
|
6319
5930
|
console.log(
|
|
6320
|
-
` ${
|
|
5931
|
+
` ${chalk10.dim("API_KEY:")} ${options.full ? chalk10.green(service.getApiKey()) : chalk10.yellow(maskKey2(service.getApiKey()))}`
|
|
6321
5932
|
);
|
|
6322
5933
|
console.log();
|
|
6323
5934
|
try {
|
|
@@ -6326,39 +5937,39 @@ async function handleOpenAiKeysCommand(options) {
|
|
|
6326
5937
|
service.getLimits()
|
|
6327
5938
|
]);
|
|
6328
5939
|
const allowedModels = models.filter((m) => m.allowed);
|
|
6329
|
-
console.log(
|
|
5940
|
+
console.log(chalk10.bold("\u{1F4E6} Available Models"));
|
|
6330
5941
|
if (allowedModels.length === 0) {
|
|
6331
|
-
console.log(
|
|
5942
|
+
console.log(chalk10.dim(" Kh\xF4ng c\xF3 models kh\u1EA3 d\u1EE5ng"));
|
|
6332
5943
|
} else {
|
|
6333
5944
|
for (const model of allowedModels) {
|
|
6334
|
-
const usageText = model.dailyLimit !== void 0 && model.usedToday !== void 0 ?
|
|
6335
|
-
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}`);
|
|
6336
5947
|
}
|
|
6337
5948
|
}
|
|
6338
5949
|
console.log();
|
|
6339
5950
|
const defaultModel = allowedModels[0]?.id || "gpt-4o";
|
|
6340
|
-
console.log(
|
|
5951
|
+
console.log(chalk10.bold("\u{1F4DD} Sample cURL"));
|
|
6341
5952
|
console.log();
|
|
6342
5953
|
const curlSample = options.full ? service.generateFullCurlSample(defaultModel) : service.generateCurlSample(defaultModel);
|
|
6343
5954
|
const curlLines = curlSample.split("\n");
|
|
6344
5955
|
for (const line of curlLines) {
|
|
6345
|
-
console.log(
|
|
5956
|
+
console.log(chalk10.dim(` ${line}`));
|
|
6346
5957
|
}
|
|
6347
5958
|
console.log();
|
|
6348
|
-
console.log(
|
|
6349
|
-
console.log(
|
|
6350
|
-
console.log(
|
|
6351
|
-
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'));
|
|
6352
5963
|
if (!options.full) {
|
|
6353
|
-
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'));
|
|
6354
5965
|
}
|
|
6355
5966
|
} catch (error) {
|
|
6356
5967
|
console.log();
|
|
6357
5968
|
console.log(
|
|
6358
|
-
|
|
6359
|
-
|
|
5969
|
+
chalk10.red("\u274C L\u1ED7i khi l\u1EA5y th\xF4ng tin API:"),
|
|
5970
|
+
chalk10.dim(error instanceof Error ? error.message : String(error))
|
|
6360
5971
|
);
|
|
6361
|
-
console.log(
|
|
5972
|
+
console.log(chalk10.dim('\n\u{1F4A1} Ki\u1EC3m tra API URL v\xE0 access key v\u1EDBi "jai1 status"'));
|
|
6362
5973
|
}
|
|
6363
5974
|
}
|
|
6364
5975
|
function createOpenAiKeysCommand() {
|
|
@@ -6371,7 +5982,7 @@ function createOpenAiKeysCommand() {
|
|
|
6371
5982
|
// src/commands/stats.ts
|
|
6372
5983
|
import { Command as Command16 } from "commander";
|
|
6373
5984
|
import Table2 from "cli-table3";
|
|
6374
|
-
import
|
|
5985
|
+
import chalk11 from "chalk";
|
|
6375
5986
|
async function handleStatsCommand() {
|
|
6376
5987
|
const configService = new ConfigService();
|
|
6377
5988
|
const config = await configService.load();
|
|
@@ -6381,8 +5992,8 @@ async function handleStatsCommand() {
|
|
|
6381
5992
|
);
|
|
6382
5993
|
}
|
|
6383
5994
|
const service = new LlmProxyService(config);
|
|
6384
|
-
console.log(
|
|
6385
|
-
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)));
|
|
6386
5997
|
try {
|
|
6387
5998
|
const [limits, usage7Days, usageToday] = await Promise.all([
|
|
6388
5999
|
service.getLimits(),
|
|
@@ -6392,7 +6003,7 @@ async function handleStatsCommand() {
|
|
|
6392
6003
|
const today = (/* @__PURE__ */ new Date()).toLocaleDateString("en-CA", {
|
|
6393
6004
|
timeZone: "Asia/Ho_Chi_Minh"
|
|
6394
6005
|
});
|
|
6395
|
-
console.log(
|
|
6006
|
+
console.log(chalk11.cyan("\n\u{1F4C5} Kho\u1EA3ng th\u1EDDi gian: 7 ng\xE0y qua\n"));
|
|
6396
6007
|
const usageByModel = /* @__PURE__ */ new Map();
|
|
6397
6008
|
let total7DaysRequests = 0;
|
|
6398
6009
|
usage7Days.data?.forEach((record) => {
|
|
@@ -6412,16 +6023,16 @@ async function handleStatsCommand() {
|
|
|
6412
6023
|
modelData.today = record.count;
|
|
6413
6024
|
}
|
|
6414
6025
|
});
|
|
6415
|
-
console.log(
|
|
6416
|
-
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)}
|
|
6417
6028
|
`);
|
|
6418
|
-
console.log(
|
|
6029
|
+
console.log(chalk11.bold("\u{1F4E6} Th\u1ED1ng k\xEA theo model\n"));
|
|
6419
6030
|
const table = new Table2({
|
|
6420
6031
|
head: [
|
|
6421
|
-
|
|
6422
|
-
|
|
6423
|
-
|
|
6424
|
-
|
|
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")
|
|
6425
6036
|
],
|
|
6426
6037
|
style: {
|
|
6427
6038
|
head: ["cyan"],
|
|
@@ -6433,7 +6044,7 @@ async function handleStatsCommand() {
|
|
|
6433
6044
|
const rateLimits = limits.effectiveRateLimits || {};
|
|
6434
6045
|
if (allowedModels.length === 0) {
|
|
6435
6046
|
table.push([
|
|
6436
|
-
{ colSpan: 4, content:
|
|
6047
|
+
{ colSpan: 4, content: chalk11.yellow("Kh\xF4ng c\xF3 model n\xE0o kh\u1EA3 d\u1EE5ng") }
|
|
6437
6048
|
]);
|
|
6438
6049
|
} else {
|
|
6439
6050
|
allowedModels.forEach((modelId) => {
|
|
@@ -6442,25 +6053,25 @@ async function handleStatsCommand() {
|
|
|
6442
6053
|
const usagePercent = limit > 0 ? usage.today / limit : 0;
|
|
6443
6054
|
let todayDisplay = `${usage.today}/${limit}`;
|
|
6444
6055
|
if (usagePercent >= 0.9) {
|
|
6445
|
-
todayDisplay =
|
|
6056
|
+
todayDisplay = chalk11.red(todayDisplay);
|
|
6446
6057
|
} else if (usagePercent >= 0.7) {
|
|
6447
|
-
todayDisplay =
|
|
6058
|
+
todayDisplay = chalk11.yellow(todayDisplay);
|
|
6448
6059
|
} else {
|
|
6449
|
-
todayDisplay =
|
|
6060
|
+
todayDisplay = chalk11.green(todayDisplay);
|
|
6450
6061
|
}
|
|
6451
6062
|
table.push([modelId, todayDisplay, `${limit}/ng\xE0y`, String(usage.total7Days)]);
|
|
6452
6063
|
});
|
|
6453
6064
|
}
|
|
6454
6065
|
console.log(table.toString());
|
|
6455
6066
|
console.log(
|
|
6456
|
-
|
|
6067
|
+
chalk11.dim('\n\u{1F4A1} M\u1EB9o: Ch\u1EA1y "jai1 openai-keys" \u0111\u1EC3 xem danh s\xE1ch model kh\u1EA3 d\u1EE5ng')
|
|
6457
6068
|
);
|
|
6458
6069
|
} catch (error) {
|
|
6459
6070
|
console.error(
|
|
6460
|
-
|
|
6071
|
+
chalk11.red("\n\u274C Kh\xF4ng th\u1EC3 l\u1EA5y th\u1ED1ng k\xEA:"),
|
|
6461
6072
|
error instanceof Error ? error.message : String(error)
|
|
6462
6073
|
);
|
|
6463
|
-
console.log(
|
|
6074
|
+
console.log(chalk11.dim('\n\u{1F4A1} Ki\u1EC3m tra k\u1EBFt n\u1ED1i API v\u1EDBi "jai1 status"'));
|
|
6464
6075
|
}
|
|
6465
6076
|
}
|
|
6466
6077
|
function createStatsCommand() {
|
|
@@ -6827,7 +6438,7 @@ function createTranslateCommand() {
|
|
|
6827
6438
|
|
|
6828
6439
|
// src/commands/image/index.ts
|
|
6829
6440
|
import { Command as Command22 } from "commander";
|
|
6830
|
-
import
|
|
6441
|
+
import chalk12 from "chalk";
|
|
6831
6442
|
|
|
6832
6443
|
// src/commands/image/gen.ts
|
|
6833
6444
|
import { Command as Command18 } from "commander";
|
|
@@ -7102,22 +6713,22 @@ function createImageDeleteCommand() {
|
|
|
7102
6713
|
|
|
7103
6714
|
// src/commands/image/index.ts
|
|
7104
6715
|
function showImageHelp() {
|
|
7105
|
-
console.log(
|
|
6716
|
+
console.log(chalk12.bold.cyan("\u{1F3A8} jai1 image") + chalk12.dim(" - Image generation commands"));
|
|
7106
6717
|
console.log();
|
|
7107
|
-
console.log(
|
|
6718
|
+
console.log(chalk12.yellow("\u26A0\uFE0F Coming Soon - T\xEDnh n\u0103ng \u0111ang ph\xE1t tri\u1EC3n"));
|
|
7108
6719
|
console.log();
|
|
7109
|
-
console.log(
|
|
7110
|
-
console.log(` ${
|
|
7111
|
-
console.log(` ${
|
|
7112
|
-
console.log(` ${
|
|
7113
|
-
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`);
|
|
7114
6725
|
console.log();
|
|
7115
|
-
console.log(
|
|
7116
|
-
console.log(
|
|
7117
|
-
console.log(
|
|
7118
|
-
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>"));
|
|
7119
6730
|
console.log();
|
|
7120
|
-
console.log(
|
|
6731
|
+
console.log(chalk12.dim('Ch\u1EA1y "jai1 image <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt'));
|
|
7121
6732
|
}
|
|
7122
6733
|
function createImageCommand() {
|
|
7123
6734
|
const cmd = new Command22("image").description("Image generation commands (Coming Soon)").action(() => {
|
|
@@ -7618,11 +7229,11 @@ async function confirmSubmit(summary, jsonMode) {
|
|
|
7618
7229
|
|
|
7619
7230
|
// src/commands/errors/index.ts
|
|
7620
7231
|
import { Command as Command28 } from "commander";
|
|
7621
|
-
import
|
|
7232
|
+
import chalk14 from "chalk";
|
|
7622
7233
|
|
|
7623
7234
|
// src/commands/errors/list.ts
|
|
7624
7235
|
import { Command as Command25 } from "commander";
|
|
7625
|
-
import
|
|
7236
|
+
import chalk13 from "chalk";
|
|
7626
7237
|
import Table3 from "cli-table3";
|
|
7627
7238
|
function createErrorsListSubcommand() {
|
|
7628
7239
|
return new Command25("list").description("Danh s\xE1ch error logs").option("--json", "Output JSON format").action(async (options) => {
|
|
@@ -7659,7 +7270,7 @@ function createErrorsListSubcommand() {
|
|
|
7659
7270
|
});
|
|
7660
7271
|
for (const log of logs) {
|
|
7661
7272
|
table.push([
|
|
7662
|
-
|
|
7273
|
+
chalk13.cyan(log.id),
|
|
7663
7274
|
log.timestamp || "-",
|
|
7664
7275
|
log.command || "-",
|
|
7665
7276
|
log.message || "-"
|
|
@@ -7738,19 +7349,19 @@ function createErrorsClearSubcommand() {
|
|
|
7738
7349
|
|
|
7739
7350
|
// src/commands/errors/index.ts
|
|
7740
7351
|
function showErrorsHelp() {
|
|
7741
|
-
console.log(
|
|
7352
|
+
console.log(chalk14.bold.cyan("\u{1F9FE} jai1 errors") + chalk14.dim(" - Qu\u1EA3n l\xFD error logs c\u1EE5c b\u1ED9"));
|
|
7742
7353
|
console.log();
|
|
7743
|
-
console.log(
|
|
7744
|
-
console.log(` ${
|
|
7745
|
-
console.log(` ${
|
|
7746
|
-
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`);
|
|
7747
7358
|
console.log();
|
|
7748
|
-
console.log(
|
|
7749
|
-
console.log(
|
|
7750
|
-
console.log(
|
|
7751
|
-
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"));
|
|
7752
7363
|
console.log();
|
|
7753
|
-
console.log(
|
|
7364
|
+
console.log(chalk14.dim('Ch\u1EA1y "jai1 errors <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt'));
|
|
7754
7365
|
}
|
|
7755
7366
|
function createErrorsCommand() {
|
|
7756
7367
|
const errorsCommand = new Command28("errors").description("Manage local error logs").action(() => {
|
|
@@ -7764,7 +7375,7 @@ function createErrorsCommand() {
|
|
|
7764
7375
|
|
|
7765
7376
|
// src/commands/utils/index.ts
|
|
7766
7377
|
import { Command as Command42 } from "commander";
|
|
7767
|
-
import
|
|
7378
|
+
import chalk15 from "chalk";
|
|
7768
7379
|
|
|
7769
7380
|
// src/commands/utils/password.ts
|
|
7770
7381
|
import { Command as Command29 } from "commander";
|
|
@@ -8686,28 +8297,28 @@ Examples:
|
|
|
8686
8297
|
}
|
|
8687
8298
|
|
|
8688
8299
|
// src/commands/utils/interactive.ts
|
|
8689
|
-
import
|
|
8690
|
-
import { render as
|
|
8300
|
+
import React25 from "react";
|
|
8301
|
+
import { render as render4 } from "ink";
|
|
8691
8302
|
|
|
8692
8303
|
// src/ui/utils/UtilsApp.tsx
|
|
8693
|
-
import
|
|
8694
|
-
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";
|
|
8695
8306
|
|
|
8696
8307
|
// src/ui/utils/views/PasswordView.tsx
|
|
8697
|
-
import
|
|
8698
|
-
import { Box as
|
|
8308
|
+
import React13, { useState as useState7 } from "react";
|
|
8309
|
+
import { Box as Box9, Text as Text10, useInput as useInput5 } from "ink";
|
|
8699
8310
|
import TextInput4 from "ink-text-input";
|
|
8700
8311
|
var PasswordView = () => {
|
|
8701
|
-
const [length, setLength] =
|
|
8702
|
-
const [count, setCount] =
|
|
8703
|
-
const [passwords, setPasswords] =
|
|
8704
|
-
const [focusedField, setFocusedField] =
|
|
8705
|
-
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);
|
|
8706
8317
|
const service = new UtilsService();
|
|
8707
|
-
|
|
8318
|
+
React13.useEffect(() => {
|
|
8708
8319
|
handleGenerate();
|
|
8709
8320
|
}, []);
|
|
8710
|
-
|
|
8321
|
+
useInput5((input5, key) => {
|
|
8711
8322
|
if (key.tab) {
|
|
8712
8323
|
if (focusedField === "length") setFocusedField("count");
|
|
8713
8324
|
else if (focusedField === "count") setFocusedField("generate");
|
|
@@ -8745,8 +8356,8 @@ var PasswordView = () => {
|
|
|
8745
8356
|
} catch (error) {
|
|
8746
8357
|
}
|
|
8747
8358
|
};
|
|
8748
|
-
return /* @__PURE__ */
|
|
8749
|
-
|
|
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,
|
|
8750
8361
|
{
|
|
8751
8362
|
flexDirection: "column",
|
|
8752
8363
|
borderStyle: "single",
|
|
@@ -8755,11 +8366,11 @@ var PasswordView = () => {
|
|
|
8755
8366
|
paddingY: 1,
|
|
8756
8367
|
marginBottom: 1
|
|
8757
8368
|
},
|
|
8758
|
-
/* @__PURE__ */
|
|
8759
|
-
/* @__PURE__ */
|
|
8760
|
-
/* @__PURE__ */
|
|
8761
|
-
/* @__PURE__ */
|
|
8762
|
-
|
|
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,
|
|
8763
8374
|
{
|
|
8764
8375
|
bold: true,
|
|
8765
8376
|
backgroundColor: focusedField === "generate" ? "green" : void 0,
|
|
@@ -8768,8 +8379,8 @@ var PasswordView = () => {
|
|
|
8768
8379
|
focusedField === "generate" ? "\u25B6 " : " ",
|
|
8769
8380
|
"[ Generate Passwords ]"
|
|
8770
8381
|
))
|
|
8771
|
-
), passwords.length > 0 && /* @__PURE__ */
|
|
8772
|
-
|
|
8382
|
+
), passwords.length > 0 && /* @__PURE__ */ React13.createElement(
|
|
8383
|
+
Box9,
|
|
8773
8384
|
{
|
|
8774
8385
|
flexDirection: "column",
|
|
8775
8386
|
borderStyle: "single",
|
|
@@ -8777,27 +8388,27 @@ var PasswordView = () => {
|
|
|
8777
8388
|
paddingX: 2,
|
|
8778
8389
|
paddingY: 1
|
|
8779
8390
|
},
|
|
8780
|
-
/* @__PURE__ */
|
|
8781
|
-
passwords.map((password, index) => /* @__PURE__ */
|
|
8782
|
-
), /* @__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")));
|
|
8783
8394
|
};
|
|
8784
8395
|
|
|
8785
8396
|
// src/ui/utils/views/UuidView.tsx
|
|
8786
|
-
import
|
|
8787
|
-
import { Box as
|
|
8397
|
+
import React14, { useState as useState8 } from "react";
|
|
8398
|
+
import { Box as Box10, Text as Text11, useInput as useInput6 } from "ink";
|
|
8788
8399
|
import TextInput5 from "ink-text-input";
|
|
8789
8400
|
var UuidView = () => {
|
|
8790
|
-
const [count, setCount] =
|
|
8791
|
-
const [uppercase, setUppercase] =
|
|
8792
|
-
const [noHyphens, setNoHyphens] =
|
|
8793
|
-
const [uuids, setUuids] =
|
|
8794
|
-
const [focusedField, setFocusedField] =
|
|
8795
|
-
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);
|
|
8796
8407
|
const service = new UtilsService();
|
|
8797
|
-
|
|
8408
|
+
React14.useEffect(() => {
|
|
8798
8409
|
handleGenerate();
|
|
8799
8410
|
}, []);
|
|
8800
|
-
|
|
8411
|
+
useInput6((input5, key) => {
|
|
8801
8412
|
if (key.tab) {
|
|
8802
8413
|
const fields = ["count", "uppercase", "hyphens", "generate"];
|
|
8803
8414
|
const currentIndex = fields.indexOf(focusedField);
|
|
@@ -8832,8 +8443,8 @@ var UuidView = () => {
|
|
|
8832
8443
|
} catch (error) {
|
|
8833
8444
|
}
|
|
8834
8445
|
};
|
|
8835
|
-
return /* @__PURE__ */
|
|
8836
|
-
|
|
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,
|
|
8837
8448
|
{
|
|
8838
8449
|
flexDirection: "column",
|
|
8839
8450
|
borderStyle: "single",
|
|
@@ -8842,12 +8453,12 @@ var UuidView = () => {
|
|
|
8842
8453
|
paddingY: 1,
|
|
8843
8454
|
marginBottom: 1
|
|
8844
8455
|
},
|
|
8845
|
-
/* @__PURE__ */
|
|
8846
|
-
/* @__PURE__ */
|
|
8847
|
-
/* @__PURE__ */
|
|
8848
|
-
/* @__PURE__ */
|
|
8849
|
-
/* @__PURE__ */
|
|
8850
|
-
|
|
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,
|
|
8851
8462
|
{
|
|
8852
8463
|
bold: true,
|
|
8853
8464
|
backgroundColor: focusedField === "generate" ? "green" : void 0,
|
|
@@ -8856,8 +8467,8 @@ var UuidView = () => {
|
|
|
8856
8467
|
focusedField === "generate" ? "\u25B6 " : " ",
|
|
8857
8468
|
"[ Generate UUIDs ]"
|
|
8858
8469
|
))
|
|
8859
|
-
), uuids.length > 0 && /* @__PURE__ */
|
|
8860
|
-
|
|
8470
|
+
), uuids.length > 0 && /* @__PURE__ */ React14.createElement(
|
|
8471
|
+
Box10,
|
|
8861
8472
|
{
|
|
8862
8473
|
flexDirection: "column",
|
|
8863
8474
|
borderStyle: "single",
|
|
@@ -8865,27 +8476,27 @@ var UuidView = () => {
|
|
|
8865
8476
|
paddingX: 2,
|
|
8866
8477
|
paddingY: 1
|
|
8867
8478
|
},
|
|
8868
|
-
/* @__PURE__ */
|
|
8869
|
-
uuids.map((uuid, index) => /* @__PURE__ */
|
|
8870
|
-
), /* @__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")));
|
|
8871
8482
|
};
|
|
8872
8483
|
|
|
8873
8484
|
// src/ui/utils/views/HashView.tsx
|
|
8874
|
-
import
|
|
8875
|
-
import { Box as
|
|
8485
|
+
import React15, { useState as useState9 } from "react";
|
|
8486
|
+
import { Box as Box11, Text as Text12, useInput as useInput7 } from "ink";
|
|
8876
8487
|
import TextInput6 from "ink-text-input";
|
|
8877
8488
|
var ALGORITHMS = ["sha256", "sha512", "sha1", "md5", "bcrypt"];
|
|
8878
8489
|
var HashView = () => {
|
|
8879
|
-
const [text, setText] =
|
|
8880
|
-
const [algorithm, setAlgorithm] =
|
|
8881
|
-
const [hash, setHash] =
|
|
8882
|
-
const [focusedField, setFocusedField] =
|
|
8883
|
-
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);
|
|
8884
8495
|
const service = new UtilsService();
|
|
8885
|
-
|
|
8496
|
+
React15.useEffect(() => {
|
|
8886
8497
|
handleGenerate();
|
|
8887
8498
|
}, []);
|
|
8888
|
-
|
|
8499
|
+
useInput7((input5, key) => {
|
|
8889
8500
|
if (key.tab) {
|
|
8890
8501
|
const fields = ["text", "algorithm", "generate"];
|
|
8891
8502
|
const currentIndex = fields.indexOf(focusedField);
|
|
@@ -8922,8 +8533,8 @@ var HashView = () => {
|
|
|
8922
8533
|
} catch (error) {
|
|
8923
8534
|
}
|
|
8924
8535
|
};
|
|
8925
|
-
return /* @__PURE__ */
|
|
8926
|
-
|
|
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,
|
|
8927
8538
|
{
|
|
8928
8539
|
flexDirection: "column",
|
|
8929
8540
|
borderStyle: "single",
|
|
@@ -8932,11 +8543,11 @@ var HashView = () => {
|
|
|
8932
8543
|
paddingY: 1,
|
|
8933
8544
|
marginBottom: 1
|
|
8934
8545
|
},
|
|
8935
|
-
/* @__PURE__ */
|
|
8936
|
-
/* @__PURE__ */
|
|
8937
|
-
/* @__PURE__ */
|
|
8938
|
-
/* @__PURE__ */
|
|
8939
|
-
|
|
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,
|
|
8940
8551
|
{
|
|
8941
8552
|
bold: true,
|
|
8942
8553
|
backgroundColor: focusedField === "generate" ? "green" : void 0,
|
|
@@ -8945,8 +8556,8 @@ var HashView = () => {
|
|
|
8945
8556
|
focusedField === "generate" ? "\u25B6 " : " ",
|
|
8946
8557
|
"[ Generate Hash ]"
|
|
8947
8558
|
))
|
|
8948
|
-
), hash && /* @__PURE__ */
|
|
8949
|
-
|
|
8559
|
+
), hash && /* @__PURE__ */ React15.createElement(
|
|
8560
|
+
Box11,
|
|
8950
8561
|
{
|
|
8951
8562
|
flexDirection: "column",
|
|
8952
8563
|
borderStyle: "single",
|
|
@@ -8954,25 +8565,25 @@ var HashView = () => {
|
|
|
8954
8565
|
paddingX: 2,
|
|
8955
8566
|
paddingY: 1
|
|
8956
8567
|
},
|
|
8957
|
-
/* @__PURE__ */
|
|
8958
|
-
/* @__PURE__ */
|
|
8959
|
-
), /* @__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")));
|
|
8960
8571
|
};
|
|
8961
8572
|
|
|
8962
8573
|
// src/ui/utils/views/Base64View.tsx
|
|
8963
|
-
import
|
|
8964
|
-
import { Box as
|
|
8574
|
+
import React16, { useState as useState10 } from "react";
|
|
8575
|
+
import { Box as Box12, Text as Text13, useInput as useInput8 } from "ink";
|
|
8965
8576
|
import TextInput7 from "ink-text-input";
|
|
8966
8577
|
var Base64View = () => {
|
|
8967
|
-
const [input5, setInput] =
|
|
8968
|
-
const [mode, setMode] =
|
|
8969
|
-
const [urlSafe, setUrlSafe] =
|
|
8970
|
-
const [result, setResult] =
|
|
8971
|
-
const [error, setError] =
|
|
8972
|
-
const [focusedField, setFocusedField] =
|
|
8973
|
-
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);
|
|
8974
8585
|
const service = new UtilsService();
|
|
8975
|
-
|
|
8586
|
+
useInput8((input6, key) => {
|
|
8976
8587
|
if (key.tab) {
|
|
8977
8588
|
const fields = ["input", "mode", "urlsafe", "convert"];
|
|
8978
8589
|
const currentIndex = fields.indexOf(focusedField);
|
|
@@ -9020,8 +8631,8 @@ var Base64View = () => {
|
|
|
9020
8631
|
} catch (error2) {
|
|
9021
8632
|
}
|
|
9022
8633
|
};
|
|
9023
|
-
return /* @__PURE__ */
|
|
9024
|
-
|
|
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,
|
|
9025
8636
|
{
|
|
9026
8637
|
flexDirection: "column",
|
|
9027
8638
|
borderStyle: "single",
|
|
@@ -9030,12 +8641,12 @@ var Base64View = () => {
|
|
|
9030
8641
|
paddingY: 1,
|
|
9031
8642
|
marginBottom: 1
|
|
9032
8643
|
},
|
|
9033
|
-
/* @__PURE__ */
|
|
9034
|
-
/* @__PURE__ */
|
|
9035
|
-
/* @__PURE__ */
|
|
9036
|
-
mode === "encode" && /* @__PURE__ */
|
|
9037
|
-
/* @__PURE__ */
|
|
9038
|
-
|
|
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,
|
|
9039
8650
|
{
|
|
9040
8651
|
bold: true,
|
|
9041
8652
|
backgroundColor: focusedField === "convert" ? "green" : void 0,
|
|
@@ -9046,8 +8657,8 @@ var Base64View = () => {
|
|
|
9046
8657
|
mode === "encode" ? "Encode" : "Decode",
|
|
9047
8658
|
" ]"
|
|
9048
8659
|
))
|
|
9049
|
-
), error && /* @__PURE__ */
|
|
9050
|
-
|
|
8660
|
+
), error && /* @__PURE__ */ React16.createElement(
|
|
8661
|
+
Box12,
|
|
9051
8662
|
{
|
|
9052
8663
|
flexDirection: "column",
|
|
9053
8664
|
borderStyle: "single",
|
|
@@ -9056,9 +8667,9 @@ var Base64View = () => {
|
|
|
9056
8667
|
paddingY: 1,
|
|
9057
8668
|
marginBottom: 1
|
|
9058
8669
|
},
|
|
9059
|
-
/* @__PURE__ */
|
|
9060
|
-
), result && /* @__PURE__ */
|
|
9061
|
-
|
|
8670
|
+
/* @__PURE__ */ React16.createElement(Text13, { color: "red" }, "\u2717 Error: ", error)
|
|
8671
|
+
), result && /* @__PURE__ */ React16.createElement(
|
|
8672
|
+
Box12,
|
|
9062
8673
|
{
|
|
9063
8674
|
flexDirection: "column",
|
|
9064
8675
|
borderStyle: "single",
|
|
@@ -9066,24 +8677,24 @@ var Base64View = () => {
|
|
|
9066
8677
|
paddingX: 2,
|
|
9067
8678
|
paddingY: 1
|
|
9068
8679
|
},
|
|
9069
|
-
/* @__PURE__ */
|
|
9070
|
-
/* @__PURE__ */
|
|
9071
|
-
), /* @__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")));
|
|
9072
8683
|
};
|
|
9073
8684
|
|
|
9074
8685
|
// src/ui/utils/views/UrlView.tsx
|
|
9075
|
-
import
|
|
9076
|
-
import { Box as
|
|
8686
|
+
import React17, { useState as useState11 } from "react";
|
|
8687
|
+
import { Box as Box13, Text as Text14, useInput as useInput9 } from "ink";
|
|
9077
8688
|
import TextInput8 from "ink-text-input";
|
|
9078
8689
|
var UrlView = () => {
|
|
9079
|
-
const [input5, setInput] =
|
|
9080
|
-
const [mode, setMode] =
|
|
9081
|
-
const [fullUrl, setFullUrl] =
|
|
9082
|
-
const [result, setResult] =
|
|
9083
|
-
const [focusedField, setFocusedField] =
|
|
9084
|
-
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);
|
|
9085
8696
|
const service = new UtilsService();
|
|
9086
|
-
|
|
8697
|
+
useInput9((input6, key) => {
|
|
9087
8698
|
if (key.tab) {
|
|
9088
8699
|
const fields = ["input", "mode", "full", "convert"];
|
|
9089
8700
|
const currentIndex = fields.indexOf(focusedField);
|
|
@@ -9121,8 +8732,8 @@ var UrlView = () => {
|
|
|
9121
8732
|
} catch (error) {
|
|
9122
8733
|
}
|
|
9123
8734
|
};
|
|
9124
|
-
return /* @__PURE__ */
|
|
9125
|
-
|
|
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,
|
|
9126
8737
|
{
|
|
9127
8738
|
flexDirection: "column",
|
|
9128
8739
|
borderStyle: "single",
|
|
@@ -9131,12 +8742,12 @@ var UrlView = () => {
|
|
|
9131
8742
|
paddingY: 1,
|
|
9132
8743
|
marginBottom: 1
|
|
9133
8744
|
},
|
|
9134
|
-
/* @__PURE__ */
|
|
9135
|
-
/* @__PURE__ */
|
|
9136
|
-
/* @__PURE__ */
|
|
9137
|
-
/* @__PURE__ */
|
|
9138
|
-
/* @__PURE__ */
|
|
9139
|
-
|
|
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,
|
|
9140
8751
|
{
|
|
9141
8752
|
bold: true,
|
|
9142
8753
|
backgroundColor: focusedField === "convert" ? "green" : void 0,
|
|
@@ -9147,8 +8758,8 @@ var UrlView = () => {
|
|
|
9147
8758
|
mode === "encode" ? "Encode" : "Decode",
|
|
9148
8759
|
" ]"
|
|
9149
8760
|
))
|
|
9150
|
-
), result && /* @__PURE__ */
|
|
9151
|
-
|
|
8761
|
+
), result && /* @__PURE__ */ React17.createElement(
|
|
8762
|
+
Box13,
|
|
9152
8763
|
{
|
|
9153
8764
|
flexDirection: "column",
|
|
9154
8765
|
borderStyle: "single",
|
|
@@ -9156,26 +8767,26 @@ var UrlView = () => {
|
|
|
9156
8767
|
paddingX: 2,
|
|
9157
8768
|
paddingY: 1
|
|
9158
8769
|
},
|
|
9159
|
-
/* @__PURE__ */
|
|
9160
|
-
/* @__PURE__ */
|
|
9161
|
-
), /* @__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")));
|
|
9162
8773
|
};
|
|
9163
8774
|
|
|
9164
8775
|
// src/ui/utils/views/UnixTimeView.tsx
|
|
9165
|
-
import
|
|
9166
|
-
import { Box as
|
|
8776
|
+
import React18, { useState as useState12 } from "react";
|
|
8777
|
+
import { Box as Box14, Text as Text15, useInput as useInput10 } from "ink";
|
|
9167
8778
|
import TextInput9 from "ink-text-input";
|
|
9168
8779
|
var UnixTimeView = () => {
|
|
9169
|
-
const [input5, setInput] =
|
|
9170
|
-
const [mode, setMode] =
|
|
9171
|
-
const [format, setFormat] =
|
|
9172
|
-
const [useMs, setUseMs] =
|
|
9173
|
-
const [result, setResult] =
|
|
9174
|
-
const [error, setError] =
|
|
9175
|
-
const [focusedField, setFocusedField] =
|
|
9176
|
-
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);
|
|
9177
8788
|
const service = new UtilsService();
|
|
9178
|
-
|
|
8789
|
+
useInput10((input6, key) => {
|
|
9179
8790
|
if (key.tab) {
|
|
9180
8791
|
const fields = mode === "now" ? ["mode", "ms", "convert"] : mode === "to-human" ? ["mode", "input", "format", "convert"] : ["mode", "input", "convert"];
|
|
9181
8792
|
const currentIndex = fields.indexOf(focusedField);
|
|
@@ -9236,8 +8847,8 @@ var UnixTimeView = () => {
|
|
|
9236
8847
|
} catch (error2) {
|
|
9237
8848
|
}
|
|
9238
8849
|
};
|
|
9239
|
-
return /* @__PURE__ */
|
|
9240
|
-
|
|
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,
|
|
9241
8852
|
{
|
|
9242
8853
|
flexDirection: "column",
|
|
9243
8854
|
borderStyle: "single",
|
|
@@ -9246,20 +8857,20 @@ var UnixTimeView = () => {
|
|
|
9246
8857
|
paddingY: 1,
|
|
9247
8858
|
marginBottom: 1
|
|
9248
8859
|
},
|
|
9249
|
-
/* @__PURE__ */
|
|
9250
|
-
/* @__PURE__ */
|
|
9251
|
-
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(
|
|
9252
8863
|
TextInput9,
|
|
9253
8864
|
{
|
|
9254
8865
|
value: input5,
|
|
9255
8866
|
onChange: setInput,
|
|
9256
8867
|
placeholder: mode === "to-human" ? "1702550400" : "2024-01-15 10:30:00"
|
|
9257
8868
|
}
|
|
9258
|
-
) : /* @__PURE__ */
|
|
9259
|
-
mode === "to-human" && /* @__PURE__ */
|
|
9260
|
-
mode === "now" && /* @__PURE__ */
|
|
9261
|
-
/* @__PURE__ */
|
|
9262
|
-
|
|
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,
|
|
9263
8874
|
{
|
|
9264
8875
|
bold: true,
|
|
9265
8876
|
backgroundColor: focusedField === "convert" ? "green" : void 0,
|
|
@@ -9270,8 +8881,8 @@ var UnixTimeView = () => {
|
|
|
9270
8881
|
mode === "now" ? "Get Current" : "Convert",
|
|
9271
8882
|
" ]"
|
|
9272
8883
|
))
|
|
9273
|
-
), error && /* @__PURE__ */
|
|
9274
|
-
|
|
8884
|
+
), error && /* @__PURE__ */ React18.createElement(
|
|
8885
|
+
Box14,
|
|
9275
8886
|
{
|
|
9276
8887
|
flexDirection: "column",
|
|
9277
8888
|
borderStyle: "single",
|
|
@@ -9280,9 +8891,9 @@ var UnixTimeView = () => {
|
|
|
9280
8891
|
paddingY: 1,
|
|
9281
8892
|
marginBottom: 1
|
|
9282
8893
|
},
|
|
9283
|
-
/* @__PURE__ */
|
|
9284
|
-
), result && /* @__PURE__ */
|
|
9285
|
-
|
|
8894
|
+
/* @__PURE__ */ React18.createElement(Text15, { color: "red" }, "\u2717 Error: ", error)
|
|
8895
|
+
), result && /* @__PURE__ */ React18.createElement(
|
|
8896
|
+
Box14,
|
|
9286
8897
|
{
|
|
9287
8898
|
flexDirection: "column",
|
|
9288
8899
|
borderStyle: "single",
|
|
@@ -9290,26 +8901,26 @@ var UnixTimeView = () => {
|
|
|
9290
8901
|
paddingX: 2,
|
|
9291
8902
|
paddingY: 1
|
|
9292
8903
|
},
|
|
9293
|
-
/* @__PURE__ */
|
|
9294
|
-
/* @__PURE__ */
|
|
9295
|
-
), /* @__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")));
|
|
9296
8907
|
};
|
|
9297
8908
|
|
|
9298
8909
|
// src/ui/utils/views/JwtView.tsx
|
|
9299
|
-
import
|
|
9300
|
-
import { Box as
|
|
8910
|
+
import React19, { useState as useState13 } from "react";
|
|
8911
|
+
import { Box as Box15, Text as Text16, useInput as useInput11 } from "ink";
|
|
9301
8912
|
import TextInput10 from "ink-text-input";
|
|
9302
8913
|
var JwtView = () => {
|
|
9303
|
-
const [mode, setMode] =
|
|
9304
|
-
const [token, setToken] =
|
|
9305
|
-
const [payload, setPayload] =
|
|
9306
|
-
const [secret, setSecret] =
|
|
9307
|
-
const [result, setResult] =
|
|
9308
|
-
const [error, setError] =
|
|
9309
|
-
const [focusedField, setFocusedField] =
|
|
9310
|
-
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);
|
|
9311
8922
|
const service = new UtilsService();
|
|
9312
|
-
|
|
8923
|
+
useInput11((input5, key) => {
|
|
9313
8924
|
if (key.tab) {
|
|
9314
8925
|
const fields = mode === "decode" ? ["mode", "token", "process"] : ["mode", "payload", "secret", "process"];
|
|
9315
8926
|
const currentIndex = fields.indexOf(focusedField);
|
|
@@ -9364,8 +8975,8 @@ var JwtView = () => {
|
|
|
9364
8975
|
} catch (error2) {
|
|
9365
8976
|
}
|
|
9366
8977
|
};
|
|
9367
|
-
return /* @__PURE__ */
|
|
9368
|
-
|
|
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,
|
|
9369
8980
|
{
|
|
9370
8981
|
flexDirection: "column",
|
|
9371
8982
|
borderStyle: "single",
|
|
@@ -9374,23 +8985,23 @@ var JwtView = () => {
|
|
|
9374
8985
|
paddingY: 1,
|
|
9375
8986
|
marginBottom: 1
|
|
9376
8987
|
},
|
|
9377
|
-
/* @__PURE__ */
|
|
9378
|
-
/* @__PURE__ */
|
|
9379
|
-
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(
|
|
9380
8991
|
TextInput10,
|
|
9381
8992
|
{
|
|
9382
8993
|
value: token,
|
|
9383
8994
|
onChange: setToken,
|
|
9384
8995
|
placeholder: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
|
9385
8996
|
}
|
|
9386
|
-
) : /* @__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(
|
|
9387
8998
|
TextInput10,
|
|
9388
8999
|
{
|
|
9389
9000
|
value: payload,
|
|
9390
9001
|
onChange: setPayload,
|
|
9391
9002
|
placeholder: '{"sub":"123","name":"John"}'
|
|
9392
9003
|
}
|
|
9393
|
-
) : /* @__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(
|
|
9394
9005
|
TextInput10,
|
|
9395
9006
|
{
|
|
9396
9007
|
value: secret,
|
|
@@ -9398,9 +9009,9 @@ var JwtView = () => {
|
|
|
9398
9009
|
placeholder: "your-secret-key",
|
|
9399
9010
|
mask: "*"
|
|
9400
9011
|
}
|
|
9401
|
-
) : /* @__PURE__ */
|
|
9402
|
-
/* @__PURE__ */
|
|
9403
|
-
|
|
9012
|
+
) : /* @__PURE__ */ React19.createElement(Text16, { dimColor: !secret }, secret ? "*".repeat(secret.length) : "(empty)")))),
|
|
9013
|
+
/* @__PURE__ */ React19.createElement(Box15, { marginTop: 1 }, /* @__PURE__ */ React19.createElement(
|
|
9014
|
+
Text16,
|
|
9404
9015
|
{
|
|
9405
9016
|
bold: true,
|
|
9406
9017
|
backgroundColor: focusedField === "process" ? "green" : void 0,
|
|
@@ -9411,8 +9022,8 @@ var JwtView = () => {
|
|
|
9411
9022
|
mode === "decode" ? "Decode" : "Encode",
|
|
9412
9023
|
" ]"
|
|
9413
9024
|
))
|
|
9414
|
-
), error && /* @__PURE__ */
|
|
9415
|
-
|
|
9025
|
+
), error && /* @__PURE__ */ React19.createElement(
|
|
9026
|
+
Box15,
|
|
9416
9027
|
{
|
|
9417
9028
|
flexDirection: "column",
|
|
9418
9029
|
borderStyle: "single",
|
|
@@ -9421,9 +9032,9 @@ var JwtView = () => {
|
|
|
9421
9032
|
paddingY: 1,
|
|
9422
9033
|
marginBottom: 1
|
|
9423
9034
|
},
|
|
9424
|
-
/* @__PURE__ */
|
|
9425
|
-
), (result.header || result.token) && /* @__PURE__ */
|
|
9426
|
-
|
|
9035
|
+
/* @__PURE__ */ React19.createElement(Text16, { color: "red" }, "\u2717 Error: ", error)
|
|
9036
|
+
), (result.header || result.token) && /* @__PURE__ */ React19.createElement(
|
|
9037
|
+
Box15,
|
|
9427
9038
|
{
|
|
9428
9039
|
flexDirection: "column",
|
|
9429
9040
|
borderStyle: "single",
|
|
@@ -9431,23 +9042,23 @@ var JwtView = () => {
|
|
|
9431
9042
|
paddingX: 2,
|
|
9432
9043
|
paddingY: 1
|
|
9433
9044
|
},
|
|
9434
|
-
/* @__PURE__ */
|
|
9435
|
-
/* @__PURE__ */
|
|
9436
|
-
), /* @__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")));
|
|
9437
9048
|
};
|
|
9438
9049
|
|
|
9439
9050
|
// src/ui/utils/views/CronView.tsx
|
|
9440
|
-
import
|
|
9441
|
-
import { Box as
|
|
9051
|
+
import React20, { useState as useState14 } from "react";
|
|
9052
|
+
import { Box as Box16, Text as Text17, useInput as useInput12 } from "ink";
|
|
9442
9053
|
import TextInput11 from "ink-text-input";
|
|
9443
9054
|
var CronView = () => {
|
|
9444
|
-
const [expression, setExpression] =
|
|
9445
|
-
const [result, setResult] =
|
|
9446
|
-
const [error, setError] =
|
|
9447
|
-
const [focusedField, setFocusedField] =
|
|
9448
|
-
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);
|
|
9449
9060
|
const service = new UtilsService();
|
|
9450
|
-
|
|
9061
|
+
useInput12((input5, key) => {
|
|
9451
9062
|
if (key.tab) {
|
|
9452
9063
|
setFocusedField(focusedField === "expression" ? "parse" : "expression");
|
|
9453
9064
|
} else if (key.return) {
|
|
@@ -9485,8 +9096,8 @@ ${result.nextRuns.join("\n")}`;
|
|
|
9485
9096
|
} catch (error2) {
|
|
9486
9097
|
}
|
|
9487
9098
|
};
|
|
9488
|
-
return /* @__PURE__ */
|
|
9489
|
-
|
|
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,
|
|
9490
9101
|
{
|
|
9491
9102
|
flexDirection: "column",
|
|
9492
9103
|
borderStyle: "single",
|
|
@@ -9495,18 +9106,18 @@ ${result.nextRuns.join("\n")}`;
|
|
|
9495
9106
|
paddingY: 1,
|
|
9496
9107
|
marginBottom: 1
|
|
9497
9108
|
},
|
|
9498
|
-
/* @__PURE__ */
|
|
9499
|
-
/* @__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(
|
|
9500
9111
|
TextInput11,
|
|
9501
9112
|
{
|
|
9502
9113
|
value: expression,
|
|
9503
9114
|
onChange: setExpression,
|
|
9504
9115
|
placeholder: "0 5 * * * (5-field or 6-field)"
|
|
9505
9116
|
}
|
|
9506
|
-
) : /* @__PURE__ */
|
|
9507
|
-
/* @__PURE__ */
|
|
9508
|
-
/* @__PURE__ */
|
|
9509
|
-
|
|
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,
|
|
9510
9121
|
{
|
|
9511
9122
|
bold: true,
|
|
9512
9123
|
backgroundColor: focusedField === "parse" ? "green" : void 0,
|
|
@@ -9515,8 +9126,8 @@ ${result.nextRuns.join("\n")}`;
|
|
|
9515
9126
|
focusedField === "parse" ? "\u25B6 " : " ",
|
|
9516
9127
|
"[ Parse Expression ]"
|
|
9517
9128
|
))
|
|
9518
|
-
), error && /* @__PURE__ */
|
|
9519
|
-
|
|
9129
|
+
), error && /* @__PURE__ */ React20.createElement(
|
|
9130
|
+
Box16,
|
|
9520
9131
|
{
|
|
9521
9132
|
flexDirection: "column",
|
|
9522
9133
|
borderStyle: "single",
|
|
@@ -9525,9 +9136,9 @@ ${result.nextRuns.join("\n")}`;
|
|
|
9525
9136
|
paddingY: 1,
|
|
9526
9137
|
marginBottom: 1
|
|
9527
9138
|
},
|
|
9528
|
-
/* @__PURE__ */
|
|
9529
|
-
), result && /* @__PURE__ */
|
|
9530
|
-
|
|
9139
|
+
/* @__PURE__ */ React20.createElement(Text17, { color: "red" }, "\u2717 Error: ", error)
|
|
9140
|
+
), result && /* @__PURE__ */ React20.createElement(
|
|
9141
|
+
Box16,
|
|
9531
9142
|
{
|
|
9532
9143
|
flexDirection: "column",
|
|
9533
9144
|
borderStyle: "single",
|
|
@@ -9535,25 +9146,25 @@ ${result.nextRuns.join("\n")}`;
|
|
|
9535
9146
|
paddingX: 2,
|
|
9536
9147
|
paddingY: 1
|
|
9537
9148
|
},
|
|
9538
|
-
/* @__PURE__ */
|
|
9539
|
-
/* @__PURE__ */
|
|
9540
|
-
), /* @__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")));
|
|
9541
9152
|
};
|
|
9542
9153
|
|
|
9543
9154
|
// src/ui/utils/views/TimezoneView.tsx
|
|
9544
|
-
import
|
|
9545
|
-
import { Box as
|
|
9155
|
+
import React21, { useState as useState15 } from "react";
|
|
9156
|
+
import { Box as Box17, Text as Text18, useInput as useInput13 } from "ink";
|
|
9546
9157
|
import TextInput12 from "ink-text-input";
|
|
9547
9158
|
var TimezoneView = () => {
|
|
9548
|
-
const [time, setTime] =
|
|
9549
|
-
const [fromTz, setFromTz] =
|
|
9550
|
-
const [toTz, setToTz] =
|
|
9551
|
-
const [result, setResult] =
|
|
9552
|
-
const [error, setError] =
|
|
9553
|
-
const [focusedField, setFocusedField] =
|
|
9554
|
-
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);
|
|
9555
9166
|
const service = new UtilsService();
|
|
9556
|
-
|
|
9167
|
+
useInput13((input5, key) => {
|
|
9557
9168
|
if (key.tab) {
|
|
9558
9169
|
const fields = ["time", "from", "to", "convert"];
|
|
9559
9170
|
const currentIndex = fields.indexOf(focusedField);
|
|
@@ -9592,8 +9203,8 @@ var TimezoneView = () => {
|
|
|
9592
9203
|
} catch (error2) {
|
|
9593
9204
|
}
|
|
9594
9205
|
};
|
|
9595
|
-
return /* @__PURE__ */
|
|
9596
|
-
|
|
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,
|
|
9597
9208
|
{
|
|
9598
9209
|
flexDirection: "column",
|
|
9599
9210
|
borderStyle: "single",
|
|
@@ -9602,34 +9213,34 @@ var TimezoneView = () => {
|
|
|
9602
9213
|
paddingY: 1,
|
|
9603
9214
|
marginBottom: 1
|
|
9604
9215
|
},
|
|
9605
|
-
/* @__PURE__ */
|
|
9606
|
-
/* @__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(
|
|
9607
9218
|
TextInput12,
|
|
9608
9219
|
{
|
|
9609
9220
|
value: time,
|
|
9610
9221
|
onChange: setTime,
|
|
9611
9222
|
placeholder: "2024-01-15 10:00:00"
|
|
9612
9223
|
}
|
|
9613
|
-
) : /* @__PURE__ */
|
|
9614
|
-
/* @__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(
|
|
9615
9226
|
TextInput12,
|
|
9616
9227
|
{
|
|
9617
9228
|
value: fromTz,
|
|
9618
9229
|
onChange: setFromTz,
|
|
9619
9230
|
placeholder: "UTC or America/New_York"
|
|
9620
9231
|
}
|
|
9621
|
-
) : /* @__PURE__ */
|
|
9622
|
-
/* @__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(
|
|
9623
9234
|
TextInput12,
|
|
9624
9235
|
{
|
|
9625
9236
|
value: toTz,
|
|
9626
9237
|
onChange: setToTz,
|
|
9627
9238
|
placeholder: "Asia/Tokyo or Europe/London"
|
|
9628
9239
|
}
|
|
9629
|
-
) : /* @__PURE__ */
|
|
9630
|
-
/* @__PURE__ */
|
|
9631
|
-
/* @__PURE__ */
|
|
9632
|
-
|
|
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,
|
|
9633
9244
|
{
|
|
9634
9245
|
bold: true,
|
|
9635
9246
|
backgroundColor: focusedField === "convert" ? "green" : void 0,
|
|
@@ -9638,8 +9249,8 @@ var TimezoneView = () => {
|
|
|
9638
9249
|
focusedField === "convert" ? "\u25B6 " : " ",
|
|
9639
9250
|
"[ Convert ]"
|
|
9640
9251
|
))
|
|
9641
|
-
), error && /* @__PURE__ */
|
|
9642
|
-
|
|
9252
|
+
), error && /* @__PURE__ */ React21.createElement(
|
|
9253
|
+
Box17,
|
|
9643
9254
|
{
|
|
9644
9255
|
flexDirection: "column",
|
|
9645
9256
|
borderStyle: "single",
|
|
@@ -9648,9 +9259,9 @@ var TimezoneView = () => {
|
|
|
9648
9259
|
paddingY: 1,
|
|
9649
9260
|
marginBottom: 1
|
|
9650
9261
|
},
|
|
9651
|
-
/* @__PURE__ */
|
|
9652
|
-
), result && /* @__PURE__ */
|
|
9653
|
-
|
|
9262
|
+
/* @__PURE__ */ React21.createElement(Text18, { color: "red" }, "\u2717 Error: ", error)
|
|
9263
|
+
), result && /* @__PURE__ */ React21.createElement(
|
|
9264
|
+
Box17,
|
|
9654
9265
|
{
|
|
9655
9266
|
flexDirection: "column",
|
|
9656
9267
|
borderStyle: "single",
|
|
@@ -9658,28 +9269,28 @@ var TimezoneView = () => {
|
|
|
9658
9269
|
paddingX: 2,
|
|
9659
9270
|
paddingY: 1
|
|
9660
9271
|
},
|
|
9661
|
-
/* @__PURE__ */
|
|
9662
|
-
/* @__PURE__ */
|
|
9663
|
-
), /* @__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")));
|
|
9664
9275
|
};
|
|
9665
9276
|
|
|
9666
9277
|
// src/ui/utils/views/HttpView.tsx
|
|
9667
|
-
import
|
|
9668
|
-
import { Box as
|
|
9278
|
+
import React22, { useState as useState16 } from "react";
|
|
9279
|
+
import { Box as Box18, Text as Text19, useInput as useInput14 } from "ink";
|
|
9669
9280
|
import TextInput13 from "ink-text-input";
|
|
9670
9281
|
var METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE"];
|
|
9671
9282
|
var HttpView = () => {
|
|
9672
|
-
const [url, setUrl] =
|
|
9673
|
-
const [method, setMethod] =
|
|
9674
|
-
const [headers, setHeaders] =
|
|
9675
|
-
const [body, setBody] =
|
|
9676
|
-
const [response, setResponse] =
|
|
9677
|
-
const [error, setError] =
|
|
9678
|
-
const [loading, setLoading] =
|
|
9679
|
-
const [focusedField, setFocusedField] =
|
|
9680
|
-
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);
|
|
9681
9292
|
const service = new UtilsService();
|
|
9682
|
-
|
|
9293
|
+
useInput14((input5, key) => {
|
|
9683
9294
|
if (loading) return;
|
|
9684
9295
|
if (key.tab) {
|
|
9685
9296
|
const fields = ["url", "method", "headers", "body", "send"];
|
|
@@ -9740,8 +9351,8 @@ var HttpView = () => {
|
|
|
9740
9351
|
} catch (error2) {
|
|
9741
9352
|
}
|
|
9742
9353
|
};
|
|
9743
|
-
return /* @__PURE__ */
|
|
9744
|
-
|
|
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,
|
|
9745
9356
|
{
|
|
9746
9357
|
flexDirection: "column",
|
|
9747
9358
|
borderStyle: "single",
|
|
@@ -9750,34 +9361,34 @@ var HttpView = () => {
|
|
|
9750
9361
|
paddingY: 1,
|
|
9751
9362
|
marginBottom: 1
|
|
9752
9363
|
},
|
|
9753
|
-
/* @__PURE__ */
|
|
9754
|
-
/* @__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(
|
|
9755
9366
|
TextInput13,
|
|
9756
9367
|
{
|
|
9757
9368
|
value: url,
|
|
9758
9369
|
onChange: setUrl,
|
|
9759
9370
|
placeholder: "https://api.example.com/endpoint"
|
|
9760
9371
|
}
|
|
9761
|
-
) : /* @__PURE__ */
|
|
9762
|
-
/* @__PURE__ */
|
|
9763
|
-
/* @__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(
|
|
9764
9375
|
TextInput13,
|
|
9765
9376
|
{
|
|
9766
9377
|
value: headers,
|
|
9767
9378
|
onChange: setHeaders,
|
|
9768
9379
|
placeholder: "Authorization: Bearer token"
|
|
9769
9380
|
}
|
|
9770
|
-
) : /* @__PURE__ */
|
|
9771
|
-
(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(
|
|
9772
9383
|
TextInput13,
|
|
9773
9384
|
{
|
|
9774
9385
|
value: body,
|
|
9775
9386
|
onChange: setBody,
|
|
9776
9387
|
placeholder: '{"key":"value"}'
|
|
9777
9388
|
}
|
|
9778
|
-
) : /* @__PURE__ */
|
|
9779
|
-
/* @__PURE__ */
|
|
9780
|
-
|
|
9389
|
+
) : /* @__PURE__ */ React22.createElement(Text19, { dimColor: !body }, body || "(empty)"))),
|
|
9390
|
+
/* @__PURE__ */ React22.createElement(Box18, { marginTop: 1 }, /* @__PURE__ */ React22.createElement(
|
|
9391
|
+
Text19,
|
|
9781
9392
|
{
|
|
9782
9393
|
bold: true,
|
|
9783
9394
|
backgroundColor: focusedField === "send" ? "green" : void 0,
|
|
@@ -9788,8 +9399,8 @@ var HttpView = () => {
|
|
|
9788
9399
|
loading ? "Sending..." : "Send Request",
|
|
9789
9400
|
" ]"
|
|
9790
9401
|
))
|
|
9791
|
-
), error && /* @__PURE__ */
|
|
9792
|
-
|
|
9402
|
+
), error && /* @__PURE__ */ React22.createElement(
|
|
9403
|
+
Box18,
|
|
9793
9404
|
{
|
|
9794
9405
|
flexDirection: "column",
|
|
9795
9406
|
borderStyle: "single",
|
|
@@ -9798,9 +9409,9 @@ var HttpView = () => {
|
|
|
9798
9409
|
paddingY: 1,
|
|
9799
9410
|
marginBottom: 1
|
|
9800
9411
|
},
|
|
9801
|
-
/* @__PURE__ */
|
|
9802
|
-
), response && /* @__PURE__ */
|
|
9803
|
-
|
|
9412
|
+
/* @__PURE__ */ React22.createElement(Text19, { color: "red" }, "\u2717 Error: ", error)
|
|
9413
|
+
), response && /* @__PURE__ */ React22.createElement(
|
|
9414
|
+
Box18,
|
|
9804
9415
|
{
|
|
9805
9416
|
flexDirection: "column",
|
|
9806
9417
|
borderStyle: "single",
|
|
@@ -9808,23 +9419,23 @@ var HttpView = () => {
|
|
|
9808
9419
|
paddingX: 2,
|
|
9809
9420
|
paddingY: 1
|
|
9810
9421
|
},
|
|
9811
|
-
/* @__PURE__ */
|
|
9812
|
-
/* @__PURE__ */
|
|
9813
|
-
), /* @__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")));
|
|
9814
9425
|
};
|
|
9815
9426
|
|
|
9816
9427
|
// src/ui/utils/views/MarkdownView.tsx
|
|
9817
|
-
import
|
|
9818
|
-
import { Box as
|
|
9428
|
+
import React23, { useState as useState17 } from "react";
|
|
9429
|
+
import { Box as Box19, Text as Text20, useInput as useInput15 } from "ink";
|
|
9819
9430
|
import TextInput14 from "ink-text-input";
|
|
9820
9431
|
import * as fs15 from "fs";
|
|
9821
9432
|
import * as path7 from "path";
|
|
9822
9433
|
var MarkdownView = () => {
|
|
9823
|
-
const [filePath, setFilePath] =
|
|
9824
|
-
const [content, setContent] =
|
|
9825
|
-
const [error, setError] =
|
|
9826
|
-
const [focusedField, setFocusedField] =
|
|
9827
|
-
|
|
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) => {
|
|
9828
9439
|
if (key.tab) {
|
|
9829
9440
|
setFocusedField(focusedField === "file" ? "preview" : "file");
|
|
9830
9441
|
} else if (key.return) {
|
|
@@ -9865,8 +9476,8 @@ ${code.trim()}
|
|
|
9865
9476
|
setContent("");
|
|
9866
9477
|
}
|
|
9867
9478
|
};
|
|
9868
|
-
return /* @__PURE__ */
|
|
9869
|
-
|
|
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,
|
|
9870
9481
|
{
|
|
9871
9482
|
flexDirection: "column",
|
|
9872
9483
|
borderStyle: "single",
|
|
@@ -9875,17 +9486,17 @@ ${code.trim()}
|
|
|
9875
9486
|
paddingY: 1,
|
|
9876
9487
|
marginBottom: 1
|
|
9877
9488
|
},
|
|
9878
|
-
/* @__PURE__ */
|
|
9879
|
-
/* @__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(
|
|
9880
9491
|
TextInput14,
|
|
9881
9492
|
{
|
|
9882
9493
|
value: filePath,
|
|
9883
9494
|
onChange: setFilePath,
|
|
9884
9495
|
placeholder: "./README.md or /path/to/file.md"
|
|
9885
9496
|
}
|
|
9886
|
-
) : /* @__PURE__ */
|
|
9887
|
-
/* @__PURE__ */
|
|
9888
|
-
|
|
9497
|
+
) : /* @__PURE__ */ React23.createElement(Text20, { dimColor: !filePath }, filePath || "(empty)"))),
|
|
9498
|
+
/* @__PURE__ */ React23.createElement(Box19, { marginTop: 1 }, /* @__PURE__ */ React23.createElement(
|
|
9499
|
+
Text20,
|
|
9889
9500
|
{
|
|
9890
9501
|
bold: true,
|
|
9891
9502
|
backgroundColor: focusedField === "preview" ? "green" : void 0,
|
|
@@ -9894,8 +9505,8 @@ ${code.trim()}
|
|
|
9894
9505
|
focusedField === "preview" ? "\u25B6 " : " ",
|
|
9895
9506
|
"[ Preview File ]"
|
|
9896
9507
|
))
|
|
9897
|
-
), error && /* @__PURE__ */
|
|
9898
|
-
|
|
9508
|
+
), error && /* @__PURE__ */ React23.createElement(
|
|
9509
|
+
Box19,
|
|
9899
9510
|
{
|
|
9900
9511
|
flexDirection: "column",
|
|
9901
9512
|
borderStyle: "single",
|
|
@@ -9904,9 +9515,9 @@ ${code.trim()}
|
|
|
9904
9515
|
paddingY: 1,
|
|
9905
9516
|
marginBottom: 1
|
|
9906
9517
|
},
|
|
9907
|
-
/* @__PURE__ */
|
|
9908
|
-
), content && /* @__PURE__ */
|
|
9909
|
-
|
|
9518
|
+
/* @__PURE__ */ React23.createElement(Text20, { color: "red" }, "\u2717 Error: ", error)
|
|
9519
|
+
), content && /* @__PURE__ */ React23.createElement(
|
|
9520
|
+
Box19,
|
|
9910
9521
|
{
|
|
9911
9522
|
flexDirection: "column",
|
|
9912
9523
|
borderStyle: "single",
|
|
@@ -9914,9 +9525,9 @@ ${code.trim()}
|
|
|
9914
9525
|
paddingX: 2,
|
|
9915
9526
|
paddingY: 1
|
|
9916
9527
|
},
|
|
9917
|
-
/* @__PURE__ */
|
|
9918
|
-
/* @__PURE__ */
|
|
9919
|
-
), /* @__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")));
|
|
9920
9531
|
};
|
|
9921
9532
|
|
|
9922
9533
|
// src/ui/utils/UtilsApp.tsx
|
|
@@ -9936,10 +9547,10 @@ var MENU_ITEMS = [
|
|
|
9936
9547
|
{ id: "markdown", icon: "\u{1F4C4}", label: "Markdown", description: "Preview markdown" }
|
|
9937
9548
|
];
|
|
9938
9549
|
var UtilsApp = ({ onExit }) => {
|
|
9939
|
-
const [selectedIndex, setSelectedIndex] =
|
|
9940
|
-
const [activeView, setActiveView] =
|
|
9941
|
-
const { exit } =
|
|
9942
|
-
|
|
9550
|
+
const [selectedIndex, setSelectedIndex] = useState18(0);
|
|
9551
|
+
const [activeView, setActiveView] = useState18(null);
|
|
9552
|
+
const { exit } = useApp4();
|
|
9553
|
+
useInput16((input5, key) => {
|
|
9943
9554
|
if (activeView) {
|
|
9944
9555
|
if (key.escape) {
|
|
9945
9556
|
setActiveView(null);
|
|
@@ -9957,8 +9568,8 @@ var UtilsApp = ({ onExit }) => {
|
|
|
9957
9568
|
exit();
|
|
9958
9569
|
}
|
|
9959
9570
|
});
|
|
9960
|
-
return /* @__PURE__ */
|
|
9961
|
-
|
|
9571
|
+
return /* @__PURE__ */ React24.createElement(Box20, { flexDirection: "column", width: "100%", height: "100%" }, /* @__PURE__ */ React24.createElement(
|
|
9572
|
+
Box20,
|
|
9962
9573
|
{
|
|
9963
9574
|
borderStyle: "single",
|
|
9964
9575
|
borderColor: "cyan",
|
|
@@ -9966,10 +9577,10 @@ var UtilsApp = ({ onExit }) => {
|
|
|
9966
9577
|
paddingY: 0,
|
|
9967
9578
|
marginBottom: 1
|
|
9968
9579
|
},
|
|
9969
|
-
/* @__PURE__ */
|
|
9970
|
-
/* @__PURE__ */
|
|
9971
|
-
), /* @__PURE__ */
|
|
9972
|
-
|
|
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,
|
|
9973
9584
|
{
|
|
9974
9585
|
flexDirection: "column",
|
|
9975
9586
|
width: 30,
|
|
@@ -9979,9 +9590,9 @@ var UtilsApp = ({ onExit }) => {
|
|
|
9979
9590
|
paddingY: 1,
|
|
9980
9591
|
marginRight: 1
|
|
9981
9592
|
},
|
|
9982
|
-
/* @__PURE__ */
|
|
9983
|
-
MENU_ITEMS.map((item, index) => /* @__PURE__ */
|
|
9984
|
-
|
|
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,
|
|
9985
9596
|
{
|
|
9986
9597
|
color: selectedIndex === index && !activeView ? "green" : void 0,
|
|
9987
9598
|
bold: selectedIndex === index && !activeView,
|
|
@@ -9992,9 +9603,9 @@ var UtilsApp = ({ onExit }) => {
|
|
|
9992
9603
|
" ",
|
|
9993
9604
|
item.label
|
|
9994
9605
|
))),
|
|
9995
|
-
/* @__PURE__ */
|
|
9996
|
-
), /* @__PURE__ */
|
|
9997
|
-
|
|
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,
|
|
9998
9609
|
{
|
|
9999
9610
|
flexDirection: "column",
|
|
10000
9611
|
flexGrow: 1,
|
|
@@ -10003,21 +9614,21 @@ var UtilsApp = ({ onExit }) => {
|
|
|
10003
9614
|
paddingX: 2,
|
|
10004
9615
|
paddingY: 1
|
|
10005
9616
|
},
|
|
10006
|
-
activeView ? /* @__PURE__ */
|
|
10007
|
-
)), /* @__PURE__ */
|
|
10008
|
-
|
|
9617
|
+
activeView ? /* @__PURE__ */ React24.createElement(ActiveUtilityView, { utilityType: activeView }) : /* @__PURE__ */ React24.createElement(WelcomeView, { selectedItem: MENU_ITEMS[selectedIndex] })
|
|
9618
|
+
)), /* @__PURE__ */ React24.createElement(
|
|
9619
|
+
Box20,
|
|
10009
9620
|
{
|
|
10010
9621
|
borderStyle: "single",
|
|
10011
9622
|
borderColor: "gray",
|
|
10012
9623
|
paddingX: 2,
|
|
10013
9624
|
marginTop: 1
|
|
10014
9625
|
},
|
|
10015
|
-
/* @__PURE__ */
|
|
9626
|
+
/* @__PURE__ */ React24.createElement(Text21, { dimColor: true }, "jai1-cli | Use arrow keys or j/k to navigate")
|
|
10016
9627
|
));
|
|
10017
9628
|
};
|
|
10018
9629
|
var WelcomeView = ({ selectedItem }) => {
|
|
10019
|
-
return /* @__PURE__ */
|
|
10020
|
-
|
|
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,
|
|
10021
9632
|
{
|
|
10022
9633
|
borderStyle: "single",
|
|
10023
9634
|
borderColor: "yellow",
|
|
@@ -10025,49 +9636,49 @@ var WelcomeView = ({ selectedItem }) => {
|
|
|
10025
9636
|
paddingY: 1,
|
|
10026
9637
|
marginBottom: 2
|
|
10027
9638
|
},
|
|
10028
|
-
/* @__PURE__ */
|
|
10029
|
-
), /* @__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.")));
|
|
10030
9641
|
};
|
|
10031
9642
|
var ActiveUtilityView = ({ utilityType }) => {
|
|
10032
9643
|
switch (utilityType) {
|
|
10033
9644
|
case "password":
|
|
10034
|
-
return /* @__PURE__ */
|
|
9645
|
+
return /* @__PURE__ */ React24.createElement(PasswordView, null);
|
|
10035
9646
|
case "uuid":
|
|
10036
|
-
return /* @__PURE__ */
|
|
9647
|
+
return /* @__PURE__ */ React24.createElement(UuidView, null);
|
|
10037
9648
|
case "hash":
|
|
10038
|
-
return /* @__PURE__ */
|
|
9649
|
+
return /* @__PURE__ */ React24.createElement(HashView, null);
|
|
10039
9650
|
case "base64-encode":
|
|
10040
9651
|
case "base64-decode":
|
|
10041
|
-
return /* @__PURE__ */
|
|
9652
|
+
return /* @__PURE__ */ React24.createElement(Base64View, null);
|
|
10042
9653
|
case "url-encode":
|
|
10043
9654
|
case "url-decode":
|
|
10044
|
-
return /* @__PURE__ */
|
|
9655
|
+
return /* @__PURE__ */ React24.createElement(UrlView, null);
|
|
10045
9656
|
case "unix-time":
|
|
10046
|
-
return /* @__PURE__ */
|
|
9657
|
+
return /* @__PURE__ */ React24.createElement(UnixTimeView, null);
|
|
10047
9658
|
case "jwt":
|
|
10048
|
-
return /* @__PURE__ */
|
|
9659
|
+
return /* @__PURE__ */ React24.createElement(JwtView, null);
|
|
10049
9660
|
case "cron":
|
|
10050
|
-
return /* @__PURE__ */
|
|
9661
|
+
return /* @__PURE__ */ React24.createElement(CronView, null);
|
|
10051
9662
|
case "timezone":
|
|
10052
|
-
return /* @__PURE__ */
|
|
9663
|
+
return /* @__PURE__ */ React24.createElement(TimezoneView, null);
|
|
10053
9664
|
case "http":
|
|
10054
|
-
return /* @__PURE__ */
|
|
9665
|
+
return /* @__PURE__ */ React24.createElement(HttpView, null);
|
|
10055
9666
|
case "markdown":
|
|
10056
|
-
return /* @__PURE__ */
|
|
9667
|
+
return /* @__PURE__ */ React24.createElement(MarkdownView, null);
|
|
10057
9668
|
default:
|
|
10058
|
-
return /* @__PURE__ */
|
|
9669
|
+
return /* @__PURE__ */ React24.createElement(PlaceholderView, { utilityType });
|
|
10059
9670
|
}
|
|
10060
9671
|
};
|
|
10061
9672
|
var PlaceholderView = ({ utilityType }) => {
|
|
10062
9673
|
const item = MENU_ITEMS.find((m) => m.id === utilityType);
|
|
10063
|
-
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.")));
|
|
10064
9675
|
};
|
|
10065
9676
|
|
|
10066
9677
|
// src/commands/utils/interactive.ts
|
|
10067
9678
|
async function runInteractiveMode() {
|
|
10068
9679
|
return new Promise((resolve4) => {
|
|
10069
|
-
const { unmount, waitUntilExit } =
|
|
10070
|
-
|
|
9680
|
+
const { unmount, waitUntilExit } = render4(
|
|
9681
|
+
React25.createElement(UtilsApp, {
|
|
10071
9682
|
onExit: () => {
|
|
10072
9683
|
unmount();
|
|
10073
9684
|
resolve4();
|
|
@@ -10082,40 +9693,40 @@ async function runInteractiveMode() {
|
|
|
10082
9693
|
|
|
10083
9694
|
// src/commands/utils/index.ts
|
|
10084
9695
|
function showUtilsHelp() {
|
|
10085
|
-
console.log(
|
|
9696
|
+
console.log(chalk15.bold.cyan("\u{1F6E0}\uFE0F jai1 utils") + chalk15.dim(" - Developer utilities"));
|
|
10086
9697
|
console.log();
|
|
10087
|
-
console.log(
|
|
10088
|
-
console.log(` ${
|
|
10089
|
-
console.log(` ${
|
|
10090
|
-
console.log(` ${
|
|
10091
|
-
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`);
|
|
10092
9703
|
console.log();
|
|
10093
|
-
console.log(
|
|
10094
|
-
console.log(` ${
|
|
10095
|
-
console.log(` ${
|
|
10096
|
-
console.log(` ${
|
|
10097
|
-
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`);
|
|
10098
9709
|
console.log();
|
|
10099
|
-
console.log(
|
|
10100
|
-
console.log(` ${
|
|
10101
|
-
console.log(` ${
|
|
10102
|
-
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`);
|
|
10103
9714
|
console.log();
|
|
10104
|
-
console.log(
|
|
10105
|
-
console.log(` ${
|
|
10106
|
-
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`);
|
|
10107
9718
|
console.log();
|
|
10108
|
-
console.log(
|
|
10109
|
-
console.log(
|
|
10110
|
-
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"));
|
|
10111
9722
|
console.log();
|
|
10112
|
-
console.log(
|
|
10113
|
-
console.log(
|
|
10114
|
-
console.log(
|
|
10115
|
-
console.log(
|
|
10116
|
-
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"));
|
|
10117
9728
|
console.log();
|
|
10118
|
-
console.log(
|
|
9729
|
+
console.log(chalk15.dim('Ch\u1EA1y "jai1 utils <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt'));
|
|
10119
9730
|
}
|
|
10120
9731
|
function createUtilsCommand() {
|
|
10121
9732
|
const utilsCommand = new Command42("utils").description("Developer utilities for common tasks").option("-i, --interactive", "Run in interactive mode");
|
|
@@ -10144,11 +9755,11 @@ function createUtilsCommand() {
|
|
|
10144
9755
|
|
|
10145
9756
|
// src/commands/deps/index.ts
|
|
10146
9757
|
import { Command as Command45 } from "commander";
|
|
10147
|
-
import
|
|
9758
|
+
import chalk18 from "chalk";
|
|
10148
9759
|
|
|
10149
9760
|
// src/commands/deps/check.ts
|
|
10150
9761
|
import { Command as Command43 } from "commander";
|
|
10151
|
-
import
|
|
9762
|
+
import chalk16 from "chalk";
|
|
10152
9763
|
import Table4 from "cli-table3";
|
|
10153
9764
|
import ora from "ora";
|
|
10154
9765
|
|
|
@@ -10751,7 +10362,7 @@ function createDepsCheckCommand() {
|
|
|
10751
10362
|
if (projects.length === 0) {
|
|
10752
10363
|
spinner.fail("Kh\xF4ng t\xECm th\u1EA5y project n\xE0o \u0111\u01B0\u1EE3c h\u1ED7 tr\u1EE3");
|
|
10753
10364
|
console.log();
|
|
10754
|
-
console.log(
|
|
10365
|
+
console.log(chalk16.dim("H\u1ED7 tr\u1EE3: Node.js (package.json), PHP (composer.json), Python (requirements.txt/Pipfile)"));
|
|
10755
10366
|
process.exit(1);
|
|
10756
10367
|
}
|
|
10757
10368
|
spinner.succeed(`Ph\xE1t hi\u1EC7n ${projects.length} project:`);
|
|
@@ -10765,7 +10376,7 @@ function createDepsCheckCommand() {
|
|
|
10765
10376
|
await checkEcosystem(project.ecosystem, project.manager, cwd);
|
|
10766
10377
|
}
|
|
10767
10378
|
console.log();
|
|
10768
|
-
console.log(
|
|
10379
|
+
console.log(chalk16.dim('\u{1F4A1} Ch\u1EA1y "jai1 deps upgrade" \u0111\u1EC3 n\xE2ng c\u1EA5p packages.'));
|
|
10769
10380
|
});
|
|
10770
10381
|
return checkCommand;
|
|
10771
10382
|
}
|
|
@@ -10798,7 +10409,7 @@ async function checkEcosystem(ecosystem, manager, cwd) {
|
|
|
10798
10409
|
});
|
|
10799
10410
|
} catch (error) {
|
|
10800
10411
|
spinner.fail(`L\u1ED7i ki\u1EC3m tra ${label}`);
|
|
10801
|
-
console.log(
|
|
10412
|
+
console.log(chalk16.red(error.message));
|
|
10802
10413
|
console.log();
|
|
10803
10414
|
return;
|
|
10804
10415
|
}
|
|
@@ -10811,10 +10422,10 @@ async function checkEcosystem(ecosystem, manager, cwd) {
|
|
|
10811
10422
|
console.log();
|
|
10812
10423
|
const table = new Table4({
|
|
10813
10424
|
head: [
|
|
10814
|
-
|
|
10815
|
-
|
|
10816
|
-
|
|
10817
|
-
|
|
10425
|
+
chalk16.cyan("Package"),
|
|
10426
|
+
chalk16.cyan("Hi\u1EC7n t\u1EA1i"),
|
|
10427
|
+
chalk16.cyan("M\u1EDBi nh\u1EA5t"),
|
|
10428
|
+
chalk16.cyan("Lo\u1EA1i")
|
|
10818
10429
|
],
|
|
10819
10430
|
style: {
|
|
10820
10431
|
head: [],
|
|
@@ -10825,9 +10436,9 @@ async function checkEcosystem(ecosystem, manager, cwd) {
|
|
|
10825
10436
|
const upgradeIcon = pkg.upgradeType === "major" ? "\u{1F534}" : pkg.upgradeType === "minor" ? "\u{1F7E1}" : "\u{1F7E2}";
|
|
10826
10437
|
table.push([
|
|
10827
10438
|
`${upgradeIcon} ${pkg.name}`,
|
|
10828
|
-
|
|
10829
|
-
|
|
10830
|
-
pkg.type === "dev" ?
|
|
10439
|
+
chalk16.dim(pkg.current),
|
|
10440
|
+
chalk16.green(pkg.latest),
|
|
10441
|
+
pkg.type === "dev" ? chalk16.dim("dev") : "dep"
|
|
10831
10442
|
]);
|
|
10832
10443
|
}
|
|
10833
10444
|
console.log(table.toString());
|
|
@@ -10835,13 +10446,13 @@ async function checkEcosystem(ecosystem, manager, cwd) {
|
|
|
10835
10446
|
if (result.isLaravel) {
|
|
10836
10447
|
const blockedPackages = result.packages.filter((p) => p.blockedReason);
|
|
10837
10448
|
if (blockedPackages.length > 0) {
|
|
10838
|
-
console.log(
|
|
10449
|
+
console.log(chalk16.yellow("\u26A0\uFE0F Laravel major version upgrades blocked (nguy hi\u1EC3m):"));
|
|
10839
10450
|
for (const pkg of blockedPackages) {
|
|
10840
|
-
console.log(
|
|
10451
|
+
console.log(chalk16.dim(` - ${pkg.name}: ${pkg.current} \u2192 ${pkg.latest}`));
|
|
10841
10452
|
}
|
|
10842
10453
|
console.log();
|
|
10843
|
-
console.log(
|
|
10844
|
-
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}`));
|
|
10845
10456
|
console.log();
|
|
10846
10457
|
}
|
|
10847
10458
|
}
|
|
@@ -10850,7 +10461,7 @@ async function checkEcosystem(ecosystem, manager, cwd) {
|
|
|
10850
10461
|
// src/commands/deps/upgrade.ts
|
|
10851
10462
|
import { Command as Command44 } from "commander";
|
|
10852
10463
|
import { checkbox as checkbox3, confirm as confirm8 } from "@inquirer/prompts";
|
|
10853
|
-
import
|
|
10464
|
+
import chalk17 from "chalk";
|
|
10854
10465
|
import ora2 from "ora";
|
|
10855
10466
|
import Table5 from "cli-table3";
|
|
10856
10467
|
function createDepsUpgradeCommand() {
|
|
@@ -10867,7 +10478,7 @@ async function handleDepsUpgrade(options) {
|
|
|
10867
10478
|
if (projects.length === 0) {
|
|
10868
10479
|
spinner.fail("Kh\xF4ng t\xECm th\u1EA5y project n\xE0o \u0111\u01B0\u1EE3c h\u1ED7 tr\u1EE3");
|
|
10869
10480
|
console.log();
|
|
10870
|
-
console.log(
|
|
10481
|
+
console.log(chalk17.dim("H\u1ED7 tr\u1EE3: Node.js (package.json), PHP (composer.json), Python (requirements.txt/Pipfile)"));
|
|
10871
10482
|
process.exit(1);
|
|
10872
10483
|
}
|
|
10873
10484
|
spinner.succeed(`Ph\xE1t hi\u1EC7n ${projects.length} project:`);
|
|
@@ -10881,9 +10492,9 @@ async function handleDepsUpgrade(options) {
|
|
|
10881
10492
|
await upgradeEcosystem(project, cwd, options);
|
|
10882
10493
|
}
|
|
10883
10494
|
console.log();
|
|
10884
|
-
console.log(
|
|
10495
|
+
console.log(chalk17.green("\u2705 Ho\xE0n th\xE0nh!"));
|
|
10885
10496
|
} catch (error) {
|
|
10886
|
-
console.error(
|
|
10497
|
+
console.error(chalk17.red(`
|
|
10887
10498
|
\u274C ${error.message}
|
|
10888
10499
|
`));
|
|
10889
10500
|
process.exit(1);
|
|
@@ -10892,10 +10503,10 @@ async function handleDepsUpgrade(options) {
|
|
|
10892
10503
|
async function upgradeEcosystem(project, cwd, options) {
|
|
10893
10504
|
const service = getService(project.ecosystem);
|
|
10894
10505
|
const label = `${getEcosystemIcon(project.ecosystem)} ${getEcosystemLabel(project.ecosystem)}`;
|
|
10895
|
-
console.log(
|
|
10506
|
+
console.log(chalk17.bold.cyan(`
|
|
10896
10507
|
${"\u2501".repeat(80)}`));
|
|
10897
|
-
console.log(
|
|
10898
|
-
console.log(
|
|
10508
|
+
console.log(chalk17.bold.cyan(`${label}`));
|
|
10509
|
+
console.log(chalk17.bold.cyan("\u2501".repeat(80)));
|
|
10899
10510
|
console.log();
|
|
10900
10511
|
const spinner = ora2("\u0110ang ki\u1EC3m tra packages...").start();
|
|
10901
10512
|
let packages;
|
|
@@ -10906,7 +10517,7 @@ ${"\u2501".repeat(80)}`));
|
|
|
10906
10517
|
packages = result.packages;
|
|
10907
10518
|
} catch (error) {
|
|
10908
10519
|
spinner.fail("L\u1ED7i ki\u1EC3m tra packages");
|
|
10909
|
-
console.log(
|
|
10520
|
+
console.log(chalk17.red(error.message));
|
|
10910
10521
|
return;
|
|
10911
10522
|
}
|
|
10912
10523
|
if (packages.length === 0) {
|
|
@@ -10919,7 +10530,7 @@ ${"\u2501".repeat(80)}`));
|
|
|
10919
10530
|
let selectedPackages;
|
|
10920
10531
|
if (options.all) {
|
|
10921
10532
|
selectedPackages = packages;
|
|
10922
|
-
console.log(
|
|
10533
|
+
console.log(chalk17.cyan(`\u{1F4CB} \u0110\xE3 ch\u1ECDn t\u1EA5t c\u1EA3 ${selectedPackages.length} packages
|
|
10923
10534
|
`));
|
|
10924
10535
|
} else {
|
|
10925
10536
|
try {
|
|
@@ -10937,12 +10548,12 @@ ${"\u2501".repeat(80)}`));
|
|
|
10937
10548
|
theme: checkboxTheme
|
|
10938
10549
|
});
|
|
10939
10550
|
if (selected.length === 0) {
|
|
10940
|
-
console.log(
|
|
10551
|
+
console.log(chalk17.yellow("\u23F8\uFE0F Kh\xF4ng c\xF3 packages n\xE0o \u0111\u01B0\u1EE3c ch\u1ECDn\n"));
|
|
10941
10552
|
return;
|
|
10942
10553
|
}
|
|
10943
10554
|
selectedPackages = packages.filter((p) => selected.includes(p.name));
|
|
10944
10555
|
} catch {
|
|
10945
|
-
console.log(
|
|
10556
|
+
console.log(chalk17.yellow("\n\u23F8\uFE0F \u0110\xE3 h\u1EE7y\n"));
|
|
10946
10557
|
return;
|
|
10947
10558
|
}
|
|
10948
10559
|
}
|
|
@@ -10953,35 +10564,35 @@ ${"\u2501".repeat(80)}`));
|
|
|
10953
10564
|
default: true
|
|
10954
10565
|
});
|
|
10955
10566
|
} catch {
|
|
10956
|
-
console.log(
|
|
10567
|
+
console.log(chalk17.yellow("\n\u23F8\uFE0F \u0110\xE3 h\u1EE7y\n"));
|
|
10957
10568
|
return;
|
|
10958
10569
|
}
|
|
10959
10570
|
if (!shouldProceed) {
|
|
10960
|
-
console.log(
|
|
10571
|
+
console.log(chalk17.yellow("\u23F8\uFE0F Upgrade \u0111\xE3 h\u1EE7y\n"));
|
|
10961
10572
|
return;
|
|
10962
10573
|
}
|
|
10963
10574
|
console.log();
|
|
10964
|
-
console.log(
|
|
10965
|
-
console.log(
|
|
10575
|
+
console.log(chalk17.cyan(`\u{1F527} Package manager: ${project.manager}`));
|
|
10576
|
+
console.log(chalk17.cyan("\u{1F4E5} \u0110ang upgrade...\n"));
|
|
10966
10577
|
const commands = service.getUpgradeCommands(selectedPackages);
|
|
10967
10578
|
try {
|
|
10968
10579
|
if (commands.deps) {
|
|
10969
|
-
console.log(
|
|
10580
|
+
console.log(chalk17.dim(`$ ${commands.deps}
|
|
10970
10581
|
`));
|
|
10971
10582
|
}
|
|
10972
10583
|
if (commands.devDeps) {
|
|
10973
|
-
console.log(
|
|
10584
|
+
console.log(chalk17.dim(`$ ${commands.devDeps}
|
|
10974
10585
|
`));
|
|
10975
10586
|
}
|
|
10976
10587
|
await service.upgrade(cwd, { packages: selectedPackages });
|
|
10977
|
-
console.log(
|
|
10588
|
+
console.log(chalk17.green(`
|
|
10978
10589
|
\u2705 \u0110\xE3 upgrade ${selectedPackages.length} packages th\xE0nh c\xF4ng!`));
|
|
10979
10590
|
} catch (error) {
|
|
10980
|
-
console.error(
|
|
10981
|
-
console.error(
|
|
10982
|
-
console.log(
|
|
10983
|
-
if (commands.deps) console.log(
|
|
10984
|
-
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}`));
|
|
10985
10596
|
console.log();
|
|
10986
10597
|
throw error;
|
|
10987
10598
|
}
|
|
@@ -10989,10 +10600,10 @@ ${"\u2501".repeat(80)}`));
|
|
|
10989
10600
|
function displayUpgradeTable(packages) {
|
|
10990
10601
|
const table = new Table5({
|
|
10991
10602
|
head: [
|
|
10992
|
-
|
|
10993
|
-
|
|
10994
|
-
|
|
10995
|
-
|
|
10603
|
+
chalk17.cyan("Package"),
|
|
10604
|
+
chalk17.cyan("Hi\u1EC7n t\u1EA1i"),
|
|
10605
|
+
chalk17.cyan("M\u1EDBi nh\u1EA5t"),
|
|
10606
|
+
chalk17.cyan("Lo\u1EA1i")
|
|
10996
10607
|
],
|
|
10997
10608
|
style: {
|
|
10998
10609
|
head: [],
|
|
@@ -11003,9 +10614,9 @@ function displayUpgradeTable(packages) {
|
|
|
11003
10614
|
const upgradeIcon = pkg.upgradeType === "major" ? "\u{1F534}" : pkg.upgradeType === "minor" ? "\u{1F7E1}" : "\u{1F7E2}";
|
|
11004
10615
|
table.push([
|
|
11005
10616
|
`${upgradeIcon} ${pkg.name}`,
|
|
11006
|
-
|
|
11007
|
-
|
|
11008
|
-
pkg.type === "dev" ?
|
|
10617
|
+
chalk17.dim(pkg.current),
|
|
10618
|
+
chalk17.green(pkg.latest),
|
|
10619
|
+
pkg.type === "dev" ? chalk17.dim("dev") : "dep"
|
|
11009
10620
|
]);
|
|
11010
10621
|
}
|
|
11011
10622
|
console.log(table.toString());
|
|
@@ -11048,23 +10659,23 @@ function getEcosystemLabel(ecosystem) {
|
|
|
11048
10659
|
|
|
11049
10660
|
// src/commands/deps/index.ts
|
|
11050
10661
|
function showDepsHelp() {
|
|
11051
|
-
console.log(
|
|
10662
|
+
console.log(chalk18.bold.cyan("\u{1F4E6} jai1 deps") + chalk18.dim(" - Qu\u1EA3n l\xFD dependencies trong project"));
|
|
11052
10663
|
console.log();
|
|
11053
|
-
console.log(
|
|
11054
|
-
console.log(` ${
|
|
11055
|
-
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`);
|
|
11056
10667
|
console.log();
|
|
11057
|
-
console.log(
|
|
11058
|
-
console.log(
|
|
11059
|
-
console.log(
|
|
11060
|
-
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)"));
|
|
11061
10672
|
console.log();
|
|
11062
|
-
console.log(
|
|
11063
|
-
console.log(
|
|
11064
|
-
console.log(
|
|
11065
|
-
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"));
|
|
11066
10677
|
console.log();
|
|
11067
|
-
console.log(
|
|
10678
|
+
console.log(chalk18.dim('Ch\u1EA1y "jai1 deps <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt'));
|
|
11068
10679
|
}
|
|
11069
10680
|
function createDepsCommand() {
|
|
11070
10681
|
const depsCommand = new Command45("deps").description("Qu\u1EA3n l\xFD dependencies trong project").action(() => {
|
|
@@ -11080,13 +10691,13 @@ import { Command as Command56 } from "commander";
|
|
|
11080
10691
|
|
|
11081
10692
|
// src/commands/tasks/add.ts
|
|
11082
10693
|
import { Command as Command46 } from "commander";
|
|
11083
|
-
import
|
|
10694
|
+
import chalk19 from "chalk";
|
|
11084
10695
|
function createTaskAddCommand() {
|
|
11085
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) => {
|
|
11086
10697
|
const service = new TaskService();
|
|
11087
10698
|
const priority = Number(options.priority ?? 2);
|
|
11088
10699
|
if (priority < 0 || priority > 3) {
|
|
11089
|
-
console.error(
|
|
10700
|
+
console.error(chalk19.red("\u274C Priority must be 0-3"));
|
|
11090
10701
|
process.exit(1);
|
|
11091
10702
|
}
|
|
11092
10703
|
const tags = options.tags ? options.tags.split(",").map((t) => t.trim()) : [];
|
|
@@ -11102,21 +10713,21 @@ function createTaskAddCommand() {
|
|
|
11102
10713
|
}
|
|
11103
10714
|
const icon = PRIORITY_ICONS[task.priority] || "\u{1F7E1}";
|
|
11104
10715
|
const label = PRIORITY_LABELS[task.priority] || "Medium";
|
|
11105
|
-
console.log(
|
|
11106
|
-
console.log(` ${
|
|
11107
|
-
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}`);
|
|
11108
10719
|
if (task.parent) {
|
|
11109
|
-
console.log(` ${
|
|
10720
|
+
console.log(` ${chalk19.dim("Parent:")} ${task.parent}`);
|
|
11110
10721
|
}
|
|
11111
10722
|
if (task.tags.length > 0) {
|
|
11112
|
-
console.log(` ${
|
|
10723
|
+
console.log(` ${chalk19.dim("Tags:")} ${task.tags.join(", ")}`);
|
|
11113
10724
|
}
|
|
11114
10725
|
});
|
|
11115
10726
|
}
|
|
11116
10727
|
|
|
11117
10728
|
// src/commands/tasks/list.ts
|
|
11118
10729
|
import { Command as Command47 } from "commander";
|
|
11119
|
-
import
|
|
10730
|
+
import chalk20 from "chalk";
|
|
11120
10731
|
function createTaskListCommand() {
|
|
11121
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) => {
|
|
11122
10733
|
await handleTaskList(options);
|
|
@@ -11137,12 +10748,12 @@ async function handleTaskList(options) {
|
|
|
11137
10748
|
return;
|
|
11138
10749
|
}
|
|
11139
10750
|
if (tasks.length === 0) {
|
|
11140
|
-
console.log(
|
|
10751
|
+
console.log(chalk20.dim("No tasks found."));
|
|
11141
10752
|
return;
|
|
11142
10753
|
}
|
|
11143
10754
|
const doneIds = new Set(allTasks.filter((t) => t.status === "done").map((t) => t.id));
|
|
11144
10755
|
const header = options.parent ? `\u{1F4CB} ${options.parent} (${tasks.length} tasks)` : `\u{1F4CB} All tasks (${tasks.length})`;
|
|
11145
|
-
console.log(
|
|
10756
|
+
console.log(chalk20.bold(header));
|
|
11146
10757
|
console.log();
|
|
11147
10758
|
for (const task of tasks) {
|
|
11148
10759
|
printTaskLine(task, doneIds);
|
|
@@ -11152,23 +10763,23 @@ function printTaskLine(task, doneIds) {
|
|
|
11152
10763
|
const isBlocked = task.status === "todo" && task.depends_on.length > 0 && !task.depends_on.every((id) => doneIds.has(id));
|
|
11153
10764
|
const statusIcon = isBlocked ? BLOCKED_ICON : STATUS_ICONS[task.status] || "\u{1F4CB}";
|
|
11154
10765
|
const priorityIcon = PRIORITY_ICONS[task.priority] || "\u{1F7E1}";
|
|
11155
|
-
let line = ` ${statusIcon} ${
|
|
10766
|
+
let line = ` ${statusIcon} ${chalk20.dim(task.id)} P${task.priority}${priorityIcon} ${task.title}`;
|
|
11156
10767
|
if (task.status === "in_progress" && task.assigned_to) {
|
|
11157
|
-
line +=
|
|
10768
|
+
line += chalk20.cyan(` @${task.assigned_to}`);
|
|
11158
10769
|
}
|
|
11159
10770
|
if (isBlocked) {
|
|
11160
10771
|
const blockedBy = task.depends_on.filter((id) => !doneIds.has(id));
|
|
11161
|
-
line +=
|
|
10772
|
+
line += chalk20.red(` (blocked: ${blockedBy.join(", ")})`);
|
|
11162
10773
|
}
|
|
11163
10774
|
if (task.parent) {
|
|
11164
|
-
line +=
|
|
10775
|
+
line += chalk20.dim(` [${task.parent}]`);
|
|
11165
10776
|
}
|
|
11166
10777
|
console.log(line);
|
|
11167
10778
|
}
|
|
11168
10779
|
|
|
11169
10780
|
// src/commands/tasks/ready.ts
|
|
11170
10781
|
import { Command as Command48 } from "commander";
|
|
11171
|
-
import
|
|
10782
|
+
import chalk21 from "chalk";
|
|
11172
10783
|
function createTaskReadyCommand() {
|
|
11173
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) => {
|
|
11174
10785
|
const service = new TaskService();
|
|
@@ -11178,33 +10789,33 @@ function createTaskReadyCommand() {
|
|
|
11178
10789
|
return;
|
|
11179
10790
|
}
|
|
11180
10791
|
if (tasks.length === 0) {
|
|
11181
|
-
console.log(
|
|
11182
|
-
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"));
|
|
11183
10794
|
return;
|
|
11184
10795
|
}
|
|
11185
|
-
console.log(
|
|
10796
|
+
console.log(chalk21.bold(`\u{1F4CB} Ready to pick (${tasks.length} tasks):`));
|
|
11186
10797
|
console.log();
|
|
11187
10798
|
for (const task of tasks) {
|
|
11188
10799
|
const icon = PRIORITY_ICONS[task.priority] || "\u{1F7E1}";
|
|
11189
|
-
let line = ` P${task.priority}${icon} ${
|
|
10800
|
+
let line = ` P${task.priority}${icon} ${chalk21.dim(task.id)} ${task.title}`;
|
|
11190
10801
|
if (task.parent) {
|
|
11191
|
-
line +=
|
|
10802
|
+
line += chalk21.dim(` [${task.parent}]`);
|
|
11192
10803
|
}
|
|
11193
10804
|
console.log(line);
|
|
11194
10805
|
}
|
|
11195
10806
|
console.log();
|
|
11196
|
-
console.log(
|
|
10807
|
+
console.log(chalk21.dim("\u{1F4A1} Run: jai1 t pick"));
|
|
11197
10808
|
});
|
|
11198
10809
|
}
|
|
11199
10810
|
|
|
11200
10811
|
// src/commands/tasks/update.ts
|
|
11201
10812
|
import { Command as Command49 } from "commander";
|
|
11202
|
-
import
|
|
10813
|
+
import chalk22 from "chalk";
|
|
11203
10814
|
var VALID_STATUSES = ["todo", "in_progress", "done", "cancelled"];
|
|
11204
10815
|
function createTaskUpdateCommand() {
|
|
11205
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) => {
|
|
11206
10817
|
if (!VALID_STATUSES.includes(options.status)) {
|
|
11207
|
-
console.error(
|
|
10818
|
+
console.error(chalk22.red(`\u274C Invalid status. Must be: ${VALID_STATUSES.join(", ")}`));
|
|
11208
10819
|
process.exit(1);
|
|
11209
10820
|
}
|
|
11210
10821
|
const service = new TaskService();
|
|
@@ -11215,9 +10826,9 @@ function createTaskUpdateCommand() {
|
|
|
11215
10826
|
return;
|
|
11216
10827
|
}
|
|
11217
10828
|
const icon = STATUS_ICONS[task.status] || "\u{1F4CB}";
|
|
11218
|
-
console.log(
|
|
10829
|
+
console.log(chalk22.green(`\u2705 ${task.id} \u2192 ${icon} ${task.status}`));
|
|
11219
10830
|
} catch (error) {
|
|
11220
|
-
console.error(
|
|
10831
|
+
console.error(chalk22.red(`\u274C ${error instanceof Error ? error.message : String(error)}`));
|
|
11221
10832
|
process.exit(1);
|
|
11222
10833
|
}
|
|
11223
10834
|
});
|
|
@@ -11225,14 +10836,14 @@ function createTaskUpdateCommand() {
|
|
|
11225
10836
|
|
|
11226
10837
|
// src/commands/tasks/show.ts
|
|
11227
10838
|
import { Command as Command50 } from "commander";
|
|
11228
|
-
import
|
|
10839
|
+
import chalk23 from "chalk";
|
|
11229
10840
|
function createTaskShowCommand() {
|
|
11230
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) => {
|
|
11231
10842
|
const service = new TaskService();
|
|
11232
10843
|
if (query.startsWith("T-")) {
|
|
11233
10844
|
const task = await service.findById(query);
|
|
11234
10845
|
if (!task) {
|
|
11235
|
-
console.error(
|
|
10846
|
+
console.error(chalk23.red(`\u274C Task ${query} not found`));
|
|
11236
10847
|
process.exit(1);
|
|
11237
10848
|
}
|
|
11238
10849
|
if (options.json) {
|
|
@@ -11243,34 +10854,34 @@ function createTaskShowCommand() {
|
|
|
11243
10854
|
const statusIcon = blocked ? BLOCKED_ICON : STATUS_ICONS[task.status] || "\u{1F4CB}";
|
|
11244
10855
|
const priIcon = PRIORITY_ICONS[task.priority] || "\u{1F7E1}";
|
|
11245
10856
|
const priLabel = PRIORITY_LABELS[task.priority] || "Medium";
|
|
11246
|
-
console.log(
|
|
10857
|
+
console.log(chalk23.bold(`
|
|
11247
10858
|
\u{1F4CC} ${task.id}: ${task.title}
|
|
11248
10859
|
`));
|
|
11249
|
-
console.log(` ${
|
|
11250
|
-
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}`);
|
|
11251
10862
|
if (task.parent) {
|
|
11252
|
-
console.log(` ${
|
|
10863
|
+
console.log(` ${chalk23.dim("Parent:")} ${task.parent}`);
|
|
11253
10864
|
}
|
|
11254
10865
|
if (task.assigned_to) {
|
|
11255
|
-
console.log(` ${
|
|
10866
|
+
console.log(` ${chalk23.dim("Assigned:")} @${task.assigned_to} (${task.claimed_at})`);
|
|
11256
10867
|
}
|
|
11257
10868
|
if (task.depends_on.length > 0) {
|
|
11258
|
-
console.log(` ${
|
|
10869
|
+
console.log(` ${chalk23.dim("Depends on:")} ${task.depends_on.join(", ")}`);
|
|
11259
10870
|
if (blocked) {
|
|
11260
|
-
console.log(` ${
|
|
10871
|
+
console.log(` ${chalk23.dim("Blocked by:")} ${chalk23.red(blockedBy.join(", "))}`);
|
|
11261
10872
|
}
|
|
11262
10873
|
}
|
|
11263
10874
|
if (task.tags.length > 0) {
|
|
11264
|
-
console.log(` ${
|
|
10875
|
+
console.log(` ${chalk23.dim("Tags:")} ${task.tags.join(", ")}`);
|
|
11265
10876
|
}
|
|
11266
10877
|
if (task.branch) {
|
|
11267
|
-
console.log(` ${
|
|
10878
|
+
console.log(` ${chalk23.dim("Branch:")} ${task.branch}`);
|
|
11268
10879
|
}
|
|
11269
10880
|
if (task.notes) {
|
|
11270
|
-
console.log(` ${
|
|
10881
|
+
console.log(` ${chalk23.dim("Notes:")} ${task.notes}`);
|
|
11271
10882
|
}
|
|
11272
|
-
console.log(` ${
|
|
11273
|
-
console.log(` ${
|
|
10883
|
+
console.log(` ${chalk23.dim("Created:")} ${task.created}`);
|
|
10884
|
+
console.log(` ${chalk23.dim("Updated:")} ${task.updated}`);
|
|
11274
10885
|
console.log();
|
|
11275
10886
|
} else {
|
|
11276
10887
|
const tasks = await service.filter({ parent: query });
|
|
@@ -11279,10 +10890,10 @@ function createTaskShowCommand() {
|
|
|
11279
10890
|
return;
|
|
11280
10891
|
}
|
|
11281
10892
|
if (tasks.length === 0) {
|
|
11282
|
-
console.log(
|
|
10893
|
+
console.log(chalk23.dim(`No tasks for parent: ${query}`));
|
|
11283
10894
|
return;
|
|
11284
10895
|
}
|
|
11285
|
-
console.log(
|
|
10896
|
+
console.log(chalk23.bold(`
|
|
11286
10897
|
\u{1F4CB} ${query} (${tasks.length} tasks)
|
|
11287
10898
|
`));
|
|
11288
10899
|
const allTasks = await service.readAll();
|
|
@@ -11290,11 +10901,11 @@ function createTaskShowCommand() {
|
|
|
11290
10901
|
for (const task of tasks) {
|
|
11291
10902
|
const isBlocked = task.status === "todo" && task.depends_on.length > 0 && !task.depends_on.every((id) => doneIds.has(id));
|
|
11292
10903
|
const icon = isBlocked ? BLOCKED_ICON : STATUS_ICONS[task.status] || "\u{1F4CB}";
|
|
11293
|
-
let line = ` ${icon} ${
|
|
11294
|
-
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}`);
|
|
11295
10906
|
if (isBlocked) {
|
|
11296
10907
|
const bb = task.depends_on.filter((id) => !doneIds.has(id));
|
|
11297
|
-
line +=
|
|
10908
|
+
line += chalk23.red(` (blocked: ${bb.join(", ")})`);
|
|
11298
10909
|
}
|
|
11299
10910
|
console.log(line);
|
|
11300
10911
|
}
|
|
@@ -11305,7 +10916,7 @@ function createTaskShowCommand() {
|
|
|
11305
10916
|
|
|
11306
10917
|
// src/commands/tasks/pick.ts
|
|
11307
10918
|
import { Command as Command51 } from "commander";
|
|
11308
|
-
import
|
|
10919
|
+
import chalk24 from "chalk";
|
|
11309
10920
|
import { confirm as confirm9 } from "@inquirer/prompts";
|
|
11310
10921
|
function createTaskPickCommand() {
|
|
11311
10922
|
return new Command51("pick").description("Claim the next available task").option("-j, --json", "Output JSON").action(async (options) => {
|
|
@@ -11316,8 +10927,8 @@ function createTaskPickCommand() {
|
|
|
11316
10927
|
console.log(JSON.stringify({ picked: null, message: "No tasks ready" }));
|
|
11317
10928
|
return;
|
|
11318
10929
|
}
|
|
11319
|
-
console.log(
|
|
11320
|
-
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 "..."'));
|
|
11321
10932
|
return;
|
|
11322
10933
|
}
|
|
11323
10934
|
const top = ready[0];
|
|
@@ -11327,13 +10938,13 @@ function createTaskPickCommand() {
|
|
|
11327
10938
|
console.log(JSON.stringify(picked2, null, 2));
|
|
11328
10939
|
return;
|
|
11329
10940
|
}
|
|
11330
|
-
console.log(
|
|
11331
|
-
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}`);
|
|
11332
10943
|
if (top.parent) {
|
|
11333
|
-
console.log(` ${
|
|
10944
|
+
console.log(` ${chalk24.dim("Parent:")} ${top.parent}`);
|
|
11334
10945
|
}
|
|
11335
10946
|
if (ready.length > 1) {
|
|
11336
|
-
console.log(
|
|
10947
|
+
console.log(chalk24.dim(`
|
|
11337
10948
|
+${ready.length - 1} more tasks ready`));
|
|
11338
10949
|
}
|
|
11339
10950
|
const proceed = await confirm9({
|
|
@@ -11341,18 +10952,18 @@ function createTaskPickCommand() {
|
|
|
11341
10952
|
default: true
|
|
11342
10953
|
});
|
|
11343
10954
|
if (!proceed) {
|
|
11344
|
-
console.log(
|
|
10955
|
+
console.log(chalk24.dim("\nCancelled."));
|
|
11345
10956
|
return;
|
|
11346
10957
|
}
|
|
11347
10958
|
const picked = await service.pick(top.id);
|
|
11348
|
-
console.log(
|
|
10959
|
+
console.log(chalk24.green(`
|
|
11349
10960
|
\u2705 ${picked.id} assigned to @${picked.assigned_to}, status \u2192 in_progress`));
|
|
11350
10961
|
});
|
|
11351
10962
|
}
|
|
11352
10963
|
|
|
11353
10964
|
// src/commands/tasks/done.ts
|
|
11354
10965
|
import { Command as Command52 } from "commander";
|
|
11355
|
-
import
|
|
10966
|
+
import chalk25 from "chalk";
|
|
11356
10967
|
function createTaskDoneCommand() {
|
|
11357
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) => {
|
|
11358
10969
|
const service = new TaskService();
|
|
@@ -11362,9 +10973,9 @@ function createTaskDoneCommand() {
|
|
|
11362
10973
|
console.log(JSON.stringify(task, null, 2));
|
|
11363
10974
|
return;
|
|
11364
10975
|
}
|
|
11365
|
-
console.log(
|
|
10976
|
+
console.log(chalk25.green(`\u2705 ${task.id}: ${task.title} \u2192 done`));
|
|
11366
10977
|
} catch (error) {
|
|
11367
|
-
console.error(
|
|
10978
|
+
console.error(chalk25.red(`\u274C ${error instanceof Error ? error.message : String(error)}`));
|
|
11368
10979
|
process.exit(1);
|
|
11369
10980
|
}
|
|
11370
10981
|
});
|
|
@@ -11372,7 +10983,7 @@ function createTaskDoneCommand() {
|
|
|
11372
10983
|
|
|
11373
10984
|
// src/commands/tasks/dep.ts
|
|
11374
10985
|
import { Command as Command53 } from "commander";
|
|
11375
|
-
import
|
|
10986
|
+
import chalk26 from "chalk";
|
|
11376
10987
|
function createTaskDepCommand() {
|
|
11377
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) => {
|
|
11378
10989
|
const service = new TaskService();
|
|
@@ -11382,10 +10993,10 @@ function createTaskDepCommand() {
|
|
|
11382
10993
|
console.log(JSON.stringify(task, null, 2));
|
|
11383
10994
|
return;
|
|
11384
10995
|
}
|
|
11385
|
-
console.log(
|
|
11386
|
-
console.log(
|
|
10996
|
+
console.log(chalk26.green(`\u2705 ${childId} now depends on ${parentId}`));
|
|
10997
|
+
console.log(chalk26.dim(` ${task.title} \u2192 waits for ${parentId}`));
|
|
11387
10998
|
} catch (error) {
|
|
11388
|
-
console.error(
|
|
10999
|
+
console.error(chalk26.red(`\u274C ${error instanceof Error ? error.message : String(error)}`));
|
|
11389
11000
|
process.exit(1);
|
|
11390
11001
|
}
|
|
11391
11002
|
});
|
|
@@ -11393,27 +11004,27 @@ function createTaskDepCommand() {
|
|
|
11393
11004
|
|
|
11394
11005
|
// src/commands/tasks/sync.ts
|
|
11395
11006
|
import { Command as Command54 } from "commander";
|
|
11396
|
-
import
|
|
11007
|
+
import chalk27 from "chalk";
|
|
11397
11008
|
function createTaskSyncCommand() {
|
|
11398
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) => {
|
|
11399
11010
|
const service = new TaskService();
|
|
11400
11011
|
if (options.pull) {
|
|
11401
|
-
console.log(
|
|
11012
|
+
console.log(chalk27.dim("\u23F3 Pulling tasks from origin/main..."));
|
|
11402
11013
|
try {
|
|
11403
11014
|
const result = await service.syncPull();
|
|
11404
|
-
console.log(
|
|
11015
|
+
console.log(chalk27.green(`\u2705 Sync pull complete: ${result.merged} tasks merged`));
|
|
11405
11016
|
} catch (error) {
|
|
11406
|
-
console.error(
|
|
11017
|
+
console.error(chalk27.red(`\u274C ${error instanceof Error ? error.message : String(error)}`));
|
|
11407
11018
|
process.exit(1);
|
|
11408
11019
|
}
|
|
11409
11020
|
return;
|
|
11410
11021
|
}
|
|
11411
|
-
console.log(
|
|
11022
|
+
console.log(chalk27.dim("\u23F3 Syncing tasks to git..."));
|
|
11412
11023
|
try {
|
|
11413
11024
|
await service.syncPush();
|
|
11414
|
-
console.log(
|
|
11025
|
+
console.log(chalk27.green("\u2705 Tasks synced to git"));
|
|
11415
11026
|
} catch (error) {
|
|
11416
|
-
console.error(
|
|
11027
|
+
console.error(chalk27.red(`\u274C ${error instanceof Error ? error.message : String(error)}`));
|
|
11417
11028
|
process.exit(1);
|
|
11418
11029
|
}
|
|
11419
11030
|
});
|
|
@@ -11421,107 +11032,107 @@ function createTaskSyncCommand() {
|
|
|
11421
11032
|
|
|
11422
11033
|
// src/commands/tasks/guide.ts
|
|
11423
11034
|
import { Command as Command55 } from "commander";
|
|
11424
|
-
import
|
|
11035
|
+
import chalk28 from "chalk";
|
|
11425
11036
|
var GUIDE_TEXT = `
|
|
11426
|
-
${
|
|
11427
|
-
|
|
11428
|
-
${
|
|
11429
|
-
${
|
|
11430
|
-
${
|
|
11431
|
-
${
|
|
11432
|
-
${
|
|
11433
|
-
${
|
|
11434
|
-
|
|
11435
|
-
${
|
|
11436
|
-
${
|
|
11437
|
-
${
|
|
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
|
-
1. ${
|
|
11496
|
-
2. ${
|
|
11497
|
-
3. ${
|
|
11498
|
-
4. ${
|
|
11499
|
-
|
|
11500
|
-
${
|
|
11501
|
-
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>)
|
|
11502
11113
|
2. Implement task
|
|
11503
|
-
3. ${
|
|
11114
|
+
3. ${chalk28.cyan("jai1 t done")} <id>
|
|
11504
11115
|
|
|
11505
|
-
${
|
|
11116
|
+
${chalk28.dim("Status transitions:")}
|
|
11506
11117
|
add \u2192 todo (default)
|
|
11507
11118
|
pick \u2192 in_progress (auto assign)
|
|
11508
11119
|
done \u2192 done
|
|
11509
11120
|
update -s \u2192 any valid status
|
|
11510
11121
|
|
|
11511
|
-
${
|
|
11512
|
-
${
|
|
11513
|
-
${
|
|
11514
|
-
${
|
|
11515
|
-
${
|
|
11516
|
-
${
|
|
11517
|
-
${
|
|
11518
|
-
${
|
|
11519
|
-
${
|
|
11520
|
-
${
|
|
11521
|
-
${
|
|
11522
|
-
${
|
|
11523
|
-
|
|
11524
|
-
${
|
|
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)")}
|
|
11525
11136
|
`;
|
|
11526
11137
|
function createTaskGuideCommand() {
|
|
11527
11138
|
return new Command55("guide").description("Show full task management guide").action(() => {
|
|
@@ -11556,11 +11167,11 @@ function createTasksCommand() {
|
|
|
11556
11167
|
|
|
11557
11168
|
// src/commands/kit/index.ts
|
|
11558
11169
|
import { Command as Command60 } from "commander";
|
|
11559
|
-
import
|
|
11170
|
+
import chalk30 from "chalk";
|
|
11560
11171
|
|
|
11561
11172
|
// src/commands/kit/list.ts
|
|
11562
11173
|
import { Command as Command57 } from "commander";
|
|
11563
|
-
import
|
|
11174
|
+
import chalk29 from "chalk";
|
|
11564
11175
|
import Table6 from "cli-table3";
|
|
11565
11176
|
|
|
11566
11177
|
// src/services/starter-kit.service.ts
|
|
@@ -11634,7 +11245,7 @@ function createKitListCommand() {
|
|
|
11634
11245
|
if (!config) {
|
|
11635
11246
|
throw new ValidationError('Not initialized. Run "jai1 auth" first.');
|
|
11636
11247
|
}
|
|
11637
|
-
console.log(
|
|
11248
|
+
console.log(chalk29.cyan("\u{1F4E6} \u0110ang t\u1EA3i danh s\xE1ch starter kits..."));
|
|
11638
11249
|
console.log();
|
|
11639
11250
|
const kitService = new StarterKitService();
|
|
11640
11251
|
const kits = await kitService.list(config, {
|
|
@@ -11642,9 +11253,9 @@ function createKitListCommand() {
|
|
|
11642
11253
|
search: options.search
|
|
11643
11254
|
});
|
|
11644
11255
|
if (kits.length === 0) {
|
|
11645
|
-
console.log(
|
|
11256
|
+
console.log(chalk29.yellow("Kh\xF4ng t\xECm th\u1EA5y starter kits n\xE0o."));
|
|
11646
11257
|
if (options.category || options.search) {
|
|
11647
|
-
console.log(
|
|
11258
|
+
console.log(chalk29.dim("Th\u1EED b\u1ECF filter \u0111\u1EC3 xem t\u1EA5t c\u1EA3."));
|
|
11648
11259
|
}
|
|
11649
11260
|
return;
|
|
11650
11261
|
}
|
|
@@ -11668,28 +11279,28 @@ function createKitListCommand() {
|
|
|
11668
11279
|
const categoryKits = byCategory[category];
|
|
11669
11280
|
const categoryIcon = category === "frontend" ? "\u{1F3A8}" : category === "backend" ? "\u2699\uFE0F" : category === "fullstack" ? "\u{1F680}" : "\u{1F4E6}";
|
|
11670
11281
|
console.log(
|
|
11671
|
-
|
|
11282
|
+
chalk29.bold(`${categoryIcon} ${category.charAt(0).toUpperCase() + category.slice(1)}`)
|
|
11672
11283
|
);
|
|
11673
11284
|
const table = new Table6({
|
|
11674
11285
|
head: [
|
|
11675
|
-
|
|
11676
|
-
|
|
11677
|
-
|
|
11286
|
+
chalk29.cyan("Slug"),
|
|
11287
|
+
chalk29.cyan("M\xF4 t\u1EA3"),
|
|
11288
|
+
chalk29.cyan("Version")
|
|
11678
11289
|
],
|
|
11679
11290
|
style: { head: [], border: ["gray"] }
|
|
11680
11291
|
});
|
|
11681
11292
|
for (const kit of categoryKits) {
|
|
11682
11293
|
table.push([
|
|
11683
|
-
|
|
11684
|
-
|
|
11685
|
-
|
|
11294
|
+
chalk29.white(kit.slug),
|
|
11295
|
+
chalk29.dim(kit.description.slice(0, 50)),
|
|
11296
|
+
chalk29.green(`v${kit.version}`)
|
|
11686
11297
|
]);
|
|
11687
11298
|
}
|
|
11688
11299
|
console.log(table.toString());
|
|
11689
11300
|
console.log();
|
|
11690
11301
|
}
|
|
11691
|
-
console.log(
|
|
11692
|
-
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'));
|
|
11693
11304
|
});
|
|
11694
11305
|
}
|
|
11695
11306
|
|
|
@@ -11969,20 +11580,20 @@ async function getAllFiles(dir) {
|
|
|
11969
11580
|
|
|
11970
11581
|
// src/commands/kit/index.ts
|
|
11971
11582
|
function showKitHelp() {
|
|
11972
|
-
console.log(
|
|
11583
|
+
console.log(chalk30.bold.cyan("\u{1F4E6} jai1 kit") + chalk30.dim(" - Qu\u1EA3n l\xFD starter kits"));
|
|
11973
11584
|
console.log();
|
|
11974
|
-
console.log(
|
|
11975
|
-
console.log(` ${
|
|
11976
|
-
console.log(` ${
|
|
11977
|
-
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`);
|
|
11978
11589
|
console.log();
|
|
11979
|
-
console.log(
|
|
11980
|
-
console.log(
|
|
11981
|
-
console.log(
|
|
11982
|
-
console.log(
|
|
11983
|
-
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"));
|
|
11984
11595
|
console.log();
|
|
11985
|
-
console.log(
|
|
11596
|
+
console.log(chalk30.dim('Ch\u1EA1y "jai1 kit <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt'));
|
|
11986
11597
|
}
|
|
11987
11598
|
function createKitCommand() {
|
|
11988
11599
|
const cmd = new Command60("kit").description("Manage starter kits for new projects").action(() => {
|
|
@@ -11996,11 +11607,11 @@ function createKitCommand() {
|
|
|
11996
11607
|
|
|
11997
11608
|
// src/commands/rules/index.ts
|
|
11998
11609
|
import { Command as Command67 } from "commander";
|
|
11999
|
-
import
|
|
11610
|
+
import chalk32 from "chalk";
|
|
12000
11611
|
|
|
12001
11612
|
// src/commands/rules/list.ts
|
|
12002
11613
|
import { Command as Command61 } from "commander";
|
|
12003
|
-
import
|
|
11614
|
+
import chalk31 from "chalk";
|
|
12004
11615
|
import Table7 from "cli-table3";
|
|
12005
11616
|
function createRulesListCommand() {
|
|
12006
11617
|
return new Command61("list").description("List available rule presets").option("--json", "Output as JSON").action(async (options) => {
|
|
@@ -12009,7 +11620,7 @@ function createRulesListCommand() {
|
|
|
12009
11620
|
if (!config) {
|
|
12010
11621
|
throw new ValidationError('Not initialized. Run "jai1 auth" first.');
|
|
12011
11622
|
}
|
|
12012
|
-
console.log(
|
|
11623
|
+
console.log(chalk31.cyan("\u{1F4CB} \u0110ang t\u1EA3i danh s\xE1ch rule presets..."));
|
|
12013
11624
|
console.log();
|
|
12014
11625
|
try {
|
|
12015
11626
|
const response = await fetch(`${config.apiUrl}/api/rules/presets`, {
|
|
@@ -12026,23 +11637,23 @@ function createRulesListCommand() {
|
|
|
12026
11637
|
return;
|
|
12027
11638
|
}
|
|
12028
11639
|
if (data.total === 0) {
|
|
12029
|
-
console.log(
|
|
11640
|
+
console.log(chalk31.yellow("Kh\xF4ng c\xF3 presets n\xE0o."));
|
|
12030
11641
|
return;
|
|
12031
11642
|
}
|
|
12032
11643
|
console.log(
|
|
12033
|
-
|
|
11644
|
+
chalk31.green(`\u2713 T\xECm th\u1EA5y ${chalk31.bold(data.total)} preset${data.total > 1 ? "s" : ""}`)
|
|
12034
11645
|
);
|
|
12035
11646
|
console.log();
|
|
12036
11647
|
for (const preset of data.presets) {
|
|
12037
|
-
console.log(
|
|
11648
|
+
console.log(chalk31.bold.cyan(`\u{1F4E6} ${preset.slug}`));
|
|
12038
11649
|
const table = new Table7({
|
|
12039
11650
|
style: { head: [], border: ["gray"], compact: true },
|
|
12040
11651
|
colWidths: [15, 55]
|
|
12041
11652
|
});
|
|
12042
11653
|
table.push(
|
|
12043
|
-
[
|
|
12044
|
-
[
|
|
12045
|
-
[
|
|
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}`)]
|
|
12046
11657
|
);
|
|
12047
11658
|
const stackParts = [];
|
|
12048
11659
|
if (preset.stack.frontend) stackParts.push(preset.stack.frontend);
|
|
@@ -12050,16 +11661,16 @@ function createRulesListCommand() {
|
|
|
12050
11661
|
if (preset.stack.css) stackParts.push(preset.stack.css);
|
|
12051
11662
|
if (preset.stack.database) stackParts.push(preset.stack.database);
|
|
12052
11663
|
if (stackParts.length > 0) {
|
|
12053
|
-
table.push([
|
|
11664
|
+
table.push([chalk31.dim("Stack"), chalk31.yellow(stackParts.join(" + "))]);
|
|
12054
11665
|
}
|
|
12055
11666
|
table.push(
|
|
12056
|
-
[
|
|
12057
|
-
[
|
|
11667
|
+
[chalk31.dim("Tags"), chalk31.dim(preset.tags.join(", ") || "-")],
|
|
11668
|
+
[chalk31.dim("Downloads"), chalk31.white(preset.downloads.toString())]
|
|
12058
11669
|
);
|
|
12059
11670
|
console.log(table.toString());
|
|
12060
11671
|
console.log();
|
|
12061
11672
|
}
|
|
12062
|
-
console.log(
|
|
11673
|
+
console.log(chalk31.dim('\u{1F4A1} Ch\u1EA1y "jai1 rules apply <name>" \u0111\u1EC3 \xE1p d\u1EE5ng preset'));
|
|
12063
11674
|
} catch (error) {
|
|
12064
11675
|
throw new Error(
|
|
12065
11676
|
`L\u1ED7i khi t\u1EA3i presets: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -13487,23 +13098,23 @@ async function checkIdeFilesExist(ideId, format) {
|
|
|
13487
13098
|
|
|
13488
13099
|
// src/commands/rules/index.ts
|
|
13489
13100
|
function showRulesHelp() {
|
|
13490
|
-
console.log(
|
|
13101
|
+
console.log(chalk32.bold.cyan("\u{1F4CB} jai1 rules") + chalk32.dim(" - Qu\u1EA3n l\xFD rule presets cho AI agents"));
|
|
13491
13102
|
console.log();
|
|
13492
|
-
console.log(
|
|
13493
|
-
console.log(` ${
|
|
13494
|
-
console.log(` ${
|
|
13495
|
-
console.log(` ${
|
|
13496
|
-
console.log(` ${
|
|
13497
|
-
console.log(` ${
|
|
13498
|
-
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`);
|
|
13499
13110
|
console.log();
|
|
13500
|
-
console.log(
|
|
13501
|
-
console.log(
|
|
13502
|
-
console.log(
|
|
13503
|
-
console.log(
|
|
13504
|
-
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"));
|
|
13505
13116
|
console.log();
|
|
13506
|
-
console.log(
|
|
13117
|
+
console.log(chalk32.dim('Ch\u1EA1y "jai1 rules <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt'));
|
|
13507
13118
|
}
|
|
13508
13119
|
function createRulesCommand() {
|
|
13509
13120
|
const rulesCommand = new Command67("rules").description("Manage rule presets for AI agents").action(() => {
|
|
@@ -15236,92 +14847,11 @@ async function resetSettings2(groupKeys) {
|
|
|
15236
14847
|
console.log("\u{1F4A1} M\u1EB9o: Kh\u1EDFi \u0111\u1ED9ng l\u1EA1i VSCode \u0111\u1EC3 \xE1p d\u1EE5ng c\xE1c thay \u0111\u1ED5i.");
|
|
15237
14848
|
}
|
|
15238
14849
|
|
|
15239
|
-
// src/commands/context.ts
|
|
15240
|
-
import React32 from "react";
|
|
15241
|
-
import { render as render6 } from "ink";
|
|
15242
|
-
import { Command as Command77 } from "commander";
|
|
15243
|
-
function createContextCommand() {
|
|
15244
|
-
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) => {
|
|
15245
|
-
let initialIDE;
|
|
15246
|
-
if (options.ide) {
|
|
15247
|
-
const validIDEs = ["cursor", "windsurf", "antigravity", "jai1"];
|
|
15248
|
-
if (!validIDEs.includes(options.ide)) {
|
|
15249
|
-
console.error(`\u274C IDE kh\xF4ng h\u1EE3p l\u1EC7: ${options.ide}`);
|
|
15250
|
-
console.error(` IDE h\u1EE3p l\u1EC7: ${validIDEs.join(", ")}`);
|
|
15251
|
-
process.exit(1);
|
|
15252
|
-
}
|
|
15253
|
-
initialIDE = options.ide;
|
|
15254
|
-
}
|
|
15255
|
-
let initialType;
|
|
15256
|
-
if (options.type) {
|
|
15257
|
-
const validTypes = ["rules", "workflows", "skills", "agents", "prompts", "context"];
|
|
15258
|
-
if (!validTypes.includes(options.type)) {
|
|
15259
|
-
console.error(`\u274C Lo\u1EA1i context kh\xF4ng h\u1EE3p l\u1EC7: ${options.type}`);
|
|
15260
|
-
console.error(` Lo\u1EA1i h\u1EE3p l\u1EC7: ${validTypes.join(", ")}`);
|
|
15261
|
-
process.exit(1);
|
|
15262
|
-
}
|
|
15263
|
-
initialType = options.type;
|
|
15264
|
-
}
|
|
15265
|
-
if (options.stats) {
|
|
15266
|
-
await printStats2();
|
|
15267
|
-
return;
|
|
15268
|
-
}
|
|
15269
|
-
const { waitUntilExit } = render6(
|
|
15270
|
-
React32.createElement(ContextApp, {
|
|
15271
|
-
initialIDE,
|
|
15272
|
-
initialType,
|
|
15273
|
-
onExit: () => {
|
|
15274
|
-
process.exit(0);
|
|
15275
|
-
}
|
|
15276
|
-
})
|
|
15277
|
-
);
|
|
15278
|
-
await waitUntilExit();
|
|
15279
|
-
});
|
|
15280
|
-
return cmd;
|
|
15281
|
-
}
|
|
15282
|
-
async function printStats2() {
|
|
15283
|
-
const scanner = new ContextScannerService();
|
|
15284
|
-
console.log("\u{1F50D} \u0110ang qu\xE9t context...\n");
|
|
15285
|
-
try {
|
|
15286
|
-
const context = await scanner.scanAll();
|
|
15287
|
-
if (context.ides.length === 0) {
|
|
15288
|
-
console.log("\u26A0\uFE0F Kh\xF4ng t\xECm th\u1EA5y context n\xE0o");
|
|
15289
|
-
console.log(" H\xE3y ch\u1EA1y `jai1 apply` \u0111\u1EC3 c\xE0i \u0111\u1EB7t context cho IDE c\u1EE7a b\u1EA1n.\n");
|
|
15290
|
-
return;
|
|
15291
|
-
}
|
|
15292
|
-
console.log("\u{1F4CA} Th\u1ED1ng k\xEA Context\n");
|
|
15293
|
-
console.log(`\u{1F4C1} Project: ${context.projectPath}`);
|
|
15294
|
-
console.log(`\u{1F550} Scan time: ${context.scanTime.toLocaleString("vi-VN")}
|
|
15295
|
-
`);
|
|
15296
|
-
for (const ideContext of context.ides) {
|
|
15297
|
-
console.log(`${ideContext.config.icon} ${ideContext.config.name}`);
|
|
15298
|
-
console.log(` Path: ${ideContext.config.basePath}`);
|
|
15299
|
-
console.log(` Items: ${ideContext.stats.totalItems}`);
|
|
15300
|
-
const types = [];
|
|
15301
|
-
if (ideContext.stats.byType.rules) types.push(`${ideContext.stats.byType.rules} rules`);
|
|
15302
|
-
if (ideContext.stats.byType.workflows) types.push(`${ideContext.stats.byType.workflows} workflows`);
|
|
15303
|
-
if (ideContext.stats.byType.skills) types.push(`${ideContext.stats.byType.skills} skills`);
|
|
15304
|
-
if (ideContext.stats.byType.agents) types.push(`${ideContext.stats.byType.agents} agents`);
|
|
15305
|
-
if (ideContext.stats.byType.prompts) types.push(`${ideContext.stats.byType.prompts} prompts`);
|
|
15306
|
-
if (ideContext.stats.byType.context) types.push(`${ideContext.stats.byType.context} context`);
|
|
15307
|
-
if (types.length > 0) {
|
|
15308
|
-
console.log(` Breakdown: ${types.join(", ")}`);
|
|
15309
|
-
}
|
|
15310
|
-
console.log("");
|
|
15311
|
-
}
|
|
15312
|
-
console.log(`\u2705 T\u1ED5ng: ${context.totalItems} items
|
|
15313
|
-
`);
|
|
15314
|
-
} catch (error) {
|
|
15315
|
-
console.error("\u274C L\u1ED7i khi qu\xE9t context:", error);
|
|
15316
|
-
process.exit(1);
|
|
15317
|
-
}
|
|
15318
|
-
}
|
|
15319
|
-
|
|
15320
14850
|
// src/commands/migrate-ide.ts
|
|
15321
|
-
import { Command as
|
|
14851
|
+
import { Command as Command77 } from "commander";
|
|
15322
14852
|
import { checkbox as checkbox8, confirm as confirm19 } from "@inquirer/prompts";
|
|
15323
14853
|
function createMigrateIdeCommand() {
|
|
15324
|
-
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) => {
|
|
15325
14855
|
await runMigrateIde(options);
|
|
15326
14856
|
});
|
|
15327
14857
|
return cmd;
|
|
@@ -15430,62 +14960,62 @@ async function runMigrateIde(options) {
|
|
|
15430
14960
|
|
|
15431
14961
|
// src/utils/help-formatter.ts
|
|
15432
14962
|
import boxen4 from "boxen";
|
|
15433
|
-
import
|
|
14963
|
+
import chalk33 from "chalk";
|
|
15434
14964
|
import gradient from "gradient-string";
|
|
15435
14965
|
import figlet from "figlet";
|
|
15436
14966
|
function showCustomHelp(version) {
|
|
15437
14967
|
const title = figlet.textSync("JAI1", { font: "Small" });
|
|
15438
14968
|
console.log(gradient.pastel(title));
|
|
15439
14969
|
console.log(
|
|
15440
|
-
boxen4(
|
|
14970
|
+
boxen4(chalk33.cyan(`Agentic Coding CLI v${version}`), {
|
|
15441
14971
|
padding: { left: 1, right: 1, top: 0, bottom: 0 },
|
|
15442
14972
|
borderStyle: "round",
|
|
15443
14973
|
borderColor: "cyan"
|
|
15444
14974
|
})
|
|
15445
14975
|
);
|
|
15446
|
-
console.log(
|
|
14976
|
+
console.log(chalk33.bold("\n\u{1F527} Thi\u1EBFt l\u1EADp & Th\xF4ng tin"));
|
|
15447
14977
|
console.log(" auth X\xE1c th\u1EF1c v\xE0 c\u1EA5u h\xECnh client");
|
|
15448
14978
|
console.log(" status Hi\u1EC3n th\u1ECB tr\u1EA1ng th\xE1i c\u1EA5u h\xECnh");
|
|
15449
14979
|
console.log(" client-info T\u1EA1o th\xF4ng tin client \u0111\u1EC3 g\u1EEDi \u0111\u1ED9i ph\xE1t tri\u1EC3n");
|
|
15450
14980
|
console.log(" errors Qu\u1EA3n l\xFD error logs c\u1EE5c b\u1ED9");
|
|
15451
14981
|
console.log(" guide H\u01B0\u1EDBng d\u1EABn s\u1EED d\u1EE5ng nhanh");
|
|
15452
14982
|
console.log(" doctor Chu\u1EA9n \u0111o\xE1n project hi\u1EC7n t\u1EA1i");
|
|
15453
|
-
console.log(
|
|
14983
|
+
console.log(chalk33.bold("\n\u{1F4E6} Qu\u1EA3n l\xFD Components"));
|
|
15454
14984
|
console.log(" apply C\xE0i \u0111\u1EB7t components (interactive)");
|
|
15455
14985
|
console.log(" update C\u1EADp nh\u1EADt components \u0111\xE3 c\xE0i");
|
|
15456
14986
|
console.log(" check Ki\u1EC3m tra c\u1EADp nh\u1EADt t\u1EEB server");
|
|
15457
|
-
console.log(
|
|
14987
|
+
console.log(chalk33.bold("\n\u{1F5A5}\uFE0F IDE & T\xEDch h\u1EE3p"));
|
|
15458
14988
|
console.log(" ide L\u1EC7nh c\u1EA5u h\xECnh IDE");
|
|
15459
14989
|
console.log(" chat Chat AI v\u1EDBi Jai1 LLM Proxy");
|
|
15460
14990
|
console.log(" openai-keys Th\xF4ng tin API credentials");
|
|
15461
|
-
console.log(
|
|
14991
|
+
console.log(chalk33.bold("\n\u{1F916} AI Tools"));
|
|
15462
14992
|
console.log(" translate D\u1ECBch v\u0103n b\u1EA3n/file b\u1EB1ng AI");
|
|
15463
14993
|
console.log(" image T\u1EA1o \u1EA3nh (Coming Soon)");
|
|
15464
14994
|
console.log(" stats Th\u1ED1ng k\xEA s\u1EED d\u1EE5ng LLM");
|
|
15465
14995
|
console.log(" feedback G\u1EEDi b\xE1o c\xE1o/\u0111\u1EC1 xu\u1EA5t");
|
|
15466
|
-
console.log(
|
|
14996
|
+
console.log(chalk33.bold("\n\u{1F4C1} Project"));
|
|
15467
14997
|
console.log(" kit Qu\u1EA3n l\xFD starter kits");
|
|
15468
14998
|
console.log(" rules Qu\u1EA3n l\xFD rule presets");
|
|
15469
14999
|
console.log(" deps Qu\u1EA3n l\xFD dependencies");
|
|
15470
15000
|
console.log(" redmine Redmine context sync");
|
|
15471
|
-
console.log(
|
|
15001
|
+
console.log(chalk33.bold("\n\u2699\uFE0F B\u1EA3o tr\xEC"));
|
|
15472
15002
|
console.log(" upgrade C\u1EADp nh\u1EADt CLI client");
|
|
15473
15003
|
console.log(" clean D\u1ECDn d\u1EB9p cache/backup");
|
|
15474
15004
|
console.log(" utils Developer utilities");
|
|
15475
15005
|
const name = getCliName();
|
|
15476
|
-
console.log(
|
|
15006
|
+
console.log(chalk33.dim(`
|
|
15477
15007
|
S\u1EED d\u1EE5ng: ${name} [l\u1EC7nh] --help \u0111\u1EC3 xem chi ti\u1EBFt`));
|
|
15478
15008
|
}
|
|
15479
15009
|
function showUnknownCommand(commandName) {
|
|
15480
|
-
console.error(
|
|
15010
|
+
console.error(chalk33.red(`\u274C L\u1EC7nh kh\xF4ng t\u1ED3n t\u1EA1i: ${commandName}`));
|
|
15481
15011
|
const name = getCliName();
|
|
15482
|
-
console.error(
|
|
15012
|
+
console.error(chalk33.dim(`
|
|
15483
15013
|
G\u1EE3i \xFD: Ch\u1EA1y ${name} --help \u0111\u1EC3 xem danh s\xE1ch l\u1EC7nh`));
|
|
15484
15014
|
}
|
|
15485
15015
|
|
|
15486
15016
|
// src/cli.ts
|
|
15487
15017
|
checkNodeVersion();
|
|
15488
|
-
var program = new
|
|
15018
|
+
var program = new Command78();
|
|
15489
15019
|
if (process.argv.includes("-v") || process.argv.includes("--version")) {
|
|
15490
15020
|
console.log(package_default.version);
|
|
15491
15021
|
if (!process.argv.includes("--skip-update-check")) {
|
|
@@ -15524,9 +15054,9 @@ program.addCommand(createKitCommand());
|
|
|
15524
15054
|
program.addCommand(createRulesCommand());
|
|
15525
15055
|
program.addCommand(createUpgradeCommand());
|
|
15526
15056
|
program.addCommand(createCleanCommand());
|
|
15527
|
-
var redmineCommand = new
|
|
15057
|
+
var redmineCommand = new Command78("redmine").description("Redmine context sync commands");
|
|
15528
15058
|
redmineCommand.addCommand(createRedmineCheckCommand());
|
|
15529
|
-
var syncCommand = new
|
|
15059
|
+
var syncCommand = new Command78("sync").description("Sync Redmine issues to markdown files");
|
|
15530
15060
|
syncCommand.addCommand(createSyncIssueCommand());
|
|
15531
15061
|
syncCommand.addCommand(createSyncProjectCommand());
|
|
15532
15062
|
redmineCommand.addCommand(syncCommand);
|