mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-14 05:14:54 +00:00
@@ -9,7 +9,6 @@ import {
|
||||
Resolver,
|
||||
} from '@nestjs/graphql';
|
||||
import type { Request } from 'express';
|
||||
import { SafeIntResolver } from 'graphql-scalars';
|
||||
import GraphQLUpload, {
|
||||
type FileUpload,
|
||||
} from 'graphql-upload/GraphQLUpload.mjs';
|
||||
@@ -19,16 +18,22 @@ import {
|
||||
CopilotEmbeddingUnavailable,
|
||||
CopilotFailedToAddWorkspaceFileEmbedding,
|
||||
Mutex,
|
||||
paginate,
|
||||
PaginationInput,
|
||||
TooManyRequest,
|
||||
UserFriendlyError,
|
||||
} from '../../../base';
|
||||
import { CurrentUser } from '../../../core/auth';
|
||||
import { AccessController } from '../../../core/permission';
|
||||
import { WorkspaceType } from '../../../core/workspaces';
|
||||
import { CopilotWorkspaceFile, Models } from '../../../models';
|
||||
import { COPILOT_LOCKER } from '../resolver';
|
||||
import { MAX_EMBEDDABLE_SIZE } from '../types';
|
||||
import { CopilotWorkspaceService } from './service';
|
||||
import {
|
||||
CopilotWorkspaceFileType,
|
||||
PaginatedCopilotWorkspaceFileType,
|
||||
PaginatedIgnoredDocsType,
|
||||
} from './types';
|
||||
|
||||
@ObjectType('CopilotWorkspaceConfig')
|
||||
export class CopilotWorkspaceConfigType {
|
||||
@@ -36,27 +41,6 @@ export class CopilotWorkspaceConfigType {
|
||||
workspaceId!: string;
|
||||
}
|
||||
|
||||
@ObjectType('CopilotWorkspaceFile')
|
||||
export class CopilotWorkspaceFileType implements CopilotWorkspaceFile {
|
||||
@Field(() => String)
|
||||
workspaceId!: string;
|
||||
|
||||
@Field(() => String)
|
||||
fileId!: string;
|
||||
|
||||
@Field(() => String)
|
||||
fileName!: string;
|
||||
|
||||
@Field(() => String)
|
||||
mimeType!: string;
|
||||
|
||||
@Field(() => SafeIntResolver)
|
||||
size!: number;
|
||||
|
||||
@Field(() => Date)
|
||||
createdAt!: Date;
|
||||
}
|
||||
|
||||
/**
|
||||
* Workspace embedding config resolver
|
||||
* Public apis rate limit: 10 req/m
|
||||
@@ -86,18 +70,24 @@ export class CopilotWorkspaceEmbeddingResolver {
|
||||
export class CopilotWorkspaceEmbeddingConfigResolver {
|
||||
constructor(
|
||||
private readonly ac: AccessController,
|
||||
private readonly models: Models,
|
||||
private readonly mutex: Mutex,
|
||||
private readonly copilotWorkspace: CopilotWorkspaceService
|
||||
) {}
|
||||
|
||||
@ResolveField(() => [String], {
|
||||
@ResolveField(() => PaginatedIgnoredDocsType, {
|
||||
complexity: 2,
|
||||
})
|
||||
async ignoredDocs(
|
||||
@Parent() config: CopilotWorkspaceConfigType
|
||||
): Promise<string[]> {
|
||||
return this.models.copilotWorkspace.listIgnoredDocs(config.workspaceId);
|
||||
@Parent() config: CopilotWorkspaceConfigType,
|
||||
@Args('pagination', PaginationInput.decode) pagination: PaginationInput
|
||||
): Promise<PaginatedIgnoredDocsType> {
|
||||
const [ignoredDocs, totalCount] =
|
||||
await this.copilotWorkspace.listIgnoredDocs(
|
||||
config.workspaceId,
|
||||
pagination
|
||||
);
|
||||
|
||||
return paginate(ignoredDocs, 'createdAt', pagination, totalCount);
|
||||
}
|
||||
|
||||
@Mutation(() => Number, {
|
||||
@@ -118,20 +108,26 @@ export class CopilotWorkspaceEmbeddingConfigResolver {
|
||||
.user(user.id)
|
||||
.workspace(workspaceId)
|
||||
.assert('Workspace.Settings.Update');
|
||||
return await this.models.copilotWorkspace.updateIgnoredDocs(
|
||||
return await this.copilotWorkspace.updateIgnoredDocs(
|
||||
workspaceId,
|
||||
add,
|
||||
remove
|
||||
);
|
||||
}
|
||||
|
||||
@ResolveField(() => [CopilotWorkspaceFileType], {
|
||||
@ResolveField(() => PaginatedCopilotWorkspaceFileType, {
|
||||
complexity: 2,
|
||||
})
|
||||
async files(
|
||||
@Parent() config: CopilotWorkspaceConfigType
|
||||
): Promise<CopilotWorkspaceFileType[]> {
|
||||
return this.models.copilotWorkspace.listWorkspaceFiles(config.workspaceId);
|
||||
@Parent() config: CopilotWorkspaceConfigType,
|
||||
@Args('pagination', PaginationInput.decode) pagination: PaginationInput
|
||||
): Promise<PaginatedCopilotWorkspaceFileType> {
|
||||
const [files, totalCount] = await this.copilotWorkspace.listWorkspaceFiles(
|
||||
config.workspaceId,
|
||||
pagination
|
||||
);
|
||||
|
||||
return paginate(files, 'createdAt', pagination, totalCount);
|
||||
}
|
||||
|
||||
@Mutation(() => CopilotWorkspaceFileType, {
|
||||
@@ -210,9 +206,6 @@ export class CopilotWorkspaceEmbeddingConfigResolver {
|
||||
.workspace(workspaceId)
|
||||
.assert('Workspace.Settings.Update');
|
||||
|
||||
return await this.models.copilotWorkspace.removeWorkspaceFile(
|
||||
workspaceId,
|
||||
fileId
|
||||
);
|
||||
return await this.copilotWorkspace.removeWorkspaceFile(workspaceId, fileId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,31 +2,11 @@ import { createHash } from 'node:crypto';
|
||||
|
||||
import { Injectable, OnApplicationBootstrap } from '@nestjs/common';
|
||||
|
||||
import { FileUpload, JobQueue } from '../../../base';
|
||||
import { FileUpload, JobQueue, PaginationInput } from '../../../base';
|
||||
import { Models } from '../../../models';
|
||||
import { CopilotStorage } from '../storage';
|
||||
import { readStream } from '../utils';
|
||||
|
||||
declare global {
|
||||
interface Events {
|
||||
'workspace.file.embedding.finished': {
|
||||
jobId: string;
|
||||
};
|
||||
'workspace.file.embedding.failed': {
|
||||
jobId: string;
|
||||
};
|
||||
}
|
||||
interface Jobs {
|
||||
'copilot.workspace.embedding.files': {
|
||||
userId: string;
|
||||
workspaceId: string;
|
||||
blobId: string;
|
||||
fileId: string;
|
||||
fileName: string;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class CopilotWorkspaceService implements OnApplicationBootstrap {
|
||||
private supportEmbedding = false;
|
||||
@@ -49,6 +29,30 @@ export class CopilotWorkspaceService implements OnApplicationBootstrap {
|
||||
return this.supportEmbedding;
|
||||
}
|
||||
|
||||
async updateIgnoredDocs(
|
||||
workspaceId: string,
|
||||
add?: string[],
|
||||
remove?: string[]
|
||||
) {
|
||||
return await this.models.copilotWorkspace.updateIgnoredDocs(
|
||||
workspaceId,
|
||||
add,
|
||||
remove
|
||||
);
|
||||
}
|
||||
|
||||
async listIgnoredDocs(
|
||||
workspaceId: string,
|
||||
pagination?: {
|
||||
includeRead?: boolean;
|
||||
} & PaginationInput
|
||||
) {
|
||||
return await Promise.all([
|
||||
this.models.copilotWorkspace.listIgnoredDocs(workspaceId, pagination),
|
||||
this.models.copilotWorkspace.countIgnoredDocs(workspaceId),
|
||||
]);
|
||||
}
|
||||
|
||||
async addWorkspaceFile(
|
||||
userId: string,
|
||||
workspaceId: string,
|
||||
@@ -70,6 +74,18 @@ export class CopilotWorkspaceService implements OnApplicationBootstrap {
|
||||
return await this.models.copilotWorkspace.getFile(workspaceId, fileId);
|
||||
}
|
||||
|
||||
async listWorkspaceFiles(
|
||||
workspaceId: string,
|
||||
pagination?: {
|
||||
includeRead?: boolean;
|
||||
} & PaginationInput
|
||||
) {
|
||||
return await Promise.all([
|
||||
this.models.copilotWorkspace.listWorkspaceFiles(workspaceId, pagination),
|
||||
this.models.copilotWorkspace.countIgnoredDocs(workspaceId),
|
||||
]);
|
||||
}
|
||||
|
||||
async addWorkspaceFileEmbeddingQueue(
|
||||
file: Jobs['copilot.workspace.embedding.files']
|
||||
) {
|
||||
@@ -84,4 +100,11 @@ export class CopilotWorkspaceService implements OnApplicationBootstrap {
|
||||
fileName,
|
||||
});
|
||||
}
|
||||
|
||||
async removeWorkspaceFile(workspaceId: string, fileId: string) {
|
||||
return await this.models.copilotWorkspace.removeWorkspaceFile(
|
||||
workspaceId,
|
||||
fileId
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
import { Field, ObjectType } from '@nestjs/graphql';
|
||||
import { SafeIntResolver } from 'graphql-scalars';
|
||||
|
||||
import { Paginated } from '../../../base';
|
||||
import { CopilotWorkspaceFile } from '../../../models';
|
||||
|
||||
declare global {
|
||||
interface Events {
|
||||
'workspace.file.embedding.finished': {
|
||||
jobId: string;
|
||||
};
|
||||
'workspace.file.embedding.failed': {
|
||||
jobId: string;
|
||||
};
|
||||
}
|
||||
interface Jobs {
|
||||
'copilot.workspace.embedding.files': {
|
||||
userId: string;
|
||||
workspaceId: string;
|
||||
blobId: string;
|
||||
fileId: string;
|
||||
fileName: string;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ObjectType('CopilotWorkspaceIgnoredDoc')
|
||||
export class CopilotWorkspaceIgnoredDocType {
|
||||
@Field(() => String)
|
||||
docId!: string;
|
||||
|
||||
@Field(() => Date)
|
||||
createdAt!: Date;
|
||||
}
|
||||
|
||||
@ObjectType()
|
||||
export class PaginatedIgnoredDocsType extends Paginated(
|
||||
CopilotWorkspaceIgnoredDocType
|
||||
) {}
|
||||
|
||||
@ObjectType('CopilotWorkspaceFile')
|
||||
export class CopilotWorkspaceFileType implements CopilotWorkspaceFile {
|
||||
@Field(() => String)
|
||||
workspaceId!: string;
|
||||
|
||||
@Field(() => String)
|
||||
fileId!: string;
|
||||
|
||||
@Field(() => String)
|
||||
fileName!: string;
|
||||
|
||||
@Field(() => String)
|
||||
mimeType!: string;
|
||||
|
||||
@Field(() => SafeIntResolver)
|
||||
size!: number;
|
||||
|
||||
@Field(() => Date)
|
||||
createdAt!: Date;
|
||||
}
|
||||
|
||||
@ObjectType()
|
||||
export class PaginatedCopilotWorkspaceFileType extends Paginated(
|
||||
CopilotWorkspaceFileType
|
||||
) {}
|
||||
Reference in New Issue
Block a user