lovecode-ai 0.1.1 → 0.1.3
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/README.md +2 -1
- package/dist/index.js +168 -103
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -33,13 +33,14 @@ npm install -g lovecode-ai
|
|
|
33
33
|
### From source
|
|
34
34
|
|
|
35
35
|
```bash
|
|
36
|
-
git clone https://github.com/
|
|
36
|
+
git clone https://github.com/ashispluslaxmi-debug/LoveCode.git
|
|
37
37
|
cd lovecode
|
|
38
38
|
npm install
|
|
39
39
|
npm run build
|
|
40
40
|
npm link
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
+
|
|
43
44
|
## Quick Start
|
|
44
45
|
|
|
45
46
|
```bash
|
package/dist/index.js
CHANGED
|
@@ -6406,12 +6406,12 @@ import { Command as Command13 } from "commander";
|
|
|
6406
6406
|
import chalk37 from "chalk";
|
|
6407
6407
|
|
|
6408
6408
|
// src/tui/index.ts
|
|
6409
|
-
import
|
|
6409
|
+
import React4 from "react";
|
|
6410
6410
|
import { render } from "ink";
|
|
6411
6411
|
|
|
6412
6412
|
// src/tui/App.tsx
|
|
6413
|
-
import { useState as
|
|
6414
|
-
import { Box as
|
|
6413
|
+
import { useState as useState3, useCallback as useCallback2 } from "react";
|
|
6414
|
+
import { Box as Box3 } from "ink";
|
|
6415
6415
|
|
|
6416
6416
|
// src/tui/components.tsx
|
|
6417
6417
|
import React, { useEffect as useEffect2 } from "react";
|
|
@@ -6571,19 +6571,6 @@ function Pane({ title, children, focused = false, borderColor, height }) {
|
|
|
6571
6571
|
}
|
|
6572
6572
|
);
|
|
6573
6573
|
}
|
|
6574
|
-
function ChatMessage({ role, content, streaming, streamedContent }) {
|
|
6575
|
-
const theme = getTheme();
|
|
6576
|
-
const displayContent = streaming && streamedContent !== void 0 ? streamedContent : content;
|
|
6577
|
-
const label = role === "user" ? "You" : role === "assistant" ? "LoveCode" : "System";
|
|
6578
|
-
const labelColor = role === "user" ? theme.colors.success : role === "assistant" ? theme.colors.primary : theme.colors.warning;
|
|
6579
|
-
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
6580
|
-
/* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Text, { bold: true, color: labelColor, children: label }) }),
|
|
6581
|
-
/* @__PURE__ */ jsxs(Box, { children: [
|
|
6582
|
-
/* @__PURE__ */ jsx(Text, { color: theme.colors.text, children: displayContent }),
|
|
6583
|
-
streaming && /* @__PURE__ */ jsx(Text, { color: theme.colors.primary, children: "\u2588" })
|
|
6584
|
-
] })
|
|
6585
|
-
] });
|
|
6586
|
-
}
|
|
6587
6574
|
function RepoContextPane({ projectName, branch, fileCount, language, framework, status, focused }) {
|
|
6588
6575
|
const theme = getTheme();
|
|
6589
6576
|
return /* @__PURE__ */ jsx(Pane, { title: "Repo Context", focused, height: 7, children: /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 2, children: [
|
|
@@ -6623,25 +6610,6 @@ function RepoContextPane({ projectName, branch, fileCount, language, framework,
|
|
|
6623
6610
|
] })
|
|
6624
6611
|
] }) });
|
|
6625
6612
|
}
|
|
6626
|
-
function ChatPane({ messages, streaming, streamedIndex, streamedContent, focused }) {
|
|
6627
|
-
const scroll = useScroll();
|
|
6628
|
-
useEffect2(() => {
|
|
6629
|
-
scroll.scrollToBottom();
|
|
6630
|
-
}, [messages.length]);
|
|
6631
|
-
return /* @__PURE__ */ jsx(Pane, { title: "Chat", focused, height: "100%", children: /* @__PURE__ */ jsxs(Box, { flexDirection: "column", overflowY: "hidden", overflowX: "hidden", children: [
|
|
6632
|
-
messages.length === 0 && /* @__PURE__ */ jsx(Text, { color: getTheme().colors.textDim, children: "Start typing to chat with LoveCode AI" }),
|
|
6633
|
-
messages.map((msg, i) => /* @__PURE__ */ jsx(
|
|
6634
|
-
ChatMessage,
|
|
6635
|
-
{
|
|
6636
|
-
role: msg.role,
|
|
6637
|
-
content: streaming && i === streamedIndex && streamedContent !== void 0 ? streamedContent : msg.content,
|
|
6638
|
-
streaming: streaming && i === streamedIndex,
|
|
6639
|
-
streamedContent: streaming && i === streamedIndex ? streamedContent : void 0
|
|
6640
|
-
},
|
|
6641
|
-
i
|
|
6642
|
-
))
|
|
6643
|
-
] }) });
|
|
6644
|
-
}
|
|
6645
6613
|
function CommandPane({ commands, focused }) {
|
|
6646
6614
|
const spinner = useSpinner();
|
|
6647
6615
|
const theme = getTheme();
|
|
@@ -6664,16 +6632,6 @@ function CommandPane({ commands, focused }) {
|
|
|
6664
6632
|
] }, i))
|
|
6665
6633
|
] }) });
|
|
6666
6634
|
}
|
|
6667
|
-
function InputPane({ value, placeholder, focused, mode, vimMode }) {
|
|
6668
|
-
const theme = getTheme();
|
|
6669
|
-
const cursor = vimMode ? mode === "normal" ? "\u258C" : "\u2588" : "\u2588";
|
|
6670
|
-
const modeIndicator = vimMode ? mode === "normal" ? " NORMAL " : " INSERT " : "";
|
|
6671
|
-
return /* @__PURE__ */ jsx(Pane, { title: `Input${modeIndicator}`, focused, height: 4, children: /* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
|
|
6672
|
-
/* @__PURE__ */ jsx(Text, { bold: true, color: theme.colors.success, children: " > " }),
|
|
6673
|
-
/* @__PURE__ */ jsx(Text, { color: theme.colors.text, children: value || (placeholder ? /* @__PURE__ */ jsx(Text, { color: theme.colors.textDim, children: placeholder }) : null) }),
|
|
6674
|
-
focused && /* @__PURE__ */ jsx(Text, { color: theme.colors.primary, children: cursor })
|
|
6675
|
-
] }) });
|
|
6676
|
-
}
|
|
6677
6635
|
function StatusBar({ mode, theme: themeName, focus, vimMode, messages }) {
|
|
6678
6636
|
const theme = getTheme();
|
|
6679
6637
|
return /* @__PURE__ */ jsxs(
|
|
@@ -6710,8 +6668,153 @@ function StatusBar({ mode, theme: themeName, focus, vimMode, messages }) {
|
|
|
6710
6668
|
);
|
|
6711
6669
|
}
|
|
6712
6670
|
|
|
6713
|
-
// src/tui/
|
|
6671
|
+
// src/tui/ChatBox.tsx
|
|
6672
|
+
import { useState as useState2, useEffect as useEffect3, useRef as useRef2 } from "react";
|
|
6673
|
+
import { Box as Box2, Text as Text2, useInput as useInput2 } from "ink";
|
|
6714
6674
|
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
6675
|
+
function MessageRow({ msg, isStreaming, streamContent }) {
|
|
6676
|
+
const theme = getTheme();
|
|
6677
|
+
const displayContent = isStreaming && streamContent !== void 0 ? streamContent : msg.content;
|
|
6678
|
+
const label = msg.role === "user" ? "You" : msg.role === "assistant" ? "LoveCode" : "System";
|
|
6679
|
+
const labelColor = msg.role === "user" ? theme.colors.success : msg.role === "assistant" ? theme.colors.primary : theme.colors.warning;
|
|
6680
|
+
const formatted = msg.role === "assistant" || msg.role === "system" ? renderMarkdown(displayContent) : displayContent;
|
|
6681
|
+
return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", marginBottom: 1, children: [
|
|
6682
|
+
/* @__PURE__ */ jsx2(Box2, { children: /* @__PURE__ */ jsx2(Text2, { bold: true, color: labelColor, children: label }) }),
|
|
6683
|
+
/* @__PURE__ */ jsxs2(Box2, { children: [
|
|
6684
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.colors.text, children: formatted }),
|
|
6685
|
+
isStreaming && /* @__PURE__ */ jsx2(Text2, { color: theme.colors.primary, children: "\u2588" })
|
|
6686
|
+
] })
|
|
6687
|
+
] });
|
|
6688
|
+
}
|
|
6689
|
+
function ChatBox({ messages, onSend, streaming, streamedContent, focused, placeholder = "Type a message..." }) {
|
|
6690
|
+
const [input, setInput] = useState2("");
|
|
6691
|
+
const [vimMode, setVimMode] = useState2("insert");
|
|
6692
|
+
const scroll = useScroll();
|
|
6693
|
+
const inputRef = useRef2(input);
|
|
6694
|
+
inputRef.current = input;
|
|
6695
|
+
useEffect3(() => {
|
|
6696
|
+
scroll.scrollToBottom();
|
|
6697
|
+
}, [messages.length, streamedContent]);
|
|
6698
|
+
useInput2((text, key) => {
|
|
6699
|
+
if (!focused) return;
|
|
6700
|
+
if (vimMode === "normal") {
|
|
6701
|
+
if (text === "i") {
|
|
6702
|
+
setVimMode("insert");
|
|
6703
|
+
return;
|
|
6704
|
+
}
|
|
6705
|
+
if (text === "a") {
|
|
6706
|
+
setVimMode("insert");
|
|
6707
|
+
setInput((prev) => prev + " ");
|
|
6708
|
+
return;
|
|
6709
|
+
}
|
|
6710
|
+
if (text === "j") {
|
|
6711
|
+
scroll.scrollDown();
|
|
6712
|
+
return;
|
|
6713
|
+
}
|
|
6714
|
+
if (text === "k") {
|
|
6715
|
+
scroll.scrollUp();
|
|
6716
|
+
return;
|
|
6717
|
+
}
|
|
6718
|
+
if (text === "g") {
|
|
6719
|
+
scroll.scrollToTop();
|
|
6720
|
+
return;
|
|
6721
|
+
}
|
|
6722
|
+
if (text === "G") {
|
|
6723
|
+
scroll.scrollToBottom();
|
|
6724
|
+
return;
|
|
6725
|
+
}
|
|
6726
|
+
return;
|
|
6727
|
+
}
|
|
6728
|
+
if (key.escape) {
|
|
6729
|
+
setVimMode("normal");
|
|
6730
|
+
return;
|
|
6731
|
+
}
|
|
6732
|
+
if (key.return && input.trim()) {
|
|
6733
|
+
onSend(input);
|
|
6734
|
+
setInput("");
|
|
6735
|
+
return;
|
|
6736
|
+
}
|
|
6737
|
+
if (key.backspace || key.delete) {
|
|
6738
|
+
setInput((prev) => prev.slice(0, -1));
|
|
6739
|
+
return;
|
|
6740
|
+
}
|
|
6741
|
+
if (key.upArrow) {
|
|
6742
|
+
scroll.scrollUp();
|
|
6743
|
+
return;
|
|
6744
|
+
}
|
|
6745
|
+
if (key.downArrow) {
|
|
6746
|
+
scroll.scrollDown();
|
|
6747
|
+
return;
|
|
6748
|
+
}
|
|
6749
|
+
if (key.pageUp) {
|
|
6750
|
+
for (let i = 0; i < 10; i++) scroll.scrollUp();
|
|
6751
|
+
return;
|
|
6752
|
+
}
|
|
6753
|
+
if (key.pageDown) {
|
|
6754
|
+
for (let i = 0; i < 10; i++) scroll.scrollDown();
|
|
6755
|
+
return;
|
|
6756
|
+
}
|
|
6757
|
+
if (text && text.length === 1 && !key.ctrl && !key.meta) {
|
|
6758
|
+
setInput((prev) => prev + text);
|
|
6759
|
+
}
|
|
6760
|
+
});
|
|
6761
|
+
const theme = getTheme();
|
|
6762
|
+
const cursor = vimMode === "normal" ? "\u258C" : "\u2588";
|
|
6763
|
+
const modeIndicator = vimMode === "normal" ? " NORMAL " : " INSERT ";
|
|
6764
|
+
const maxVisible = 10;
|
|
6765
|
+
return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", height: "100%", width: "100%", children: [
|
|
6766
|
+
/* @__PURE__ */ jsxs2(
|
|
6767
|
+
Box2,
|
|
6768
|
+
{
|
|
6769
|
+
flexDirection: "column",
|
|
6770
|
+
flexGrow: 1,
|
|
6771
|
+
overflowY: "hidden",
|
|
6772
|
+
overflowX: "hidden",
|
|
6773
|
+
paddingX: 1,
|
|
6774
|
+
paddingY: 0,
|
|
6775
|
+
children: [
|
|
6776
|
+
messages.length === 0 && /* @__PURE__ */ jsx2(Text2, { color: theme.colors.textDim, children: "Start typing to chat with LoveCode AI" }),
|
|
6777
|
+
messages.map((msg, i) => /* @__PURE__ */ jsx2(
|
|
6778
|
+
MessageRow,
|
|
6779
|
+
{
|
|
6780
|
+
msg,
|
|
6781
|
+
isStreaming: streaming && i === messages.length - 1,
|
|
6782
|
+
streamContent: streaming && i === messages.length - 1 ? streamedContent : void 0
|
|
6783
|
+
},
|
|
6784
|
+
i
|
|
6785
|
+
)),
|
|
6786
|
+
messages.length > maxVisible && /* @__PURE__ */ jsxs2(Text2, { color: theme.colors.textDim, children: [
|
|
6787
|
+
"-- Press j/k to scroll (",
|
|
6788
|
+
scroll.offset + 1,
|
|
6789
|
+
"-",
|
|
6790
|
+
Math.min(scroll.offset + maxVisible, messages.length),
|
|
6791
|
+
" of ",
|
|
6792
|
+
messages.length,
|
|
6793
|
+
") --"
|
|
6794
|
+
] })
|
|
6795
|
+
]
|
|
6796
|
+
}
|
|
6797
|
+
),
|
|
6798
|
+
/* @__PURE__ */ jsxs2(
|
|
6799
|
+
Box2,
|
|
6800
|
+
{
|
|
6801
|
+
borderStyle: "round",
|
|
6802
|
+
borderColor: focused ? theme.colors.primary : theme.colors.border,
|
|
6803
|
+
marginX: 0,
|
|
6804
|
+
paddingX: 1,
|
|
6805
|
+
children: [
|
|
6806
|
+
/* @__PURE__ */ jsx2(Text2, { bold: true, color: theme.colors.warning, children: modeIndicator }),
|
|
6807
|
+
/* @__PURE__ */ jsx2(Text2, { bold: true, color: theme.colors.success, children: " > " }),
|
|
6808
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.colors.text, children: input || /* @__PURE__ */ jsx2(Text2, { color: theme.colors.textDim, children: placeholder }) }),
|
|
6809
|
+
focused && vimMode === "insert" && /* @__PURE__ */ jsx2(Text2, { color: theme.colors.primary, children: cursor })
|
|
6810
|
+
]
|
|
6811
|
+
}
|
|
6812
|
+
)
|
|
6813
|
+
] });
|
|
6814
|
+
}
|
|
6815
|
+
|
|
6816
|
+
// src/tui/App.tsx
|
|
6817
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
6715
6818
|
function App({
|
|
6716
6819
|
initialMessages = [],
|
|
6717
6820
|
projectName: _pn,
|
|
@@ -6723,57 +6826,31 @@ function App({
|
|
|
6723
6826
|
onSendMessage,
|
|
6724
6827
|
onRunCommand
|
|
6725
6828
|
}) {
|
|
6726
|
-
const [messages, setMessages] =
|
|
6727
|
-
const [commands, setCommands] =
|
|
6728
|
-
const [
|
|
6729
|
-
const [
|
|
6730
|
-
const [streamedContent, setStreamedContent] = useState2("");
|
|
6731
|
-
const [streamedIndex, setStreamedIndex] = useState2(0);
|
|
6732
|
-
const [vimMode, setVimMode] = useState2("insert");
|
|
6829
|
+
const [messages, setMessages] = useState3(initialMessages);
|
|
6830
|
+
const [commands, setCommands] = useState3([]);
|
|
6831
|
+
const [streaming, setStreaming] = useState3(false);
|
|
6832
|
+
const [streamedContent, setStreamedContent] = useState3("");
|
|
6733
6833
|
const [focus, setFocus] = useFocus();
|
|
6734
|
-
const [currentTheme, setCurrentThemeState] =
|
|
6834
|
+
const [currentTheme, setCurrentThemeState] = useState3("default");
|
|
6735
6835
|
useTerminalSize();
|
|
6736
6836
|
const setCurrentTheme = useCallback2((name) => {
|
|
6737
6837
|
setTheme(name);
|
|
6738
6838
|
setCurrentThemeState(name);
|
|
6739
6839
|
}, []);
|
|
6740
6840
|
useKeyboard({
|
|
6741
|
-
onKey: (key) => {
|
|
6742
|
-
if (focus === "input") {
|
|
6743
|
-
if (vimMode === "normal") {
|
|
6744
|
-
if (key === "i") setVimMode("insert");
|
|
6745
|
-
else if (key === "h") {
|
|
6746
|
-
setFocus("chat");
|
|
6747
|
-
} else if (key === "l") {
|
|
6748
|
-
setFocus("command");
|
|
6749
|
-
}
|
|
6750
|
-
}
|
|
6751
|
-
}
|
|
6752
|
-
},
|
|
6753
|
-
onEnter: () => {
|
|
6754
|
-
if (focus === "input" && input.trim() && vimMode === "insert") {
|
|
6755
|
-
handleSend(input);
|
|
6756
|
-
}
|
|
6757
|
-
},
|
|
6758
|
-
onEscape: () => {
|
|
6759
|
-
if (vimMode === "insert") setVimMode("normal");
|
|
6760
|
-
},
|
|
6761
6841
|
onTab: () => {
|
|
6762
|
-
setFocus(focus === "
|
|
6842
|
+
setFocus(focus === "chat" ? "command" : focus === "command" ? "repo" : focus === "repo" ? "chat" : "chat");
|
|
6763
6843
|
}
|
|
6764
6844
|
});
|
|
6765
6845
|
async function handleSend(text) {
|
|
6766
6846
|
const userMsg = { role: "user", content: text };
|
|
6767
6847
|
setMessages((prev) => [...prev, userMsg]);
|
|
6768
|
-
setInput("");
|
|
6769
6848
|
if (text.startsWith("/")) {
|
|
6770
6849
|
handleCommand(text);
|
|
6771
6850
|
return;
|
|
6772
6851
|
}
|
|
6773
6852
|
if (onSendMessage) {
|
|
6774
6853
|
setStreaming(true);
|
|
6775
|
-
const idx = messages.length + 1;
|
|
6776
|
-
setStreamedIndex(idx);
|
|
6777
6854
|
setStreamedContent("");
|
|
6778
6855
|
try {
|
|
6779
6856
|
const response = await onSendMessage(text);
|
|
@@ -6802,8 +6879,7 @@ function App({
|
|
|
6802
6879
|
setMessages((prev) => [...prev, { role: "system", content: `Unknown theme: ${name}. Available: ${names.join(", ")}` }]);
|
|
6803
6880
|
}
|
|
6804
6881
|
} else if (cmd === "vim") {
|
|
6805
|
-
|
|
6806
|
-
setMessages((prev) => [...prev, { role: "system", content: `Vim mode: ${vimMode === "normal" ? "insert" : "normal"}` }]);
|
|
6882
|
+
setMessages((prev) => [...prev, { role: "system", content: "Vim mode is built into the chat box (Esc = normal, i = insert)" }]);
|
|
6807
6883
|
} else if (cmd === "exit" || cmd === "quit") {
|
|
6808
6884
|
process.exit(0);
|
|
6809
6885
|
} else if (cmd.startsWith("!")) {
|
|
@@ -6834,9 +6910,9 @@ function App({
|
|
|
6834
6910
|
}
|
|
6835
6911
|
}
|
|
6836
6912
|
}
|
|
6837
|
-
return /* @__PURE__ */
|
|
6838
|
-
/* @__PURE__ */
|
|
6839
|
-
/* @__PURE__ */
|
|
6913
|
+
return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", width: "100%", height: "100%", children: [
|
|
6914
|
+
/* @__PURE__ */ jsx3(Box3, { flexDirection: "column", flexGrow: 1, paddingX: 0, children: /* @__PURE__ */ jsxs3(SplitPane, { direction: "vertical", sizes: [15, 60, 25], children: [
|
|
6915
|
+
/* @__PURE__ */ jsx3(
|
|
6840
6916
|
RepoContextPane,
|
|
6841
6917
|
{
|
|
6842
6918
|
projectName: _pn || "LoveCode",
|
|
@@ -6848,43 +6924,32 @@ function App({
|
|
|
6848
6924
|
focused: focus === "repo"
|
|
6849
6925
|
}
|
|
6850
6926
|
),
|
|
6851
|
-
/* @__PURE__ */
|
|
6852
|
-
|
|
6927
|
+
/* @__PURE__ */ jsx3(
|
|
6928
|
+
ChatBox,
|
|
6853
6929
|
{
|
|
6854
6930
|
messages,
|
|
6931
|
+
onSend: handleSend,
|
|
6855
6932
|
streaming,
|
|
6856
|
-
streamedIndex,
|
|
6857
6933
|
streamedContent,
|
|
6858
|
-
focused: focus === "chat"
|
|
6934
|
+
focused: focus === "chat",
|
|
6935
|
+
placeholder: "Type a message or /help..."
|
|
6859
6936
|
}
|
|
6860
6937
|
),
|
|
6861
|
-
/* @__PURE__ */
|
|
6938
|
+
/* @__PURE__ */ jsx3(
|
|
6862
6939
|
CommandPane,
|
|
6863
6940
|
{
|
|
6864
6941
|
commands,
|
|
6865
6942
|
focused: focus === "command"
|
|
6866
6943
|
}
|
|
6867
|
-
),
|
|
6868
|
-
/* @__PURE__ */ jsx2(
|
|
6869
|
-
InputPane,
|
|
6870
|
-
{
|
|
6871
|
-
value: input,
|
|
6872
|
-
onChange: setInput,
|
|
6873
|
-
onSubmit: handleSend,
|
|
6874
|
-
placeholder: "Type a message or /help...",
|
|
6875
|
-
focused: focus === "input",
|
|
6876
|
-
mode: vimMode,
|
|
6877
|
-
vimMode: true
|
|
6878
|
-
}
|
|
6879
6944
|
)
|
|
6880
6945
|
] }) }),
|
|
6881
|
-
/* @__PURE__ */
|
|
6946
|
+
/* @__PURE__ */ jsx3(
|
|
6882
6947
|
StatusBar,
|
|
6883
6948
|
{
|
|
6884
6949
|
mode: "chat",
|
|
6885
6950
|
theme: currentTheme,
|
|
6886
6951
|
focus,
|
|
6887
|
-
vimMode:
|
|
6952
|
+
vimMode: "INSERT",
|
|
6888
6953
|
messages: messages.length
|
|
6889
6954
|
}
|
|
6890
6955
|
)
|
|
@@ -6893,7 +6958,7 @@ function App({
|
|
|
6893
6958
|
|
|
6894
6959
|
// src/tui/index.ts
|
|
6895
6960
|
function startTUI(props) {
|
|
6896
|
-
const { waitUntilExit } = render(
|
|
6961
|
+
const { waitUntilExit } = render(React4.createElement(App, props));
|
|
6897
6962
|
waitUntilExit().then(() => process.exit(0));
|
|
6898
6963
|
}
|
|
6899
6964
|
|