Shun Miyazawa 11 месяцев назад
Родитель
Сommit
db31e684ec

+ 16 - 14
apps/app/src/features/openai/client/components/AiAssistant/AiAssistantSidebar/AiAssistantSidebar.tsx

@@ -60,7 +60,6 @@ const AiAssistantSidebarSubstance: React.FC<AiAssistantSidebarSubstanceProps> =
     closeAiAssistantSidebar,
   } = props;
 
-  const [currentThreadTitle, setCurrentThreadTitle] = useState<string | undefined>(threadData?.title);
   const [currentThreadId, setCurrentThreadId] = useState<string | undefined>(threadData?.threadId);
   const [messageLogs, setMessageLogs] = useState<Message[]>([]);
   const [generatingAnswerMessage, setGeneratingAnswerMessage] = useState<Message>();
@@ -77,6 +76,9 @@ const AiAssistantSidebarSubstance: React.FC<AiAssistantSidebarSubstanceProps> =
     createThread: createThreadForKnowledgeAssistant,
     postMessage: postMessageForKnowledgeAssistant,
     processMessage: processMessageForKnowledgeAssistant,
+    headerIcon: headerIconForKnowledgeAssistant,
+    headerText: headerTextForKnowledgeAssistant,
+    placeHolder: placeHolderForKnowledgeAssistant,
   } = useKnowledgeAssistant();
 
   const {
@@ -85,6 +87,9 @@ const AiAssistantSidebarSubstance: React.FC<AiAssistantSidebarSubstanceProps> =
     processMessage: processMessageForEditorAssistant,
     accept,
     reject,
+    headerIcon: headerIconForEditorAssistant,
+    headerText: headerTextForEditorAssistant,
+    placeHolder: placeHolderForEditorAssistant,
   } = useEditorAssistant();
 
   const form = useForm<FormData>({
@@ -154,24 +159,24 @@ const AiAssistantSidebarSubstance: React.FC<AiAssistantSidebarSubstanceProps> =
 
   const headerIcon = useMemo(() => {
     return isEditorAssistant
-      ? <span className="material-symbols-outlined growi-ai-chat-icon me-3 fs-4">support_agent</span>
-      : <span className="growi-custom-icons growi-ai-chat-icon me-3 fs-4">ai_assistant</span>;
-  }, [isEditorAssistant]);
+      ? headerIconForEditorAssistant
+      : headerIconForKnowledgeAssistant;
+  }, [headerIconForEditorAssistant, headerIconForKnowledgeAssistant, isEditorAssistant]);
 
   const headerText = useMemo(() => {
     return isEditorAssistant
-      ? <>{t('Editor Assistant')}</>
-      : <>{currentThreadTitle ?? aiAssistantData?.name}</>;
-  }, [isEditorAssistant, currentThreadTitle, aiAssistantData?.name, t]);
+      ? headerTextForEditorAssistant
+      : headerTextForKnowledgeAssistant;
+  }, [isEditorAssistant, headerTextForEditorAssistant, headerTextForKnowledgeAssistant]);
 
   const placeHolder = useMemo(() => {
     if (form.formState.isSubmitting) {
       return '';
     }
     return t(isEditorAssistant
-      ? 'sidebar_ai_assistant.editor_assistant_placeholder'
-      : 'sidebar_ai_assistant.knowledge_assistant_placeholder');
-  }, [form.formState.isSubmitting, isEditorAssistant, t]);
+      ? placeHolderForEditorAssistant
+      : placeHolderForKnowledgeAssistant);
+  }, [form.formState.isSubmitting, isEditorAssistant, placeHolderForEditorAssistant, placeHolderForKnowledgeAssistant, t]);
 
   const isGenerating = generatingAnswerMessage != null;
   const submit = useCallback(async(data: FormData) => {
@@ -214,10 +219,7 @@ const AiAssistantSidebarSubstance: React.FC<AiAssistantSidebarSubstanceProps> =
           return;
         }
 
-        // const thread = res.data;
-
         setCurrentThreadId(thread.threadId);
-        setCurrentThreadTitle(thread.title);
 
         currentThreadId_ = thread.threadId;
 
@@ -343,7 +345,7 @@ const AiAssistantSidebarSubstance: React.FC<AiAssistantSidebarSubstanceProps> =
     }
 
   // eslint-disable-next-line max-len
