diff --git a/app/components/chat.tsx b/app/components/chat.tsx index f7b67b293..9e4a2bd9a 100644 --- a/app/components/chat.tsx +++ b/app/components/chat.tsx @@ -19,6 +19,7 @@ import LightIcon from "../icons/light.svg"; import DarkIcon from "../icons/dark.svg"; import AutoIcon from "../icons/auto.svg"; import BottomIcon from "../icons/bottom.svg"; +import StopIcon from "../icons/pause.svg"; import { Message, @@ -38,7 +39,6 @@ import { isMobileScreen, selectOrCopy, autoGrowTextArea, - getCSSVar, } from "../utils"; import dynamic from "next/dynamic"; @@ -355,8 +355,8 @@ export function ChatActions(props: { }) { const chatStore = useChatStore(); + // switch themes const theme = chatStore.config.theme; - function nextTheme() { const themes = [Theme.Auto, Theme.Light, Theme.Dark]; const themeIndex = themes.indexOf(theme); @@ -365,8 +365,20 @@ export function ChatActions(props: { chatStore.updateConfig((config) => (config.theme = nextTheme)); } + // stop all responses + const couldStop = ControllerPool.hasPending(); + const stopAll = () => ControllerPool.stopAll(); + return (
+ {couldStop && ( +
+ +
+ )} {!props.hitBottom && (
+ diff --git a/app/icons/pause.svg b/app/icons/pause.svg new file mode 100644 index 000000000..382f7a939 --- /dev/null +++ b/app/icons/pause.svg @@ -0,0 +1 @@ + diff --git a/app/requests.ts b/app/requests.ts index c48ef2817..db91f6fc3 100644 --- a/app/requests.ts +++ b/app/requests.ts @@ -2,7 +2,7 @@ import type { ChatRequest, ChatResponse } from "./api/openai/typing"; import { Message, ModelConfig, useAccessStore, useChatStore } from "./store"; import { showToast } from "./components/ui-lib"; -const TIME_OUT_MS = 30000; +const TIME_OUT_MS = 60000; const makeRequestParam = ( messages: Message[], @@ -167,15 +167,14 @@ export async function requestChatStream( options?.onController?.(controller); while (true) { - // handle time out, will stop if no response in 10 secs const resTimeoutId = setTimeout(() => finish(), TIME_OUT_MS); const content = await reader?.read(); clearTimeout(resTimeoutId); - + if (!content || !content.value) { break; } - + const text = decoder.decode(content.value, { stream: true }); responseText += text; @@ -235,6 +234,14 @@ export const ControllerPool = { controller?.abort(); }, + stopAll() { + Object.values(this.controllers).forEach((v) => v.abort()); + }, + + hasPending() { + return Object.values(this.controllers).length > 0; + }, + remove(sessionIndex: number, messageId: number) { const key = this.key(sessionIndex, messageId); delete this.controllers[key]; diff --git a/app/store/app.ts b/app/store/app.ts index 813668905..c4c1c3411 100644 --- a/app/store/app.ts +++ b/app/store/app.ts @@ -421,7 +421,7 @@ export const useChatStore = create()( onError(error, statusCode) { if (statusCode === 401) { botMessage.content = Locale.Error.Unauthorized; - } else { + } else if (!error.message.includes("aborted")) { botMessage.content += "\n\n" + Locale.Store.Error; } botMessage.streaming = false; diff --git a/package.json b/package.json index 9fcb74e77..9a3e6d41c 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,8 @@ "start": "next start", "lint": "next lint", "fetch": "node ./scripts/fetch-prompts.mjs", - "prepare": "husky install" + "prepare": "husky install", + "proxy-dev": "sh ./scripts/init-proxy.sh && proxychains -f ./scripts/proxychains.conf yarn dev" }, "dependencies": { "@hello-pangea/dnd": "^16.2.0", diff --git a/scripts/.gitignore b/scripts/.gitignore new file mode 100644 index 000000000..80fe56c37 --- /dev/null +++ b/scripts/.gitignore @@ -0,0 +1 @@ +proxychains.conf diff --git a/scripts/init-proxy.sh b/scripts/init-proxy.sh new file mode 100644 index 000000000..acba064f4 --- /dev/null +++ b/scripts/init-proxy.sh @@ -0,0 +1,5 @@ +dir="$(dirname "$0")" +config=$dir/proxychains.conf +host_ip=$(grep nameserver /etc/resolv.conf | sed 's/nameserver //') +cp $dir/proxychains.template.conf $config +sed -i "\$s/.*/http $host_ip 7890/" $config diff --git a/scripts/proxychains.template.conf b/scripts/proxychains.template.conf new file mode 100644 index 000000000..e78b96a68 --- /dev/null +++ b/scripts/proxychains.template.conf @@ -0,0 +1,12 @@ +strict_chain +proxy_dns + +remote_dns_subnet 224 + +tcp_read_time_out 15000 +tcp_connect_time_out 8000 + +localnet 127.0.0.0/255.0.0.0 + +[ProxyList] +socks4 127.0.0.1 9050