|
|
@@ -2,7 +2,10 @@ import assert from 'node:assert';
|
|
|
import { Readable, Transform } from 'stream';
|
|
|
import { pipeline } from 'stream/promises';
|
|
|
|
|
|
-import { PageGrant, isPopulated } from '@growi/core';
|
|
|
+import {
|
|
|
+ IUser,
|
|
|
+ IUserGroup, PageGrant, Ref, getIdForRef, isPopulated,
|
|
|
+} from '@growi/core';
|
|
|
import { isGrobPatternPath } from '@growi/core/dist/utils/page-path-utils';
|
|
|
import escapeStringRegexp from 'escape-string-regexp';
|
|
|
import type { HydratedDocument, Types } from 'mongoose';
|
|
|
@@ -17,12 +20,13 @@ import VectorStoreFileRelationModel, {
|
|
|
prepareVectorStoreFileRelations,
|
|
|
} from '~/features/openai/server/models/vector-store-file-relation';
|
|
|
import type { PageDocument, PageModel } from '~/server/models/page';
|
|
|
+import userGroupRelation from '~/server/models/user-group-relation';
|
|
|
import { configManager } from '~/server/service/config-manager';
|
|
|
import { createBatchStream } from '~/server/util/batch-stream';
|
|
|
import loggerFactory from '~/utils/logger';
|
|
|
|
|
|
import { OpenaiServiceTypes } from '../../interfaces/ai';
|
|
|
-import { type AiAssistant } from '../../interfaces/ai-assistant';
|
|
|
+import { type AiAssistant, AiAssistantAccessScope, AiAssistantShareScope } from '../../interfaces/ai-assistant';
|
|
|
import AiAssistantModel, { type AiAssistantDocument } from '../models/ai-assistant';
|
|
|
import { convertMarkdownToHtml } from '../utils/convert-markdown-to-html';
|
|
|
|
|
|
@@ -419,16 +423,57 @@ class OpenaiService implements IOpenaiService {
|
|
|
await pipeline(pagesStream, batchStream, createVectorStoreFileStream);
|
|
|
}
|
|
|
|
|
|
+ private async createConditionForCreateAiAssistant(data: AiAssistant): Promise<mongoose.FilterQuery<PageDocument>> {
|
|
|
+ const converterdPagePatgPatterns = convertPathPatternsToRegExp(data.pagePathPatterns);
|
|
|
+
|
|
|
+ if (data.accessScope === AiAssistantAccessScope.PUBLIC_ONLY) {
|
|
|
+ return {
|
|
|
+ grant: PageGrant.GRANT_PUBLIC,
|
|
|
+ path: { $in: converterdPagePatgPatterns },
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ if (data.accessScope === AiAssistantAccessScope.GROUPS) {
|
|
|
+ if (data.grantedGroups != null && data.grantedGroups.length > 0) {
|
|
|
+ const ownerMemberGroups = (await userGroupRelation.findAllUserGroupIdsRelatedToUser(data.owner)).map(group => group.toString());
|
|
|
+ const isValid = data.grantedGroups.every(group => ownerMemberGroups.includes(getIdForRef(group.item).toString()));
|
|
|
+ if (!isValid) {
|
|
|
+ throw new Error('A group to which the owner does not belong is specified.');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return {
|
|
|
+ grant: { $in: [PageGrant.GRANT_PUBLIC, PageGrant.GRANT_USER_GROUP] },
|
|
|
+ path: { $in: converterdPagePatgPatterns },
|
|
|
+ $or: [
|
|
|
+ { 'grantedGroups.item': { $in: data.grantedGroups?.map(group => getIdForRef(group.item)) } },
|
|
|
+ { grant: PageGrant.GRANT_PUBLIC },
|
|
|
+ ],
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ if (data.accessScope === AiAssistantAccessScope.OWNER) {
|
|
|
+ return {
|
|
|
+ grant: { $in: [PageGrant.GRANT_PUBLIC, PageGrant.GRANT_OWNER] },
|
|
|
+ path: { $in: converterdPagePatgPatterns },
|
|
|
+ $or: [
|
|
|
+ { grantedUsers: { $in: [getIdForRef(data.owner)] } },
|
|
|
+ { grant: PageGrant.GRANT_PUBLIC },
|
|
|
+ ],
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ throw new Error('Invalid accessScope value');
|
|
|
+ }
|
|
|
+
|
|
|
async createAiAssistant(data: Omit<AiAssistant, 'vectorStore'>): Promise<AiAssistantDocument> {
|
|
|
+ const conditions = await this.createConditionForCreateAiAssistant(data as AiAssistant);
|
|
|
+
|
|
|
const vectorStoreRelation = await this.createVectorStore(data.name);
|
|
|
const aiAssistant = await AiAssistantModel.create({
|
|
|
...data, vectorStore: vectorStoreRelation,
|
|
|
});
|
|
|
|
|
|
- const conditions = {
|
|
|
- path: { $in: convertPathPatternsToRegExp(data.pagePathPatterns) },
|
|
|
- };
|
|
|
-
|
|
|
// VectorStore creation process does not await
|
|
|
this.createVectorStoreFileWithStream(vectorStoreRelation, conditions);
|
|
|
|