Skip to content

Commit 26a340f

Browse files
authored
Merge branch 'Yidadaa:main' into release
2 parents 3e6829b + 7f13a8d commit 26a340f

26 files changed

+489
-60
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ One-Click to deploy well-designed ChatGPT web UI on Vercel.
3131
- New in v2: create, share and debug your chat tools with prompt templates (mask)
3232
- Awesome prompts powered by [awesome-chatgpt-prompts-zh](https://github.com/PlexPt/awesome-chatgpt-prompts-zh) and [awesome-chatgpt-prompts](https://github.com/f/awesome-chatgpt-prompts)
3333
- Automatically compresses chat history to support long conversations while also saving your tokens
34-
- I18n: English, 简体中文, 繁体中文, 日本語, Français, Español, Italiano, Türkçe, Deutsch, Tiếng Việt, Русский, Čeština
34+
- I18n: English, 简体中文, 繁体中文, 日本語, Français, Español, Italiano, Türkçe, Deutsch, Tiếng Việt, Русский, Čeština, 한국어
3535

3636
## Roadmap
3737

app/api/common.ts

+28-12
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const PROTOCOL = process.env.PROTOCOL ?? DEFAULT_PROTOCOL;
66
const BASE_URL = process.env.BASE_URL ?? OPENAI_URL;
77

88
export async function requestOpenai(req: NextRequest) {
9+
const controller = new AbortController();
910
const authValue = req.headers.get("Authorization") ?? "";
1011
const openaiPath = `${req.nextUrl.pathname}${req.nextUrl.search}`.replaceAll(
1112
"/api/openai/",
@@ -25,16 +26,31 @@ export async function requestOpenai(req: NextRequest) {
2526
console.log("[Org ID]", process.env.OPENAI_ORG_ID);
2627
}
2728

28-
return fetch(`${baseUrl}/${openaiPath}`, {
29-
headers: {
30-
"Content-Type": "application/json",
31-
Authorization: authValue,
32-
...(process.env.OPENAI_ORG_ID && {
33-
"OpenAI-Organization": process.env.OPENAI_ORG_ID,
34-
}),
35-
},
36-
cache: "no-store",
37-
method: req.method,
38-
body: req.body,
39-
});
29+
const timeoutId = setTimeout(() => {
30+
controller.abort();
31+
}, 10 * 60 * 1000);
32+
33+
try {
34+
return await fetch(`${baseUrl}/${openaiPath}`, {
35+
headers: {
36+
"Content-Type": "application/json",
37+
Authorization: authValue,
38+
...(process.env.OPENAI_ORG_ID && {
39+
"OpenAI-Organization": process.env.OPENAI_ORG_ID,
40+
}),
41+
},
42+
cache: "no-store",
43+
method: req.method,
44+
body: req.body,
45+
signal: controller.signal,
46+
});
47+
} catch (err: unknown) {
48+
if (err instanceof Error && err.name === 'AbortError') {
49+
console.log('Fetch aborted');
50+
} else {
51+
throw err;
52+
}
53+
} finally {
54+
clearTimeout(timeoutId);
55+
}
4056
}

app/client/platforms/openai.ts

+8-2
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,9 @@ export class ChatGPTApi implements LLMApi {
9999

100100
if (
101101
!res.ok ||
102-
res.headers.get("content-type") !== EventStreamContentType ||
102+
!res.headers
103+
.get("content-type")
104+
?.startsWith(EventStreamContentType) ||
103105
res.status !== 200
104106
) {
105107
const responseTexts = [responseText];
@@ -187,10 +189,14 @@ export class ChatGPTApi implements LLMApi {
187189
}),
188190
]);
189191

190-
if (!used.ok || !subs.ok || used.status === 401) {
192+
if (used.status === 401) {
191193
throw new Error(Locale.Error.Unauthorized);
192194
}
193195

196+
if (!used.ok || !subs.ok) {
197+
throw new Error("Failed to query usage from openai");
198+
}
199+
194200
const response = (await used.json()) as {
195201
total_usage?: number;
196202
error?: {

app/components/chat.tsx

+13-5
Original file line numberDiff line numberDiff line change
@@ -487,18 +487,26 @@ export function Chat() {
487487

488488
// stop response
489489
const onUserStop = (messageId: number) => {
490+
ChatControllerPool.stop(sessionIndex, messageId);
491+
};
492+
493+
useEffect(() => {
490494
chatStore.updateCurrentSession((session) => {
491495
const stopTiming = Date.now() - REQUEST_TIMEOUT_MS;
492496
session.messages.forEach((m) => {
493497
// check if should stop all stale messages
494-
if (m.streaming && new Date(m.date).getTime() < stopTiming) {
495-
m.isError = false;
496-
m.streaming = false;
498+
if (new Date(m.date).getTime() < stopTiming) {
499+
if (m.streaming) {
500+
m.streaming = false;
501+
}
502+
503+
if (m.content.length === 0) {
504+
m.content = "No content in this message.";
505+
}
497506
}
498507
});
499508
});
500-
ChatControllerPool.stop(sessionIndex, messageId);
501-
};
509+
}, []);
502510

503511
// check if should send message
504512
const onInputKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {

app/components/mask.tsx

+5
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,11 @@ export function MaskPage() {
256256
maskStore.create(mask);
257257
}
258258
}
259+
return;
260+
}
261+
//if the content is a single mask.
262+
if (importMasks.name) {
263+
maskStore.create(importMasks);
259264
}
260265
} catch {}
261266
});

app/locales/cn.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ const cn = {
8282
vi: "Tiếng Việt",
8383
ru: "Русский",
8484
cs: "Čeština",
85+
ko: "한국어",
8586
},
8687
},
8788
Avatar: "头像",
@@ -240,6 +241,11 @@ const cn = {
240241
},
241242
};
242243

