xiao commited on
Commit
d64cd05
·
1 Parent(s): a7c621e
Dockerfile CHANGED
@@ -19,6 +19,7 @@ FROM base AS builder
19
  RUN apk update && apk add --no-cache git
20
 
21
  ENV OPENAI_API_KEY=""
 
22
  ENV CODE=""
23
  ARG DOCKER=true
24
 
@@ -32,6 +33,7 @@ FROM base AS runner
32
  WORKDIR /app
33
 
34
  ENV OPENAI_API_KEY=""
 
35
  ENV CODE=""
36
 
37
  COPY --from=builder /app/public ./public
 
19
  RUN apk update && apk add --no-cache git
20
 
21
  ENV OPENAI_API_KEY=""
22
+ ENV COOKIES=""
23
  ENV CODE=""
24
  ARG DOCKER=true
25
 
 
33
  WORKDIR /app
34
 
35
  ENV OPENAI_API_KEY=""
36
+ ENV COOKIES=""
37
  ENV CODE=""
38
 
39
  COPY --from=builder /app/public ./public
app/components/settings.tsx CHANGED
@@ -24,7 +24,7 @@ import {
24
  import { Avatar, PromptHints } from "./home";
25
 
26
  import Locale, { AllLangs, changeLang, getLang } from "../locales";
27
- import { getCurrentCommitId } from "../utils";
28
  import Link from "next/link";
29
  import { UPDATE_URL } from "../constant";
30
  import { SearchService, usePromptStore } from "../store/prompt";
@@ -132,6 +132,7 @@ export function Settings(props: { closeSettings: () => void }) {
132
  <EmojiPicker
133
  lazyLoadEmojis
134
  theme={EmojiTheme.AUTO}
 
135
  onEmojiClick={(e) => {
136
  updateConfig((config) => (config.avatar = e.unified));
137
  setShowEmojiPicker(false);
@@ -388,6 +389,7 @@ export function Settings(props: { closeSettings: () => void }) {
388
  (config.modelConfig.model = e.currentTarget.value),
389
  );
390
  }}
 
391
  >
392
  {ALL_MODELS.map((v) => (
393
  <option value={v.name} key={v.name} disabled={!v.available}>
 
24
  import { Avatar, PromptHints } from "./home";
25
 
26
  import Locale, { AllLangs, changeLang, getLang } from "../locales";
27
+ import { getCurrentCommitId, getEmojiUrl } from "../utils";
28
  import Link from "next/link";
29
  import { UPDATE_URL } from "../constant";
30
  import { SearchService, usePromptStore } from "../store/prompt";
 
132
  <EmojiPicker
133
  lazyLoadEmojis
134
  theme={EmojiTheme.AUTO}
135
+ getEmojiUrl={getEmojiUrl}
136
  onEmojiClick={(e) => {
137
  updateConfig((config) => (config.avatar = e.unified));
138
  setShowEmojiPicker(false);
 
389
  (config.modelConfig.model = e.currentTarget.value),
390
  );
391
  }}
392
+ disabled={config.model != "聊天"}
393
  >
394
  {ALL_MODELS.map((v) => (
395
  <option value={v.name} key={v.name} disabled={!v.available}>
app/locales/cn.ts CHANGED
@@ -111,7 +111,7 @@ const cn = {
111
  Store: {
112
  DefaultTopic: "新的聊天",
113
  BotHello: "有什么可以帮你的吗",
114
- Error: "出错了,稍后重试吧",
115
  Prompt: {
116
  History: (content: string) =>
117
  "这是 ai 和用户的历史聊天总结作为前情提要:" + content,
 
111
  Store: {
112
  DefaultTopic: "新的聊天",
113
  BotHello: "有什么可以帮你的吗",
114
+ Error: "出错了,请新建聊天试试吧",
115
  Prompt: {
116
  History: (content: string) =>
117
  "这是 ai 和用户的历史聊天总结作为前情提要:" + content,
app/requests.ts CHANGED
@@ -13,7 +13,7 @@ import {
13
  } from "./store";
14
  import Locale from "./locales";
15
  import { CreateImageRequestSizeEnum } from "openai";
16
- const TIME_OUT_MS = 180000;
17
 
18
  const makeRequestParam = (
19
  messages: Message[],
@@ -156,7 +156,7 @@ export async function requestChatStream(
156
  console.error("NetWork Error", err);
157
  options?.onError(err as Error);
158
  }
159
- } else {
160
  console.log("[Request] ", messages[messages.length - 1].content);
161
  const req = makeImageRequestParam(messages);
162
  const controller = new AbortController();
@@ -181,7 +181,59 @@ export async function requestChatStream(
181
  controller.abort();
182
  } catch (err) {
183
  console.error("NetWork Error", err);
184
- options?.onError(err as Error);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
185
  }
186
  }
187
  }
 
13
  } from "./store";
14
  import Locale from "./locales";
15
  import { CreateImageRequestSizeEnum } from "openai";
16
+ const TIME_OUT_MS = 120000;
17
 
18
  const makeRequestParam = (
19
  messages: Message[],
 
156
  console.error("NetWork Error", err);
157
  options?.onError(err as Error);
158
  }
159
+ } else if (model == "AI绘画") {
160
  console.log("[Request] ", messages[messages.length - 1].content);
161
  const req = makeImageRequestParam(messages);
162
  const controller = new AbortController();
 
181
  controller.abort();
182
  } catch (err) {
183
  console.error("NetWork Error", err);
184
+ options?.onMessage("请换一个问题试试吧", true);
185
+ }
186
+ } else if (model == "必应") {
187
+ console.log("[Request] ", messages[messages.length - 1].content);
188
+ const controller = new AbortController();
189
+ const reqTimeoutId = setTimeout(() => controller.abort(), TIME_OUT_MS);
190
+ try {
191
+ const res = await fetch("/api/newbing", {
192
+ method: "POST",
193
+ headers: {
194
+ "Content-Type": "application/json",
195
+ ...getHeaders(),
196
+ },
197
+ body: JSON.stringify(messages[messages.length - 1].content),
198
+ });
199
+
200
+ clearTimeout(reqTimeoutId);
201
+
202
+ let message = await res.text();
203
+ // let responseText = "";
204
+ // for (let i = 1; i <= message.length; i++) {
205
+ // // handle time out, will stop if no response in 10 secs
206
+ // let messages = message.slice(0,i);
207
+ // console.log(message)
208
+ // responseText = messages;
209
+ // options?.onMessage(responseText, false);
210
+ // }
211
+ options?.onMessage(message, true);
212
+ controller.abort();
213
+ } catch (err) {
214
+ console.error("NetWork Error", err);
215
+ options?.onMessage("请换一个问题试试吧", true);
216
+ }
217
+ } else {
218
+ console.log("[Request] ", messages[messages.length - 1].content);
219
+ const controller = new AbortController();
220
+ const reqTimeoutId = setTimeout(() => controller.abort(), TIME_OUT_MS);
221
+ try {
222
+ const res = await fetch("/api/wanjuan", {
223
+ method: "POST",
224
+ headers: {
225
+ "Content-Type": "application/json",
226
+ ...getHeaders(),
227
+ },
228
+ body: JSON.stringify(messages[messages.length - 1].content),
229
+ });
230
+
231
+ clearTimeout(reqTimeoutId);
232
+ options?.onMessage(await res.text(), true);
233
+ controller.abort();
234
+ } catch (err) {
235
+ console.error("NetWork Error", err);
236
+ options?.onMessage("请换一个问题试试吧", true);
237
  }
238
  }
239
  }
app/store/app.ts CHANGED
@@ -92,6 +92,14 @@ export const ALL_MODEL = [
92
  name: "AI绘画",
93
  available: true,
94
  },
 
 
 
 
 
 
 
 
95
  ];
96
 
97
  export function isValidModel(name: string) {
@@ -407,19 +415,23 @@ export const useChatStore = create<ChatStore>()(
407
 
408
  summarizeSession() {
409
  const session = get().currentSession();
410
-
411
  if (session.topic === DEFAULT_TOPIC && session.messages.length >= 3) {
412
- // should summarize topic
413
- requestWithPrompt(session.messages, Locale.Store.Prompt.Topic).then(
414
- (res) => {
415
- get().updateCurrentSession(
416
- (session) => (session.topic = trimTopic(res)),
417
- );
418
- },
419
- );
 
 
 
 
 
 
420
  }
421
-
422
- const config = get().config;
423
  let toBeSummarizedMsgs = session.messages.slice(
424
  session.lastSummarizeIndex,
425
  );
 
92
  name: "AI绘画",
93
  available: true,
94
  },
95
+ {
96
+ name: "必应",
97
+ available: true,
98
+ },
99
+ {
100
+ name: "万卷",
101
+ available: true,
102
+ },
103
  ];
104
 
105
  export function isValidModel(name: string) {
 
415
 
416
  summarizeSession() {
417
  const session = get().currentSession();
418
+ const config = get().config;
419
  if (session.topic === DEFAULT_TOPIC && session.messages.length >= 3) {
420
+ if (config.model == "必应" || config.model == "万卷") {
421
+ get().updateCurrentSession(
422
+ (session) => (session.topic = trimTopic(config.model)),
423
+ );
424
+ } else {
425
+ // should summarize topic
426
+ requestWithPrompt(session.messages, Locale.Store.Prompt.Topic).then(
427
+ (res) => {
428
+ get().updateCurrentSession(
429
+ (session) => (session.topic = trimTopic(res)),
430
+ );
431
+ },
432
+ );
433
+ }
434
  }
 
 
435
  let toBeSummarizedMsgs = session.messages.slice(
436
  session.lastSummarizeIndex,
437
  );
app/utils.ts CHANGED
@@ -1,3 +1,4 @@
 
1
  import { showToast } from "./components/ui-lib";
2
  import Locale from "./locales";
3
 
@@ -14,21 +15,31 @@ export function trimTopic(topic: string) {
14
  }
15
 
16
  export function copyToClipboard(text: string) {
17
- navigator.clipboard
18
- .writeText(text)
19
- .then((res) => {
20
- showToast(Locale.Copy.Success);
21
- })
22
- .catch((err) => {
23
- showToast(Locale.Copy.Failed);
24
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
  }
26
 
27
  export function downloadAs(text: string, filename: string) {
28
  const element = document.createElement("a");
29
  element.setAttribute(
30
  "href",
31
- "data:text/plain;charset=utf-8," + encodeURIComponent(text)
32
  );
33
  element.setAttribute("download", filename);
34
 
@@ -61,7 +72,7 @@ export function queryMeta(key: string, defaultValue?: string): string {
61
  let ret: string;
62
  if (document) {
63
  const meta = document.head.querySelector(
64
- `meta[name='${key}']`
65
  ) as HTMLMetaElement;
66
  ret = meta?.content ?? "";
67
  } else {
@@ -81,3 +92,7 @@ export function getCurrentCommitId() {
81
 
82
  return currentId;
83
  }
 
 
 
 
 
1
+ import { EmojiStyle } from "emoji-picker-react";
2
  import { showToast } from "./components/ui-lib";
3
  import Locale from "./locales";
4
 
 
15
  }
16
 
17
  export function copyToClipboard(text: string) {
18
+ if (navigator.clipboard) {
19
+ navigator.clipboard.writeText(text).catch((err) => {
20
+ console.error("Failed to copy: ", err);
 
 
 
 
21
  });
22
+ } else {
23
+ const textArea = document.createElement("textarea");
24
+ textArea.value = text;
25
+ document.body.appendChild(textArea);
26
+ textArea.focus();
27
+ textArea.select();
28
+ try {
29
+ document.execCommand("copy");
30
+ console.log("Text copied to clipboard");
31
+ } catch (err) {
32
+ console.error("Failed to copy: ", err);
33
+ }
34
+ document.body.removeChild(textArea);
35
+ }
36
  }
37
 
38
  export function downloadAs(text: string, filename: string) {
39
  const element = document.createElement("a");
40
  element.setAttribute(
41
  "href",
42
+ "data:text/plain;charset=utf-8," + encodeURIComponent(text),
43
  );
44
  element.setAttribute("download", filename);
45
 
 
72
  let ret: string;
73
  if (document) {
74
  const meta = document.head.querySelector(
75
+ `meta[name='${key}']`,
76
  ) as HTMLMetaElement;
77
  ret = meta?.content ?? "";
78
  } else {
 
92
 
93
  return currentId;
94
  }
95
+
96
+ export function getEmojiUrl(unified: string, style: EmojiStyle) {
97
+ return `https://cdn.staticfile.org/emoji-datasource-apple/14.0.0/img/${style}/64/${unified}.png`;
98
+ }
middleware.ts CHANGED
@@ -3,7 +3,7 @@ import { ACCESS_CODES } from "./app/api/access";
3
  import md5 from "spark-md5";
4
 
5
  export const config = {
6
- matcher: ["/api/chat", "/api/chat-stream","/api/chat-image"],
7
  };
8
 
9
  export function middleware(req: NextRequest, res: NextResponse) {
 
3
  import md5 from "spark-md5";
4
 
5
  export const config = {
6
+ matcher: ["/api/chat", "/api/chat-stream","/api/chat-image","/api/newbing","/api/wanjuan"],
7
  };
8
 
9
  export function middleware(req: NextRequest, res: NextResponse) {
package.json CHANGED
@@ -14,6 +14,8 @@
14
  "dependencies": {
15
  "@svgr/webpack": "^6.5.1",
16
  "@vercel/analytics": "^0.1.11",
 
 
17
  "emoji-picker-react": "^4.4.7",
18
  "eventsource-parser": "^0.1.0",
19
  "fuse.js": "^6.6.2",
@@ -30,6 +32,7 @@
30
  "sass": "^1.59.2",
31
  "spark-md5": "^3.0.2",
32
  "use-debounce": "^9.0.3",
 
33
  "zustand": "^4.3.6"
34
  },
35
  "devDependencies": {
 
14
  "dependencies": {
15
  "@svgr/webpack": "^6.5.1",
16
  "@vercel/analytics": "^0.1.11",
17
+ "bing-chat": "^0.2.3",
18
+ "bufferutil": "^4.0.7",
19
  "emoji-picker-react": "^4.4.7",
20
  "eventsource-parser": "^0.1.0",
21
  "fuse.js": "^6.6.2",
 
32
  "sass": "^1.59.2",
33
  "spark-md5": "^3.0.2",
34
  "use-debounce": "^9.0.3",
35
+ "utf-8-validate": "^6.0.3",
36
  "zustand": "^4.3.6"
37
  },
38
  "devDependencies": {
yarn.lock CHANGED
@@ -1679,6 +1679,13 @@ binary-extensions@^2.0.0:
1679
  resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
1680
  integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
1681
 
 
 
 
 
 
 
 
1682
  boolbase@^1.0.0:
1683
  version "1.0.0"
1684
  resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
@@ -1709,6 +1716,13 @@ browserslist@^4.21.3, browserslist@^4.21.5:
1709
  node-releases "^2.0.8"
1710
  update-browserslist-db "^1.0.10"
1711
 
 
 
 
 
 
 
 
1712
  call-bind@^1.0.0, call-bind@^1.0.2:
1713
  version "1.0.2"
1714
  resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c"
@@ -3950,6 +3964,11 @@ node-fetch@^3.3.1:
3950
  fetch-blob "^3.1.4"
3951
  formdata-polyfill "^4.0.10"
3952
 
 
 
 
 
 
3953
  node-releases@^2.0.8:
3954
  version "2.0.10"
3955
  resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.10.tgz#c311ebae3b6a148c89b1813fd7c4d3c024ef537f"
@@ -5033,6 +5052,13 @@ [email protected]:
5033
  resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a"
5034
  integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==
5035
 
 
 
 
 
 
 
 
5036
  uvu@^0.5.0:
5037
  version "0.5.6"
5038
  resolved "https://registry.yarnpkg.com/uvu/-/uvu-0.5.6.tgz#2754ca20bcb0bb59b64e9985e84d2e81058502df"
@@ -5147,6 +5173,11 @@ wrappy@1:
5147
  resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
5148
  integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==
5149
 
 
 
 
 
 
5150
  yallist@^3.0.2:
5151
  version "3.1.1"
5152
  resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
 
1679
  resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
1680
  integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
1681
 
1682
+ bing-chat@^0.2.3:
1683
+ version "0.2.3"
1684
+ resolved "https://registry.yarnpkg.com/bing-chat/-/bing-chat-0.2.3.tgz#aba19c55e5dfbe12ceae6e26cbbaf405c146703f"
1685
+ integrity sha512-q9JIGqrrEhBEgIhTdtawvxcwQO5sdhMN3uATbLxpd52sH0+Jm7QhtsaodlLUbQgEQGo+YXfFPWWpK5lWMXGvHw==
1686
+ dependencies:
1687
+ ws "^8.13.0"
1688
+
1689
  boolbase@^1.0.0:
1690
  version "1.0.0"
1691
  resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
 
1716
  node-releases "^2.0.8"
1717
  update-browserslist-db "^1.0.10"
1718
 
1719
+ bufferutil@^4.0.7:
1720
+ version "4.0.7"
1721
+ resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.7.tgz#60c0d19ba2c992dd8273d3f73772ffc894c153ad"
1722
+ integrity sha512-kukuqc39WOHtdxtw4UScxF/WVnMFVSQVKhtx3AjZJzhd0RGZZldcrfSEbVsWWe6KNH253574cq5F+wpv0G9pJw==
1723
+ dependencies:
1724
+ node-gyp-build "^4.3.0"
1725
+
1726
  call-bind@^1.0.0, call-bind@^1.0.2:
1727
  version "1.0.2"
1728
  resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c"
 
3964
  fetch-blob "^3.1.4"
3965
  formdata-polyfill "^4.0.10"
3966
 
3967
+ node-gyp-build@^4.3.0:
3968
+ version "4.6.0"
3969
+ resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.6.0.tgz#0c52e4cbf54bbd28b709820ef7b6a3c2d6209055"
3970
+ integrity sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ==
3971
+
3972
  node-releases@^2.0.8:
3973
  version "2.0.10"
3974
  resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.10.tgz#c311ebae3b6a148c89b1813fd7c4d3c024ef537f"
 
5052
  resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a"
5053
  integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==
5054
 
5055
+ utf-8-validate@^6.0.3:
5056
+ version "6.0.3"
5057
+ resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-6.0.3.tgz#7d8c936d854e86b24d1d655f138ee27d2636d777"
5058
+ integrity sha512-uIuGf9TWQ/y+0Lp+KGZCMuJWc3N9BHA+l/UmHd/oUHwJJDeysyTRxNQVkbzsIWfGFbRe3OcgML/i0mvVRPOyDA==
5059
+ dependencies:
5060
+ node-gyp-build "^4.3.0"
5061
+
5062
  uvu@^0.5.0:
5063
  version "0.5.6"
5064
  resolved "https://registry.yarnpkg.com/uvu/-/uvu-0.5.6.tgz#2754ca20bcb0bb59b64e9985e84d2e81058502df"
 
5173
  resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
5174
  integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==
5175
 
5176
+ ws@^8.13.0:
5177
+ version "8.13.0"
5178
+ resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0"
5179
+ integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==
5180
+
5181
  yallist@^3.0.2:
5182
  version "3.1.1"
5183
  resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"