Prechádzať zdrojové kódy

add plugin selector on chat

lloydzhou 1 rok pred
rodič
commit
044116c14c

+ 30 - 0
app/components/chat.tsx

@@ -37,6 +37,7 @@ import AutoIcon from "../icons/auto.svg";
 import BottomIcon from "../icons/bottom.svg";
 import StopIcon from "../icons/pause.svg";
 import RobotIcon from "../icons/robot.svg";
+import PluginIcon from "../icons/plugin.svg";
 
 import {
   ChatMessage,
@@ -89,6 +90,7 @@ import {
   REQUEST_TIMEOUT_MS,
   UNFINISHED_INPUT,
   ServiceProvider,
+  Plugin,
 } from "../constant";
 import { Avatar } from "./emoji";
 import { ContextPrompts, MaskAvatar, MaskConfig } from "./mask";
@@ -476,6 +478,7 @@ export function ChatActions(props: {
     return model?.displayName ?? "";
   }, [models, currentModel, currentProviderName]);
   const [showModelSelector, setShowModelSelector] = useState(false);
+  const [showPluginSelector, setShowPluginSelector] = useState(false);
   const [showUploadImage, setShowUploadImage] = useState(false);
 
   useEffect(() => {
@@ -620,6 +623,33 @@ export function ChatActions(props: {
           }}
         />
       )}
+
+      <ChatAction
+        onClick={() => setShowPluginSelector(true)}
+        text={Locale.Plugin.Name}
+        icon={<PluginIcon />}
+      />
+      {showPluginSelector && (
+        <Selector
+          multiple
+          defaultSelectedValue={chatStore.currentSession().mask?.plugin}
+          items={[
+            {
+              title: Locale.Plugin.Artifact,
+              value: Plugin.Artifact,
+            },
+          ]}
+          onClose={() => setShowPluginSelector(false)}
+          onSelection={(s) => {
+            if (s.length === 0) return;
+            const plugin = s[0];
+            chatStore.updateCurrentSession((session) => {
+              session.mask.plugin = s;
+            });
+            showToast(plugin);
+          }}
+        />
+      )}
     </div>
   );
 }

+ 5 - 2
app/components/ui-lib.tsx

@@ -443,7 +443,7 @@ export function Selector<T>(props: {
     subTitle?: string;
     value: T;
   }>;
-  defaultSelectedValue?: T;
+  defaultSelectedValue?: T[] | T;
   onSelection?: (selection: T[]) => void;
   onClose?: () => void;
   multiple?: boolean;
@@ -453,7 +453,10 @@ export function Selector<T>(props: {
       <div className={styles["selector-content"]}>
         <List>
           {props.items.map((item, i) => {
-            const selected = props.defaultSelectedValue === item.value;
+            // @ts-ignore
+            const selected = props.multiple
+              ? props.defaultSelectedValue?.includes(item.value)
+              : props.defaultSelectedValue === item.value;
             return (
               <ListItem
                 className={styles["selector-item"]}

+ 4 - 0
app/constant.ts

@@ -57,6 +57,10 @@ export enum FileName {
   Prompts = "prompts.json",
 }
 
+export enum Plugin {
+  Artifact = "artifact",
+}
+
 export enum StoreKey {
   Chat = "chat-next-web-store",
   Access = "access-control",

+ 1 - 0
app/locales/cn.ts

@@ -450,6 +450,7 @@ const cn = {
   },
   Plugin: {
     Name: "插件",
+    Artifact: "Artifact",
   },
   FineTuned: {
     Sysmessage: "你是一个助手",

+ 1 - 0
app/locales/en.ts

@@ -457,6 +457,7 @@ const en: LocaleType = {
   },
   Plugin: {
     Name: "Plugin",
+    Artifact: "Artifact",
   },
   FineTuned: {
     Sysmessage: "You are an assistant that",

+ 2 - 1
app/store/mask.ts

@@ -2,7 +2,7 @@ import { BUILTIN_MASKS } from "../masks";
 import { getLang, Lang } from "../locales";
 import { DEFAULT_TOPIC, ChatMessage } from "./chat";
 import { ModelConfig, useAppConfig } from "./config";
-import { StoreKey } from "../constant";
+import { StoreKey, Plugin } from "../constant";
 import { nanoid } from "nanoid";
 import { createPersistStore } from "../utils/store";
 
@@ -17,6 +17,7 @@ export type Mask = {
   modelConfig: ModelConfig;
   lang: Lang;
   builtin: boolean;
+  plugin?: Plugin[];
 };
 
 export const DEFAULT_MASK_STATE = {