243-
export type LocaleType = typeof cn;
244+
type DeepPartial<T> = T extends object
245+
? {
246+
[P in keyof T]?: DeepPartial<T[P]>;
247+
}
248+
: T;
249+
export type LocaleType = DeepPartial<typeof cn>;
244250

245251
export default cn;

app/locales/cs.ts

+1
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ const cs: LocaleType = {
8484
vi: "Tiếng Việt",
8585
ru: "Русский",
8686
cs: "Čeština",
87+
ko: "한국어",
8788
},
8889
},
8990
Avatar: "Avatar",

app/locales/de.ts

+1
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ const de: LocaleType = {
8585
vi: "Tiếng Việt",
8686
ru: "Русский",
8787
cs: "Čeština",
88+
ko: "한국어",
8889
},
8990
},
9091
Avatar: "Avatar",

app/locales/en.ts

+1
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ const en: LocaleType = {
8484
vi: "Tiếng Việt",
8585
ru: "Русский",
8686
cs: "Čeština",
87+
ko: "한국어",
8788
},
8889
},
8990
Avatar: "Avatar",

app/locales/es.ts

+1
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ const es: LocaleType = {
8484
vi: "Tiếng Việt",
8585
ru: "Русский",
8686
cs: "Čeština",
87+
ko: "한국어"
8788
},
8889
},
8990
Avatar: "Avatar",

app/locales/fr.ts

+1
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ const fr: LocaleType = {
8585
vi: "Vietnamese",
8686
ru: "Русский",
8787
cs: "Čeština",
88+
ko: "한국어"
8889
},
8990
},
9091

app/locales/index.ts

+11-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import DE from "./de";
1010
import VI from "./vi";
1111
import RU from "./ru";
1212
import CS from "./cs";
13+
import KO from "./ko";
14+
import { merge } from "../utils/merge";
1315

1416
export type { LocaleType } from "./cn";
1517

@@ -26,6 +28,7 @@ export const AllLangs = [
2628
"vi",
2729
"ru",
2830
"cs",
31+
"ko",
2932
] as const;
3033
export type Lang = (typeof AllLangs)[number];
3134

@@ -78,7 +81,8 @@ export function changeLang(lang: Lang) {
7881
location.reload();
7982
}
8083

81-
export default {
84+
const fallbackLang = EN;
85+
const targetLang = {
8286
en: EN,
8387
cn: CN,
8488
tw: TW,
@@ -91,4 +95,10 @@ export default {
9195
vi: VI,
9296
ru: RU,
9397
cs: CS,
98+
ko: KO,
9499
}[getLang()] as typeof CN;
100+
101+
// if target lang missing some fields, it will use fallback lang string
102+
merge(fallbackLang, targetLang);
103+
104+
export default fallbackLang as typeof CN;

app/locales/it.ts

+1
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ const it: LocaleType = {
8484
vi: "Tiếng Việt",
8585
ru: "Русский",
8686
cs: "Čeština",
87+
ko: "한국어",
8788
},
8889
},
8990
Avatar: "Avatar",

app/locales/jp.ts

+1
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ const jp: LocaleType = {
8484
vi: "Tiếng Việt",
8585
ru: "Русский",
8686
cs: "Čeština",
87+
ko: "한국어"
8788
},
8889
},
8990
Avatar: "アバター",

0 commit comments

Comments
 (0)