resolve conflict

This commit is contained in:
dakai 2023-04-03 12:43:21 +08:00
commit c51de32384
12 changed files with 82 additions and 50 deletions

View File

@ -2,13 +2,14 @@ name: Upstream Sync
on: on:
schedule: schedule:
- cron: '0 */12 * * *' # every 12 hours - cron: "0 */6 * * *" # every 6 hours
workflow_dispatch: # on button click workflow_dispatch:
jobs: jobs:
sync_latest_from_upstream: sync_latest_from_upstream:
name: Sync latest commits from upstream repo name: Sync latest commits from upstream repo
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: ${{ github.event.repository.fork }}
steps: steps:
# Step 1: run a standard checkout action, provided by github # Step 1: run a standard checkout action, provided by github

View File

@ -182,16 +182,8 @@ docker run -d -p 3000:3000 -e OPENAI_API_KEY="" -e CODE="" yidadaa/chatgpt-next-
![更多展示 More](./static/more.png) ![更多展示 More](./static/more.png)
## 捐赠 Donate USDT
> BNB Smart Chain (BEP 20)
```
0x67cD02c7EB62641De576a1fA3EdB32eA0c3ffD89
```
## 鸣谢 Special Thanks ## 鸣谢 Special Thanks
### 捐赠者 Sponsor ### 捐赠者 Sponsor
[@mushan0x0](https://github.com/mushan0x0) [@mushan0x0](https://github.com/mushan0x0)

View File

@ -8,6 +8,15 @@ async function createStream(req: NextRequest) {
const res = await requestOpenai(req); const res = await requestOpenai(req);
const contentType = res.headers.get("Content-Type") ?? "";
if (!contentType.includes("stream")) {
const content = await (
await res.text()
).replace(/provided:.*. You/, "provided: ***. You");
console.log("[Stream] error ", content);
return "```json\n" + content + "```";
}
const stream = new ReadableStream({ const stream = new ReadableStream({
async start(controller) { async start(controller) {
function onParse(event: any) { function onParse(event: any) {

View File

@ -452,7 +452,7 @@ export function Chat(props: {}) {
role: "user", role: "user",
content: userInput, content: userInput,
date: new Date().toLocaleString(), date: new Date().toLocaleString(),
preview: false, preview: true,
}, },
] ]
: [], : [],
@ -460,6 +460,12 @@ export function Chat(props: {}) {
const [showPromptModal, setShowPromptModal] = useState(false); const [showPromptModal, setShowPromptModal] = useState(false);
// Auto focus
useEffect(() => {
if (sidebarCollapse && isMobileScreen()) return;
inputRef.current?.focus();
}, [sidebarCollapse]);
return ( return (
<div className={styles.chat} key={session.id}> <div className={styles.chat} key={session.id}>
<div className={styles["window-header"]}> <div className={styles["window-header"]}>
@ -525,6 +531,7 @@ export function Chat(props: {}) {
className={styles["chat-body"]} className={styles["chat-body"]}
ref={scrollRef} ref={scrollRef}
onScroll={(e) => onChatBodyScroll(e.currentTarget)} onScroll={(e) => onChatBodyScroll(e.currentTarget)}
onTouchStart={() => inputRef.current?.blur()}
> >
{messages.map((message, i) => { {messages.map((message, i) => {
const isUser = message.role === "user"; const isUser = message.role === "user";
@ -545,10 +552,7 @@ export function Chat(props: {}) {
{Locale.Chat.Typing} {Locale.Chat.Typing}
</div> </div>
)} )}
<div <div className={styles["chat-message-item"]}>
className={styles["chat-message-item"]}
onMouseOver={() => inputRef.current?.blur()}
>
{!isUser && {!isUser &&
!(message.preview || message.content.length === 0) && ( !(message.preview || message.content.length === 0) && (
<div className={styles["chat-message-top-actions"]}> <div className={styles["chat-message-top-actions"]}>
@ -588,6 +592,7 @@ export function Chat(props: {}) {
if (!isMobileScreen()) return; if (!isMobileScreen()) return;
setUserInput(message.content); setUserInput(message.content);
}} }}
onMouseOver={() => inputRef.current?.blur()}
> >
<Markdown content={message.content} /> <Markdown content={message.content} />
</div> </div>
@ -622,6 +627,9 @@ export function Chat(props: {}) {
setAutoScroll(false); setAutoScroll(false);
setTimeout(() => setPromptHints([]), 500); setTimeout(() => setPromptHints([]), 500);
}} }}
onMouseOver={() => {
inputRef.current?.focus();
}}
autoFocus={sidebarCollapse} autoFocus={sidebarCollapse}
/> />
<IconButton <IconButton

View File

@ -449,6 +449,7 @@
.chat-input-panel { .chat-input-panel {
width: 100%; width: 100%;
padding: 20px; padding: 20px;
padding-top: 5px;
box-sizing: border-box; box-sizing: border-box;
flex-direction: column; flex-direction: column;
} }

View File

@ -59,7 +59,7 @@ export function Markdown(props: { content: string }) {
[ [
RehypeHighlight, RehypeHighlight,
{ {
detect: true, detect: false,
ignoreMissing: true, ignoreMissing: true,
}, },
], ],

View File

@ -128,6 +128,8 @@
justify-content: center; justify-content: center;
.toast-content { .toast-content {
max-width: 80vw;
word-break: break-all;
font-size: 14px; font-size: 14px;
background-color: var(--white); background-color: var(--white);
box-shadow: var(--card-shadow); box-shadow: var(--card-shadow);

View File

@ -1,6 +1,7 @@
import type { ChatRequest, ChatReponse } from "./api/openai/typing"; import type { ChatRequest, ChatReponse } from "./api/openai/typing";
import { filterConfig, Message, ModelConfig, useAccessStore } from "./store"; import { filterConfig, Message, ModelConfig, useAccessStore } from "./store";
import Locale from "./locales"; import Locale from "./locales";
import { showToast } from "./components/ui-lib";
if (!Array.prototype.at) { if (!Array.prototype.at) {
require("array.prototype.at/auto"); require("array.prototype.at/auto");
@ -91,8 +92,21 @@ export async function requestUsage() {
try { try {
const response = (await res.json()) as { const response = (await res.json()) as {
total_usage: number; total_usage: number;
error?: {
type: string;
message: string;
}; };
return Math.round(response.total_usage) / 100; };
if (response.error && response.error.type) {
showToast(response.error.message);
return;
}
if (response.total_usage) {
response.total_usage = Math.round(response.total_usage) / 100;
}
return response.total_usage;
} catch (error) { } catch (error) {
console.error("[Request usage] ", error, res.body); console.error("[Request usage] ", error, res.body);
} }

View File

@ -106,7 +106,7 @@ export function filterConfig(oldConfig: ModelConfig): Partial<ModelConfig> {
return isValidModel(x as string); return isValidModel(x as string);
}, },
max_tokens(x) { max_tokens(x) {
return isValidNumber(x as number, 100, 4000); return isValidNumber(x as number, 100, 32000);
}, },
presence_penalty(x) { presence_penalty(x) {
return isValidNumber(x as number, -2, 2); return isValidNumber(x as number, -2, 2);

View File

@ -190,7 +190,7 @@ input[type="text"] {
appearance: none; appearance: none;
border-radius: 10px; border-radius: 10px;
border: var(--border-in-light); border: var(--border-in-light);
height: 36px; min-height: 36px;
box-sizing: border-box; box-sizing: border-box;
background: var(--white); background: var(--white);
color: var(--black); color: var(--black);

View File

@ -8,16 +8,22 @@
font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;
} }
pre code.hljs { pre code {
display: block; display: block;
overflow-x: auto; overflow-x: auto;
padding: 1em; padding: 1em;
} }
code.hljs { code {
padding: 3px 5px; padding: 3px 5px;
} }
.hljs,
pre {
background: #1a1b26;
color: #cbd2ea;
}
/*! /*!
Theme: Tokyo-night-Dark Theme: Tokyo-night-Dark
origin: https://github.com/enkia/tokyo-night-vscode-theme origin: https://github.com/enkia/tokyo-night-vscode-theme
@ -99,11 +105,6 @@
color: #c0caf5; color: #c0caf5;
} }
.hljs {
background: #1a1b26;
color: #9aa5ce;
}
.hljs-emphasis { .hljs-emphasis {
font-style: italic; font-style: italic;
} }

View File

@ -5,15 +5,19 @@ export function trimTopic(topic: string) {
return topic.replace(/[,。!?、,.!?]*$/, ""); return topic.replace(/[,。!?、,.!?]*$/, "");
} }
export function copyToClipboard(text: string) { export async function copyToClipboard(text: string) {
navigator.clipboard try {
.writeText(text) await navigator.clipboard.writeText(text);
.then((res) => { } catch (error) {
const textarea = document.createElement("textarea");
textarea.value = text;
document.body.appendChild(textarea);
textarea.select();
document.execCommand("copy");
document.body.removeChild(textarea);
} finally {
showToast(Locale.Copy.Success); showToast(Locale.Copy.Success);
}) }
.catch((err) => {
showToast(Locale.Copy.Failed);
});
} }
export function downloadAs(text: string, filename: string) { export function downloadAs(text: string, filename: string) {