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

Merge pull request #9237 from weseek/imprv/155101-move-open-ai-related-files-to-features-directly

feat: Move OpenAI related files to features directly
Shun Miyazawa 1 год назад
Родитель
Сommit
9048b878de
29 измененных файлов с 41 добавлено и 33 удалено
  1. 1 1
      apps/app/src/client/components/PageControls/PageControls.tsx
  2. 2 1
      apps/app/src/features/openai/chat/components/AiChatModal/AiChatModal.tsx
  3. 0 0
      apps/app/src/features/openai/client/components/AiIntegration/AiIntegration.tsx
  4. 0 0
      apps/app/src/features/openai/client/components/AiIntegration/AiIntegrationDisableMode.tsx
  5. 1 1
      apps/app/src/features/openai/client/components/RagSearchButton.module.scss
  6. 2 1
      apps/app/src/features/openai/client/components/RagSearchButton.tsx
  7. 0 0
      apps/app/src/features/openai/client/stores/rag-search.ts
  8. 0 0
      apps/app/src/features/openai/interfaces/ai.ts
  9. 0 0
      apps/app/src/features/openai/server/routes/index.ts
  10. 8 7
      apps/app/src/features/openai/server/routes/message.ts
  11. 2 1
      apps/app/src/features/openai/server/routes/middlewares/certify-ai-service.ts
  12. 5 4
      apps/app/src/features/openai/server/routes/rebuild-vector-store.ts
  13. 9 7
      apps/app/src/features/openai/server/routes/thread.ts
  14. 2 1
      apps/app/src/features/openai/server/services/assistant/assistant.ts
  15. 0 0
      apps/app/src/features/openai/server/services/assistant/index.ts
  16. 0 0
      apps/app/src/features/openai/server/services/client-delegator/azure-openai-client-delegator.ts
  17. 1 1
      apps/app/src/features/openai/server/services/client-delegator/get-client.ts
  18. 0 0
      apps/app/src/features/openai/server/services/client-delegator/index.ts
  19. 0 0
      apps/app/src/features/openai/server/services/client-delegator/interfaces.ts
  20. 0 0
      apps/app/src/features/openai/server/services/client-delegator/openai-client-delegator.ts
  21. 0 0
      apps/app/src/features/openai/server/services/client.ts
  22. 0 0
      apps/app/src/features/openai/server/services/embeddings.ts
  23. 0 0
      apps/app/src/features/openai/server/services/index.ts
  24. 2 1
      apps/app/src/features/openai/server/services/openai.ts
  25. 2 2
      apps/app/src/pages/admin/ai-integration.page.tsx
  26. 1 1
      apps/app/src/server/routes/apiv3/index.js
  27. 1 1
      apps/app/src/server/routes/apiv3/page/create-page.ts
  28. 1 2
      apps/app/src/server/routes/apiv3/page/update-page.ts
  29. 1 1
      apps/app/src/server/service/page/index.ts

+ 1 - 1
apps/app/src/client/components/PageControls/PageControls.tsx

@@ -16,6 +16,7 @@ import {
   toggleLike, toggleSubscribe,
   toggleLike, toggleSubscribe,
 } from '~/client/services/page-operation';
 } from '~/client/services/page-operation';
 import { toastError } from '~/client/util/toastr';
 import { toastError } from '~/client/util/toastr';