-  }, [isGenerating, messageLogs, form, currentThreadId, isEditorAssistant, selectedAiAssistant?._id, aiAssistantData?._id, mutateThreadData, t, postMessageForEditorAssistant, postMessageForKnowledgeAssistant, processMessageForKnowledgeAssistant, processMessageForEditorAssistant, growiCloudUri]);
+  }, [isGenerating, messageLogs, form, currentThreadId, createThread, isEditorAssistant, mutateThreadData, t, aiAssistantData?._id, postMessageForEditorAssistant, postMessageForKnowledgeAssistant, processMessageForKnowledgeAssistant, processMessageForEditorAssistant, growiCloudUri]);
 
   const keyDownHandler = (event: KeyboardEvent<HTMLTextAreaElement>) => {
     if (event.key === 'Enter' && (event.ctrlKey || event.metaKey)) {

+ 28 - 1
apps/app/src/features/openai/client/services/editor-assistant.tsx

@@ -1,5 +1,5 @@
 import {
-  useCallback, useEffect, useState, useRef,
+  useCallback, useEffect, useState, useRef, useMemo,
 } from 'react';
 
 import { GlobalCodeMirrorEditorKey } from '@growi/editor';
@@ -8,6 +8,7 @@ import {
 } from '@growi/editor/dist/client/services/unified-merge-view';
 import { useCodeMirrorEditorIsolated } from '@growi/editor/dist/client/stores/codemirror-editor';
 import { useSecondaryYdocs } from '@growi/editor/dist/client/stores/use-secondary-ydocs';
+import { useTranslation } from 'react-i18next';
 import { type Text as YText } from 'yjs';
 
 import { apiv3Post } from '~/client/util/apiv3-client';
@@ -56,6 +57,11 @@ type UseEditorAssistant = () => {
   processMessage: ProcessMessage,
   accept: () => void,
   reject: () => void,
+
+  // Views
+  headerIcon: JSX.Element,
+  headerText: JSX.Element,
+  placeHolder: string,
 }
 
 const insertTextAtLine = (yText: YText, lineNumber: number, textToInsert: string): void => {
@@ -126,6 +132,9 @@ export const useEditorAssistant: UseEditorAssistant = () => {
   const { data: codeMirrorEditor } = useCodeMirrorEditorIsolated(GlobalCodeMirrorEditorKey.MAIN);
   const yDocs = useSecondaryYdocs(isEnableUnifiedMergeView ?? false, { pageId: currentPageId ?? undefined, useSecondary: isEnableUnifiedMergeView ?? false });
 
+  // Hooks
+  const { t } = useTranslation();
+
   // Functions
   const createThread: CreateThread = useCallback(async(aiAssistantId) => {
     const response = await apiv3Post<IThreadRelationHasId>('/openai/thread', {
@@ -266,11 +275,29 @@ export const useEditorAssistant: UseEditorAssistant = () => {
     }
   }, [codeMirrorEditor, detectedDiff, selectedText, yDocs?.secondaryDoc]);
 
+
+  // Views
+  const headerIcon = useMemo(() => {
+    return <span className="material-symbols-outlined growi-ai-chat-icon me-3 fs-4">support_agent</span>;
+  }, []);
+
+  const headerText = useMemo(() => {
+    return <>{t('Editor Assistant')}</>;
+  }, [t]);
+
+  const placeHolder = useMemo(() => { return 'sidebar_ai_assistant.editor_assistant_placeholder' }, []);
+
+
   return {
     createThread,
     postMessage,
     processMessage,
     accept,
     reject,
+
+    // Views
+    headerIcon,
+    headerText,
+    placeHolder,
   };
 };

+ 35 - 1
apps/app/src/features/openai/client/services/knowledge-assistant.tsx

@@ -1,4 +1,4 @@
-import { useCallback, useMemo } from 'react';
+import { useCallback, useMemo, useState } from 'react';
 
 import { apiv3Post } from '~/client/util/apiv3-client';
 import { SseMessageSchema, type SseMessage } from '~/features/openai/interfaces/knowledge-assistant/sse-schemas';
@@ -6,6 +6,7 @@ import { handleIfSuccessfullyParsed } from '~/features/openai/utils/handle-if-su
 
 import type { IThreadRelationHasId } from '../../interfaces/thread-relation';
 import { ThreadType } from '../../interfaces/thread-relation';
+import { useAiAssistantSidebar } from '../stores/ai-assistant';
 
 interface CreateThread {
   (aiAssistantId: string, initialUserMessage: string): Promise<IThreadRelationHasId>;
@@ -25,10 +26,23 @@ type UseKnowledgeAssistant = () => {
   createThread: CreateThread
   postMessage: PostMessage
   processMessage: ProcessMessage
+
+  // Views
+  headerIcon: JSX.Element
+  headerText: JSX.Element
+  placeHolder: string
 }
 
 export const useKnowledgeAssistant: UseKnowledgeAssistant = () => {
+  // Hooks
+  const { data: aiAssistantSidebarData } = useAiAssistantSidebar();
+  const { aiAssistantData } = aiAssistantSidebarData ?? {};
+  const { threadData } = aiAssistantSidebarData ?? {};
+
+  // States
+  const [currentThreadTitle, setCurrentThreadId] = useState(threadData?.title);
 
+  // Functions
   const createThread: CreateThread = useCallback(async(aiAssistantId, initialUserMessage) => {
     const response = await apiv3Post<IThreadRelationHasId>('/openai/thread', {
       type: ThreadType.KNOWLEDGE,
@@ -36,6 +50,9 @@ export const useKnowledgeAssistant: UseKnowledgeAssistant = () => {
       initialUserMessage,
     });
     const thread = response.data;
+
+    setCurrentThreadId(thread.title);
+
     return thread;
   }, []);
 
@@ -59,9 +76,26 @@ export const useKnowledgeAssistant: UseKnowledgeAssistant = () => {
     });
   }, []);
 
+  // Views
+  const headerIcon = useMemo(() => {
+    return <span className="growi-custom-icons growi-ai-chat-icon me-3 fs-4">ai_assistant</span>;
+  }, []);
+
+  const headerText = useMemo(() => {
+    return <>{currentThreadTitle ?? aiAssistantData?.name}</>;
+  }, [aiAssistantData?.name, currentThreadTitle]);
+
+  const placeHolder = useMemo(() => { return 'sidebar_ai_assistant.knowledge_assistant_placeholder' }, []);
+
   return {
+    // Functions
     createThread,
     postMessage,
     processMessage,
+
+    // Views
+    headerIcon,
+    headerText,
+    placeHolder,
   };
 };