feat(EE): AI vector search (#1691)

* WIP

* AI module - init

* WIP

* sync

* WIP

* refactor naming

* new columns

* sync

* sync

* fix search bug

* stream response

* WIP

* feat embeddings sync

* refine

* Add workspaceId to page events

* refine

* WIP

* add translation string

* sync

* reset ai answer on query change

* hide AI search in cloud

* capture streaming error

* sync
This commit is contained in:
Philip Okugbe
2025-12-01 11:50:25 +00:00
committed by GitHub
parent c3b350d943
commit 9fb16bc842
46 changed files with 1608 additions and 68 deletions
+24 -14
View File
@@ -1,23 +1,23 @@
import {
Controller,
Post,
BadRequestException,
Body,
Controller,
ForbiddenException,
HttpCode,
HttpStatus,
UseGuards,
ForbiddenException,
NotFoundException,
BadRequestException,
Post,
UseGuards,
} from '@nestjs/common';
import { PageService } from './services/page.service';
import { CreatePageDto } from './dto/create-page.dto';
import { UpdatePageDto } from './dto/update-page.dto';
import { MovePageDto, MovePageToSpaceDto } from './dto/move-page.dto';
import {
DeletePageDto,
PageHistoryIdDto,
PageIdDto,
PageInfoDto,
DeletePageDto,
} from './dto/page.dto';
import { PageHistoryService } from './services/page-history.service';
import { AuthUser } from '../../common/decorators/auth-user.decorator';
@@ -106,7 +106,11 @@ export class PageController {
@HttpCode(HttpStatus.OK)
@Post('delete')
async delete(@Body() deletePageDto: DeletePageDto, @AuthUser() user: User) {
async delete(
@Body() deletePageDto: DeletePageDto,
@AuthUser() user: User,
@AuthWorkspace() workspace: Workspace,
) {
const page = await this.pageRepo.findById(deletePageDto.pageId);
if (!page) {
@@ -122,19 +126,27 @@ export class PageController {
'Only space admins can permanently delete pages',
);
}
await this.pageService.forceDelete(deletePageDto.pageId);
await this.pageService.forceDelete(deletePageDto.pageId, workspace.id);
} else {
// Soft delete requires page manage permissions
if (ability.cannot(SpaceCaslAction.Manage, SpaceCaslSubject.Page)) {
throw new ForbiddenException();
}
await this.pageService.remove(deletePageDto.pageId, user.id);
await this.pageService.removePage(
deletePageDto.pageId,
user.id,
workspace.id,
);
}
}
@HttpCode(HttpStatus.OK)
@Post('restore')
async restore(@Body() pageIdDto: PageIdDto, @AuthUser() user: User) {
async restore(
@Body() pageIdDto: PageIdDto,
@AuthUser() user: User,
@AuthWorkspace() workspace: Workspace,
) {
const page = await this.pageRepo.findById(pageIdDto.pageId);
if (!page) {
@@ -146,13 +158,11 @@ export class PageController {
throw new ForbiddenException();
}
await this.pageRepo.restorePage(pageIdDto.pageId);
await this.pageRepo.restorePage(pageIdDto.pageId, workspace.id);
// Return the restored page data with hasChildren info
const restoredPage = await this.pageRepo.findById(pageIdDto.pageId, {
return this.pageRepo.findById(pageIdDto.pageId, {
includeHasChildren: true,
});
return restoredPage;
}
@HttpCode(HttpStatus.OK)