+import RagSearchButton from '~/features/openai/client/components/RagSearchButton';
 import { useIsGuestUser, useIsReadOnlyUser, useIsSearchPage } from '~/stores-universal/context';
 import { useIsGuestUser, useIsReadOnlyUser, useIsSearchPage } from '~/stores-universal/context';
 import {
 import {
   EditorMode, useEditorMode,
   EditorMode, useEditorMode,
@@ -36,7 +37,6 @@ import {
 
 
 import { BookmarkButtons } from './BookmarkButtons';
 import { BookmarkButtons } from './BookmarkButtons';
 import LikeButtons from './LikeButtons';
 import LikeButtons from './LikeButtons';
-import RagSearchButton from './RagSearchButton';
 import SearchButton from './SearchButton';
 import SearchButton from './SearchButton';
 import SeenUserInfo from './SeenUserInfo';
 import SeenUserInfo from './SeenUserInfo';
 import SubscribeButton from './SubscribeButton';
 import SubscribeButton from './SubscribeButton';

+ 2 - 1
apps/app/src/features/openai/chat/components/AiChatModal/AiChatModal.tsx

@@ -8,9 +8,10 @@ import {
 } from 'reactstrap';
 } from 'reactstrap';
 
 
 import { apiv3Post } from '~/client/util/apiv3-client';
 import { apiv3Post } from '~/client/util/apiv3-client';
-import { useRagSearchModal } from '~/stores/rag-search';
 import loggerFactory from '~/utils/logger';
 import loggerFactory from '~/utils/logger';
 
 
+import { useRagSearchModal } from '../../../client/stores/rag-search';
+
 import { MessageCard } from './MessageCard';
 import { MessageCard } from './MessageCard';
 import { ResizableTextarea } from './ResizableTextArea';
 import { ResizableTextarea } from './ResizableTextArea';
 
 

+ 0 - 0
apps/app/src/client/components/Admin/AiIntegration/AiIntegration.tsx → apps/app/src/features/openai/client/components/AiIntegration/AiIntegration.tsx


+ 0 - 0
apps/app/src/client/components/Admin/AiIntegration/AiIntegrationDisableMode.tsx → apps/app/src/features/openai/client/components/AiIntegration/AiIntegrationDisableMode.tsx


+ 1 - 1
apps/app/src/client/components/PageControls/RagSearchButton.module.scss → apps/app/src/features/openai/client/components/RagSearchButton.module.scss

@@ -1,7 +1,7 @@
 @use '@growi/core-styles/scss/bootstrap/init' as bs;
 @use '@growi/core-styles/scss/bootstrap/init' as bs;
 @use '@growi/core-styles/scss/variables/growi-official-colors';
 @use '@growi/core-styles/scss/variables/growi-official-colors';
 @use '@growi/ui/scss/atoms/btn-muted';
 @use '@growi/ui/scss/atoms/btn-muted';
-@use './button-styles';
+@use '~/client/components/PageControls/button-styles';
 
 
 .btn-rag-search :global {
 .btn-rag-search :global {
   @extend %btn-basis;
   @extend %btn-basis;

+ 2 - 1
apps/app/src/client/components/PageControls/RagSearchButton.tsx → apps/app/src/features/openai/client/components/RagSearchButton.tsx

@@ -2,7 +2,8 @@ import React, { useCallback } from 'react';
 
 
 import { NotAvailableForGuest } from '~/client/components/NotAvailableForGuest';
 import { NotAvailableForGuest } from '~/client/components/NotAvailableForGuest';
 import { useIsAiEnabled } from '~/stores-universal/context';
 import { useIsAiEnabled } from '~/stores-universal/context';
-import { useRagSearchModal } from '~/stores/rag-search';
+
+import { useRagSearchModal } from '../stores/rag-search';
 
 
 import styles from './RagSearchButton.module.scss';
 import styles from './RagSearchButton.module.scss';
 
 

+ 0 - 0
apps/app/src/stores/rag-search.ts → apps/app/src/features/openai/client/stores/rag-search.ts


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


+ 0 - 0
apps/app/src/server/routes/apiv3/openai/index.ts → apps/app/src/features/openai/server/routes/index.ts


+ 8 - 7
apps/app/src/server/routes/apiv3/openai/message.ts → apps/app/src/features/openai/server/routes/message.ts

@@ -6,15 +6,16 @@ import { body } from 'express-validator';
 import type { AssistantStream } from 'openai/lib/AssistantStream';
 import type { AssistantStream } from 'openai/lib/AssistantStream';
 import type { MessageDelta } from 'openai/resources/beta/threads/messages.mjs';
 import type { MessageDelta } from 'openai/resources/beta/threads/messages.mjs';
 
 
+import { getOrCreateChatAssistant } from '~/features/openai/server/services/assistant';
 import type Crowi from '~/server/crowi';
 import type Crowi from '~/server/crowi';
-import { openaiClient } from '~/server/service/openai';
-import { getOrCreateChatAssistant } from '~/server/service/openai/assistant';
+import { apiV3FormValidator } from '~/server/middlewares/apiv3-form-validator';
 import loggerFactory from '~/utils/logger';
 import loggerFactory from '~/utils/logger';
 
 
-import { apiV3FormValidator } from '../../../middlewares/apiv3-form-validator';
+import { openaiClient } from '../services';
 
 
+import { certifyAiService } from './middlewares/certify-ai-service';
 
 
-const logger = loggerFactory('growi:routes:apiv3:openai:chat');
+const logger = loggerFactory('growi:routes:apiv3:openai:message');
 
 
 
 
 type ReqBody = {
 type ReqBody = {
@@ -27,8 +28,8 @@ type Req = Request<undefined, Response, ReqBody>
 type PostMessageHandlersFactory = (crowi: Crowi) => RequestHandler[];
 type PostMessageHandlersFactory = (crowi: Crowi) => RequestHandler[];
 
 
 export const postMessageHandlersFactory: PostMessageHandlersFactory = (crowi) => {
 export const postMessageHandlersFactory: PostMessageHandlersFactory = (crowi) => {
-  const accessTokenParser = require('../../../middlewares/access-token-parser')(crowi);
-  const loginRequiredStrictly = require('../../../middlewares/login-required')(crowi);
+  const accessTokenParser = require('~/server/middlewares/access-token-parser')(crowi);
+  const loginRequiredStrictly = require('~/server/middlewares/login-required')(crowi);
 
 
   const validator: ValidationChain[] = [
   const validator: ValidationChain[] = [
     body('userMessage')
     body('userMessage')
@@ -40,7 +41,7 @@ export const postMessageHandlersFactory: PostMessageHandlersFactory = (crowi) =>
   ];
   ];
 
 
   return [
   return [
-    accessTokenParser, loginRequiredStrictly, validator, apiV3FormValidator,
+    accessTokenParser, loginRequiredStrictly, certifyAiService, validator, apiV3FormValidator,
     async(req: Req, res: Response) => {
     async(req: Req, res: Response) => {
 
 
       const threadId = req.body.threadId;
       const threadId = req.body.threadId;

+ 2 - 1
apps/app/src/server/middlewares/certify-ai-service.ts → apps/app/src/features/openai/server/routes/middlewares/certify-ai-service.ts

@@ -1,9 +1,10 @@
 import type { NextFunction, Request, Response } from 'express';
 import type { NextFunction, Request, Response } from 'express';
 
 
-import { OpenaiServiceTypes } from '~/interfaces/ai';
 import { configManager } from '~/server/service/config-manager';
 import { configManager } from '~/server/service/config-manager';
 import loggerFactory from '~/utils/logger';
 import loggerFactory from '~/utils/logger';
 
 
+import { OpenaiServiceTypes } from '../../../interfaces/ai';
+
 const logger = loggerFactory('growi:middlewares:certify-ai-service');
 const logger = loggerFactory('growi:middlewares:certify-ai-service');
 
 
 export const certifyAiService = (req: Request, res: Response & { apiv3Err }, next: NextFunction): void => {
 export const certifyAiService = (req: Request, res: Response & { apiv3Err }, next: NextFunction): void => {

+ 5 - 4
apps/app/src/server/routes/apiv3/openai/rebuild-vector-store.ts → apps/app/src/features/openai/server/routes/rebuild-vector-store.ts

@@ -3,12 +3,13 @@ import type { Request, RequestHandler } from 'express';
 import type { ValidationChain } from 'express-validator';
 import type { ValidationChain } from 'express-validator';
 
 
 import type Crowi from '~/server/crowi';
 import type Crowi from '~/server/crowi';
-import { certifyAiService } from '~/server/middlewares/certify-ai-service';
-import { getOpenaiService } from '~/server/service/openai/openai';
+import { apiV3FormValidator } from '~/server/middlewares/apiv3-form-validator';
+import type { ApiV3Response } from '~/server/routes/apiv3/interfaces/apiv3-response';
 import loggerFactory from '~/utils/logger';
 import loggerFactory from '~/utils/logger';
 
 
-import { apiV3FormValidator } from '../../../middlewares/apiv3-form-validator';
-import type { ApiV3Response } from '../interfaces/apiv3-response';
+import { getOpenaiService } from '../services/openai';
+
+import { certifyAiService } from './middlewares/certify-ai-service';
 
 
 const logger = loggerFactory('growi:routes:apiv3:openai:rebuild-vector-store');
 const logger = loggerFactory('growi:routes:apiv3:openai:rebuild-vector-store');
 
 

+ 9 - 7
apps/app/src/server/routes/apiv3/openai/thread.ts → apps/app/src/features/openai/server/routes/thread.ts

@@ -3,12 +3,14 @@ import type { ValidationChain } from 'express-validator';
 import { body } from 'express-validator';
 import { body } from 'express-validator';
 
 
 import type Crowi from '~/server/crowi';
 import type Crowi from '~/server/crowi';
-import { openaiClient } from '~/server/service/openai';
-import { getOpenaiService } from '~/server/service/openai/openai';
+import { apiV3FormValidator } from '~/server/middlewares/apiv3-form-validator';
+import type { ApiV3Response } from '~/server/routes/apiv3/interfaces/apiv3-response';
 import loggerFactory from '~/utils/logger';
 import loggerFactory from '~/utils/logger';
 
 
-import { apiV3FormValidator } from '../../../middlewares/apiv3-form-validator';
-import type { ApiV3Response } from '../interfaces/apiv3-response';
+import { openaiClient } from '../services';
+import { getOpenaiService } from '../services/openai';
+
+import { certifyAiService } from './middlewares/certify-ai-service';
 
 
 const logger = loggerFactory('growi:routes:apiv3:openai:thread');
 const logger = loggerFactory('growi:routes:apiv3:openai:thread');
 
 
@@ -20,15 +22,15 @@ type CreateThreadReq = Request<undefined, ApiV3Response, {
 type CreateThreadFactory = (crowi: Crowi) => RequestHandler[];
 type CreateThreadFactory = (crowi: Crowi) => RequestHandler[];
 
 
 export const createThreadHandlersFactory: CreateThreadFactory = (crowi) => {
 export const createThreadHandlersFactory: CreateThreadFactory = (crowi) => {
-  const accessTokenParser = require('../../../middlewares/access-token-parser')(crowi);
-  const loginRequiredStrictly = require('../../../middlewares/login-required')(crowi);
+  const accessTokenParser = require('~/server/middlewares/access-token-parser')(crowi);
+  const loginRequiredStrictly = require('~/server/middlewares/login-required')(crowi);
 
 
   const validator: ValidationChain[] = [
   const validator: ValidationChain[] = [
     body('threadId').optional().isString().withMessage('threadId must be string'),
     body('threadId').optional().isString().withMessage('threadId must be string'),
   ];
   ];
 
 
   return [
   return [
-    accessTokenParser, loginRequiredStrictly, validator, apiV3FormValidator,
+    accessTokenParser, loginRequiredStrictly, certifyAiService, validator, apiV3FormValidator,
     async(req: CreateThreadReq, res: ApiV3Response) => {
     async(req: CreateThreadReq, res: ApiV3Response) => {
       const openaiService = getOpenaiService();
       const openaiService = getOpenaiService();
       if (openaiService == null) {
       if (openaiService == null) {

+ 2 - 1
apps/app/src/server/service/openai/assistant/assistant.ts → apps/app/src/features/openai/server/services/assistant/assistant.ts

@@ -1,6 +1,7 @@
 import type OpenAI from 'openai';
 import type OpenAI from 'openai';
 
 
-import { configManager } from '../../config-manager';
+import { configManager } from '~/server/service/config-manager';
+
 import { openaiClient } from '../client';
 import { openaiClient } from '../client';
 
 
 
 

+ 0 - 0
apps/app/src/server/service/openai/assistant/index.ts → apps/app/src/features/openai/server/services/assistant/index.ts


+ 0 - 0
apps/app/src/server/service/openai/client-delegator/azure-openai-client-delegator.ts → apps/app/src/features/openai/server/services/client-delegator/azure-openai-client-delegator.ts


+ 1 - 1
apps/app/src/server/service/openai/client-delegator/get-client.ts → apps/app/src/features/openai/server/services/client-delegator/get-client.ts

@@ -1,4 +1,4 @@
-import { OpenaiServiceType } from '~/interfaces/ai';
+import { OpenaiServiceType } from '../../../interfaces/ai';
 
 
 import { AzureOpenaiClientDelegator } from './azure-openai-client-delegator';
 import { AzureOpenaiClientDelegator } from './azure-openai-client-delegator';
 import type { IOpenaiClientDelegator } from './interfaces';
 import type { IOpenaiClientDelegator } from './interfaces';

+ 0 - 0
apps/app/src/server/service/openai/client-delegator/index.ts → apps/app/src/features/openai/server/services/client-delegator/index.ts


+ 0 - 0
apps/app/src/server/service/openai/client-delegator/interfaces.ts → apps/app/src/features/openai/server/services/client-delegator/interfaces.ts


+ 0 - 0
apps/app/src/server/service/openai/client-delegator/openai-client-delegator.ts → apps/app/src/features/openai/server/services/client-delegator/openai-client-delegator.ts


+ 0 - 0
apps/app/src/server/service/openai/client.ts → apps/app/src/features/openai/server/services/client.ts


+ 0 - 0
apps/app/src/server/service/openai/embeddings.ts → apps/app/src/features/openai/server/services/embeddings.ts


+ 0 - 0
apps/app/src/server/service/openai/index.ts → apps/app/src/features/openai/server/services/index.ts


+ 2 - 1
apps/app/src/server/service/openai/openai.ts → apps/app/src/features/openai/server/services/openai.ts

@@ -12,12 +12,13 @@ import VectorStoreFileRelationModel, {
   type VectorStoreFileRelation,
   type VectorStoreFileRelation,
   prepareVectorStoreFileRelations,
   prepareVectorStoreFileRelations,
 } from '~/features/openai/server/models/vector-store-file-relation';
 } from '~/features/openai/server/models/vector-store-file-relation';
-import { OpenaiServiceTypes } from '~/interfaces/ai';
 import type { PageDocument, PageModel } from '~/server/models/page';
 import type { PageDocument, PageModel } from '~/server/models/page';
 import { configManager } from '~/server/service/config-manager';
 import { configManager } from '~/server/service/config-manager';
 import { createBatchStream } from '~/server/util/batch-stream';
 import { createBatchStream } from '~/server/util/batch-stream';
 import loggerFactory from '~/utils/logger';
 import loggerFactory from '~/utils/logger';
 
 
+import { OpenaiServiceTypes } from '../../interfaces/ai';
+
 
 
 import { getClient } from './client-delegator';
 import { getClient } from './client-delegator';
 
 

+ 2 - 2
apps/app/src/pages/admin/ai-integration.page.tsx

@@ -13,9 +13,9 @@ import { retrieveServerSideProps } from '../../utils/admin-page-util';
 
 
 const AdminLayout = dynamic(() => import('~/components/Layout/AdminLayout'), { ssr: false });
 const AdminLayout = dynamic(() => import('~/components/Layout/AdminLayout'), { ssr: false });
 const ForbiddenPage = dynamic(() => import('~/client/components/Admin/ForbiddenPage').then(mod => mod.ForbiddenPage), { ssr: false });
 const ForbiddenPage = dynamic(() => import('~/client/components/Admin/ForbiddenPage').then(mod => mod.ForbiddenPage), { ssr: false });
-const AiIntegration = dynamic(() => import('~/client/components/Admin/AiIntegration/AiIntegration').then(mod => mod.AiIntegration), { ssr: false });
+const AiIntegration = dynamic(() => import('~/features/openai/client/components/AiIntegration/AiIntegration').then(mod => mod.AiIntegration), { ssr: false });
 const AiIntegrationDisableMode = dynamic(
 const AiIntegrationDisableMode = dynamic(
-  () => import('~/client/components/Admin/AiIntegration/AiIntegrationDisableMode').then(mod => mod.AiIntegrationDisableMode), { ssr: false },
+  () => import('~/features/openai/client/components/AiIntegration/AiIntegrationDisableMode').then(mod => mod.AiIntegrationDisableMode), { ssr: false },
 );
 );
 
 
 type Props = CommonProps & {
 type Props = CommonProps & {

+ 1 - 1
apps/app/src/server/routes/apiv3/index.js

@@ -1,4 +1,5 @@
 import growiPlugin from '~/features/growi-plugin/server/routes/apiv3/admin';
 import growiPlugin from '~/features/growi-plugin/server/routes/apiv3/admin';
+import openai from '~/features/openai/server/routes';
 import loggerFactory from '~/utils/logger';
 import loggerFactory from '~/utils/logger';
 
 
 import { generateAddActivityMiddleware } from '../../middlewares/add-activity';
 import { generateAddActivityMiddleware } from '../../middlewares/add-activity';
@@ -8,7 +9,6 @@ import * as registerFormValidator from '../../middlewares/register-form-validato
 
 
 import g2gTransfer from './g2g-transfer';
 import g2gTransfer from './g2g-transfer';
 import importRoute from './import';
 import importRoute from './import';
-import openai from './openai';
 import pageListing from './page-listing';
 import pageListing from './page-listing';
 import securitySettings from './security-settings';
 import securitySettings from './security-settings';
 import * as userActivation from './user-activation';
 import * as userActivation from './user-activation';

+ 1 - 1
apps/app/src/server/routes/apiv3/page/create-page.ts

@@ -11,6 +11,7 @@ import { body } from 'express-validator';
 import type { HydratedDocument } from 'mongoose';
 import type { HydratedDocument } from 'mongoose';
 import mongoose from 'mongoose';
 import mongoose from 'mongoose';
 
 
+import { getOpenaiService } from '~/features/openai/server/services/openai';
 import { SupportedAction, SupportedTargetModel } from '~/interfaces/activity';
 import { SupportedAction, SupportedTargetModel } from '~/interfaces/activity';
 import type { IApiv3PageCreateParams } from '~/interfaces/apiv3';
 import type { IApiv3PageCreateParams } from '~/interfaces/apiv3';
 import { subscribeRuleNames } from '~/interfaces/in-app-notification';
 import { subscribeRuleNames } from '~/interfaces/in-app-notification';
@@ -23,7 +24,6 @@ import PageTagRelation from '~/server/models/page-tag-relation';
 import { serializePageSecurely, serializeRevisionSecurely } from '~/server/models/serializers';
 import { serializePageSecurely, serializeRevisionSecurely } from '~/server/models/serializers';
 import { configManager } from '~/server/service/config-manager';
 import { configManager } from '~/server/service/config-manager';
 import { getTranslation } from '~/server/service/i18next';
 import { getTranslation } from '~/server/service/i18next';
-import { getOpenaiService } from '~/server/service/openai/openai';
 import loggerFactory from '~/utils/logger';
 import loggerFactory from '~/utils/logger';
 
 
 import { apiV3FormValidator } from '../../../middlewares/apiv3-form-validator';
 import { apiV3FormValidator } from '../../../middlewares/apiv3-form-validator';

+ 1 - 2
apps/app/src/server/routes/apiv3/page/update-page.ts

@@ -11,6 +11,7 @@ import { body } from 'express-validator';
 import type { HydratedDocument } from 'mongoose';
 import type { HydratedDocument } from 'mongoose';
 import mongoose from 'mongoose';
 import mongoose from 'mongoose';
 
 
+import { getOpenaiService } from '~/features/openai/server/services/openai';
 import { SupportedAction, SupportedTargetModel } from '~/interfaces/activity';
 import { SupportedAction, SupportedTargetModel } from '~/interfaces/activity';
 import { type IApiv3PageUpdateParams, PageUpdateErrorCode } from '~/interfaces/apiv3';
 import { type IApiv3PageUpdateParams, PageUpdateErrorCode } from '~/interfaces/apiv3';
 import type { IOptionsForUpdate } from '~/interfaces/page';
 import type { IOptionsForUpdate } from '~/interfaces/page';
@@ -19,8 +20,6 @@ import { generateAddActivityMiddleware } from '~/server/middlewares/add-activity
 import { GlobalNotificationSettingEvent } from '~/server/models/GlobalNotificationSetting';
 import { GlobalNotificationSettingEvent } from '~/server/models/GlobalNotificationSetting';
 import type { PageDocument, PageModel } from '~/server/models/page';
 import type { PageDocument, PageModel } from '~/server/models/page';
 import { serializePageSecurely, serializeRevisionSecurely } from '~/server/models/serializers';
 import { serializePageSecurely, serializeRevisionSecurely } from '~/server/models/serializers';
-import { configManager } from '~/server/service/config-manager';
-import { getOpenaiService } from '~/server/service/openai/openai';
 import { preNotifyService } from '~/server/service/pre-notify';
 import { preNotifyService } from '~/server/service/pre-notify';
 import { normalizeLatestRevisionIfBroken } from '~/server/service/revision/normalize-latest-revision-if-broken';
 import { normalizeLatestRevisionIfBroken } from '~/server/service/revision/normalize-latest-revision-if-broken';
 import { getYjsService } from '~/server/service/yjs';
 import { getYjsService } from '~/server/service/yjs';

+ 1 - 1
apps/app/src/server/service/page/index.ts

@@ -22,6 +22,7 @@ import streamToPromise from 'stream-to-promise';
 import { Comment } from '~/features/comment/server';
 import { Comment } from '~/features/comment/server';
 import type { ExternalUserGroupDocument } from '~/features/external-user-group/server/models/external-user-group';
 import type { ExternalUserGroupDocument } from '~/features/external-user-group/server/models/external-user-group';
 import ExternalUserGroupRelation from '~/features/external-user-group/server/models/external-user-group-relation';
 import ExternalUserGroupRelation from '~/features/external-user-group/server/models/external-user-group-relation';
+import { getOpenaiService } from '~/features/openai/server/services/openai';
 import { SupportedAction } from '~/interfaces/activity';
 import { SupportedAction } from '~/interfaces/activity';
 import { V5ConversionErrCode } from '~/interfaces/errors/v5-conversion-error';
 import { V5ConversionErrCode } from '~/interfaces/errors/v5-conversion-error';
 import type { IOptionsForCreate, IOptionsForUpdate } from '~/interfaces/page';
 import type { IOptionsForCreate, IOptionsForUpdate } from '~/interfaces/page';
@@ -43,7 +44,6 @@ import {
 import type { PageTagRelationDocument } from '~/server/models/page-tag-relation';
 import type { PageTagRelationDocument } from '~/server/models/page-tag-relation';
 import PageTagRelation from '~/server/models/page-tag-relation';
 import PageTagRelation from '~/server/models/page-tag-relation';
 import type { UserGroupDocument } from '~/server/models/user-group';
 import type { UserGroupDocument } from '~/server/models/user-group';
-import { getOpenaiService } from '~/server/service/openai/openai';
 import { createBatchStream } from '~/server/util/batch-stream';
 import { createBatchStream } from '~/server/util/batch-stream';
 import { collectAncestorPaths } from '~/server/util/collect-ancestor-paths';
 import { collectAncestorPaths } from '~/server/util/collect-ancestor-paths';
 import { generalXssFilter } from '~/services/general-xss-filter';
 import { generalXssFilter } from '~/services/general-xss-filter';