diff --git a/app/command.ts b/app/command.ts
new file mode 100644
index 00000000..40bad92b
--- /dev/null
+++ b/app/command.ts
@@ -0,0 +1,28 @@
+import { useSearchParams } from "react-router-dom";
+
+type Command = (param: string) => void;
+interface Commands {
+ fill?: Command;
+ submit?: Command;
+ mask?: Command;
+}
+
+export function useCommand(commands: Commands = {}) {
+ const [searchParams, setSearchParams] = useSearchParams();
+
+ if (commands === undefined) return;
+
+ let shouldUpdate = false;
+ searchParams.forEach((param, name) => {
+ const commandName = name as keyof Commands;
+ if (typeof commands[commandName] === "function") {
+ commands[commandName]!(param);
+ searchParams.delete(name);
+ shouldUpdate = true;
+ }
+ });
+
+ if (shouldUpdate) {
+ setSearchParams(searchParams);
+ }
+}
diff --git a/app/components/chat.tsx b/app/components/chat.tsx
index ca51a06a..8786877b 100644
--- a/app/components/chat.tsx
+++ b/app/components/chat.tsx
@@ -26,12 +26,10 @@ import {
SubmitKey,
useChatStore,
BOT_HELLO,
- ROLES,
createMessage,
useAccessStore,
Theme,
useAppConfig,
- ModelConfig,
DEFAULT_TOPIC,
} from "../store";
@@ -58,11 +56,8 @@ import { useLocation, useNavigate } from "react-router-dom";
import { Path } from "../constant";
import { Avatar } from "./emoji";
import { MaskAvatar, MaskConfig } from "./mask";
-import {
- DEFAULT_MASK_AVATAR,
- DEFAULT_MASK_ID,
- useMaskStore,
-} from "../store/mask";
+import { useMaskStore } from "../store/mask";
+import { useCommand } from "../command";
const Markdown = dynamic(async () => (await import("./markdown")).Markdown, {
loading: () => ,
@@ -478,8 +473,7 @@ export function Chat() {
}
};
- // submit user input
- const onUserSubmit = () => {
+ const doSubmit = (userInput: string) => {
if (userInput.trim() === "") return;
setIsLoading(true);
chatStore.onUserInput(userInput).then(() => setIsLoading(false));
@@ -504,7 +498,7 @@ export function Chat() {
return;
}
if (shouldSubmit(e)) {
- onUserSubmit();
+ doSubmit(userInput);
e.preventDefault();
}
};
@@ -618,6 +612,13 @@ export function Chat() {
const isChat = location.pathname === Path.Chat;
const autoFocus = !isMobileScreen || isChat; // only focus in chat page
+ useCommand({
+ fill: setUserInput,
+ submit: (text) => {
+ doSubmit(text);
+ },
+ });
+
return (
@@ -816,7 +817,7 @@ export function Chat() {
text={Locale.Chat.Send}
className={styles["chat-input-send"]}
type="primary"
- onClick={onUserSubmit}
+ onClick={() => doSubmit(userInput)}
/>
diff --git a/app/components/home.tsx b/app/components/home.tsx
index a83a7798..4c3d0a64 100644
--- a/app/components/home.tsx
+++ b/app/components/home.tsx
@@ -23,6 +23,7 @@ import {
} from "react-router-dom";
import { SideBar } from "./sidebar";
import { useAppConfig } from "../store/config";
+import { useMaskStore } from "../store/mask";
export function Loading(props: { noLogo?: boolean }) {
return (
diff --git a/app/components/mask.tsx b/app/components/mask.tsx
index 964a3cc3..9794c974 100644
--- a/app/components/mask.tsx
+++ b/app/components/mask.tsx
@@ -20,7 +20,7 @@ import Locale, { AllLangs, Lang } from "../locales";
import { useNavigate } from "react-router-dom";
import chatStyle from "./chat.module.scss";
-import { useEffect, useState } from "react";
+import { useState } from "react";
import { downloadAs, readFromFile } from "../utils";
import { Updater } from "../api/openai/typing";
import { ModelConfigList } from "./model-config";
@@ -197,7 +197,7 @@ export function ContextPrompts(props: {
className={chatStyle["context-prompt-button"]}
onClick={() =>
addContextPrompt({
- role: "system",
+ role: "user",
content: "",
date: "",
})
diff --git a/app/components/new-chat.tsx b/app/components/new-chat.tsx
index 42612e0a..81858fb0 100644
--- a/app/components/new-chat.tsx
+++ b/app/components/new-chat.tsx
@@ -13,6 +13,7 @@ import { Mask, useMaskStore } from "../store/mask";
import Locale from "../locales";
import { useAppConfig, useChatStore } from "../store";
import { MaskAvatar } from "./mask";
+import { useCommand } from "../command";
function getIntersectionArea(aRect: DOMRect, bRect: DOMRect) {
const xmin = Math.max(aRect.x, bRect.x);
@@ -108,9 +109,20 @@ export function NewChat() {
const startChat = (mask?: Mask) => {
chatStore.newSession(mask);
- navigate(Path.Chat);
+ setTimeout(() => navigate(Path.Chat), 1);
};
+ useCommand({
+ mask: (id) => {
+ try {
+ const mask = maskStore.get(parseInt(id));
+ startChat(mask ?? undefined);
+ } catch {
+ console.error("[New Chat] failed to create chat from mask id=", id);
+ }
+ },
+ });
+
return (
diff --git a/app/locales/cn.ts b/app/locales/cn.ts
index 8bec7c40..112b3b5c 100644
--- a/app/locales/cn.ts
+++ b/app/locales/cn.ts
@@ -4,7 +4,7 @@ const cn = {
WIP: "该功能仍在开发中……",
Error: {
Unauthorized:
- "现在是未授权状态,请点击左下角[设置](/#/settings)按钮输入访问密码。",
+ "访问密码不正确或为空,请前往[设置](/#/settings)页输入正确的访问密码,或者填入你自己的 OpenAI API Key。",
},
ChatItem: {
ChatItemCount: (count: number) => `${count} 条对话`,
@@ -149,7 +149,7 @@ const cn = {
},
AccessCode: {
Title: "访问密码",
- SubTitle: "已开启加密访问",
+ SubTitle: "管理员已开启加密访问",
Placeholder: "请输入访问密码",
},
Model: "模型 (model)",
diff --git a/app/store/chat.ts b/app/store/chat.ts
index 0d66580d..c938d787 100644
--- a/app/store/chat.ts
+++ b/app/store/chat.ts
@@ -7,11 +7,11 @@ import {
requestChatStream,
requestWithPrompt,
} from "../requests";
-import { isMobileScreen, trimTopic } from "../utils";
+import { trimTopic } from "../utils";
import Locale from "../locales";
import { showToast } from "../components/ui-lib";
-import { DEFAULT_CONFIG, ModelConfig, ModelType, useAppConfig } from "./config";
+import { ModelType } from "./config";
import { createEmptyMask, Mask } from "./mask";
import { StoreKey } from "../constant";
@@ -33,7 +33,7 @@ export function createMessage(override: Partial): Message {
};
}
-export const ROLES: Message["role"][] = ["user", "system", "assistant"];
+export const ROLES: Message["role"][] = ["system", "user", "assistant"];
export interface ChatStat {
tokenCount: number;
diff --git a/app/store/config.ts b/app/store/config.ts
index da77c7b3..926c296f 100644
--- a/app/store/config.ts
+++ b/app/store/config.ts
@@ -31,7 +31,7 @@ export const DEFAULT_CONFIG = {
modelConfig: {
model: "gpt-3.5-turbo" as ModelType,
- temperature: 1,
+ temperature: 0.5,
max_tokens: 2000,
presence_penalty: 0,
sendMemory: true,
diff --git a/next.config.mjs b/next.config.mjs
index 3f7c2fb6..c62f8840 100644
--- a/next.config.mjs
+++ b/next.config.mjs
@@ -5,7 +5,12 @@ const nextConfig = {
appDir: true,
},
async rewrites() {
- const ret = [];
+ const ret = [
+ {
+ source: "/api/proxy/:path*",
+ destination: "https://api.openai.com/:path*",
+ },
+ ];
const apiUrl = process.env.API_URL;
if (apiUrl) {