Просмотр исходного кода

Merge pull request #9561 from weseek/feat/159176-implementation-of-an-api-client-for-ai-assistant

feat: Implementation of an API client for AiAssistant
Shun Miyazawa 1 год назад
Родитель
Сommit
7367ca9e96

+ 28 - 1
apps/app/src/features/openai/client/components/AiAssistant/AiAssistantManegementModal.tsx

@@ -5,17 +5,23 @@ import {
   Modal, ModalHeader, ModalBody, ModalFooter, Form, FormGroup, Label, Input,
 } from 'reactstrap';
 
+import { toastError, toastSuccess } from '~/client/util/toastr';
 import type { IPageForItem } from '~/interfaces/page';
 import { usePageSelectModal } from '~/stores/modal';
+import loggerFactory from '~/utils/logger';
 
 import type { SelectedPage } from '../../../interfaces/selected-page';
+import { createAiAssistant } from '../../services/ai-assistant';
 import { useAiAssistantManegementModal } from '../../stores/ai-assistant';
 import { SelectedPageList } from '../Common/SelectedPageList';
 
+
 import styles from './AiAssistantManegementModal.module.scss';
 
 const moduleClass = styles['grw-ai-assistant-manegement'] ?? '';
 
+const logger = loggerFactory('growi:openai:client:components:AiAssistantManegementModal');
+
 const AiAssistantManegementModalSubstance = (): JSX.Element => {
   const { open: openPageSelectModal } = usePageSelectModal();
   const [selectedPages, setSelectedPages] = useState<SelectedPage[]>([]);
@@ -36,6 +42,27 @@ const AiAssistantManegementModalSubstance = (): JSX.Element => {
     setSelectedPages(selectedPages.filter(selectedPage => selectedPage.page._id !== pageId));
   }, [selectedPages]);
 
+  const clickCreateAiAssistantHandler = useCallback(async() => {
+    try {
+      const pagePathPatterns = selectedPages
+        .map(selectedPage => (selectedPage.isIncludeSubPage ? `${selectedPage.page.path}/*` : selectedPage.page.path))
+        .filter((path): path is string => path !== undefined && path !== null);
+
+      await createAiAssistant({
+        name: 'test',
+        description: 'test',
+        additionalInstruction: 'test',
+        pagePathPatterns,
+        shareScope: 'publicOnly',
+        accessScope: 'publicOnly',
+      });
+      toastSuccess('アシスタントを作成しました');
+    }
+    catch (err) {
+      toastError('アシスタントの作成に失敗しました');
+      logger.error(err);
+    }
+  }, [selectedPages]);
 
   return (
     <div className="px-4">
@@ -136,7 +163,7 @@ const AiAssistantManegementModalSubstance = (): JSX.Element => {
 
       <ModalFooter className="border-0 pt-0 mb-3">
         <button type="button" className="btn btn-outline-secondary" onClick={() => {}}>キャンセル</button>
-        <button type="button" className="btn btn-primary" onClick={() => {}}>作成</button>
+        <button type="button" className="btn btn-primary" onClick={clickCreateAiAssistantHandler}>作成</button>
       </ModalFooter>
     </div>
   );

+ 10 - 2
apps/app/src/features/openai/client/components/Common/SelectedPageList.tsx

@@ -1,10 +1,16 @@
+import type { FC } from 'react';
 import { memo } from 'react';
 
 import { useTranslation } from 'react-i18next';
 
 import type { SelectedPage } from '../../../interfaces/selected-page';
 
-export const SelectedPageList = memo(({ selectedPages, onRemove }: { selectedPages: SelectedPage[], onRemove?: (pageId?: string) => void }): JSX.Element => {
+type SelectedPageListProps = {
+  selectedPages: SelectedPage[];
+  onRemove?: (pageId?: string) => void;
+};
+
+const SelectedPageListBase: FC<SelectedPageListProps> = ({ selectedPages, onRemove }) => {
   const { t } = useTranslation();
 
   if (selectedPages.length === 0) {
@@ -26,4 +32,6 @@ export const SelectedPageList = memo(({ selectedPages, onRemove }: { selectedPag
       ))}
     </div>
   );
-});
+};
+
+export const SelectedPageList = memo(SelectedPageListBase);

+ 7 - 0
apps/app/src/features/openai/client/services/ai-assistant.ts

@@ -0,0 +1,7 @@
+import { apiv3Post } from '~/client/util/apiv3-client';
+
+import type { IApiv3AiAssistantCreateParams } from '../../interfaces/ai-assistant';
+
+export const createAiAssistant = async(body: IApiv3AiAssistantCreateParams): Promise<void> => {
+  await apiv3Post('/openai/ai-assistant', body);
+};

+ 2 - 0
apps/app/src/features/openai/interfaces/ai-assistant.ts

@@ -34,3 +34,5 @@ export interface AiAssistant {
   shareScope: AiAssistantShareScope
   accessScope: AiAssistantAccessScope
 }
+
+export type IApiv3AiAssistantCreateParams = Omit<AiAssistant, 'owner' | 'vectorStore'>

+ 2 - 4
apps/app/src/features/openai/server/routes/ai-assistant.ts

@@ -10,7 +10,7 @@ import { apiV3FormValidator } from '~/server/middlewares/apiv3-form-validator';
 import type { ApiV3Response } from '~/server/routes/apiv3/interfaces/apiv3-response';
 import loggerFactory from '~/utils/logger';
 
-import { type AiAssistant, AiAssistantShareScope, AiAssistantAccessScope } from '../../interfaces/ai-assistant';
+import { type IApiv3AiAssistantCreateParams, AiAssistantShareScope, AiAssistantAccessScope } from '../../interfaces/ai-assistant';
 import { getOpenaiService } from '../services/openai';
 
 import { certifyAiService } from './middlewares/certify-ai-service';
@@ -19,9 +19,7 @@ const logger = loggerFactory('growi:routes:apiv3:openai:create-ai-assistant');
 
 type CreateAssistantFactory = (crowi: Crowi) => RequestHandler[];
 
-type ReqBody = Omit<AiAssistant, 'vectorStore' | 'owner'>
-
-type Req = Request<undefined, Response, ReqBody> & {
+type Req = Request<undefined, Response, IApiv3AiAssistantCreateParams> & {
   user: IUserHasId,
 }