@jvittechs/jai1-cli 0.1.66 → 0.1.68

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 CHANGED
@@ -33,7 +33,7 @@ var NetworkError = class extends Jai1Error {
33
33
  // package.json
34
34
  var package_default = {
35
35
  name: "@jvittechs/jai1-cli",
36
- version: "0.1.66",
36
+ version: "0.1.68",
37
37
  description: "Unified CLI for Jai1 Framework Management and Redmine Context Sync",
38
38
  type: "module",
39
39
  bin: {
@@ -388,9 +388,9 @@ async function handleAuth(options) {
388
388
  output: process.stdout
389
389
  });
390
390
  const question = (prompt) => {
391
- return new Promise((resolve3) => {
391
+ return new Promise((resolve4) => {
392
392
  rl.question(prompt, (answer) => {
393
- resolve3(answer);
393
+ resolve4(answer);
394
394
  });
395
395
  });
396
396
  };
@@ -3534,7 +3534,7 @@ var AgenticGuideView = ({ onBack }) => {
3534
3534
  setMessages((prev) => [...prev, userMessage]);
3535
3535
  setInputValue("");
3536
3536
  setIsTyping(true);
3537
- await new Promise((resolve3) => setTimeout(resolve3, 800 + Math.random() * 700));
3537
+ await new Promise((resolve4) => setTimeout(resolve4, 800 + Math.random() * 700));
3538
3538
  const response = getMockResponse(text);
3539
3539
  const assistantMessage = {
3540
3540
  id: `assistant-${Date.now()}`,
@@ -5717,12 +5717,1231 @@ Examples:
5717
5717
  }
5718
5718
 
5719
5719
  // src/commands/utils/interactive.ts
5720
- import React28 from "react";
5720
+ import React39 from "react";
5721
5721
  import { render as render5 } from "ink";
5722
5722
 
5723
5723
  // src/ui/utils/UtilsApp.tsx
5724
+ import React38, { useState as useState25 } from "react";
5725
+ import { Box as Box28, Text as Text29, useInput as useInput23, useApp as useApp5 } from "ink";
5726
+
5727
+ // src/ui/utils/views/PasswordView.tsx
5724
5728
  import React27, { useState as useState14 } from "react";
5725
- import { Box as Box17, Text as Text18, useInput as useInput12, useApp as useApp5 } from "ink";
5729
+ import { Box as Box17, Text as Text18, useInput as useInput12 } from "ink";
5730
+ import TextInput4 from "ink-text-input";
5731
+ var PasswordView = () => {
5732
+ const [length, setLength] = useState14("16");
5733
+ const [count, setCount] = useState14("1");
5734
+ const [passwords, setPasswords] = useState14([]);
5735
+ const [focusedField, setFocusedField] = useState14("length");
5736
+ const [copiedIndex, setCopiedIndex] = useState14(null);
5737
+ const service = new UtilsService();
5738
+ useInput12((input, key) => {
5739
+ if (key.tab) {
5740
+ if (focusedField === "length") setFocusedField("count");
5741
+ else if (focusedField === "count") setFocusedField("generate");
5742
+ else setFocusedField("length");
5743
+ } else if (key.return && focusedField === "generate") {
5744
+ handleGenerate();
5745
+ } else if (input === "c" && passwords.length > 0) {
5746
+ handleCopy(0);
5747
+ }
5748
+ });
5749
+ const handleGenerate = () => {
5750
+ const newPasswords = [];
5751
+ const lengthNum = parseInt(length, 10) || 16;
5752
+ const countNum = parseInt(count, 10) || 1;
5753
+ for (let i = 0; i < countNum; i++) {
5754
+ newPasswords.push(
5755
+ service.generatePassword({
5756
+ length: lengthNum,
5757
+ lowercase: true,
5758
+ uppercase: true,
5759
+ digits: true,
5760
+ symbols: true
5761
+ })
5762
+ );
5763
+ }
5764
+ setPasswords(newPasswords);
5765
+ setCopiedIndex(null);
5766
+ };
5767
+ const handleCopy = async (index) => {
5768
+ try {
5769
+ const { default: clipboardy } = await import("clipboardy");
5770
+ await clipboardy.write(passwords[index]);
5771
+ setCopiedIndex(index);
5772
+ setTimeout(() => setCopiedIndex(null), 2e3);
5773
+ } catch (error) {
5774
+ }
5775
+ };
5776
+ return /* @__PURE__ */ React27.createElement(Box17, { flexDirection: "column" }, /* @__PURE__ */ React27.createElement(Box17, { marginBottom: 1 }, /* @__PURE__ */ React27.createElement(Text18, { bold: true, color: "cyan" }, "\u{1F510} Password Generator")), /* @__PURE__ */ React27.createElement(
5777
+ Box17,
5778
+ {
5779
+ flexDirection: "column",
5780
+ borderStyle: "single",
5781
+ borderColor: "gray",
5782
+ paddingX: 2,
5783
+ paddingY: 1,
5784
+ marginBottom: 1
5785
+ },
5786
+ /* @__PURE__ */ React27.createElement(Text18, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
5787
+ /* @__PURE__ */ React27.createElement(Box17, { marginBottom: 1 }, /* @__PURE__ */ React27.createElement(Box17, { width: 20 }, /* @__PURE__ */ React27.createElement(Text18, { color: focusedField === "length" ? "green" : void 0 }, focusedField === "length" ? "\u25B6 " : " ", "Length:")), /* @__PURE__ */ React27.createElement(Box17, { width: 10 }, focusedField === "length" ? /* @__PURE__ */ React27.createElement(TextInput4, { value: length, onChange: setLength }) : /* @__PURE__ */ React27.createElement(Text18, null, length)), /* @__PURE__ */ React27.createElement(Text18, { dimColor: true }, "(characters)")),
5788
+ /* @__PURE__ */ React27.createElement(Box17, { marginBottom: 1 }, /* @__PURE__ */ React27.createElement(Box17, { width: 20 }, /* @__PURE__ */ React27.createElement(Text18, { color: focusedField === "count" ? "green" : void 0 }, focusedField === "count" ? "\u25B6 " : " ", "Count:")), /* @__PURE__ */ React27.createElement(Box17, { width: 10 }, focusedField === "count" ? /* @__PURE__ */ React27.createElement(TextInput4, { value: count, onChange: setCount }) : /* @__PURE__ */ React27.createElement(Text18, null, count)), /* @__PURE__ */ React27.createElement(Text18, { dimColor: true }, "(passwords to generate)")),
5789
+ /* @__PURE__ */ React27.createElement(Box17, { marginTop: 1 }, /* @__PURE__ */ React27.createElement(
5790
+ Text18,
5791
+ {
5792
+ bold: true,
5793
+ backgroundColor: focusedField === "generate" ? "green" : void 0,
5794
+ color: focusedField === "generate" ? "black" : "green"
5795
+ },
5796
+ focusedField === "generate" ? "\u25B6 " : " ",
5797
+ "[ Generate Passwords ]"
5798
+ ))
5799
+ ), passwords.length > 0 && /* @__PURE__ */ React27.createElement(
5800
+ Box17,
5801
+ {
5802
+ flexDirection: "column",
5803
+ borderStyle: "single",
5804
+ borderColor: "green",
5805
+ paddingX: 2,
5806
+ paddingY: 1
5807
+ },
5808
+ /* @__PURE__ */ React27.createElement(Text18, { bold: true, color: "green", marginBottom: 1 }, "\u2713 Generated Passwords:"),
5809
+ passwords.map((password, index) => /* @__PURE__ */ React27.createElement(Box17, { key: index, marginBottom: 0 }, /* @__PURE__ */ React27.createElement(Box17, { width: 4 }, /* @__PURE__ */ React27.createElement(Text18, { dimColor: true }, index + 1, ".")), /* @__PURE__ */ React27.createElement(Box17, { flexGrow: 1 }, /* @__PURE__ */ React27.createElement(Text18, null, password)), copiedIndex === index && /* @__PURE__ */ React27.createElement(Text18, { color: "green" }, " \u2713 Copied!")))
5810
+ ), /* @__PURE__ */ React27.createElement(Box17, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 2 }, /* @__PURE__ */ React27.createElement(Text18, { dimColor: true }, "Tab: Next field | Enter: Generate | C: Copy | Esc: Back")));
5811
+ };
5812
+
5813
+ // src/ui/utils/views/UuidView.tsx
5814
+ import React28, { useState as useState15 } from "react";
5815
+ import { Box as Box18, Text as Text19, useInput as useInput13 } from "ink";
5816
+ import TextInput5 from "ink-text-input";
5817
+ var UuidView = () => {
5818
+ const [count, setCount] = useState15("1");
5819
+ const [uppercase, setUppercase] = useState15(false);
5820
+ const [noHyphens, setNoHyphens] = useState15(false);
5821
+ const [uuids, setUuids] = useState15([]);
5822
+ const [focusedField, setFocusedField] = useState15("count");
5823
+ const [copiedIndex, setCopiedIndex] = useState15(null);
5824
+ const service = new UtilsService();
5825
+ useInput13((input, key) => {
5826
+ if (key.tab) {
5827
+ const fields = ["count", "uppercase", "hyphens", "generate"];
5828
+ const currentIndex = fields.indexOf(focusedField);
5829
+ setFocusedField(fields[(currentIndex + 1) % fields.length]);
5830
+ } else if (key.return) {
5831
+ if (focusedField === "uppercase") {
5832
+ setUppercase(!uppercase);
5833
+ } else if (focusedField === "hyphens") {
5834
+ setNoHyphens(!noHyphens);
5835
+ } else if (focusedField === "generate") {
5836
+ handleGenerate();
5837
+ }
5838
+ } else if (input === "c" && uuids.length > 0) {
5839
+ handleCopy(0);
5840
+ }
5841
+ });
5842
+ const handleGenerate = () => {
5843
+ const newUuids = [];
5844
+ const countNum = parseInt(count, 10) || 1;
5845
+ for (let i = 0; i < countNum; i++) {
5846
+ newUuids.push(service.generateUuid({ uppercase, noHyphens }));
5847
+ }
5848
+ setUuids(newUuids);
5849
+ setCopiedIndex(null);
5850
+ };
5851
+ const handleCopy = async (index) => {
5852
+ try {
5853
+ const { default: clipboardy } = await import("clipboardy");
5854
+ await clipboardy.write(uuids[index]);
5855
+ setCopiedIndex(index);
5856
+ setTimeout(() => setCopiedIndex(null), 2e3);
5857
+ } catch (error) {
5858
+ }
5859
+ };
5860
+ return /* @__PURE__ */ React28.createElement(Box18, { flexDirection: "column" }, /* @__PURE__ */ React28.createElement(Box18, { marginBottom: 1 }, /* @__PURE__ */ React28.createElement(Text19, { bold: true, color: "cyan" }, "\u{1F194} UUID Generator")), /* @__PURE__ */ React28.createElement(
5861
+ Box18,
5862
+ {
5863
+ flexDirection: "column",
5864
+ borderStyle: "single",
5865
+ borderColor: "gray",
5866
+ paddingX: 2,
5867
+ paddingY: 1,
5868
+ marginBottom: 1
5869
+ },
5870
+ /* @__PURE__ */ React28.createElement(Text19, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
5871
+ /* @__PURE__ */ React28.createElement(Box18, { marginBottom: 1 }, /* @__PURE__ */ React28.createElement(Box18, { width: 20 }, /* @__PURE__ */ React28.createElement(Text19, { color: focusedField === "count" ? "green" : void 0 }, focusedField === "count" ? "\u25B6 " : " ", "Count:")), /* @__PURE__ */ React28.createElement(Box18, { width: 10 }, focusedField === "count" ? /* @__PURE__ */ React28.createElement(TextInput5, { value: count, onChange: setCount }) : /* @__PURE__ */ React28.createElement(Text19, null, count))),
5872
+ /* @__PURE__ */ React28.createElement(Box18, { marginBottom: 1 }, /* @__PURE__ */ React28.createElement(Text19, { color: focusedField === "uppercase" ? "green" : void 0 }, focusedField === "uppercase" ? "\u25B6 " : " ", "[", uppercase ? "\u2713" : " ", "] Uppercase")),
5873
+ /* @__PURE__ */ React28.createElement(Box18, { marginBottom: 1 }, /* @__PURE__ */ React28.createElement(Text19, { color: focusedField === "hyphens" ? "green" : void 0 }, focusedField === "hyphens" ? "\u25B6 " : " ", "[", noHyphens ? "\u2713" : " ", "] No Hyphens")),
5874
+ /* @__PURE__ */ React28.createElement(Box18, { marginTop: 1 }, /* @__PURE__ */ React28.createElement(
5875
+ Text19,
5876
+ {
5877
+ bold: true,
5878
+ backgroundColor: focusedField === "generate" ? "green" : void 0,
5879
+ color: focusedField === "generate" ? "black" : "green"
5880
+ },
5881
+ focusedField === "generate" ? "\u25B6 " : " ",
5882
+ "[ Generate UUIDs ]"
5883
+ ))
5884
+ ), uuids.length > 0 && /* @__PURE__ */ React28.createElement(
5885
+ Box18,
5886
+ {
5887
+ flexDirection: "column",
5888
+ borderStyle: "single",
5889
+ borderColor: "green",
5890
+ paddingX: 2,
5891
+ paddingY: 1
5892
+ },
5893
+ /* @__PURE__ */ React28.createElement(Text19, { bold: true, color: "green", marginBottom: 1 }, "\u2713 Generated UUIDs:"),
5894
+ uuids.map((uuid, index) => /* @__PURE__ */ React28.createElement(Box18, { key: index, marginBottom: 0 }, /* @__PURE__ */ React28.createElement(Box18, { width: 4 }, /* @__PURE__ */ React28.createElement(Text19, { dimColor: true }, index + 1, ".")), /* @__PURE__ */ React28.createElement(Box18, { flexGrow: 1 }, /* @__PURE__ */ React28.createElement(Text19, null, uuid)), copiedIndex === index && /* @__PURE__ */ React28.createElement(Text19, { color: "green" }, " \u2713 Copied!")))
5895
+ ), /* @__PURE__ */ React28.createElement(Box18, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 2 }, /* @__PURE__ */ React28.createElement(Text19, { dimColor: true }, "Tab: Next | Enter: Toggle/Generate | C: Copy | Esc: Back")));
5896
+ };
5897
+
5898
+ // src/ui/utils/views/HashView.tsx
5899
+ import React29, { useState as useState16 } from "react";
5900
+ import { Box as Box19, Text as Text20, useInput as useInput14 } from "ink";
5901
+ import TextInput6 from "ink-text-input";
5902
+ var ALGORITHMS = ["sha256", "sha512", "sha1", "md5", "bcrypt"];
5903
+ var HashView = () => {
5904
+ const [text, setText] = useState16("");
5905
+ const [algorithm, setAlgorithm] = useState16("sha256");
5906
+ const [hash, setHash] = useState16("");
5907
+ const [focusedField, setFocusedField] = useState16("text");
5908
+ const [copied, setCopied] = useState16(false);
5909
+ const service = new UtilsService();
5910
+ useInput14((input, key) => {
5911
+ if (key.tab) {
5912
+ const fields = ["text", "algorithm", "generate"];
5913
+ const currentIndex = fields.indexOf(focusedField);
5914
+ setFocusedField(fields[(currentIndex + 1) % fields.length]);
5915
+ } else if (key.return && focusedField === "generate") {
5916
+ handleGenerate();
5917
+ } else if (key.leftArrow && focusedField === "algorithm") {
5918
+ const currentIndex = ALGORITHMS.indexOf(algorithm);
5919
+ setAlgorithm(ALGORITHMS[currentIndex > 0 ? currentIndex - 1 : ALGORITHMS.length - 1]);
5920
+ } else if (key.rightArrow && focusedField === "algorithm") {
5921
+ const currentIndex = ALGORITHMS.indexOf(algorithm);
5922
+ setAlgorithm(ALGORITHMS[(currentIndex + 1) % ALGORITHMS.length]);
5923
+ } else if (input === "c" && hash) {
5924
+ handleCopy();
5925
+ }
5926
+ });
5927
+ const handleGenerate = async () => {
5928
+ if (!text) return;
5929
+ let result;
5930
+ if (algorithm === "bcrypt") {
5931
+ result = await service.hashBcrypt(text, 10);
5932
+ } else {
5933
+ result = await service.hash(text, algorithm);
5934
+ }
5935
+ setHash(result);
5936
+ setCopied(false);
5937
+ };
5938
+ const handleCopy = async () => {
5939
+ try {
5940
+ const { default: clipboardy } = await import("clipboardy");
5941
+ await clipboardy.write(hash);
5942
+ setCopied(true);
5943
+ setTimeout(() => setCopied(false), 2e3);
5944
+ } catch (error) {
5945
+ }
5946
+ };
5947
+ return /* @__PURE__ */ React29.createElement(Box19, { flexDirection: "column" }, /* @__PURE__ */ React29.createElement(Box19, { marginBottom: 1 }, /* @__PURE__ */ React29.createElement(Text20, { bold: true, color: "cyan" }, "\u{1F512} Hash Generator")), /* @__PURE__ */ React29.createElement(
5948
+ Box19,
5949
+ {
5950
+ flexDirection: "column",
5951
+ borderStyle: "single",
5952
+ borderColor: "gray",
5953
+ paddingX: 2,
5954
+ paddingY: 1,
5955
+ marginBottom: 1
5956
+ },
5957
+ /* @__PURE__ */ React29.createElement(Text20, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
5958
+ /* @__PURE__ */ React29.createElement(Box19, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React29.createElement(Box19, { marginBottom: 0 }, /* @__PURE__ */ React29.createElement(Text20, { color: focusedField === "text" ? "green" : void 0 }, focusedField === "text" ? "\u25B6 " : " ", "Text to hash:")), /* @__PURE__ */ React29.createElement(Box19, { marginLeft: 2, width: 60 }, focusedField === "text" ? /* @__PURE__ */ React29.createElement(TextInput6, { value: text, onChange: setText, placeholder: "Enter text..." }) : /* @__PURE__ */ React29.createElement(Text20, { dimColor: !text }, text || "(empty)"))),
5959
+ /* @__PURE__ */ React29.createElement(Box19, { marginBottom: 1 }, /* @__PURE__ */ React29.createElement(Box19, { width: 20 }, /* @__PURE__ */ React29.createElement(Text20, { color: focusedField === "algorithm" ? "green" : void 0 }, focusedField === "algorithm" ? "\u25B6 " : " ", "Algorithm:")), /* @__PURE__ */ React29.createElement(Text20, { bold: true, color: focusedField === "algorithm" ? "yellow" : void 0 }, algorithm.toUpperCase()), focusedField === "algorithm" && /* @__PURE__ */ React29.createElement(Text20, { dimColor: true }, " (\u2190 \u2192 to change)")),
5960
+ /* @__PURE__ */ React29.createElement(Box19, { marginTop: 1 }, /* @__PURE__ */ React29.createElement(
5961
+ Text20,
5962
+ {
5963
+ bold: true,
5964
+ backgroundColor: focusedField === "generate" ? "green" : void 0,
5965
+ color: focusedField === "generate" ? "black" : "green"
5966
+ },
5967
+ focusedField === "generate" ? "\u25B6 " : " ",
5968
+ "[ Generate Hash ]"
5969
+ ))
5970
+ ), hash && /* @__PURE__ */ React29.createElement(
5971
+ Box19,
5972
+ {
5973
+ flexDirection: "column",
5974
+ borderStyle: "single",
5975
+ borderColor: "green",
5976
+ paddingX: 2,
5977
+ paddingY: 1
5978
+ },
5979
+ /* @__PURE__ */ React29.createElement(Box19, { marginBottom: 1 }, /* @__PURE__ */ React29.createElement(Text20, { bold: true, color: "green" }, "\u2713 Hash Result:"), copied && /* @__PURE__ */ React29.createElement(Box19, { marginLeft: 2 }, /* @__PURE__ */ React29.createElement(Text20, { color: "green" }, "\u2713 Copied to clipboard!"))),
5980
+ /* @__PURE__ */ React29.createElement(Box19, { flexDirection: "column" }, /* @__PURE__ */ React29.createElement(Text20, { dimColor: true }, "Algorithm: ", algorithm.toUpperCase()), /* @__PURE__ */ React29.createElement(Box19, { marginTop: 1 }, /* @__PURE__ */ React29.createElement(Text20, { wrap: "wrap" }, hash)))
5981
+ ), /* @__PURE__ */ React29.createElement(Box19, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 2 }, /* @__PURE__ */ React29.createElement(Text20, { dimColor: true }, "Tab: Next | \u2190/\u2192: Change algorithm | Enter: Generate | C: Copy | Esc: Back")));
5982
+ };
5983
+
5984
+ // src/ui/utils/views/Base64View.tsx
5985
+ import React30, { useState as useState17 } from "react";
5986
+ import { Box as Box20, Text as Text21, useInput as useInput15 } from "ink";
5987
+ import TextInput7 from "ink-text-input";
5988
+ var Base64View = () => {
5989
+ const [input, setInput] = useState17("");
5990
+ const [mode, setMode] = useState17("encode");
5991
+ const [urlSafe, setUrlSafe] = useState17(false);
5992
+ const [result, setResult] = useState17("");
5993
+ const [error, setError] = useState17("");
5994
+ const [focusedField, setFocusedField] = useState17("input");
5995
+ const [copied, setCopied] = useState17(false);
5996
+ const service = new UtilsService();
5997
+ useInput15((input2, key) => {
5998
+ if (key.tab) {
5999
+ const fields = ["input", "mode", "urlsafe", "convert"];
6000
+ const currentIndex = fields.indexOf(focusedField);
6001
+ setFocusedField(fields[(currentIndex + 1) % fields.length]);
6002
+ } else if (key.return) {
6003
+ if (focusedField === "mode") {
6004
+ setMode(mode === "encode" ? "decode" : "encode");
6005
+ setResult("");
6006
+ setError("");
6007
+ } else if (focusedField === "urlsafe") {
6008
+ setUrlSafe(!urlSafe);
6009
+ } else if (focusedField === "convert") {
6010
+ handleConvert();
6011
+ }
6012
+ } else if (input2 === "c" && result) {
6013
+ handleCopy();
6014
+ }
6015
+ });
6016
+ const handleConvert = () => {
6017
+ if (!input) {
6018
+ setError("Input cannot be empty");
6019
+ return;
6020
+ }
6021
+ try {
6022
+ setError("");
6023
+ if (mode === "encode") {
6024
+ const encoded = service.base64Encode(input, urlSafe);
6025
+ setResult(encoded);
6026
+ } else {
6027
+ const decoded = service.base64Decode(input);
6028
+ setResult(decoded.toString("utf-8"));
6029
+ }
6030
+ setCopied(false);
6031
+ } catch (err) {
6032
+ setError(`Failed to ${mode}: ${err instanceof Error ? err.message : "Unknown error"}`);
6033
+ setResult("");
6034
+ }
6035
+ };
6036
+ const handleCopy = async () => {
6037
+ try {
6038
+ const { default: clipboardy } = await import("clipboardy");
6039
+ await clipboardy.write(result);
6040
+ setCopied(true);
6041
+ setTimeout(() => setCopied(false), 2e3);
6042
+ } catch (error2) {
6043
+ }
6044
+ };
6045
+ return /* @__PURE__ */ React30.createElement(Box20, { flexDirection: "column" }, /* @__PURE__ */ React30.createElement(Box20, { marginBottom: 1 }, /* @__PURE__ */ React30.createElement(Text21, { bold: true, color: "cyan" }, "\u{1F4DD} Base64 Encoder/Decoder")), /* @__PURE__ */ React30.createElement(
6046
+ Box20,
6047
+ {
6048
+ flexDirection: "column",
6049
+ borderStyle: "single",
6050
+ borderColor: "gray",
6051
+ paddingX: 2,
6052
+ paddingY: 1,
6053
+ marginBottom: 1
6054
+ },
6055
+ /* @__PURE__ */ React30.createElement(Text21, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
6056
+ /* @__PURE__ */ React30.createElement(Box20, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React30.createElement(Box20, { marginBottom: 0 }, /* @__PURE__ */ React30.createElement(Text21, { color: focusedField === "input" ? "green" : void 0 }, focusedField === "input" ? "\u25B6 " : " ", "Input text:")), /* @__PURE__ */ React30.createElement(Box20, { marginLeft: 2, width: 60 }, focusedField === "input" ? /* @__PURE__ */ React30.createElement(TextInput7, { value: input, onChange: setInput, placeholder: "Enter text..." }) : /* @__PURE__ */ React30.createElement(Text21, { dimColor: !input }, input || "(empty)"))),
6057
+ /* @__PURE__ */ React30.createElement(Box20, { marginBottom: 1 }, /* @__PURE__ */ React30.createElement(Box20, { width: 20 }, /* @__PURE__ */ React30.createElement(Text21, { color: focusedField === "mode" ? "green" : void 0 }, focusedField === "mode" ? "\u25B6 " : " ", "Mode:")), /* @__PURE__ */ React30.createElement(Text21, { bold: true, color: focusedField === "mode" ? "yellow" : void 0 }, mode === "encode" ? "ENCODE" : "DECODE"), focusedField === "mode" && /* @__PURE__ */ React30.createElement(Text21, { dimColor: true }, " (Enter to toggle)")),
6058
+ mode === "encode" && /* @__PURE__ */ React30.createElement(Box20, { marginBottom: 1 }, /* @__PURE__ */ React30.createElement(Text21, { color: focusedField === "urlsafe" ? "green" : void 0 }, focusedField === "urlsafe" ? "\u25B6 " : " ", "[", urlSafe ? "\u2713" : " ", "] URL-Safe (+ \u2192 -, / \u2192 _)")),
6059
+ /* @__PURE__ */ React30.createElement(Box20, { marginTop: 1 }, /* @__PURE__ */ React30.createElement(
6060
+ Text21,
6061
+ {
6062
+ bold: true,
6063
+ backgroundColor: focusedField === "convert" ? "green" : void 0,
6064
+ color: focusedField === "convert" ? "black" : "green"
6065
+ },
6066
+ focusedField === "convert" ? "\u25B6 " : " ",
6067
+ "[ ",
6068
+ mode === "encode" ? "Encode" : "Decode",
6069
+ " ]"
6070
+ ))
6071
+ ), error && /* @__PURE__ */ React30.createElement(
6072
+ Box20,
6073
+ {
6074
+ flexDirection: "column",
6075
+ borderStyle: "single",
6076
+ borderColor: "red",
6077
+ paddingX: 2,
6078
+ paddingY: 1,
6079
+ marginBottom: 1
6080
+ },
6081
+ /* @__PURE__ */ React30.createElement(Text21, { color: "red" }, "\u2717 Error: ", error)
6082
+ ), result && /* @__PURE__ */ React30.createElement(
6083
+ Box20,
6084
+ {
6085
+ flexDirection: "column",
6086
+ borderStyle: "single",
6087
+ borderColor: "green",
6088
+ paddingX: 2,
6089
+ paddingY: 1
6090
+ },
6091
+ /* @__PURE__ */ React30.createElement(Box20, { marginBottom: 1 }, /* @__PURE__ */ React30.createElement(Text21, { bold: true, color: "green" }, "\u2713 Result:"), copied && /* @__PURE__ */ React30.createElement(Box20, { marginLeft: 2 }, /* @__PURE__ */ React30.createElement(Text21, { color: "green" }, "\u2713 Copied to clipboard!"))),
6092
+ /* @__PURE__ */ React30.createElement(Box20, { flexDirection: "column" }, /* @__PURE__ */ React30.createElement(Text21, { dimColor: true }, "Mode: ", mode.toUpperCase()), /* @__PURE__ */ React30.createElement(Box20, { marginTop: 1 }, /* @__PURE__ */ React30.createElement(Text21, { wrap: "wrap" }, result)))
6093
+ ), /* @__PURE__ */ React30.createElement(Box20, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 2 }, /* @__PURE__ */ React30.createElement(Text21, { dimColor: true }, "Tab: Next | Enter: Toggle/Convert | C: Copy | Esc: Back")));
6094
+ };
6095
+
6096
+ // src/ui/utils/views/UrlView.tsx
6097
+ import React31, { useState as useState18 } from "react";
6098
+ import { Box as Box21, Text as Text22, useInput as useInput16 } from "ink";
6099
+ import TextInput8 from "ink-text-input";
6100
+ var UrlView = () => {
6101
+ const [input, setInput] = useState18("");
6102
+ const [mode, setMode] = useState18("encode");
6103
+ const [fullUrl, setFullUrl] = useState18(false);
6104
+ const [result, setResult] = useState18("");
6105
+ const [focusedField, setFocusedField] = useState18("input");
6106
+ const [copied, setCopied] = useState18(false);
6107
+ const service = new UtilsService();
6108
+ useInput16((input2, key) => {
6109
+ if (key.tab) {
6110
+ const fields = ["input", "mode", "full", "convert"];
6111
+ const currentIndex = fields.indexOf(focusedField);
6112
+ setFocusedField(fields[(currentIndex + 1) % fields.length]);
6113
+ } else if (key.return) {
6114
+ if (focusedField === "mode") {
6115
+ setMode(mode === "encode" ? "decode" : "encode");
6116
+ setResult("");
6117
+ } else if (focusedField === "full") {
6118
+ setFullUrl(!fullUrl);
6119
+ } else if (focusedField === "convert") {
6120
+ handleConvert();
6121
+ }
6122
+ } else if (input2 === "c" && result) {
6123
+ handleCopy();
6124
+ }
6125
+ });
6126
+ const handleConvert = () => {
6127
+ if (!input) return;
6128
+ if (mode === "encode") {
6129
+ const encoded = fullUrl ? service.urlEncode(input, true) : service.urlEncode(input, false);
6130
+ setResult(encoded);
6131
+ } else {
6132
+ const decoded = fullUrl ? service.urlDecode(input, true) : service.urlDecode(input, false);
6133
+ setResult(decoded);
6134
+ }
6135
+ setCopied(false);
6136
+ };
6137
+ const handleCopy = async () => {
6138
+ try {
6139
+ const { default: clipboardy } = await import("clipboardy");
6140
+ await clipboardy.write(result);
6141
+ setCopied(true);
6142
+ setTimeout(() => setCopied(false), 2e3);
6143
+ } catch (error) {
6144
+ }
6145
+ };
6146
+ return /* @__PURE__ */ React31.createElement(Box21, { flexDirection: "column" }, /* @__PURE__ */ React31.createElement(Box21, { marginBottom: 1 }, /* @__PURE__ */ React31.createElement(Text22, { bold: true, color: "cyan" }, "\u{1F517} URL Encoder/Decoder")), /* @__PURE__ */ React31.createElement(
6147
+ Box21,
6148
+ {
6149
+ flexDirection: "column",
6150
+ borderStyle: "single",
6151
+ borderColor: "gray",
6152
+ paddingX: 2,
6153
+ paddingY: 1,
6154
+ marginBottom: 1
6155
+ },
6156
+ /* @__PURE__ */ React31.createElement(Text22, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
6157
+ /* @__PURE__ */ React31.createElement(Box21, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React31.createElement(Box21, { marginBottom: 0 }, /* @__PURE__ */ React31.createElement(Text22, { color: focusedField === "input" ? "green" : void 0 }, focusedField === "input" ? "\u25B6 " : " ", "Input text:")), /* @__PURE__ */ React31.createElement(Box21, { marginLeft: 2, width: 60 }, focusedField === "input" ? /* @__PURE__ */ React31.createElement(TextInput8, { value: input, onChange: setInput, placeholder: "Enter text or URL..." }) : /* @__PURE__ */ React31.createElement(Text22, { dimColor: !input }, input || "(empty)"))),
6158
+ /* @__PURE__ */ React31.createElement(Box21, { marginBottom: 1 }, /* @__PURE__ */ React31.createElement(Box21, { width: 20 }, /* @__PURE__ */ React31.createElement(Text22, { color: focusedField === "mode" ? "green" : void 0 }, focusedField === "mode" ? "\u25B6 " : " ", "Mode:")), /* @__PURE__ */ React31.createElement(Text22, { bold: true, color: focusedField === "mode" ? "yellow" : void 0 }, mode === "encode" ? "ENCODE" : "DECODE"), focusedField === "mode" && /* @__PURE__ */ React31.createElement(Text22, { dimColor: true }, " (Enter to toggle)")),
6159
+ /* @__PURE__ */ React31.createElement(Box21, { marginBottom: 1 }, /* @__PURE__ */ React31.createElement(Text22, { color: focusedField === "full" ? "green" : void 0 }, focusedField === "full" ? "\u25B6 " : " ", "[", fullUrl ? "\u2713" : " ", "] Full URL (encode/decode entire URL)")),
6160
+ /* @__PURE__ */ React31.createElement(Box21, { marginTop: 1 }, /* @__PURE__ */ React31.createElement(
6161
+ Text22,
6162
+ {
6163
+ bold: true,
6164
+ backgroundColor: focusedField === "convert" ? "green" : void 0,
6165
+ color: focusedField === "convert" ? "black" : "green"
6166
+ },
6167
+ focusedField === "convert" ? "\u25B6 " : " ",
6168
+ "[ ",
6169
+ mode === "encode" ? "Encode" : "Decode",
6170
+ " ]"
6171
+ ))
6172
+ ), result && /* @__PURE__ */ React31.createElement(
6173
+ Box21,
6174
+ {
6175
+ flexDirection: "column",
6176
+ borderStyle: "single",
6177
+ borderColor: "green",
6178
+ paddingX: 2,
6179
+ paddingY: 1
6180
+ },
6181
+ /* @__PURE__ */ React31.createElement(Box21, { marginBottom: 1 }, /* @__PURE__ */ React31.createElement(Text22, { bold: true, color: "green" }, "\u2713 Result:"), copied && /* @__PURE__ */ React31.createElement(Box21, { marginLeft: 2 }, /* @__PURE__ */ React31.createElement(Text22, { color: "green" }, "\u2713 Copied to clipboard!"))),
6182
+ /* @__PURE__ */ React31.createElement(Box21, { flexDirection: "column" }, /* @__PURE__ */ React31.createElement(Text22, { dimColor: true }, "Mode: ", mode.toUpperCase(), " ", fullUrl ? "(Full URL)" : "(Component)"), /* @__PURE__ */ React31.createElement(Box21, { marginTop: 1 }, /* @__PURE__ */ React31.createElement(Text22, { wrap: "wrap" }, result)))
6183
+ ), /* @__PURE__ */ React31.createElement(Box21, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 2 }, /* @__PURE__ */ React31.createElement(Text22, { dimColor: true }, "Tab: Next | Enter: Toggle/Convert | C: Copy | Esc: Back")));
6184
+ };
6185
+
6186
+ // src/ui/utils/views/UnixTimeView.tsx
6187
+ import React32, { useState as useState19 } from "react";
6188
+ import { Box as Box22, Text as Text23, useInput as useInput17 } from "ink";
6189
+ import TextInput9 from "ink-text-input";
6190
+ var UnixTimeView = () => {
6191
+ const [input, setInput] = useState19("");
6192
+ const [mode, setMode] = useState19("now");
6193
+ const [format, setFormat] = useState19("iso");
6194
+ const [useMs, setUseMs] = useState19(false);
6195
+ const [result, setResult] = useState19("");
6196
+ const [error, setError] = useState19("");
6197
+ const [focusedField, setFocusedField] = useState19("mode");
6198
+ const [copied, setCopied] = useState19(false);
6199
+ const service = new UtilsService();
6200
+ useInput17((input2, key) => {
6201
+ if (key.tab) {
6202
+ const fields = mode === "now" ? ["mode", "ms", "convert"] : mode === "to-human" ? ["mode", "input", "format", "convert"] : ["mode", "input", "convert"];
6203
+ const currentIndex = fields.indexOf(focusedField);
6204
+ setFocusedField(fields[(currentIndex + 1) % fields.length]);
6205
+ } else if (key.return) {
6206
+ if (focusedField === "mode") {
6207
+ const modes = ["now", "to-human", "to-unix"];
6208
+ const currentIndex = modes.indexOf(mode);
6209
+ setMode(modes[(currentIndex + 1) % modes.length]);
6210
+ setResult("");
6211
+ setError("");
6212
+ } else if (focusedField === "format") {
6213
+ const formats = ["iso", "local", "utc"];
6214
+ const currentIndex = formats.indexOf(format);
6215
+ setFormat(formats[(currentIndex + 1) % formats.length]);
6216
+ } else if (focusedField === "ms") {
6217
+ setUseMs(!useMs);
6218
+ } else if (focusedField === "convert") {
6219
+ handleConvert();
6220
+ }
6221
+ } else if (input2 === "c" && result) {
6222
+ handleCopy();
6223
+ }
6224
+ });
6225
+ const handleConvert = () => {
6226
+ try {
6227
+ setError("");
6228
+ if (mode === "now") {
6229
+ const timestamp = service.unixTimeCurrent(useMs);
6230
+ setResult(timestamp.toString());
6231
+ } else if (mode === "to-human") {
6232
+ if (!input) {
6233
+ setError("Please enter a timestamp");
6234
+ return;
6235
+ }
6236
+ const human = service.unixTimeToHuman(parseInt(input, 10), format);
6237
+ setResult(human);
6238
+ } else {
6239
+ if (!input) {
6240
+ setError("Please enter a date string");
6241
+ return;
6242
+ }
6243
+ const timestamp = service.unixTimeFromString(input);
6244
+ setResult(timestamp.toString());
6245
+ }
6246
+ setCopied(false);
6247
+ } catch (err) {
6248
+ setError(err instanceof Error ? err.message : "Conversion failed");
6249
+ setResult("");
6250
+ }
6251
+ };
6252
+ const handleCopy = async () => {
6253
+ try {
6254
+ const { default: clipboardy } = await import("clipboardy");
6255
+ await clipboardy.write(result);
6256
+ setCopied(true);
6257
+ setTimeout(() => setCopied(false), 2e3);
6258
+ } catch (error2) {
6259
+ }
6260
+ };
6261
+ return /* @__PURE__ */ React32.createElement(Box22, { flexDirection: "column" }, /* @__PURE__ */ React32.createElement(Box22, { marginBottom: 1 }, /* @__PURE__ */ React32.createElement(Text23, { bold: true, color: "cyan" }, "\u{1F552} Unix Time Converter")), /* @__PURE__ */ React32.createElement(
6262
+ Box22,
6263
+ {
6264
+ flexDirection: "column",
6265
+ borderStyle: "single",
6266
+ borderColor: "gray",
6267
+ paddingX: 2,
6268
+ paddingY: 1,
6269
+ marginBottom: 1
6270
+ },
6271
+ /* @__PURE__ */ React32.createElement(Text23, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
6272
+ /* @__PURE__ */ React32.createElement(Box22, { marginBottom: 1 }, /* @__PURE__ */ React32.createElement(Box22, { width: 20 }, /* @__PURE__ */ React32.createElement(Text23, { color: focusedField === "mode" ? "green" : void 0 }, focusedField === "mode" ? "\u25B6 " : " ", "Mode:")), /* @__PURE__ */ React32.createElement(Text23, { bold: true, color: focusedField === "mode" ? "yellow" : void 0 }, mode === "now" ? "CURRENT TIME" : mode === "to-human" ? "TIMESTAMP \u2192 HUMAN" : "HUMAN \u2192 TIMESTAMP"), focusedField === "mode" && /* @__PURE__ */ React32.createElement(Text23, { dimColor: true }, " (Enter to cycle)")),
6273
+ mode !== "now" && /* @__PURE__ */ React32.createElement(Box22, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React32.createElement(Box22, { marginBottom: 0 }, /* @__PURE__ */ React32.createElement(Text23, { color: focusedField === "input" ? "green" : void 0 }, focusedField === "input" ? "\u25B6 " : " ", mode === "to-human" ? "Timestamp:" : "Date string:")), /* @__PURE__ */ React32.createElement(Box22, { marginLeft: 2, width: 50 }, focusedField === "input" ? /* @__PURE__ */ React32.createElement(
6274
+ TextInput9,
6275
+ {
6276
+ value: input,
6277
+ onChange: setInput,
6278
+ placeholder: mode === "to-human" ? "1702550400" : "2024-01-15 10:30:00"
6279
+ }
6280
+ ) : /* @__PURE__ */ React32.createElement(Text23, { dimColor: !input }, input || "(empty)"))),
6281
+ mode === "to-human" && /* @__PURE__ */ React32.createElement(Box22, { marginBottom: 1 }, /* @__PURE__ */ React32.createElement(Box22, { width: 20 }, /* @__PURE__ */ React32.createElement(Text23, { color: focusedField === "format" ? "green" : void 0 }, focusedField === "format" ? "\u25B6 " : " ", "Format:")), /* @__PURE__ */ React32.createElement(Text23, { bold: true, color: focusedField === "format" ? "yellow" : void 0 }, format.toUpperCase()), focusedField === "format" && /* @__PURE__ */ React32.createElement(Text23, { dimColor: true }, " (Enter to cycle)")),
6282
+ mode === "now" && /* @__PURE__ */ React32.createElement(Box22, { marginBottom: 1 }, /* @__PURE__ */ React32.createElement(Text23, { color: focusedField === "ms" ? "green" : void 0 }, focusedField === "ms" ? "\u25B6 " : " ", "[", useMs ? "\u2713" : " ", "] Milliseconds")),
6283
+ /* @__PURE__ */ React32.createElement(Box22, { marginTop: 1 }, /* @__PURE__ */ React32.createElement(
6284
+ Text23,
6285
+ {
6286
+ bold: true,
6287
+ backgroundColor: focusedField === "convert" ? "green" : void 0,
6288
+ color: focusedField === "convert" ? "black" : "green"
6289
+ },
6290
+ focusedField === "convert" ? "\u25B6 " : " ",
6291
+ "[ ",
6292
+ mode === "now" ? "Get Current" : "Convert",
6293
+ " ]"
6294
+ ))
6295
+ ), error && /* @__PURE__ */ React32.createElement(
6296
+ Box22,
6297
+ {
6298
+ flexDirection: "column",
6299
+ borderStyle: "single",
6300
+ borderColor: "red",
6301
+ paddingX: 2,
6302
+ paddingY: 1,
6303
+ marginBottom: 1
6304
+ },
6305
+ /* @__PURE__ */ React32.createElement(Text23, { color: "red" }, "\u2717 Error: ", error)
6306
+ ), result && /* @__PURE__ */ React32.createElement(
6307
+ Box22,
6308
+ {
6309
+ flexDirection: "column",
6310
+ borderStyle: "single",
6311
+ borderColor: "green",
6312
+ paddingX: 2,
6313
+ paddingY: 1
6314
+ },
6315
+ /* @__PURE__ */ React32.createElement(Box22, { marginBottom: 1 }, /* @__PURE__ */ React32.createElement(Text23, { bold: true, color: "green" }, "\u2713 Result:"), copied && /* @__PURE__ */ React32.createElement(Box22, { marginLeft: 2 }, /* @__PURE__ */ React32.createElement(Text23, { color: "green" }, "\u2713 Copied to clipboard!"))),
6316
+ /* @__PURE__ */ React32.createElement(Box22, { flexDirection: "column" }, /* @__PURE__ */ React32.createElement(Box22, { marginTop: 1 }, /* @__PURE__ */ React32.createElement(Text23, { wrap: "wrap" }, result)))
6317
+ ), /* @__PURE__ */ React32.createElement(Box22, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 2 }, /* @__PURE__ */ React32.createElement(Text23, { dimColor: true }, "Tab: Next | Enter: Toggle/Convert | C: Copy | Esc: Back")));
6318
+ };
6319
+
6320
+ // src/ui/utils/views/JwtView.tsx
6321
+ import React33, { useState as useState20 } from "react";
6322
+ import { Box as Box23, Text as Text24, useInput as useInput18 } from "ink";
6323
+ import TextInput10 from "ink-text-input";
6324
+ var JwtView = () => {
6325
+ const [mode, setMode] = useState20("decode");
6326
+ const [token, setToken] = useState20("");
6327
+ const [payload, setPayload] = useState20("");
6328
+ const [secret, setSecret] = useState20("");
6329
+ const [result, setResult] = useState20({});
6330
+ const [error, setError] = useState20("");
6331
+ const [focusedField, setFocusedField] = useState20("mode");
6332
+ const [copied, setCopied] = useState20(false);
6333
+ const service = new UtilsService();
6334
+ useInput18((input, key) => {
6335
+ if (key.tab) {
6336
+ const fields = mode === "decode" ? ["mode", "token", "process"] : ["mode", "payload", "secret", "process"];
6337
+ const currentIndex = fields.indexOf(focusedField);
6338
+ setFocusedField(fields[(currentIndex + 1) % fields.length]);
6339
+ } else if (key.return) {
6340
+ if (focusedField === "mode") {
6341
+ setMode(mode === "decode" ? "encode" : "decode");
6342
+ setResult({});
6343
+ setError("");
6344
+ } else if (focusedField === "process") {
6345
+ handleProcess();
6346
+ }
6347
+ } else if (input === "c" && result.token) {
6348
+ handleCopy();
6349
+ }
6350
+ });
6351
+ const handleProcess = () => {
6352
+ try {
6353
+ setError("");
6354
+ if (mode === "decode") {
6355
+ if (!token) {
6356
+ setError("Please enter a JWT token");
6357
+ return;
6358
+ }
6359
+ const decoded = service.jwtDecode(token);
6360
+ setResult(decoded);
6361
+ } else {
6362
+ if (!payload) {
6363
+ setError("Please enter payload JSON");
6364
+ return;
6365
+ }
6366
+ if (!secret) {
6367
+ setError("Please enter a secret key");
6368
+ return;
6369
+ }
6370
+ const payloadObj = JSON.parse(payload);
6371
+ const encoded = service.jwtEncode(payloadObj, secret);
6372
+ setResult({ token: encoded });
6373
+ }
6374
+ setCopied(false);
6375
+ } catch (err) {
6376
+ setError(err instanceof Error ? err.message : "Processing failed");
6377
+ setResult({});
6378
+ }
6379
+ };
6380
+ const handleCopy = async () => {
6381
+ try {
6382
+ const { default: clipboardy } = await import("clipboardy");
6383
+ await clipboardy.write(result.token || "");
6384
+ setCopied(true);
6385
+ setTimeout(() => setCopied(false), 2e3);
6386
+ } catch (error2) {
6387
+ }
6388
+ };
6389
+ return /* @__PURE__ */ React33.createElement(Box23, { flexDirection: "column" }, /* @__PURE__ */ React33.createElement(Box23, { marginBottom: 1 }, /* @__PURE__ */ React33.createElement(Text24, { bold: true, color: "cyan" }, "\u{1F511} JWT Decoder/Encoder")), /* @__PURE__ */ React33.createElement(
6390
+ Box23,
6391
+ {
6392
+ flexDirection: "column",
6393
+ borderStyle: "single",
6394
+ borderColor: "gray",
6395
+ paddingX: 2,
6396
+ paddingY: 1,
6397
+ marginBottom: 1
6398
+ },
6399
+ /* @__PURE__ */ React33.createElement(Text24, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
6400
+ /* @__PURE__ */ React33.createElement(Box23, { marginBottom: 1 }, /* @__PURE__ */ React33.createElement(Box23, { width: 20 }, /* @__PURE__ */ React33.createElement(Text24, { color: focusedField === "mode" ? "green" : void 0 }, focusedField === "mode" ? "\u25B6 " : " ", "Mode:")), /* @__PURE__ */ React33.createElement(Text24, { bold: true, color: focusedField === "mode" ? "yellow" : void 0 }, mode === "decode" ? "DECODE" : "ENCODE"), focusedField === "mode" && /* @__PURE__ */ React33.createElement(Text24, { dimColor: true }, " (Enter to toggle)")),
6401
+ mode === "decode" ? /* @__PURE__ */ React33.createElement(Box23, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React33.createElement(Box23, { marginBottom: 0 }, /* @__PURE__ */ React33.createElement(Text24, { color: focusedField === "token" ? "green" : void 0 }, focusedField === "token" ? "\u25B6 " : " ", "JWT Token:")), /* @__PURE__ */ React33.createElement(Box23, { marginLeft: 2, width: 60 }, focusedField === "token" ? /* @__PURE__ */ React33.createElement(
6402
+ TextInput10,
6403
+ {
6404
+ value: token,
6405
+ onChange: setToken,
6406
+ placeholder: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
6407
+ }
6408
+ ) : /* @__PURE__ */ React33.createElement(Text24, { dimColor: !token }, token || "(empty)"))) : /* @__PURE__ */ React33.createElement(React33.Fragment, null, /* @__PURE__ */ React33.createElement(Box23, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React33.createElement(Box23, { marginBottom: 0 }, /* @__PURE__ */ React33.createElement(Text24, { color: focusedField === "payload" ? "green" : void 0 }, focusedField === "payload" ? "\u25B6 " : " ", "Payload (JSON):")), /* @__PURE__ */ React33.createElement(Box23, { marginLeft: 2, width: 60 }, focusedField === "payload" ? /* @__PURE__ */ React33.createElement(
6409
+ TextInput10,
6410
+ {
6411
+ value: payload,
6412
+ onChange: setPayload,
6413
+ placeholder: '{"sub":"123","name":"John"}'
6414
+ }
6415
+ ) : /* @__PURE__ */ React33.createElement(Text24, { dimColor: !payload }, payload || "(empty)"))), /* @__PURE__ */ React33.createElement(Box23, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React33.createElement(Box23, { marginBottom: 0 }, /* @__PURE__ */ React33.createElement(Text24, { color: focusedField === "secret" ? "green" : void 0 }, focusedField === "secret" ? "\u25B6 " : " ", "Secret Key:")), /* @__PURE__ */ React33.createElement(Box23, { marginLeft: 2, width: 60 }, focusedField === "secret" ? /* @__PURE__ */ React33.createElement(
6416
+ TextInput10,
6417
+ {
6418
+ value: secret,
6419
+ onChange: setSecret,
6420
+ placeholder: "your-secret-key",
6421
+ mask: "*"
6422
+ }
6423
+ ) : /* @__PURE__ */ React33.createElement(Text24, { dimColor: !secret }, secret ? "*".repeat(secret.length) : "(empty)")))),
6424
+ /* @__PURE__ */ React33.createElement(Box23, { marginTop: 1 }, /* @__PURE__ */ React33.createElement(
6425
+ Text24,
6426
+ {
6427
+ bold: true,
6428
+ backgroundColor: focusedField === "process" ? "green" : void 0,
6429
+ color: focusedField === "process" ? "black" : "green"
6430
+ },
6431
+ focusedField === "process" ? "\u25B6 " : " ",
6432
+ "[ ",
6433
+ mode === "decode" ? "Decode" : "Encode",
6434
+ " ]"
6435
+ ))
6436
+ ), error && /* @__PURE__ */ React33.createElement(
6437
+ Box23,
6438
+ {
6439
+ flexDirection: "column",
6440
+ borderStyle: "single",
6441
+ borderColor: "red",
6442
+ paddingX: 2,
6443
+ paddingY: 1,
6444
+ marginBottom: 1
6445
+ },
6446
+ /* @__PURE__ */ React33.createElement(Text24, { color: "red" }, "\u2717 Error: ", error)
6447
+ ), (result.header || result.token) && /* @__PURE__ */ React33.createElement(
6448
+ Box23,
6449
+ {
6450
+ flexDirection: "column",
6451
+ borderStyle: "single",
6452
+ borderColor: "green",
6453
+ paddingX: 2,
6454
+ paddingY: 1
6455
+ },
6456
+ /* @__PURE__ */ React33.createElement(Box23, { marginBottom: 1 }, /* @__PURE__ */ React33.createElement(Text24, { bold: true, color: "green" }, "\u2713 Result:"), copied && result.token && /* @__PURE__ */ React33.createElement(Box23, { marginLeft: 2 }, /* @__PURE__ */ React33.createElement(Text24, { color: "green" }, "\u2713 Copied to clipboard!"))),
6457
+ /* @__PURE__ */ React33.createElement(Box23, { flexDirection: "column" }, result.header && /* @__PURE__ */ React33.createElement(React33.Fragment, null, /* @__PURE__ */ React33.createElement(Text24, { bold: true, color: "yellow" }, "Header:"), /* @__PURE__ */ React33.createElement(Text24, null, JSON.stringify(result.header, null, 2)), /* @__PURE__ */ React33.createElement(Text24, null, " "), /* @__PURE__ */ React33.createElement(Text24, { bold: true, color: "yellow" }, "Payload:"), /* @__PURE__ */ React33.createElement(Text24, null, JSON.stringify(result.payload, null, 2)), /* @__PURE__ */ React33.createElement(Text24, null, " "), /* @__PURE__ */ React33.createElement(Text24, { bold: true, color: "yellow" }, "Signature:"), /* @__PURE__ */ React33.createElement(Text24, { dimColor: true }, result.signature)), result.token && /* @__PURE__ */ React33.createElement(React33.Fragment, null, /* @__PURE__ */ React33.createElement(Text24, { bold: true, color: "yellow" }, "Token:"), /* @__PURE__ */ React33.createElement(Text24, { wrap: "wrap" }, result.token)))
6458
+ ), /* @__PURE__ */ React33.createElement(Box23, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 2 }, /* @__PURE__ */ React33.createElement(Text24, { dimColor: true }, "Tab: Next | Enter: Toggle/", mode === "decode" ? "Decode" : "Encode", " | C: Copy | Esc: Back")));
6459
+ };
6460
+
6461
+ // src/ui/utils/views/CronView.tsx
6462
+ import React34, { useState as useState21 } from "react";
6463
+ import { Box as Box24, Text as Text25, useInput as useInput19 } from "ink";
6464
+ import TextInput11 from "ink-text-input";
6465
+ var CronView = () => {
6466
+ const [expression, setExpression] = useState21("");
6467
+ const [result, setResult] = useState21(null);
6468
+ const [error, setError] = useState21("");
6469
+ const [focusedField, setFocusedField] = useState21("expression");
6470
+ const [copied, setCopied] = useState21(false);
6471
+ const service = new UtilsService();
6472
+ useInput19((input, key) => {
6473
+ if (key.tab) {
6474
+ setFocusedField(focusedField === "expression" ? "parse" : "expression");
6475
+ } else if (key.return && focusedField === "parse") {
6476
+ handleParse();
6477
+ } else if (input === "c" && result) {
6478
+ handleCopy();
6479
+ }
6480
+ });
6481
+ const handleParse = () => {
6482
+ if (!expression) {
6483
+ setError("Please enter a cron expression");
6484
+ return;
6485
+ }
6486
+ try {
6487
+ setError("");
6488
+ const parsed = service.parseCron(expression);
6489
+ setResult(parsed);
6490
+ setCopied(false);
6491
+ } catch (err) {
6492
+ setError(err instanceof Error ? err.message : "Failed to parse cron expression");
6493
+ setResult(null);
6494
+ }
6495
+ };
6496
+ const handleCopy = async () => {
6497
+ if (!result) return;
6498
+ try {
6499
+ const { default: clipboardy } = await import("clipboardy");
6500
+ const copyText = `${result.description}
6501
+
6502
+ Next runs:
6503
+ ${result.nextRuns.join("\n")}`;
6504
+ await clipboardy.write(copyText);
6505
+ setCopied(true);
6506
+ setTimeout(() => setCopied(false), 2e3);
6507
+ } catch (error2) {
6508
+ }
6509
+ };
6510
+ return /* @__PURE__ */ React34.createElement(Box24, { flexDirection: "column" }, /* @__PURE__ */ React34.createElement(Box24, { marginBottom: 1 }, /* @__PURE__ */ React34.createElement(Text25, { bold: true, color: "cyan" }, "\u23F0 Cron Expression Parser")), /* @__PURE__ */ React34.createElement(
6511
+ Box24,
6512
+ {
6513
+ flexDirection: "column",
6514
+ borderStyle: "single",
6515
+ borderColor: "gray",
6516
+ paddingX: 2,
6517
+ paddingY: 1,
6518
+ marginBottom: 1
6519
+ },
6520
+ /* @__PURE__ */ React34.createElement(Text25, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
6521
+ /* @__PURE__ */ React34.createElement(Box24, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React34.createElement(Box24, { marginBottom: 0 }, /* @__PURE__ */ React34.createElement(Text25, { color: focusedField === "expression" ? "green" : void 0 }, focusedField === "expression" ? "\u25B6 " : " ", "Cron Expression:")), /* @__PURE__ */ React34.createElement(Box24, { marginLeft: 2, width: 50 }, focusedField === "expression" ? /* @__PURE__ */ React34.createElement(
6522
+ TextInput11,
6523
+ {
6524
+ value: expression,
6525
+ onChange: setExpression,
6526
+ placeholder: "0 5 * * * (5-field or 6-field)"
6527
+ }
6528
+ ) : /* @__PURE__ */ React34.createElement(Text25, { dimColor: !expression }, expression || "(empty)"))),
6529
+ /* @__PURE__ */ React34.createElement(Box24, { marginTop: 1, marginBottom: 1 }, /* @__PURE__ */ React34.createElement(Text25, { dimColor: true }, 'Examples: "0 5 * * *" (daily at 5am), "*/15 * * * *" (every 15 min)')),
6530
+ /* @__PURE__ */ React34.createElement(Box24, { marginTop: 1 }, /* @__PURE__ */ React34.createElement(
6531
+ Text25,
6532
+ {
6533
+ bold: true,
6534
+ backgroundColor: focusedField === "parse" ? "green" : void 0,
6535
+ color: focusedField === "parse" ? "black" : "green"
6536
+ },
6537
+ focusedField === "parse" ? "\u25B6 " : " ",
6538
+ "[ Parse Expression ]"
6539
+ ))
6540
+ ), error && /* @__PURE__ */ React34.createElement(
6541
+ Box24,
6542
+ {
6543
+ flexDirection: "column",
6544
+ borderStyle: "single",
6545
+ borderColor: "red",
6546
+ paddingX: 2,
6547
+ paddingY: 1,
6548
+ marginBottom: 1
6549
+ },
6550
+ /* @__PURE__ */ React34.createElement(Text25, { color: "red" }, "\u2717 Error: ", error)
6551
+ ), result && /* @__PURE__ */ React34.createElement(
6552
+ Box24,
6553
+ {
6554
+ flexDirection: "column",
6555
+ borderStyle: "single",
6556
+ borderColor: "green",
6557
+ paddingX: 2,
6558
+ paddingY: 1
6559
+ },
6560
+ /* @__PURE__ */ React34.createElement(Box24, { marginBottom: 1 }, /* @__PURE__ */ React34.createElement(Text25, { bold: true, color: "green" }, "\u2713 Result:"), copied && /* @__PURE__ */ React34.createElement(Box24, { marginLeft: 2 }, /* @__PURE__ */ React34.createElement(Text25, { color: "green" }, "\u2713 Copied to clipboard!"))),
6561
+ /* @__PURE__ */ React34.createElement(Box24, { flexDirection: "column" }, /* @__PURE__ */ React34.createElement(Text25, { bold: true, color: "yellow" }, "Expression:"), /* @__PURE__ */ React34.createElement(Text25, null, expression), /* @__PURE__ */ React34.createElement(Text25, null, " "), /* @__PURE__ */ React34.createElement(Text25, { bold: true, color: "yellow" }, "Meaning:"), /* @__PURE__ */ React34.createElement(Text25, null, result.description), /* @__PURE__ */ React34.createElement(Text25, null, " "), /* @__PURE__ */ React34.createElement(Text25, { bold: true, color: "yellow" }, "Next 5 executions:"), result.nextRuns.map((run, index) => /* @__PURE__ */ React34.createElement(Text25, { key: index }, " ", index + 1, ". ", run)))
6562
+ ), /* @__PURE__ */ React34.createElement(Box24, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 2 }, /* @__PURE__ */ React34.createElement(Text25, { dimColor: true }, "Tab: Next | Enter: Parse | C: Copy | Esc: Back")));
6563
+ };
6564
+
6565
+ // src/ui/utils/views/TimezoneView.tsx
6566
+ import React35, { useState as useState22 } from "react";
6567
+ import { Box as Box25, Text as Text26, useInput as useInput20 } from "ink";
6568
+ import TextInput12 from "ink-text-input";
6569
+ var TimezoneView = () => {
6570
+ const [time, setTime] = useState22("");
6571
+ const [fromTz, setFromTz] = useState22("UTC");
6572
+ const [toTz, setToTz] = useState22("America/New_York");
6573
+ const [result, setResult] = useState22("");
6574
+ const [error, setError] = useState22("");
6575
+ const [focusedField, setFocusedField] = useState22("time");
6576
+ const [copied, setCopied] = useState22(false);
6577
+ const service = new UtilsService();
6578
+ useInput20((input, key) => {
6579
+ if (key.tab) {
6580
+ const fields = ["time", "from", "to", "convert"];
6581
+ const currentIndex = fields.indexOf(focusedField);
6582
+ setFocusedField(fields[(currentIndex + 1) % fields.length]);
6583
+ } else if (key.return && focusedField === "convert") {
6584
+ handleConvert();
6585
+ } else if (input === "c" && result) {
6586
+ handleCopy();
6587
+ }
6588
+ });
6589
+ const handleConvert = () => {
6590
+ if (!time) {
6591
+ setError("Please enter a time");
6592
+ return;
6593
+ }
6594
+ if (!fromTz || !toTz) {
6595
+ setError("Please enter both timezones");
6596
+ return;
6597
+ }
6598
+ try {
6599
+ setError("");
6600
+ const converted = service.convertTimezone(time, fromTz, toTz);
6601
+ setResult(converted);
6602
+ setCopied(false);
6603
+ } catch (err) {
6604
+ setError(err instanceof Error ? err.message : "Conversion failed");
6605
+ setResult("");
6606
+ }
6607
+ };
6608
+ const handleCopy = async () => {
6609
+ try {
6610
+ const { default: clipboardy } = await import("clipboardy");
6611
+ await clipboardy.write(result);
6612
+ setCopied(true);
6613
+ setTimeout(() => setCopied(false), 2e3);
6614
+ } catch (error2) {
6615
+ }
6616
+ };
6617
+ return /* @__PURE__ */ React35.createElement(Box25, { flexDirection: "column" }, /* @__PURE__ */ React35.createElement(Box25, { marginBottom: 1 }, /* @__PURE__ */ React35.createElement(Text26, { bold: true, color: "cyan" }, "\u{1F30D} Timezone Converter")), /* @__PURE__ */ React35.createElement(
6618
+ Box25,
6619
+ {
6620
+ flexDirection: "column",
6621
+ borderStyle: "single",
6622
+ borderColor: "gray",
6623
+ paddingX: 2,
6624
+ paddingY: 1,
6625
+ marginBottom: 1
6626
+ },
6627
+ /* @__PURE__ */ React35.createElement(Text26, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
6628
+ /* @__PURE__ */ React35.createElement(Box25, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React35.createElement(Box25, { marginBottom: 0 }, /* @__PURE__ */ React35.createElement(Text26, { color: focusedField === "time" ? "green" : void 0 }, focusedField === "time" ? "\u25B6 " : " ", "Time:")), /* @__PURE__ */ React35.createElement(Box25, { marginLeft: 2, width: 50 }, focusedField === "time" ? /* @__PURE__ */ React35.createElement(
6629
+ TextInput12,
6630
+ {
6631
+ value: time,
6632
+ onChange: setTime,
6633
+ placeholder: "2024-01-15 10:00:00"
6634
+ }
6635
+ ) : /* @__PURE__ */ React35.createElement(Text26, { dimColor: !time }, time || "(empty)"))),
6636
+ /* @__PURE__ */ React35.createElement(Box25, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React35.createElement(Box25, { marginBottom: 0 }, /* @__PURE__ */ React35.createElement(Text26, { color: focusedField === "from" ? "green" : void 0 }, focusedField === "from" ? "\u25B6 " : " ", "From Timezone:")), /* @__PURE__ */ React35.createElement(Box25, { marginLeft: 2, width: 50 }, focusedField === "from" ? /* @__PURE__ */ React35.createElement(
6637
+ TextInput12,
6638
+ {
6639
+ value: fromTz,
6640
+ onChange: setFromTz,
6641
+ placeholder: "UTC or America/New_York"
6642
+ }
6643
+ ) : /* @__PURE__ */ React35.createElement(Text26, { dimColor: !fromTz }, fromTz || "(empty)"))),
6644
+ /* @__PURE__ */ React35.createElement(Box25, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React35.createElement(Box25, { marginBottom: 0 }, /* @__PURE__ */ React35.createElement(Text26, { color: focusedField === "to" ? "green" : void 0 }, focusedField === "to" ? "\u25B6 " : " ", "To Timezone:")), /* @__PURE__ */ React35.createElement(Box25, { marginLeft: 2, width: 50 }, focusedField === "to" ? /* @__PURE__ */ React35.createElement(
6645
+ TextInput12,
6646
+ {
6647
+ value: toTz,
6648
+ onChange: setToTz,
6649
+ placeholder: "Asia/Tokyo or Europe/London"
6650
+ }
6651
+ ) : /* @__PURE__ */ React35.createElement(Text26, { dimColor: !toTz }, toTz || "(empty)"))),
6652
+ /* @__PURE__ */ React35.createElement(Box25, { marginBottom: 1 }, /* @__PURE__ */ React35.createElement(Text26, { dimColor: true }, "Common: UTC, America/New_York, Europe/London, Asia/Tokyo")),
6653
+ /* @__PURE__ */ React35.createElement(Box25, { marginTop: 1 }, /* @__PURE__ */ React35.createElement(
6654
+ Text26,
6655
+ {
6656
+ bold: true,
6657
+ backgroundColor: focusedField === "convert" ? "green" : void 0,
6658
+ color: focusedField === "convert" ? "black" : "green"
6659
+ },
6660
+ focusedField === "convert" ? "\u25B6 " : " ",
6661
+ "[ Convert ]"
6662
+ ))
6663
+ ), error && /* @__PURE__ */ React35.createElement(
6664
+ Box25,
6665
+ {
6666
+ flexDirection: "column",
6667
+ borderStyle: "single",
6668
+ borderColor: "red",
6669
+ paddingX: 2,
6670
+ paddingY: 1,
6671
+ marginBottom: 1
6672
+ },
6673
+ /* @__PURE__ */ React35.createElement(Text26, { color: "red" }, "\u2717 Error: ", error)
6674
+ ), result && /* @__PURE__ */ React35.createElement(
6675
+ Box25,
6676
+ {
6677
+ flexDirection: "column",
6678
+ borderStyle: "single",
6679
+ borderColor: "green",
6680
+ paddingX: 2,
6681
+ paddingY: 1
6682
+ },
6683
+ /* @__PURE__ */ React35.createElement(Box25, { marginBottom: 1 }, /* @__PURE__ */ React35.createElement(Text26, { bold: true, color: "green" }, "\u2713 Result:"), copied && /* @__PURE__ */ React35.createElement(Box25, { marginLeft: 2 }, /* @__PURE__ */ React35.createElement(Text26, { color: "green" }, "\u2713 Copied to clipboard!"))),
6684
+ /* @__PURE__ */ React35.createElement(Box25, { flexDirection: "column" }, /* @__PURE__ */ React35.createElement(Text26, { dimColor: true }, "From: ", fromTz), /* @__PURE__ */ React35.createElement(Text26, { dimColor: true }, "To: ", toTz), /* @__PURE__ */ React35.createElement(Box25, { marginTop: 1 }, /* @__PURE__ */ React35.createElement(Text26, { wrap: "wrap" }, result)))
6685
+ ), /* @__PURE__ */ React35.createElement(Box25, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 2 }, /* @__PURE__ */ React35.createElement(Text26, { dimColor: true }, "Tab: Next | Enter: Convert | C: Copy | Esc: Back")));
6686
+ };
6687
+
6688
+ // src/ui/utils/views/HttpView.tsx
6689
+ import React36, { useState as useState23 } from "react";
6690
+ import { Box as Box26, Text as Text27, useInput as useInput21 } from "ink";
6691
+ import TextInput13 from "ink-text-input";
6692
+ var METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE"];
6693
+ var HttpView = () => {
6694
+ const [url, setUrl] = useState23("");
6695
+ const [method, setMethod] = useState23("GET");
6696
+ const [headers, setHeaders] = useState23("");
6697
+ const [body, setBody] = useState23("");
6698
+ const [response, setResponse] = useState23(null);
6699
+ const [error, setError] = useState23("");
6700
+ const [loading, setLoading] = useState23(false);
6701
+ const [focusedField, setFocusedField] = useState23("url");
6702
+ const [copied, setCopied] = useState23(false);
6703
+ const service = new UtilsService();
6704
+ useInput21((input, key) => {
6705
+ if (loading) return;
6706
+ if (key.tab) {
6707
+ const fields = ["url", "method", "headers", "body", "send"];
6708
+ const currentIndex = fields.indexOf(focusedField);
6709
+ setFocusedField(fields[(currentIndex + 1) % fields.length]);
6710
+ } else if (key.leftArrow && focusedField === "method") {
6711
+ const currentIndex = METHODS.indexOf(method);
6712
+ setMethod(METHODS[currentIndex > 0 ? currentIndex - 1 : METHODS.length - 1]);
6713
+ } else if (key.rightArrow && focusedField === "method") {
6714
+ const currentIndex = METHODS.indexOf(method);
6715
+ setMethod(METHODS[(currentIndex + 1) % METHODS.length]);
6716
+ } else if (key.return && focusedField === "send") {
6717
+ handleSend();
6718
+ } else if (input === "c" && response) {
6719
+ handleCopy();
6720
+ }
6721
+ });
6722
+ const handleSend = async () => {
6723
+ if (!url) {
6724
+ setError("Please enter a URL");
6725
+ return;
6726
+ }
6727
+ try {
6728
+ setError("");
6729
+ setLoading(true);
6730
+ const headersObj = {};
6731
+ if (headers) {
6732
+ const headerLines = headers.split("\n");
6733
+ for (const line of headerLines) {
6734
+ const [key, ...valueParts] = line.split(":");
6735
+ if (key && valueParts.length > 0) {
6736
+ headersObj[key.trim()] = valueParts.join(":").trim();
6737
+ }
6738
+ }
6739
+ }
6740
+ const result = await service.httpRequest(url, {
6741
+ method,
6742
+ headers: headersObj,
6743
+ body: body || void 0
6744
+ });
6745
+ setResponse(result);
6746
+ setCopied(false);
6747
+ } catch (err) {
6748
+ setError(err instanceof Error ? err.message : "Request failed");
6749
+ setResponse(null);
6750
+ } finally {
6751
+ setLoading(false);
6752
+ }
6753
+ };
6754
+ const handleCopy = async () => {
6755
+ if (!response) return;
6756
+ try {
6757
+ const { default: clipboardy } = await import("clipboardy");
6758
+ const copyText = typeof response.body === "string" ? response.body : JSON.stringify(response.body, null, 2);
6759
+ await clipboardy.write(copyText);
6760
+ setCopied(true);
6761
+ setTimeout(() => setCopied(false), 2e3);
6762
+ } catch (error2) {
6763
+ }
6764
+ };
6765
+ return /* @__PURE__ */ React36.createElement(Box26, { flexDirection: "column" }, /* @__PURE__ */ React36.createElement(Box26, { marginBottom: 1 }, /* @__PURE__ */ React36.createElement(Text27, { bold: true, color: "cyan" }, "\u{1F310} HTTP Request")), /* @__PURE__ */ React36.createElement(
6766
+ Box26,
6767
+ {
6768
+ flexDirection: "column",
6769
+ borderStyle: "single",
6770
+ borderColor: "gray",
6771
+ paddingX: 2,
6772
+ paddingY: 1,
6773
+ marginBottom: 1
6774
+ },
6775
+ /* @__PURE__ */ React36.createElement(Text27, { bold: true, color: "yellow", marginBottom: 1 }, "Request:"),
6776
+ /* @__PURE__ */ React36.createElement(Box26, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React36.createElement(Box26, { marginBottom: 0 }, /* @__PURE__ */ React36.createElement(Text27, { color: focusedField === "url" ? "green" : void 0 }, focusedField === "url" ? "\u25B6 " : " ", "URL:")), /* @__PURE__ */ React36.createElement(Box26, { marginLeft: 2, width: 60 }, focusedField === "url" ? /* @__PURE__ */ React36.createElement(
6777
+ TextInput13,
6778
+ {
6779
+ value: url,
6780
+ onChange: setUrl,
6781
+ placeholder: "https://api.example.com/endpoint"
6782
+ }
6783
+ ) : /* @__PURE__ */ React36.createElement(Text27, { dimColor: !url }, url || "(empty)"))),
6784
+ /* @__PURE__ */ React36.createElement(Box26, { marginBottom: 1 }, /* @__PURE__ */ React36.createElement(Box26, { width: 20 }, /* @__PURE__ */ React36.createElement(Text27, { color: focusedField === "method" ? "green" : void 0 }, focusedField === "method" ? "\u25B6 " : " ", "Method:")), /* @__PURE__ */ React36.createElement(Text27, { bold: true, color: focusedField === "method" ? "yellow" : void 0 }, method), focusedField === "method" && /* @__PURE__ */ React36.createElement(Text27, { dimColor: true }, " (\u2190 \u2192 to change)")),
6785
+ /* @__PURE__ */ React36.createElement(Box26, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React36.createElement(Box26, { marginBottom: 0 }, /* @__PURE__ */ React36.createElement(Text27, { color: focusedField === "headers" ? "green" : void 0 }, focusedField === "headers" ? "\u25B6 " : " ", "Headers (one per line, Key: Value):")), /* @__PURE__ */ React36.createElement(Box26, { marginLeft: 2, width: 60 }, focusedField === "headers" ? /* @__PURE__ */ React36.createElement(
6786
+ TextInput13,
6787
+ {
6788
+ value: headers,
6789
+ onChange: setHeaders,
6790
+ placeholder: "Authorization: Bearer token"
6791
+ }
6792
+ ) : /* @__PURE__ */ React36.createElement(Text27, { dimColor: !headers }, headers || "(none)"))),
6793
+ (method === "POST" || method === "PUT" || method === "PATCH") && /* @__PURE__ */ React36.createElement(Box26, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React36.createElement(Box26, { marginBottom: 0 }, /* @__PURE__ */ React36.createElement(Text27, { color: focusedField === "body" ? "green" : void 0 }, focusedField === "body" ? "\u25B6 " : " ", "Body (JSON):")), /* @__PURE__ */ React36.createElement(Box26, { marginLeft: 2, width: 60 }, focusedField === "body" ? /* @__PURE__ */ React36.createElement(
6794
+ TextInput13,
6795
+ {
6796
+ value: body,
6797
+ onChange: setBody,
6798
+ placeholder: '{"key":"value"}'
6799
+ }
6800
+ ) : /* @__PURE__ */ React36.createElement(Text27, { dimColor: !body }, body || "(empty)"))),
6801
+ /* @__PURE__ */ React36.createElement(Box26, { marginTop: 1 }, /* @__PURE__ */ React36.createElement(
6802
+ Text27,
6803
+ {
6804
+ bold: true,
6805
+ backgroundColor: focusedField === "send" ? "green" : void 0,
6806
+ color: focusedField === "send" ? "black" : "green"
6807
+ },
6808
+ focusedField === "send" ? "\u25B6 " : " ",
6809
+ "[ ",
6810
+ loading ? "Sending..." : "Send Request",
6811
+ " ]"
6812
+ ))
6813
+ ), error && /* @__PURE__ */ React36.createElement(
6814
+ Box26,
6815
+ {
6816
+ flexDirection: "column",
6817
+ borderStyle: "single",
6818
+ borderColor: "red",
6819
+ paddingX: 2,
6820
+ paddingY: 1,
6821
+ marginBottom: 1
6822
+ },
6823
+ /* @__PURE__ */ React36.createElement(Text27, { color: "red" }, "\u2717 Error: ", error)
6824
+ ), response && /* @__PURE__ */ React36.createElement(
6825
+ Box26,
6826
+ {
6827
+ flexDirection: "column",
6828
+ borderStyle: "single",
6829
+ borderColor: "green",
6830
+ paddingX: 2,
6831
+ paddingY: 1
6832
+ },
6833
+ /* @__PURE__ */ React36.createElement(Box26, { marginBottom: 1 }, /* @__PURE__ */ React36.createElement(Text27, { bold: true, color: "green" }, "\u2713 Response:"), copied && /* @__PURE__ */ React36.createElement(Box26, { marginLeft: 2 }, /* @__PURE__ */ React36.createElement(Text27, { color: "green" }, "\u2713 Copied body to clipboard!"))),
6834
+ /* @__PURE__ */ React36.createElement(Box26, { flexDirection: "column" }, /* @__PURE__ */ React36.createElement(Text27, null, "Status: ", /* @__PURE__ */ React36.createElement(Text27, { color: response.status < 400 ? "green" : "red" }, response.status)), /* @__PURE__ */ React36.createElement(Text27, null, "Time: ", response.time, "ms"), /* @__PURE__ */ React36.createElement(Text27, null, "Size: ", response.size), /* @__PURE__ */ React36.createElement(Text27, null, " "), /* @__PURE__ */ React36.createElement(Text27, { bold: true, color: "yellow" }, "Headers:"), Object.entries(response.headers).slice(0, 5).map(([key, value]) => /* @__PURE__ */ React36.createElement(Text27, { key, dimColor: true }, " ", key, ": ", value)), /* @__PURE__ */ React36.createElement(Text27, null, " "), /* @__PURE__ */ React36.createElement(Text27, { bold: true, color: "yellow" }, "Body:"), /* @__PURE__ */ React36.createElement(Text27, null, typeof response.body === "string" ? response.body.slice(0, 500) : JSON.stringify(response.body, null, 2).slice(0, 500)))
6835
+ ), /* @__PURE__ */ React36.createElement(Box26, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 2 }, /* @__PURE__ */ React36.createElement(Text27, { dimColor: true }, "Tab: Next | \u2190/\u2192: Change method | Enter: Send | C: Copy body | Esc: Back")));
6836
+ };
6837
+
6838
+ // src/ui/utils/views/MarkdownView.tsx
6839
+ import React37, { useState as useState24 } from "react";
6840
+ import { Box as Box27, Text as Text28, useInput as useInput22 } from "ink";
6841
+ import TextInput14 from "ink-text-input";
6842
+ import * as fs8 from "fs";
6843
+ import * as path5 from "path";
6844
+ var MarkdownView = () => {
6845
+ const [filePath, setFilePath] = useState24("");
6846
+ const [content, setContent] = useState24("");
6847
+ const [error, setError] = useState24("");
6848
+ const [focusedField, setFocusedField] = useState24("file");
6849
+ useInput22((input, key) => {
6850
+ if (key.tab) {
6851
+ setFocusedField(focusedField === "file" ? "preview" : "file");
6852
+ } else if (key.return && focusedField === "preview") {
6853
+ handlePreview();
6854
+ }
6855
+ });
6856
+ const handlePreview = async () => {
6857
+ if (!filePath) {
6858
+ setError("Please enter a file path");
6859
+ return;
6860
+ }
6861
+ try {
6862
+ setError("");
6863
+ const resolvedPath = path5.resolve(filePath);
6864
+ if (!fs8.existsSync(resolvedPath)) {
6865
+ setError(`File not found: ${resolvedPath}`);
6866
+ return;
6867
+ }
6868
+ let fileContent = fs8.readFileSync(resolvedPath, "utf-8");
6869
+ fileContent = fileContent.replace(/```mermaid\n([\s\S]*?)```/g, (match, code) => {
6870
+ return `
6871
+ \u{1F3A8} **Mermaid Diagram**
6872
+
6873
+ \`\`\`
6874
+ ${code.trim()}
6875
+ \`\`\`
6876
+
6877
+ \u{1F4A1} *Tip: Mermaid diagrams cannot be rendered in terminal. View in a Markdown viewer.*
6878
+ `;
6879
+ });
6880
+ const { marked: marked2 } = await import("marked");
6881
+ const { default: markedTerminal } = await import("marked-terminal");
6882
+ marked2.use(markedTerminal());
6883
+ const rendered = marked2(fileContent);
6884
+ setContent(rendered);
6885
+ } catch (err) {
6886
+ setError(err instanceof Error ? err.message : "Failed to preview file");
6887
+ setContent("");
6888
+ }
6889
+ };
6890
+ return /* @__PURE__ */ React37.createElement(Box27, { flexDirection: "column" }, /* @__PURE__ */ React37.createElement(Box27, { marginBottom: 1 }, /* @__PURE__ */ React37.createElement(Text28, { bold: true, color: "cyan" }, "\u{1F4C4} Markdown Preview")), /* @__PURE__ */ React37.createElement(
6891
+ Box27,
6892
+ {
6893
+ flexDirection: "column",
6894
+ borderStyle: "single",
6895
+ borderColor: "gray",
6896
+ paddingX: 2,
6897
+ paddingY: 1,
6898
+ marginBottom: 1
6899
+ },
6900
+ /* @__PURE__ */ React37.createElement(Text28, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
6901
+ /* @__PURE__ */ React37.createElement(Box27, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React37.createElement(Box27, { marginBottom: 0 }, /* @__PURE__ */ React37.createElement(Text28, { color: focusedField === "file" ? "green" : void 0 }, focusedField === "file" ? "\u25B6 " : " ", "File path:")), /* @__PURE__ */ React37.createElement(Box27, { marginLeft: 2, width: 60 }, focusedField === "file" ? /* @__PURE__ */ React37.createElement(
6902
+ TextInput14,
6903
+ {
6904
+ value: filePath,
6905
+ onChange: setFilePath,
6906
+ placeholder: "./README.md or /path/to/file.md"
6907
+ }
6908
+ ) : /* @__PURE__ */ React37.createElement(Text28, { dimColor: !filePath }, filePath || "(empty)"))),
6909
+ /* @__PURE__ */ React37.createElement(Box27, { marginTop: 1 }, /* @__PURE__ */ React37.createElement(
6910
+ Text28,
6911
+ {
6912
+ bold: true,
6913
+ backgroundColor: focusedField === "preview" ? "green" : void 0,
6914
+ color: focusedField === "preview" ? "black" : "green"
6915
+ },
6916
+ focusedField === "preview" ? "\u25B6 " : " ",
6917
+ "[ Preview File ]"
6918
+ ))
6919
+ ), error && /* @__PURE__ */ React37.createElement(
6920
+ Box27,
6921
+ {
6922
+ flexDirection: "column",
6923
+ borderStyle: "single",
6924
+ borderColor: "red",
6925
+ paddingX: 2,
6926
+ paddingY: 1,
6927
+ marginBottom: 1
6928
+ },
6929
+ /* @__PURE__ */ React37.createElement(Text28, { color: "red" }, "\u2717 Error: ", error)
6930
+ ), content && /* @__PURE__ */ React37.createElement(
6931
+ Box27,
6932
+ {
6933
+ flexDirection: "column",
6934
+ borderStyle: "single",
6935
+ borderColor: "green",
6936
+ paddingX: 2,
6937
+ paddingY: 1
6938
+ },
6939
+ /* @__PURE__ */ React37.createElement(Box27, { marginBottom: 1 }, /* @__PURE__ */ React37.createElement(Text28, { bold: true, color: "green" }, "\u2713 Preview:")),
6940
+ /* @__PURE__ */ React37.createElement(Box27, { flexDirection: "column" }, /* @__PURE__ */ React37.createElement(Text28, null, content))
6941
+ ), /* @__PURE__ */ React37.createElement(Box27, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 2 }, /* @__PURE__ */ React37.createElement(Text28, { dimColor: true }, "Tab: Next | Enter: Preview | Esc: Back")));
6942
+ };
6943
+
6944
+ // src/ui/utils/UtilsApp.tsx
5726
6945
  var MENU_ITEMS2 = [
5727
6946
  { id: "password", icon: "\u{1F510}", label: "Password", description: "Generate secure passwords" },
5728
6947
  { id: "uuid", icon: "\u{1F194}", label: "UUID", description: "Generate UUID v4" },
@@ -5739,10 +6958,10 @@ var MENU_ITEMS2 = [
5739
6958
  { id: "markdown", icon: "\u{1F4C4}", label: "Markdown", description: "Preview markdown" }
5740
6959
  ];
5741
6960
  var UtilsApp = ({ onExit }) => {
5742
- const [selectedIndex, setSelectedIndex] = useState14(0);
5743
- const [activeView, setActiveView] = useState14(null);
6961
+ const [selectedIndex, setSelectedIndex] = useState25(0);
6962
+ const [activeView, setActiveView] = useState25(null);
5744
6963
  const { exit } = useApp5();
5745
- useInput12((input, key) => {
6964
+ useInput23((input, key) => {
5746
6965
  if (activeView) {
5747
6966
  if (key.escape) {
5748
6967
  setActiveView(null);
@@ -5760,8 +6979,8 @@ var UtilsApp = ({ onExit }) => {
5760
6979
  exit();
5761
6980
  }
5762
6981
  });
5763
- return /* @__PURE__ */ React27.createElement(Box17, { flexDirection: "column", width: "100%", height: "100%" }, /* @__PURE__ */ React27.createElement(
5764
- Box17,
6982
+ return /* @__PURE__ */ React38.createElement(Box28, { flexDirection: "column", width: "100%", height: "100%" }, /* @__PURE__ */ React38.createElement(
6983
+ Box28,
5765
6984
  {
5766
6985
  borderStyle: "single",
5767
6986
  borderColor: "cyan",
@@ -5769,10 +6988,10 @@ var UtilsApp = ({ onExit }) => {
5769
6988
  paddingY: 0,
5770
6989
  marginBottom: 1
5771
6990
  },
5772
- /* @__PURE__ */ React27.createElement(Text18, { bold: true, color: "cyan" }, "\u{1F6E0}\uFE0F Developer Utilities - Interactive Mode"),
5773
- /* @__PURE__ */ React27.createElement(Box17, { marginLeft: "auto" }, /* @__PURE__ */ React27.createElement(Text18, { dimColor: true }, "Press 'q' to quit"))
5774
- ), /* @__PURE__ */ React27.createElement(Box17, { flexGrow: 1 }, /* @__PURE__ */ React27.createElement(
5775
- Box17,
6991
+ /* @__PURE__ */ React38.createElement(Text29, { bold: true, color: "cyan" }, "\u{1F6E0}\uFE0F Developer Utilities - Interactive Mode"),
6992
+ /* @__PURE__ */ React38.createElement(Box28, { marginLeft: "auto" }, /* @__PURE__ */ React38.createElement(Text29, { dimColor: true }, "Press 'q' to quit"))
6993
+ ), /* @__PURE__ */ React38.createElement(Box28, { flexGrow: 1 }, /* @__PURE__ */ React38.createElement(
6994
+ Box28,
5776
6995
  {
5777
6996
  flexDirection: "column",
5778
6997
  width: 30,
@@ -5782,9 +7001,9 @@ var UtilsApp = ({ onExit }) => {
5782
7001
  paddingY: 1,
5783
7002
  marginRight: 1
5784
7003
  },
5785
- /* @__PURE__ */ React27.createElement(Box17, { marginBottom: 1 }, /* @__PURE__ */ React27.createElement(Text18, { bold: true, color: "yellow" }, "Select Utility:")),
5786
- MENU_ITEMS2.map((item, index) => /* @__PURE__ */ React27.createElement(Box17, { key: item.id, marginBottom: 0 }, /* @__PURE__ */ React27.createElement(
5787
- Text18,
7004
+ /* @__PURE__ */ React38.createElement(Box28, { marginBottom: 1 }, /* @__PURE__ */ React38.createElement(Text29, { bold: true, color: "yellow" }, "Select Utility:")),
7005
+ MENU_ITEMS2.map((item, index) => /* @__PURE__ */ React38.createElement(Box28, { key: item.id, marginBottom: 0 }, /* @__PURE__ */ React38.createElement(
7006
+ Text29,
5788
7007
  {
5789
7008
  color: selectedIndex === index && !activeView ? "green" : void 0,
5790
7009
  bold: selectedIndex === index && !activeView,
@@ -5795,9 +7014,9 @@ var UtilsApp = ({ onExit }) => {
5795
7014
  " ",
5796
7015
  item.label
5797
7016
  ))),
5798
- /* @__PURE__ */ React27.createElement(Box17, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 1 }, /* @__PURE__ */ React27.createElement(Text18, { dimColor: true, fontSize: 10 }, "\u2191/\u2193: Navigate", "\n", "Enter: Select", "\n", "Esc: Back/Quit"))
5799
- ), /* @__PURE__ */ React27.createElement(
5800
- Box17,
7017
+ /* @__PURE__ */ React38.createElement(Box28, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 1 }, /* @__PURE__ */ React38.createElement(Text29, { dimColor: true }, "\u2191/\u2193: Navigate", "\n", "Enter: Select", "\n", "Esc: Back/Quit"))
7018
+ ), /* @__PURE__ */ React38.createElement(
7019
+ Box28,
5801
7020
  {
5802
7021
  flexDirection: "column",
5803
7022
  flexGrow: 1,
@@ -5806,21 +7025,21 @@ var UtilsApp = ({ onExit }) => {
5806
7025
  paddingX: 2,
5807
7026
  paddingY: 1
5808
7027
  },
5809
- activeView ? /* @__PURE__ */ React27.createElement(ActiveUtilityView, { utilityType: activeView }) : /* @__PURE__ */ React27.createElement(WelcomeView, { selectedItem: MENU_ITEMS2[selectedIndex] })
5810
- )), /* @__PURE__ */ React27.createElement(
5811
- Box17,
7028
+ activeView ? /* @__PURE__ */ React38.createElement(ActiveUtilityView, { utilityType: activeView }) : /* @__PURE__ */ React38.createElement(WelcomeView, { selectedItem: MENU_ITEMS2[selectedIndex] })
7029
+ )), /* @__PURE__ */ React38.createElement(
7030
+ Box28,
5812
7031
  {
5813
7032
  borderStyle: "single",
5814
7033
  borderColor: "gray",
5815
7034
  paddingX: 2,
5816
7035
  marginTop: 1
5817
7036
  },
5818
- /* @__PURE__ */ React27.createElement(Text18, { dimColor: true }, "jai1-cli v0.1.63 | Use arrow keys to navigate")
7037
+ /* @__PURE__ */ React38.createElement(Text29, { dimColor: true }, "jai1-cli | Use arrow keys or j/k to navigate")
5819
7038
  ));
5820
7039
  };
5821
7040
  var WelcomeView = ({ selectedItem }) => {
5822
- return /* @__PURE__ */ React27.createElement(Box17, { flexDirection: "column" }, /* @__PURE__ */ React27.createElement(Box17, { marginBottom: 1 }, /* @__PURE__ */ React27.createElement(Text18, { bold: true, color: "cyan" }, "Welcome to Developer Utilities")), /* @__PURE__ */ React27.createElement(Box17, { marginBottom: 2 }, /* @__PURE__ */ React27.createElement(Text18, null, "Select a utility from the left menu to get started.")), /* @__PURE__ */ React27.createElement(
5823
- Box17,
7041
+ return /* @__PURE__ */ React38.createElement(Box28, { flexDirection: "column" }, /* @__PURE__ */ React38.createElement(Box28, { marginBottom: 1 }, /* @__PURE__ */ React38.createElement(Text29, { bold: true, color: "cyan" }, "Welcome to Developer Utilities")), /* @__PURE__ */ React38.createElement(Box28, { marginBottom: 2 }, /* @__PURE__ */ React38.createElement(Text29, null, "Select a utility from the left menu to get started.")), /* @__PURE__ */ React38.createElement(
7042
+ Box28,
5824
7043
  {
5825
7044
  borderStyle: "single",
5826
7045
  borderColor: "yellow",
@@ -5828,27 +7047,57 @@ var WelcomeView = ({ selectedItem }) => {
5828
7047
  paddingY: 1,
5829
7048
  marginBottom: 2
5830
7049
  },
5831
- /* @__PURE__ */ React27.createElement(Box17, { flexDirection: "column" }, /* @__PURE__ */ React27.createElement(Text18, { bold: true, color: "yellow" }, selectedItem.icon, " ", selectedItem.label), /* @__PURE__ */ React27.createElement(Text18, { dimColor: true }, selectedItem.description))
5832
- ), /* @__PURE__ */ React27.createElement(Box17, { marginBottom: 1 }, /* @__PURE__ */ React27.createElement(Text18, { bold: true }, "Quick Actions:")), /* @__PURE__ */ React27.createElement(Box17, { flexDirection: "column", marginLeft: 2 }, /* @__PURE__ */ React27.createElement(Text18, null, "\u2022 Press ", /* @__PURE__ */ React27.createElement(Text18, { color: "green" }, "Enter"), " to open selected utility"), /* @__PURE__ */ React27.createElement(Text18, null, "\u2022 Use ", /* @__PURE__ */ React27.createElement(Text18, { color: "green" }, "\u2191/\u2193"), " or ", /* @__PURE__ */ React27.createElement(Text18, { color: "green" }, "j/k"), " to navigate"), /* @__PURE__ */ React27.createElement(Text18, null, "\u2022 Press ", /* @__PURE__ */ React27.createElement(Text18, { color: "green" }, "Esc"), " to go back or quit"), /* @__PURE__ */ React27.createElement(Text18, null, "\u2022 Press ", /* @__PURE__ */ React27.createElement(Text18, { color: "green" }, "q"), " to quit anytime")), /* @__PURE__ */ React27.createElement(Box17, { marginTop: 2 }, /* @__PURE__ */ React27.createElement(Text18, { dimColor: true }, "\u{1F4A1} Tip: Each utility provides an interactive interface for easy usage.")));
7050
+ /* @__PURE__ */ React38.createElement(Box28, { flexDirection: "column" }, /* @__PURE__ */ React38.createElement(Text29, { bold: true, color: "yellow" }, selectedItem.icon, " ", selectedItem.label), /* @__PURE__ */ React38.createElement(Text29, { dimColor: true }, selectedItem.description))
7051
+ ), /* @__PURE__ */ React38.createElement(Box28, { marginBottom: 1 }, /* @__PURE__ */ React38.createElement(Text29, { bold: true }, "Quick Actions:")), /* @__PURE__ */ React38.createElement(Box28, { flexDirection: "column", marginLeft: 2 }, /* @__PURE__ */ React38.createElement(Text29, null, "\u2022 Press ", /* @__PURE__ */ React38.createElement(Text29, { color: "green" }, "Enter"), " to open selected utility"), /* @__PURE__ */ React38.createElement(Text29, null, "\u2022 Use ", /* @__PURE__ */ React38.createElement(Text29, { color: "green" }, "\u2191/\u2193"), " or ", /* @__PURE__ */ React38.createElement(Text29, { color: "green" }, "j/k"), " to navigate"), /* @__PURE__ */ React38.createElement(Text29, null, "\u2022 Press ", /* @__PURE__ */ React38.createElement(Text29, { color: "green" }, "Esc"), " to go back or quit"), /* @__PURE__ */ React38.createElement(Text29, null, "\u2022 Press ", /* @__PURE__ */ React38.createElement(Text29, { color: "green" }, "q"), " to quit anytime")), /* @__PURE__ */ React38.createElement(Box28, { marginTop: 2 }, /* @__PURE__ */ React38.createElement(Text29, { dimColor: true }, "\u{1F4A1} Tip: Each utility provides an interactive interface for easy usage.")));
5833
7052
  };
5834
7053
  var ActiveUtilityView = ({ utilityType }) => {
5835
- const service = new UtilsService();
5836
- return /* @__PURE__ */ React27.createElement(Box17, { flexDirection: "column" }, /* @__PURE__ */ React27.createElement(Box17, { marginBottom: 1 }, /* @__PURE__ */ React27.createElement(Text18, { bold: true, color: "cyan" }, MENU_ITEMS2.find((item) => item.id === utilityType)?.icon, " ", MENU_ITEMS2.find((item) => item.id === utilityType)?.label)), /* @__PURE__ */ React27.createElement(Box17, { borderStyle: "single", borderColor: "gray", paddingX: 2, paddingY: 1 }, /* @__PURE__ */ React27.createElement(Text18, null, "This utility interface is under construction.", "\n", "\n", "For now, use the command-line version:", "\n", /* @__PURE__ */ React27.createElement(Text18, { color: "green" }, "$ jai1 utils ", utilityType, " --help"), "\n", "\n", "Press ", /* @__PURE__ */ React27.createElement(Text18, { color: "yellow" }, "Esc"), " to return to the menu.")));
7054
+ switch (utilityType) {
7055
+ case "password":
7056
+ return /* @__PURE__ */ React38.createElement(PasswordView, null);
7057
+ case "uuid":
7058
+ return /* @__PURE__ */ React38.createElement(UuidView, null);
7059
+ case "hash":
7060
+ return /* @__PURE__ */ React38.createElement(HashView, null);
7061
+ case "base64-encode":
7062
+ case "base64-decode":
7063
+ return /* @__PURE__ */ React38.createElement(Base64View, null);
7064
+ case "url-encode":
7065
+ case "url-decode":
7066
+ return /* @__PURE__ */ React38.createElement(UrlView, null);
7067
+ case "unix-time":
7068
+ return /* @__PURE__ */ React38.createElement(UnixTimeView, null);
7069
+ case "jwt":
7070
+ return /* @__PURE__ */ React38.createElement(JwtView, null);
7071
+ case "cron":
7072
+ return /* @__PURE__ */ React38.createElement(CronView, null);
7073
+ case "timezone":
7074
+ return /* @__PURE__ */ React38.createElement(TimezoneView, null);
7075
+ case "http":
7076
+ return /* @__PURE__ */ React38.createElement(HttpView, null);
7077
+ case "markdown":
7078
+ return /* @__PURE__ */ React38.createElement(MarkdownView, null);
7079
+ default:
7080
+ return /* @__PURE__ */ React38.createElement(PlaceholderView, { utilityType });
7081
+ }
7082
+ };
7083
+ var PlaceholderView = ({ utilityType }) => {
7084
+ const item = MENU_ITEMS2.find((m) => m.id === utilityType);
7085
+ return /* @__PURE__ */ React38.createElement(Box28, { flexDirection: "column" }, /* @__PURE__ */ React38.createElement(Box28, { marginBottom: 1 }, /* @__PURE__ */ React38.createElement(Text29, { bold: true, color: "cyan" }, item?.icon, " ", item?.label)), /* @__PURE__ */ React38.createElement(Box28, { borderStyle: "single", borderColor: "yellow", paddingX: 2, paddingY: 1 }, /* @__PURE__ */ React38.createElement(Text29, null, "\u{1F6A7} This utility view is under construction.", "\n", "\n", "For now, use the command-line version:", "\n", /* @__PURE__ */ React38.createElement(Text29, { color: "green" }, "$ jai1 utils ", utilityType, " --help"), "\n", "\n", "Press ", /* @__PURE__ */ React38.createElement(Text29, { color: "yellow" }, "Esc"), " to return to the menu.")));
5837
7086
  };
5838
7087
 
5839
7088
  // src/commands/utils/interactive.ts
5840
7089
  async function runInteractiveMode() {
5841
- return new Promise((resolve3) => {
7090
+ return new Promise((resolve4) => {
5842
7091
  const { unmount, waitUntilExit } = render5(
5843
- React28.createElement(UtilsApp, {
7092
+ React39.createElement(UtilsApp, {
5844
7093
  onExit: () => {
5845
7094
  unmount();
5846
- resolve3();
7095
+ resolve4();
5847
7096
  }
5848
7097
  })
5849
7098
  );
5850
7099
  waitUntilExit().then(() => {
5851
- resolve3();
7100
+ resolve4();
5852
7101
  });
5853
7102
  });
5854
7103
  }
@@ -6171,7 +7420,7 @@ import { Command as Command30 } from "commander";
6171
7420
 
6172
7421
  // src/services/redmine-config.service.ts
6173
7422
  import { readFile as readFile6 } from "fs/promises";
6174
- import { resolve } from "path";
7423
+ import { resolve as resolve2 } from "path";
6175
7424
 
6176
7425
  // src/types/redmine.types.ts
6177
7426
  import { z } from "zod";
@@ -6222,7 +7471,7 @@ import { z as z2 } from "zod";
6222
7471
  var RedmineConfigService = class {
6223
7472
  configPath;
6224
7473
  constructor(configPath) {
6225
- this.configPath = configPath ?? resolve(process.cwd(), "redmine.config.yaml");
7474
+ this.configPath = configPath ?? resolve2(process.cwd(), "redmine.config.yaml");
6226
7475
  }
6227
7476
  /**
6228
7477
  * Load Redmine configuration from YAML file
@@ -6288,8 +7537,8 @@ var RedmineApiClient = class {
6288
7537
  this.retryConfig = config.defaults.retry;
6289
7538
  this.concurrencyLimit = pLimit2(config.defaults.concurrency);
6290
7539
  }
6291
- async request(path6, options = {}) {
6292
- const url = `${this.baseUrl}${path6}`;
7540
+ async request(path7, options = {}) {
7541
+ const url = `${this.baseUrl}${path7}`;
6293
7542
  const headers = {
6294
7543
  "X-Redmine-API-Key": this.apiAccessToken,
6295
7544
  "Content-Type": "application/json",
@@ -6350,8 +7599,8 @@ var RedmineApiClient = class {
6350
7599
  if (include && include.length > 0) {
6351
7600
  params.append("include", include.join(","));
6352
7601
  }
6353
- const path6 = `/issues/${issueId}.json${params.toString() ? `?${params.toString()}` : ""}`;
6354
- return this.request(path6);
7602
+ const path7 = `/issues/${issueId}.json${params.toString() ? `?${params.toString()}` : ""}`;
7603
+ return this.request(path7);
6355
7604
  }
6356
7605
  async getIssues(projectId, options = {}) {
6357
7606
  const params = new URLSearchParams();
@@ -6371,8 +7620,8 @@ var RedmineApiClient = class {
6371
7620
  if (options.updatedSince) {
6372
7621
  params.append("updated_on", `>=${options.updatedSince}`);
6373
7622
  }
6374
- const path6 = `/issues.json?${params.toString()}`;
6375
- return this.request(path6);
7623
+ const path7 = `/issues.json?${params.toString()}`;
7624
+ return this.request(path7);
6376
7625
  }
6377
7626
  async getAllIssues(projectId, options = {}) {
6378
7627
  const pageSize = options.pageSize || 100;
@@ -6505,7 +7754,7 @@ async function handleRedmineCheck(options) {
6505
7754
  import { Command as Command31 } from "commander";
6506
7755
 
6507
7756
  // src/sync-issue.ts
6508
- import { resolve as resolve2, relative } from "path";
7757
+ import { resolve as resolve3, relative } from "path";
6509
7758
 
6510
7759
  // src/mappers.ts
6511
7760
  function mapIssueToFrontmatter(issue) {
@@ -6765,7 +8014,7 @@ async function syncIssue(issueId, config, options = {}) {
6765
8014
  const response = await client.getIssue(issueId, include);
6766
8015
  const issue = response.issue;
6767
8016
  const filename = generateFilename(issue.id, issue.subject, config.filename);
6768
- const filePath = resolve2(outputDir, filename);
8017
+ const filePath = resolve3(outputDir, filename);
6769
8018
  const relativePath = relative(process.cwd(), filePath);
6770
8019
  const existingFile = await readMarkdownFile(filePath);
6771
8020
  const existingIssueId = extractIssueIdFromFrontmatter(existingFile.frontmatter);
@@ -7048,7 +8297,7 @@ async function handleSyncProject(options) {
7048
8297
 
7049
8298
  // src/commands/framework/info.ts
7050
8299
  import { Command as Command33 } from "commander";
7051
- import { promises as fs8 } from "fs";
8300
+ import { promises as fs9 } from "fs";
7052
8301
  import { join as join5 } from "path";
7053
8302
  import { homedir as homedir5 } from "os";
7054
8303
  function createInfoCommand() {
@@ -7100,7 +8349,7 @@ function maskKey3(key) {
7100
8349
  async function getProjectStatus2() {
7101
8350
  const projectJai1 = join5(process.cwd(), ".jai1");
7102
8351
  try {
7103
- await fs8.access(projectJai1);
8352
+ await fs9.access(projectJai1);
7104
8353
  return { exists: true, version: "Synced" };
7105
8354
  } catch {
7106
8355
  return { exists: false };
@@ -7290,9 +8539,9 @@ function createClearBackupsCommand() {
7290
8539
  // src/commands/vscode/index.ts
7291
8540
  import { Command as Command36 } from "commander";
7292
8541
  import { checkbox as checkbox3, confirm as confirm8, select as select3 } from "@inquirer/prompts";
7293
- import fs9 from "fs/promises";
7294
- import path5 from "path";
7295
- import { existsSync as existsSync2 } from "fs";
8542
+ import fs10 from "fs/promises";
8543
+ import path6 from "path";
8544
+ import { existsSync as existsSync3 } from "fs";
7296
8545
  var PERFORMANCE_GROUPS2 = {
7297
8546
  telemetry: {
7298
8547
  name: "Telemetry",
@@ -7511,8 +8760,8 @@ async function selectGroupsToApply2(action) {
7511
8760
  }
7512
8761
  }
7513
8762
  async function applyGroups2(groupKeys, action) {
7514
- const vscodeDir = path5.join(process.cwd(), ".vscode");
7515
- const settingsPath = path5.join(vscodeDir, "settings.json");
8763
+ const vscodeDir = path6.join(process.cwd(), ".vscode");
8764
+ const settingsPath = path6.join(vscodeDir, "settings.json");
7516
8765
  const invalidGroups = groupKeys.filter((key) => !PERFORMANCE_GROUPS2[key]);
7517
8766
  if (invalidGroups.length > 0) {
7518
8767
  console.log(`
@@ -7520,14 +8769,14 @@ async function applyGroups2(groupKeys, action) {
7520
8769
  console.log(' \u{1F4A1} Ch\u1EA1y "jai1 vscode list" \u0111\u1EC3 xem danh s\xE1ch nh\xF3m c\xF3 s\u1EB5n.');
7521
8770
  return;
7522
8771
  }
7523
- if (!existsSync2(vscodeDir)) {
7524
- await fs9.mkdir(vscodeDir, { recursive: true });
8772
+ if (!existsSync3(vscodeDir)) {
8773
+ await fs10.mkdir(vscodeDir, { recursive: true });
7525
8774
  console.log("\u{1F4C1} \u0110\xE3 t\u1EA1o th\u01B0 m\u1EE5c .vscode/");
7526
8775
  }
7527
8776
  let currentSettings = {};
7528
- if (existsSync2(settingsPath)) {
8777
+ if (existsSync3(settingsPath)) {
7529
8778
  try {
7530
- const content = await fs9.readFile(settingsPath, "utf-8");
8779
+ const content = await fs10.readFile(settingsPath, "utf-8");
7531
8780
  currentSettings = JSON.parse(content);
7532
8781
  console.log("\u{1F4C4} \u0110\xE3 \u0111\u1ECDc c\xE0i \u0111\u1EB7t hi\u1EC7n t\u1EA1i t\u1EEB settings.json");
7533
8782
  } catch {
@@ -7567,15 +8816,15 @@ async function applyGroups2(groupKeys, action) {
7567
8816
  }
7568
8817
  }
7569
8818
  }
7570
- await fs9.writeFile(settingsPath, JSON.stringify(newSettings, null, 2));
8819
+ await fs10.writeFile(settingsPath, JSON.stringify(newSettings, null, 2));
7571
8820
  console.log(`
7572
8821
  \u2705 \u0110\xE3 c\u1EADp nh\u1EADt c\xE0i \u0111\u1EB7t VSCode t\u1EA1i: ${settingsPath}`);
7573
8822
  console.log("\u{1F4A1} M\u1EB9o: Kh\u1EDFi \u0111\u1ED9ng l\u1EA1i VSCode \u0111\u1EC3 \xE1p d\u1EE5ng c\xE1c thay \u0111\u1ED5i.");
7574
8823
  }
7575
8824
  async function resetSettings2(groupKeys) {
7576
- const vscodeDir = path5.join(process.cwd(), ".vscode");
7577
- const settingsPath = path5.join(vscodeDir, "settings.json");
7578
- if (!existsSync2(settingsPath)) {
8825
+ const vscodeDir = path6.join(process.cwd(), ".vscode");
8826
+ const settingsPath = path6.join(vscodeDir, "settings.json");
8827
+ if (!existsSync3(settingsPath)) {
7579
8828
  console.log("\n\u26A0\uFE0F Kh\xF4ng t\xECm th\u1EA5y file settings.json");
7580
8829
  return;
7581
8830
  }
@@ -7588,7 +8837,7 @@ async function resetSettings2(groupKeys) {
7588
8837
  return;
7589
8838
  }
7590
8839
  if (groupKeys.length === 0) {
7591
- await fs9.unlink(settingsPath);
8840
+ await fs10.unlink(settingsPath);
7592
8841
  console.log("\n\u2705 \u0110\xE3 x\xF3a file settings.json");
7593
8842
  } else {
7594
8843
  await applyGroups2(groupKeys, "disable");
@@ -7597,13 +8846,13 @@ async function resetSettings2(groupKeys) {
7597
8846
  }
7598
8847
 
7599
8848
  // src/commands/guide.ts
7600
- import React29 from "react";
8849
+ import React40 from "react";
7601
8850
  import { render as render6 } from "ink";
7602
8851
  import { Command as Command37 } from "commander";
7603
8852
  function createGuideCommand() {
7604
8853
  const cmd = new Command37("guide").description("Interactive guide center for Agentic Coding").option("--topic <topic>", "Open specific topic (intro, rules, workflows, prompts, skills)").action(async (options) => {
7605
8854
  const { waitUntilExit } = render6(
7606
- React29.createElement(GuideApp, {
8855
+ React40.createElement(GuideApp, {
7607
8856
  initialTopic: options.topic,
7608
8857
  onExit: () => {
7609
8858
  process.exit(0);
@@ -7616,7 +8865,7 @@ function createGuideCommand() {
7616
8865
  }
7617
8866
 
7618
8867
  // src/commands/context.ts
7619
- import React30 from "react";
8868
+ import React41 from "react";
7620
8869
  import { render as render7 } from "ink";
7621
8870
  import { Command as Command38 } from "commander";
7622
8871
  function createContextCommand() {
@@ -7646,7 +8895,7 @@ function createContextCommand() {
7646
8895
  return;
7647
8896
  }
7648
8897
  const { waitUntilExit } = render7(
7649
- React30.createElement(ContextApp, {
8898
+ React41.createElement(ContextApp, {
7650
8899
  initialIDE,
7651
8900
  initialType,
7652
8901
  onExit: () => {