mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-08-08 20:57:08 +08:00
feat(server): global embedding gql endpoint (#11809)
fix AI-30 fix AI-31 fix PD-2487
This commit is contained in:
@@ -114,13 +114,13 @@ model Workspace {
|
|||||||
name String? @db.VarChar
|
name String? @db.VarChar
|
||||||
avatarKey String? @map("avatar_key") @db.VarChar
|
avatarKey String? @map("avatar_key") @db.VarChar
|
||||||
|
|
||||||
features WorkspaceFeature[]
|
features WorkspaceFeature[]
|
||||||
docs WorkspaceDoc[]
|
docs WorkspaceDoc[]
|
||||||
permissions WorkspaceUserRole[]
|
permissions WorkspaceUserRole[]
|
||||||
docPermissions WorkspaceDocUserRole[]
|
docPermissions WorkspaceDocUserRole[]
|
||||||
blobs Blob[]
|
blobs Blob[]
|
||||||
AiWorkspaceIgnoredDocs AiWorkspaceIgnoredDocs[]
|
ignoredDocs AiWorkspaceIgnoredDocs[]
|
||||||
AiWorkspaceFiles AiWorkspaceFiles[]
|
embedFiles AiWorkspaceFiles[]
|
||||||
|
|
||||||
@@map("workspaces")
|
@@map("workspaces")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -104,22 +104,18 @@ test('should manage copilot workspace ignored docs', async t => {
|
|||||||
|
|
||||||
test('should insert and search embedding', async t => {
|
test('should insert and search embedding', async t => {
|
||||||
{
|
{
|
||||||
await t.context.copilotWorkspace.addWorkspaceFile(
|
const { fileId } = await t.context.copilotWorkspace.addFile(workspace.id, {
|
||||||
workspace.id,
|
fileName: 'file1',
|
||||||
|
mimeType: 'text/plain',
|
||||||
|
size: 1,
|
||||||
|
});
|
||||||
|
await t.context.copilotWorkspace.addFileEmbeddings(workspace.id, fileId, [
|
||||||
{
|
{
|
||||||
fileName: 'file1',
|
index: 0,
|
||||||
mimeType: 'text/plain',
|
content: 'content',
|
||||||
|
embedding: Array.from({ length: 1024 }, () => 1),
|
||||||
size: 1,
|
|
||||||
},
|
},
|
||||||
[
|
]);
|
||||||
{
|
|
||||||
index: 0,
|
|
||||||
content: 'content',
|
|
||||||
embedding: Array.from({ length: 1024 }, () => 1),
|
|
||||||
},
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
{
|
{
|
||||||
const ret = await t.context.copilotWorkspace.matchWorkspaceFileEmbedding(
|
const ret = await t.context.copilotWorkspace.matchWorkspaceFileEmbedding(
|
||||||
|
|||||||
@@ -711,15 +711,21 @@ export const USER_FRIENDLY_ERRORS = {
|
|||||||
},
|
},
|
||||||
copilot_transcription_job_exists: {
|
copilot_transcription_job_exists: {
|
||||||
type: 'bad_request',
|
type: 'bad_request',
|
||||||
message: () => 'Transcription job already exists',
|
message: 'Transcription job already exists',
|
||||||
},
|
},
|
||||||
copilot_transcription_job_not_found: {
|
copilot_transcription_job_not_found: {
|
||||||
type: 'bad_request',
|
type: 'bad_request',
|
||||||
message: () => `Transcription job not found.`,
|
message: `Transcription job not found.`,
|
||||||
},
|
},
|
||||||
copilot_transcription_audio_not_provided: {
|
copilot_transcription_audio_not_provided: {
|
||||||
type: 'bad_request',
|
type: 'bad_request',
|
||||||
message: () => `Audio not provided.`,
|
message: `Audio not provided.`,
|
||||||
|
},
|
||||||
|
copilot_failed_to_add_workspace_file_embedding: {
|
||||||
|
type: 'internal_server_error',
|
||||||
|
args: { message: 'string' },
|
||||||
|
message: ({ message }) =>
|
||||||
|
`Failed to add workspace file embedding: ${message}`,
|
||||||
},
|
},
|
||||||
|
|
||||||
// Quota & Limit errors
|
// Quota & Limit errors
|
||||||
|
|||||||
@@ -788,6 +788,16 @@ export class CopilotTranscriptionAudioNotProvided extends UserFriendlyError {
|
|||||||
super('bad_request', 'copilot_transcription_audio_not_provided', message);
|
super('bad_request', 'copilot_transcription_audio_not_provided', message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ObjectType()
|
||||||
|
class CopilotFailedToAddWorkspaceFileEmbeddingDataType {
|
||||||
|
@Field() message!: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export class CopilotFailedToAddWorkspaceFileEmbedding extends UserFriendlyError {
|
||||||
|
constructor(args: CopilotFailedToAddWorkspaceFileEmbeddingDataType, message?: string | ((args: CopilotFailedToAddWorkspaceFileEmbeddingDataType) => string)) {
|
||||||
|
super('internal_server_error', 'copilot_failed_to_add_workspace_file_embedding', message, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class BlobQuotaExceeded extends UserFriendlyError {
|
export class BlobQuotaExceeded extends UserFriendlyError {
|
||||||
constructor(message?: string) {
|
constructor(message?: string) {
|
||||||
@@ -1048,6 +1058,7 @@ export enum ErrorNames {
|
|||||||
COPILOT_TRANSCRIPTION_JOB_EXISTS,
|
COPILOT_TRANSCRIPTION_JOB_EXISTS,
|
||||||
COPILOT_TRANSCRIPTION_JOB_NOT_FOUND,
|
COPILOT_TRANSCRIPTION_JOB_NOT_FOUND,
|
||||||
COPILOT_TRANSCRIPTION_AUDIO_NOT_PROVIDED,
|
COPILOT_TRANSCRIPTION_AUDIO_NOT_PROVIDED,
|
||||||
|
COPILOT_FAILED_TO_ADD_WORKSPACE_FILE_EMBEDDING,
|
||||||
BLOB_QUOTA_EXCEEDED,
|
BLOB_QUOTA_EXCEEDED,
|
||||||
STORAGE_QUOTA_EXCEEDED,
|
STORAGE_QUOTA_EXCEEDED,
|
||||||
MEMBER_QUOTA_EXCEEDED,
|
MEMBER_QUOTA_EXCEEDED,
|
||||||
@@ -1078,5 +1089,5 @@ registerEnumType(ErrorNames, {
|
|||||||
export const ErrorDataUnionType = createUnionType({
|
export const ErrorDataUnionType = createUnionType({
|
||||||
name: 'ErrorDataUnion',
|
name: 'ErrorDataUnion',
|
||||||
types: () =>
|
types: () =>
|
||||||
[GraphqlBadRequestDataType, HttpRequestErrorDataType, QueryTooLongDataType, ValidationErrorDataType, WrongSignInCredentialsDataType, UnknownOauthProviderDataType, InvalidOauthCallbackCodeDataType, MissingOauthQueryParameterDataType, InvalidEmailDataType, InvalidPasswordLengthDataType, WorkspacePermissionNotFoundDataType, SpaceNotFoundDataType, MemberNotFoundInSpaceDataType, NotInSpaceDataType, AlreadyInSpaceDataType, SpaceAccessDeniedDataType, SpaceOwnerNotFoundDataType, SpaceShouldHaveOnlyOneOwnerDataType, DocNotFoundDataType, DocActionDeniedDataType, DocUpdateBlockedDataType, VersionRejectedDataType, InvalidHistoryTimestampDataType, DocHistoryNotFoundDataType, BlobNotFoundDataType, ExpectToGrantDocUserRolesDataType, ExpectToRevokeDocUserRolesDataType, ExpectToUpdateDocUserRoleDataType, UnsupportedSubscriptionPlanDataType, SubscriptionAlreadyExistsDataType, SubscriptionNotExistsDataType, SameSubscriptionRecurringDataType, SubscriptionPlanNotFoundDataType, CopilotDocNotFoundDataType, CopilotMessageNotFoundDataType, CopilotPromptNotFoundDataType, CopilotProviderSideErrorDataType, CopilotInvalidContextDataType, CopilotContextFileNotSupportedDataType, CopilotFailedToModifyContextDataType, CopilotFailedToMatchContextDataType, RuntimeConfigNotFoundDataType, InvalidRuntimeConfigTypeDataType, InvalidLicenseUpdateParamsDataType, WorkspaceMembersExceedLimitToDowngradeDataType, UnsupportedClientVersionDataType, MentionUserDocAccessDeniedDataType] as const,
|
[GraphqlBadRequestDataType, HttpRequestErrorDataType, QueryTooLongDataType, ValidationErrorDataType, WrongSignInCredentialsDataType, UnknownOauthProviderDataType, InvalidOauthCallbackCodeDataType, MissingOauthQueryParameterDataType, InvalidEmailDataType, InvalidPasswordLengthDataType, WorkspacePermissionNotFoundDataType, SpaceNotFoundDataType, MemberNotFoundInSpaceDataType, NotInSpaceDataType, AlreadyInSpaceDataType, SpaceAccessDeniedDataType, SpaceOwnerNotFoundDataType, SpaceShouldHaveOnlyOneOwnerDataType, DocNotFoundDataType, DocActionDeniedDataType, DocUpdateBlockedDataType, VersionRejectedDataType, InvalidHistoryTimestampDataType, DocHistoryNotFoundDataType, BlobNotFoundDataType, ExpectToGrantDocUserRolesDataType, ExpectToRevokeDocUserRolesDataType, ExpectToUpdateDocUserRoleDataType, UnsupportedSubscriptionPlanDataType, SubscriptionAlreadyExistsDataType, SubscriptionNotExistsDataType, SameSubscriptionRecurringDataType, SubscriptionPlanNotFoundDataType, CopilotDocNotFoundDataType, CopilotMessageNotFoundDataType, CopilotPromptNotFoundDataType, CopilotProviderSideErrorDataType, CopilotInvalidContextDataType, CopilotContextFileNotSupportedDataType, CopilotFailedToModifyContextDataType, CopilotFailedToMatchContextDataType, CopilotFailedToAddWorkspaceFileEmbeddingDataType, RuntimeConfigNotFoundDataType, InvalidRuntimeConfigTypeDataType, InvalidLicenseUpdateParamsDataType, WorkspaceMembersExceedLimitToDowngradeDataType, UnsupportedClientVersionDataType, MentionUserDocAccessDeniedDataType] as const,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -112,9 +112,10 @@ export const CopilotWorkspaceFileSchema = z.object({
|
|||||||
size: z.number(),
|
size: z.number(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type CopilotWorkspaceFile = z.infer<
|
export type CopilotWorkspaceFileMetadata = z.infer<
|
||||||
typeof CopilotWorkspaceFileSchema
|
typeof CopilotWorkspaceFileSchema
|
||||||
> & {
|
>;
|
||||||
|
export type CopilotWorkspaceFile = CopilotWorkspaceFileMetadata & {
|
||||||
workspaceId: string;
|
workspaceId: string;
|
||||||
fileId: string;
|
fileId: string;
|
||||||
createdAt: Date;
|
createdAt: Date;
|
||||||
|
|||||||
@@ -5,9 +5,10 @@ import { Transactional } from '@nestjs-cls/transactional';
|
|||||||
import { Prisma } from '@prisma/client';
|
import { Prisma } from '@prisma/client';
|
||||||
|
|
||||||
import { BaseModel } from './base';
|
import { BaseModel } from './base';
|
||||||
import {
|
import type {
|
||||||
type CopilotWorkspaceFile,
|
CopilotWorkspaceFile,
|
||||||
type Embedding,
|
CopilotWorkspaceFileMetadata,
|
||||||
|
Embedding,
|
||||||
FileChunkSimilarity,
|
FileChunkSimilarity,
|
||||||
} from './common';
|
} from './common';
|
||||||
|
|
||||||
@@ -95,24 +96,40 @@ export class CopilotWorkspaceConfigModel extends BaseModel {
|
|||||||
return Prisma.join(groups.map(row => Prisma.sql`(${Prisma.join(row)})`));
|
return Prisma.join(groups.map(row => Prisma.sql`(${Prisma.join(row)})`));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional()
|
async addFile(
|
||||||
async addWorkspaceFile(
|
|
||||||
workspaceId: string,
|
workspaceId: string,
|
||||||
file: Pick<CopilotWorkspaceFile, 'fileName' | 'mimeType' | 'size'>,
|
file: CopilotWorkspaceFileMetadata
|
||||||
embeddings: Embedding[]
|
): Promise<CopilotWorkspaceFile> {
|
||||||
): Promise<string> {
|
|
||||||
const fileId = randomUUID();
|
const fileId = randomUUID();
|
||||||
await this.db.aiWorkspaceFiles.create({
|
const row = await this.db.aiWorkspaceFiles.create({
|
||||||
data: { ...file, workspaceId, fileId },
|
data: { ...file, workspaceId, fileId },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getFile(workspaceId: string, fileId: string) {
|
||||||
|
const file = await this.db.aiWorkspaceFiles.findFirst({
|
||||||
|
where: {
|
||||||
|
workspaceId,
|
||||||
|
fileId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional()
|
||||||
|
async addFileEmbeddings(
|
||||||
|
workspaceId: string,
|
||||||
|
fileId: string,
|
||||||
|
embeddings: Embedding[]
|
||||||
|
) {
|
||||||
const values = this.processEmbeddings(workspaceId, fileId, embeddings);
|
const values = this.processEmbeddings(workspaceId, fileId, embeddings);
|
||||||
await this.db.$executeRaw`
|
await this.db.$executeRaw`
|
||||||
INSERT INTO "ai_workspace_file_embeddings"
|
INSERT INTO "ai_workspace_file_embeddings"
|
||||||
("workspace_id", "file_id", "chunk", "content", "embedding") VALUES ${values}
|
("workspace_id", "file_id", "chunk", "content", "embedding") VALUES ${values}
|
||||||
ON CONFLICT (workspace_id, file_id, chunk) DO NOTHING;
|
ON CONFLICT (workspace_id, file_id, chunk) DO NOTHING;
|
||||||
`;
|
`;
|
||||||
return fileId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async listWorkspaceFiles(
|
async listWorkspaceFiles(
|
||||||
@@ -152,5 +169,6 @@ export class CopilotWorkspaceConfigModel extends BaseModel {
|
|||||||
fileId,
|
fileId,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,9 +13,9 @@ import {
|
|||||||
import { DocReader } from '../../../core/doc';
|
import { DocReader } from '../../../core/doc';
|
||||||
import { Models } from '../../../models';
|
import { Models } from '../../../models';
|
||||||
import { CopilotStorage } from '../storage';
|
import { CopilotStorage } from '../storage';
|
||||||
|
import { readStream } from '../utils';
|
||||||
import { OpenAIEmbeddingClient } from './embedding';
|
import { OpenAIEmbeddingClient } from './embedding';
|
||||||
import { EmbeddingClient } from './types';
|
import { EmbeddingClient } from './types';
|
||||||
import { readStream } from './utils';
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CopilotContextDocJob {
|
export class CopilotContextDocJob {
|
||||||
|
|||||||
@@ -47,10 +47,10 @@ import {
|
|||||||
import { COPILOT_LOCKER, CopilotType } from '../resolver';
|
import { COPILOT_LOCKER, CopilotType } from '../resolver';
|
||||||
import { ChatSessionService } from '../session';
|
import { ChatSessionService } from '../session';
|
||||||
import { CopilotStorage } from '../storage';
|
import { CopilotStorage } from '../storage';
|
||||||
|
import { MAX_EMBEDDABLE_SIZE } from '../types';
|
||||||
|
import { readStream } from '../utils';
|
||||||
import { CopilotContextDocJob } from './job';
|
import { CopilotContextDocJob } from './job';
|
||||||
import { CopilotContextService } from './service';
|
import { CopilotContextService } from './service';
|
||||||
import { MAX_EMBEDDABLE_SIZE } from './types';
|
|
||||||
import { readStream } from './utils';
|
|
||||||
|
|
||||||
@InputType()
|
@InputType()
|
||||||
class AddContextCategoryInput {
|
class AddContextCategoryInput {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { File } from 'node:buffer';
|
import { File } from 'node:buffer';
|
||||||
|
|
||||||
import { CopilotContextFileNotSupported, OneMB } from '../../../base';
|
import { CopilotContextFileNotSupported } from '../../../base';
|
||||||
import { Embedding } from '../../../models';
|
import { Embedding } from '../../../models';
|
||||||
import { parseDoc } from '../../../native';
|
import { parseDoc } from '../../../native';
|
||||||
|
|
||||||
@@ -46,8 +46,6 @@ declare global {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const MAX_EMBEDDABLE_SIZE = 50 * OneMB;
|
|
||||||
|
|
||||||
export type Chunk = {
|
export type Chunk = {
|
||||||
index: number;
|
index: number;
|
||||||
content: string;
|
content: string;
|
||||||
|
|||||||
@@ -1,8 +1,3 @@
|
|||||||
import { Readable } from 'node:stream';
|
|
||||||
|
|
||||||
import { readBufferWithLimit } from '../../../base';
|
|
||||||
import { MAX_EMBEDDABLE_SIZE } from './types';
|
|
||||||
|
|
||||||
export class GqlSignal implements AsyncDisposable {
|
export class GqlSignal implements AsyncDisposable {
|
||||||
readonly abortController = new AbortController();
|
readonly abortController = new AbortController();
|
||||||
|
|
||||||
@@ -14,10 +9,3 @@ export class GqlSignal implements AsyncDisposable {
|
|||||||
this.abortController.abort();
|
this.abortController.abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function readStream(
|
|
||||||
readable: Readable,
|
|
||||||
maxSize = MAX_EMBEDDABLE_SIZE
|
|
||||||
): Promise<Buffer> {
|
|
||||||
return readBufferWithLimit(readable, maxSize);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { DocStorageModule } from '../../core/doc';
|
|||||||
import { FeatureModule } from '../../core/features';
|
import { FeatureModule } from '../../core/features';
|
||||||
import { PermissionModule } from '../../core/permission';
|
import { PermissionModule } from '../../core/permission';
|
||||||
import { QuotaModule } from '../../core/quota';
|
import { QuotaModule } from '../../core/quota';
|
||||||
|
import { WorkspaceModule } from '../../core/workspaces';
|
||||||
import {
|
import {
|
||||||
CopilotContextDocJob,
|
CopilotContextDocJob,
|
||||||
CopilotContextResolver,
|
CopilotContextResolver,
|
||||||
@@ -29,6 +30,11 @@ import {
|
|||||||
CopilotTranscriptionService,
|
CopilotTranscriptionService,
|
||||||
} from './transcript';
|
} from './transcript';
|
||||||
import { CopilotWorkflowExecutors, CopilotWorkflowService } from './workflow';
|
import { CopilotWorkflowExecutors, CopilotWorkflowService } from './workflow';
|
||||||
|
import {
|
||||||
|
CopilotWorkspaceEmbeddingConfigResolver,
|
||||||
|
CopilotWorkspaceEmbeddingResolver,
|
||||||
|
CopilotWorkspaceService,
|
||||||
|
} from './workspace';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -37,6 +43,7 @@ import { CopilotWorkflowExecutors, CopilotWorkflowService } from './workflow';
|
|||||||
QuotaModule,
|
QuotaModule,
|
||||||
PermissionModule,
|
PermissionModule,
|
||||||
ServerConfigModule,
|
ServerConfigModule,
|
||||||
|
WorkspaceModule,
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
// providers
|
// providers
|
||||||
@@ -58,6 +65,10 @@ import { CopilotWorkflowExecutors, CopilotWorkflowService } from './workflow';
|
|||||||
// transcription
|
// transcription
|
||||||
CopilotTranscriptionService,
|
CopilotTranscriptionService,
|
||||||
CopilotTranscriptionResolver,
|
CopilotTranscriptionResolver,
|
||||||
|
// workspace embeddings
|
||||||
|
CopilotWorkspaceService,
|
||||||
|
CopilotWorkspaceEmbeddingResolver,
|
||||||
|
CopilotWorkspaceEmbeddingConfigResolver,
|
||||||
// gql resolvers
|
// gql resolvers
|
||||||
UserCopilotResolver,
|
UserCopilotResolver,
|
||||||
PromptsManagementResolver,
|
PromptsManagementResolver,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { type Tokenizer } from '@affine/server-native';
|
import { type Tokenizer } from '@affine/server-native';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
|
import { OneMB } from '../../base';
|
||||||
import { fromModelName } from '../../native';
|
import { fromModelName } from '../../native';
|
||||||
import type { ChatPrompt } from './prompt';
|
import type { ChatPrompt } from './prompt';
|
||||||
import { PromptMessageSchema, PureMessageSchema } from './providers';
|
import { PromptMessageSchema, PureMessageSchema } from './providers';
|
||||||
@@ -116,3 +117,5 @@ export type CopilotContextFile = {
|
|||||||
// embedding status
|
// embedding status
|
||||||
status: 'in_progress' | 'completed' | 'failed';
|
status: 'in_progress' | 'completed' | 'failed';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const MAX_EMBEDDABLE_SIZE = 50 * OneMB;
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import { Readable } from 'node:stream';
|
||||||
|
|
||||||
|
import { readBufferWithLimit } from '../../base';
|
||||||
|
import { MAX_EMBEDDABLE_SIZE } from './types';
|
||||||
|
|
||||||
|
export function readStream(
|
||||||
|
readable: Readable,
|
||||||
|
maxSize = MAX_EMBEDDABLE_SIZE
|
||||||
|
): Promise<Buffer> {
|
||||||
|
return readBufferWithLimit(readable, maxSize);
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
export {
|
||||||
|
CopilotWorkspaceEmbeddingConfigResolver,
|
||||||
|
CopilotWorkspaceEmbeddingResolver,
|
||||||
|
} from './resolver';
|
||||||
|
export { CopilotWorkspaceService } from './service';
|
||||||
@@ -0,0 +1,218 @@
|
|||||||
|
import {
|
||||||
|
Args,
|
||||||
|
Context,
|
||||||
|
Field,
|
||||||
|
Mutation,
|
||||||
|
ObjectType,
|
||||||
|
Parent,
|
||||||
|
ResolveField,
|
||||||
|
Resolver,
|
||||||
|
} from '@nestjs/graphql';
|
||||||
|
import type { Request } from 'express';
|
||||||
|
import { SafeIntResolver } from 'graphql-scalars';
|
||||||
|
import GraphQLUpload, {
|
||||||
|
type FileUpload,
|
||||||
|
} from 'graphql-upload/GraphQLUpload.mjs';
|
||||||
|
|
||||||
|
import {
|
||||||
|
BlobQuotaExceeded,
|
||||||
|
CopilotEmbeddingUnavailable,
|
||||||
|
CopilotFailedToAddWorkspaceFileEmbedding,
|
||||||
|
Mutex,
|
||||||
|
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';
|
||||||
|
|
||||||
|
@ObjectType('CopilotWorkspaceConfig')
|
||||||
|
export class CopilotWorkspaceConfigType {
|
||||||
|
@Field(() => String)
|
||||||
|
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
|
||||||
|
* Other rate limit: 120 req/m
|
||||||
|
*/
|
||||||
|
@Resolver(() => WorkspaceType)
|
||||||
|
export class CopilotWorkspaceEmbeddingResolver {
|
||||||
|
constructor(private readonly ac: AccessController) {}
|
||||||
|
|
||||||
|
@ResolveField(() => CopilotWorkspaceConfigType, {
|
||||||
|
complexity: 2,
|
||||||
|
})
|
||||||
|
async embedding(
|
||||||
|
@CurrentUser() user: CurrentUser,
|
||||||
|
@Parent() workspace: WorkspaceType
|
||||||
|
): Promise<CopilotWorkspaceConfigType> {
|
||||||
|
await this.ac
|
||||||
|
.user(user.id)
|
||||||
|
.workspace(workspace.id)
|
||||||
|
.assert('Workspace.Read');
|
||||||
|
|
||||||
|
return { workspaceId: workspace.id };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Resolver(() => CopilotWorkspaceConfigType)
|
||||||
|
export class CopilotWorkspaceEmbeddingConfigResolver {
|
||||||
|
constructor(
|
||||||
|
private readonly ac: AccessController,
|
||||||
|
private readonly models: Models,
|
||||||
|
private readonly mutex: Mutex,
|
||||||
|
private readonly copilotWorkspace: CopilotWorkspaceService
|
||||||
|
) {}
|
||||||
|
|
||||||
|
@ResolveField(() => [String], {
|
||||||
|
complexity: 2,
|
||||||
|
})
|
||||||
|
async ignoredDocs(
|
||||||
|
@Parent() config: CopilotWorkspaceConfigType
|
||||||
|
): Promise<string[]> {
|
||||||
|
return this.models.copilotWorkspace.listIgnoredDocs(config.workspaceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Mutation(() => Number, {
|
||||||
|
name: 'updateWorkspaceEmbeddingIgnoredDocs',
|
||||||
|
complexity: 2,
|
||||||
|
description: 'Update ignored docs',
|
||||||
|
})
|
||||||
|
async updateIgnoredDocs(
|
||||||
|
@CurrentUser() user: CurrentUser,
|
||||||
|
@Args('workspaceId', { type: () => String })
|
||||||
|
workspaceId: string,
|
||||||
|
@Args('add', { type: () => [String], nullable: true })
|
||||||
|
add?: string[],
|
||||||
|
@Args('remove', { type: () => [String], nullable: true })
|
||||||
|
remove?: string[]
|
||||||
|
): Promise<number> {
|
||||||
|
await this.ac
|
||||||
|
.user(user.id)
|
||||||
|
.workspace(workspaceId)
|
||||||
|
.assert('Workspace.Settings.Update');
|
||||||
|
return await this.models.copilotWorkspace.updateIgnoredDocs(
|
||||||
|
workspaceId,
|
||||||
|
add,
|
||||||
|
remove
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ResolveField(() => [CopilotWorkspaceFileType], {
|
||||||
|
complexity: 2,
|
||||||
|
})
|
||||||
|
async files(
|
||||||
|
@Parent() config: CopilotWorkspaceConfigType
|
||||||
|
): Promise<CopilotWorkspaceFileType[]> {
|
||||||
|
return this.models.copilotWorkspace.listWorkspaceFiles(config.workspaceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Mutation(() => CopilotWorkspaceFileType, {
|
||||||
|
name: 'addWorkspaceEmbeddingFiles',
|
||||||
|
complexity: 2,
|
||||||
|
description: 'Update workspace embedding files',
|
||||||
|
})
|
||||||
|
async addFiles(
|
||||||
|
@Context() ctx: { req: Request },
|
||||||
|
@CurrentUser() user: CurrentUser,
|
||||||
|
@Args('workspaceId', { type: () => String })
|
||||||
|
workspaceId: string,
|
||||||
|
@Args({ name: 'blob', type: () => GraphQLUpload })
|
||||||
|
content: FileUpload
|
||||||
|
): Promise<CopilotWorkspaceFileType> {
|
||||||
|
await this.ac
|
||||||
|
.user(user.id)
|
||||||
|
.workspace(workspaceId)
|
||||||
|
.assert('Workspace.Settings.Update');
|
||||||
|
|
||||||
|
if (!this.copilotWorkspace.canEmbedding) {
|
||||||
|
throw new CopilotEmbeddingUnavailable();
|
||||||
|
}
|
||||||
|
|
||||||
|
const lockFlag = `${COPILOT_LOCKER}:workspace:${workspaceId}`;
|
||||||
|
await using lock = await this.mutex.acquire(lockFlag);
|
||||||
|
if (!lock) {
|
||||||
|
throw new TooManyRequest('Server is busy');
|
||||||
|
}
|
||||||
|
|
||||||
|
const length = Number(ctx.req.headers['content-length']);
|
||||||
|
if (length && length >= MAX_EMBEDDABLE_SIZE) {
|
||||||
|
throw new BlobQuotaExceeded();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { blobId, file } = await this.copilotWorkspace.addWorkspaceFile(
|
||||||
|
user.id,
|
||||||
|
workspaceId,
|
||||||
|
content
|
||||||
|
);
|
||||||
|
await this.copilotWorkspace.addWorkspaceFileEmbeddingQueue({
|
||||||
|
userId: user.id,
|
||||||
|
workspaceId,
|
||||||
|
blobId,
|
||||||
|
fileId: file.fileId,
|
||||||
|
fileName: file.fileName,
|
||||||
|
});
|
||||||
|
|
||||||
|
return file;
|
||||||
|
} catch (e: any) {
|
||||||
|
// passthrough user friendly error
|
||||||
|
if (e instanceof UserFriendlyError) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
throw new CopilotFailedToAddWorkspaceFileEmbedding({
|
||||||
|
message: e.message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Mutation(() => Boolean, {
|
||||||
|
name: 'removeWorkspaceEmbeddingFiles',
|
||||||
|
complexity: 2,
|
||||||
|
description: 'Remove workspace embedding files',
|
||||||
|
})
|
||||||
|
async removeFiles(
|
||||||
|
@CurrentUser() user: CurrentUser,
|
||||||
|
@Args('workspaceId', { type: () => String })
|
||||||
|
workspaceId: string,
|
||||||
|
@Args('fileId', { type: () => String })
|
||||||
|
fileId: string
|
||||||
|
): Promise<boolean> {
|
||||||
|
await this.ac
|
||||||
|
.user(user.id)
|
||||||
|
.workspace(workspaceId)
|
||||||
|
.assert('Workspace.Settings.Update');
|
||||||
|
|
||||||
|
return await this.models.copilotWorkspace.removeWorkspaceFile(
|
||||||
|
workspaceId,
|
||||||
|
fileId
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
import { createHash } from 'node:crypto';
|
||||||
|
|
||||||
|
import { Injectable, OnApplicationBootstrap } from '@nestjs/common';
|
||||||
|
|
||||||
|
import { FileUpload, JobQueue } 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;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private readonly models: Models,
|
||||||
|
private readonly queue: JobQueue,
|
||||||
|
private readonly storage: CopilotStorage
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async onApplicationBootstrap() {
|
||||||
|
const supportEmbedding =
|
||||||
|
await this.models.copilotContext.checkEmbeddingAvailable();
|
||||||
|
if (supportEmbedding) {
|
||||||
|
this.supportEmbedding = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get canEmbedding() {
|
||||||
|
return this.supportEmbedding;
|
||||||
|
}
|
||||||
|
|
||||||
|
async addWorkspaceFile(
|
||||||
|
userId: string,
|
||||||
|
workspaceId: string,
|
||||||
|
content: FileUpload
|
||||||
|
) {
|
||||||
|
const fileName = content.filename;
|
||||||
|
const buffer = await readStream(content.createReadStream());
|
||||||
|
const blobId = createHash('sha256').update(buffer).digest('base64url');
|
||||||
|
await this.storage.put(userId, workspaceId, blobId, buffer);
|
||||||
|
const file = await this.models.copilotWorkspace.addFile(workspaceId, {
|
||||||
|
fileName,
|
||||||
|
mimeType: content.mimetype,
|
||||||
|
size: buffer.length,
|
||||||
|
});
|
||||||
|
return { blobId, file };
|
||||||
|
}
|
||||||
|
|
||||||
|
async getWorkspaceFile(workspaceId: string, fileId: string) {
|
||||||
|
return await this.models.copilotWorkspace.getFile(workspaceId, fileId);
|
||||||
|
}
|
||||||
|
|
||||||
|
async addWorkspaceFileEmbeddingQueue(
|
||||||
|
file: Jobs['copilot.workspace.embedding.files']
|
||||||
|
) {
|
||||||
|
if (!this.supportEmbedding) return;
|
||||||
|
|
||||||
|
const { userId, workspaceId, blobId, fileId, fileName } = file;
|
||||||
|
await this.queue.add('copilot.workspace.embedding.files', {
|
||||||
|
userId,
|
||||||
|
workspaceId,
|
||||||
|
blobId,
|
||||||
|
fileId,
|
||||||
|
fileName,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -159,6 +159,10 @@ type CopilotDocType {
|
|||||||
status: ContextEmbedStatus
|
status: ContextEmbedStatus
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CopilotFailedToAddWorkspaceFileEmbeddingDataType {
|
||||||
|
message: String!
|
||||||
|
}
|
||||||
|
|
||||||
type CopilotFailedToMatchContextDataType {
|
type CopilotFailedToMatchContextDataType {
|
||||||
content: String!
|
content: String!
|
||||||
contextId: String!
|
contextId: String!
|
||||||
@@ -268,6 +272,21 @@ type CopilotSessionType {
|
|||||||
promptName: String!
|
promptName: String!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CopilotWorkspaceConfig {
|
||||||
|
files: [CopilotWorkspaceFile!]!
|
||||||
|
ignoredDocs: [String!]!
|
||||||
|
workspaceId: String!
|
||||||
|
}
|
||||||
|
|
||||||
|
type CopilotWorkspaceFile {
|
||||||
|
createdAt: DateTime!
|
||||||
|
fileId: String!
|
||||||
|
fileName: String!
|
||||||
|
mimeType: String!
|
||||||
|
size: SafeInt!
|
||||||
|
workspaceId: String!
|
||||||
|
}
|
||||||
|
|
||||||
input CreateChatMessageInput {
|
input CreateChatMessageInput {
|
||||||
attachments: [String!]
|
attachments: [String!]
|
||||||
blobs: [Upload!]
|
blobs: [Upload!]
|
||||||
@@ -404,7 +423,7 @@ type EditorType {
|
|||||||
name: String!
|
name: String!
|
||||||
}
|
}
|
||||||
|
|
||||||
union ErrorDataUnion = AlreadyInSpaceDataType | BlobNotFoundDataType | CopilotContextFileNotSupportedDataType | CopilotDocNotFoundDataType | CopilotFailedToMatchContextDataType | CopilotFailedToModifyContextDataType | CopilotInvalidContextDataType | CopilotMessageNotFoundDataType | CopilotPromptNotFoundDataType | CopilotProviderSideErrorDataType | DocActionDeniedDataType | DocHistoryNotFoundDataType | DocNotFoundDataType | DocUpdateBlockedDataType | ExpectToGrantDocUserRolesDataType | ExpectToRevokeDocUserRolesDataType | ExpectToUpdateDocUserRoleDataType | GraphqlBadRequestDataType | HttpRequestErrorDataType | InvalidEmailDataType | InvalidHistoryTimestampDataType | InvalidLicenseUpdateParamsDataType | InvalidOauthCallbackCodeDataType | InvalidPasswordLengthDataType | InvalidRuntimeConfigTypeDataType | MemberNotFoundInSpaceDataType | MentionUserDocAccessDeniedDataType | MissingOauthQueryParameterDataType | NotInSpaceDataType | QueryTooLongDataType | RuntimeConfigNotFoundDataType | SameSubscriptionRecurringDataType | SpaceAccessDeniedDataType | SpaceNotFoundDataType | SpaceOwnerNotFoundDataType | SpaceShouldHaveOnlyOneOwnerDataType | SubscriptionAlreadyExistsDataType | SubscriptionNotExistsDataType | SubscriptionPlanNotFoundDataType | UnknownOauthProviderDataType | UnsupportedClientVersionDataType | UnsupportedSubscriptionPlanDataType | ValidationErrorDataType | VersionRejectedDataType | WorkspaceMembersExceedLimitToDowngradeDataType | WorkspacePermissionNotFoundDataType | WrongSignInCredentialsDataType
|
union ErrorDataUnion = AlreadyInSpaceDataType | BlobNotFoundDataType | CopilotContextFileNotSupportedDataType | CopilotDocNotFoundDataType | CopilotFailedToAddWorkspaceFileEmbeddingDataType | CopilotFailedToMatchContextDataType | CopilotFailedToModifyContextDataType | CopilotInvalidContextDataType | CopilotMessageNotFoundDataType | CopilotPromptNotFoundDataType | CopilotProviderSideErrorDataType | DocActionDeniedDataType | DocHistoryNotFoundDataType | DocNotFoundDataType | DocUpdateBlockedDataType | ExpectToGrantDocUserRolesDataType | ExpectToRevokeDocUserRolesDataType | ExpectToUpdateDocUserRoleDataType | GraphqlBadRequestDataType | HttpRequestErrorDataType | InvalidEmailDataType | InvalidHistoryTimestampDataType | InvalidLicenseUpdateParamsDataType | InvalidOauthCallbackCodeDataType | InvalidPasswordLengthDataType | InvalidRuntimeConfigTypeDataType | MemberNotFoundInSpaceDataType | MentionUserDocAccessDeniedDataType | MissingOauthQueryParameterDataType | NotInSpaceDataType | QueryTooLongDataType | RuntimeConfigNotFoundDataType | SameSubscriptionRecurringDataType | SpaceAccessDeniedDataType | SpaceNotFoundDataType | SpaceOwnerNotFoundDataType | SpaceShouldHaveOnlyOneOwnerDataType | SubscriptionAlreadyExistsDataType | SubscriptionNotExistsDataType | SubscriptionPlanNotFoundDataType | UnknownOauthProviderDataType | UnsupportedClientVersionDataType | UnsupportedSubscriptionPlanDataType | ValidationErrorDataType | VersionRejectedDataType | WorkspaceMembersExceedLimitToDowngradeDataType | WorkspacePermissionNotFoundDataType | WrongSignInCredentialsDataType
|
||||||
|
|
||||||
enum ErrorNames {
|
enum ErrorNames {
|
||||||
ACCESS_DENIED
|
ACCESS_DENIED
|
||||||
@@ -427,6 +446,7 @@ enum ErrorNames {
|
|||||||
COPILOT_DOC_NOT_FOUND
|
COPILOT_DOC_NOT_FOUND
|
||||||
COPILOT_EMBEDDING_DISABLED
|
COPILOT_EMBEDDING_DISABLED
|
||||||
COPILOT_EMBEDDING_UNAVAILABLE
|
COPILOT_EMBEDDING_UNAVAILABLE
|
||||||
|
COPILOT_FAILED_TO_ADD_WORKSPACE_FILE_EMBEDDING
|
||||||
COPILOT_FAILED_TO_CREATE_MESSAGE
|
COPILOT_FAILED_TO_CREATE_MESSAGE
|
||||||
COPILOT_FAILED_TO_GENERATE_TEXT
|
COPILOT_FAILED_TO_GENERATE_TEXT
|
||||||
COPILOT_FAILED_TO_MATCH_CONTEXT
|
COPILOT_FAILED_TO_MATCH_CONTEXT
|
||||||
@@ -907,6 +927,9 @@ type Mutation {
|
|||||||
|
|
||||||
"""add a file to context"""
|
"""add a file to context"""
|
||||||
addContextFile(content: Upload!, options: AddContextFileInput!): CopilotContextFile!
|
addContextFile(content: Upload!, options: AddContextFileInput!): CopilotContextFile!
|
||||||
|
|
||||||
|
"""Update workspace embedding files"""
|
||||||
|
addWorkspaceEmbeddingFiles(blob: Upload!, workspaceId: String!): CopilotWorkspaceFile!
|
||||||
addWorkspaceFeature(feature: FeatureType!, workspaceId: String!): Boolean!
|
addWorkspaceFeature(feature: FeatureType!, workspaceId: String!): Boolean!
|
||||||
approveMember(userId: String!, workspaceId: String!): Boolean!
|
approveMember(userId: String!, workspaceId: String!): Boolean!
|
||||||
|
|
||||||
@@ -995,6 +1018,9 @@ type Mutation {
|
|||||||
|
|
||||||
"""remove a file from context"""
|
"""remove a file from context"""
|
||||||
removeContextFile(options: RemoveContextFileInput!): Boolean!
|
removeContextFile(options: RemoveContextFileInput!): Boolean!
|
||||||
|
|
||||||
|
"""Remove workspace embedding files"""
|
||||||
|
removeWorkspaceEmbeddingFiles(fileId: String!, workspaceId: String!): Boolean!
|
||||||
removeWorkspaceFeature(feature: FeatureType!, workspaceId: String!): Boolean!
|
removeWorkspaceFeature(feature: FeatureType!, workspaceId: String!): Boolean!
|
||||||
resumeSubscription(idempotencyKey: String @deprecated(reason: "use header `Idempotency-Key`"), plan: SubscriptionPlan = Pro, workspaceId: String): SubscriptionType!
|
resumeSubscription(idempotencyKey: String @deprecated(reason: "use header `Idempotency-Key`"), plan: SubscriptionPlan = Pro, workspaceId: String): SubscriptionType!
|
||||||
retryAudioTranscription(jobId: String!, workspaceId: String!): TranscriptionResultType
|
retryAudioTranscription(jobId: String!, workspaceId: String!): TranscriptionResultType
|
||||||
@@ -1037,6 +1063,9 @@ type Mutation {
|
|||||||
"""Update workspace"""
|
"""Update workspace"""
|
||||||
updateWorkspace(input: UpdateWorkspaceInput!): WorkspaceType!
|
updateWorkspace(input: UpdateWorkspaceInput!): WorkspaceType!
|
||||||
|
|
||||||
|
"""Update ignored docs"""
|
||||||
|
updateWorkspaceEmbeddingIgnoredDocs(add: [String!], remove: [String!], workspaceId: String!): Int!
|
||||||
|
|
||||||
"""Upload user avatar"""
|
"""Upload user avatar"""
|
||||||
uploadAvatar(avatar: Upload!): UserType!
|
uploadAvatar(avatar: Upload!): UserType!
|
||||||
verifyEmail(token: String!): Boolean!
|
verifyEmail(token: String!): Boolean!
|
||||||
@@ -1703,6 +1732,7 @@ type WorkspaceType {
|
|||||||
|
|
||||||
"""Get get with given id"""
|
"""Get get with given id"""
|
||||||
doc(docId: String!): DocType!
|
doc(docId: String!): DocType!
|
||||||
|
embedding: CopilotWorkspaceConfig!
|
||||||
|
|
||||||
"""Enable AI"""
|
"""Enable AI"""
|
||||||
enableAi: Boolean!
|
enableAi: Boolean!
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
mutation addWorkspaceEmbeddingFiles($workspaceId: String!, $blob: Upload!) {
|
||||||
|
addWorkspaceEmbeddingFiles(workspaceId: $workspaceId, blob: $blob) {
|
||||||
|
fileId
|
||||||
|
fileName
|
||||||
|
mimeType
|
||||||
|
size
|
||||||
|
createdAt
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
mutation removeWorkspaceEmbeddingFiles($workspaceId: String!, $fileId: String!) {
|
||||||
|
removeWorkspaceEmbeddingFiles(workspaceId: $workspaceId, fileId: $fileId)
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
query getWorkspaceEmbeddingConfig($workspaceId: String!) {
|
||||||
|
workspace(id: $workspaceId) {
|
||||||
|
embedding {
|
||||||
|
files {
|
||||||
|
fileId
|
||||||
|
fileName
|
||||||
|
mimeType
|
||||||
|
size
|
||||||
|
createdAt
|
||||||
|
}
|
||||||
|
ignoredDocs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
mutation updateWorkspaceEmbeddingIgnoredDocs($workspaceId: String!, $add: [String!], $remove: [String!]) {
|
||||||
|
updateWorkspaceEmbeddingIgnoredDocs(workspaceId: $workspaceId, add: $add, remove: $remove)
|
||||||
|
}
|
||||||
@@ -741,6 +741,60 @@ export const getCopilotSessionsQuery = {
|
|||||||
}`,
|
}`,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const addWorkspaceEmbeddingFilesMutation = {
|
||||||
|
id: 'addWorkspaceEmbeddingFilesMutation' as const,
|
||||||
|
op: 'addWorkspaceEmbeddingFiles',
|
||||||
|
query: `mutation addWorkspaceEmbeddingFiles($workspaceId: String!, $blob: Upload!) {
|
||||||
|
addWorkspaceEmbeddingFiles(workspaceId: $workspaceId, blob: $blob) {
|
||||||
|
fileId
|
||||||
|
fileName
|
||||||
|
mimeType
|
||||||
|
size
|
||||||
|
createdAt
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
file: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const removeWorkspaceEmbeddingFilesMutation = {
|
||||||
|
id: 'removeWorkspaceEmbeddingFilesMutation' as const,
|
||||||
|
op: 'removeWorkspaceEmbeddingFiles',
|
||||||
|
query: `mutation removeWorkspaceEmbeddingFiles($workspaceId: String!, $fileId: String!) {
|
||||||
|
removeWorkspaceEmbeddingFiles(workspaceId: $workspaceId, fileId: $fileId)
|
||||||
|
}`,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getWorkspaceEmbeddingConfigQuery = {
|
||||||
|
id: 'getWorkspaceEmbeddingConfigQuery' as const,
|
||||||
|
op: 'getWorkspaceEmbeddingConfig',
|
||||||
|
query: `query getWorkspaceEmbeddingConfig($workspaceId: String!) {
|
||||||
|
workspace(id: $workspaceId) {
|
||||||
|
embedding {
|
||||||
|
files {
|
||||||
|
fileId
|
||||||
|
fileName
|
||||||
|
mimeType
|
||||||
|
size
|
||||||
|
createdAt
|
||||||
|
}
|
||||||
|
ignoredDocs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const updateWorkspaceEmbeddingIgnoredDocsMutation = {
|
||||||
|
id: 'updateWorkspaceEmbeddingIgnoredDocsMutation' as const,
|
||||||
|
op: 'updateWorkspaceEmbeddingIgnoredDocs',
|
||||||
|
query: `mutation updateWorkspaceEmbeddingIgnoredDocs($workspaceId: String!, $add: [String!], $remove: [String!]) {
|
||||||
|
updateWorkspaceEmbeddingIgnoredDocs(
|
||||||
|
workspaceId: $workspaceId
|
||||||
|
add: $add
|
||||||
|
remove: $remove
|
||||||
|
)
|
||||||
|
}`,
|
||||||
|
};
|
||||||
|
|
||||||
export const createCheckoutSessionMutation = {
|
export const createCheckoutSessionMutation = {
|
||||||
id: 'createCheckoutSessionMutation' as const,
|
id: 'createCheckoutSessionMutation' as const,
|
||||||
op: 'createCheckoutSession',
|
op: 'createCheckoutSession',
|
||||||
|
|||||||
@@ -239,6 +239,11 @@ export interface CopilotDocType {
|
|||||||
status: Maybe<ContextEmbedStatus>;
|
status: Maybe<ContextEmbedStatus>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface CopilotFailedToAddWorkspaceFileEmbeddingDataType {
|
||||||
|
__typename?: 'CopilotFailedToAddWorkspaceFileEmbeddingDataType';
|
||||||
|
message: Scalars['String']['output'];
|
||||||
|
}
|
||||||
|
|
||||||
export interface CopilotFailedToMatchContextDataType {
|
export interface CopilotFailedToMatchContextDataType {
|
||||||
__typename?: 'CopilotFailedToMatchContextDataType';
|
__typename?: 'CopilotFailedToMatchContextDataType';
|
||||||
content: Scalars['String']['output'];
|
content: Scalars['String']['output'];
|
||||||
@@ -359,6 +364,23 @@ export interface CopilotSessionType {
|
|||||||
promptName: Scalars['String']['output'];
|
promptName: Scalars['String']['output'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface CopilotWorkspaceConfig {
|
||||||
|
__typename?: 'CopilotWorkspaceConfig';
|
||||||
|
files: Array<CopilotWorkspaceFile>;
|
||||||
|
ignoredDocs: Array<Scalars['String']['output']>;
|
||||||
|
workspaceId: Scalars['String']['output'];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CopilotWorkspaceFile {
|
||||||
|
__typename?: 'CopilotWorkspaceFile';
|
||||||
|
createdAt: Scalars['DateTime']['output'];
|
||||||
|
fileId: Scalars['String']['output'];
|
||||||
|
fileName: Scalars['String']['output'];
|
||||||
|
mimeType: Scalars['String']['output'];
|
||||||
|
size: Scalars['SafeInt']['output'];
|
||||||
|
workspaceId: Scalars['String']['output'];
|
||||||
|
}
|
||||||
|
|
||||||
export interface CreateChatMessageInput {
|
export interface CreateChatMessageInput {
|
||||||
attachments?: InputMaybe<Array<Scalars['String']['input']>>;
|
attachments?: InputMaybe<Array<Scalars['String']['input']>>;
|
||||||
blobs?: InputMaybe<Array<Scalars['Upload']['input']>>;
|
blobs?: InputMaybe<Array<Scalars['Upload']['input']>>;
|
||||||
@@ -507,6 +529,7 @@ export type ErrorDataUnion =
|
|||||||
| BlobNotFoundDataType
|
| BlobNotFoundDataType
|
||||||
| CopilotContextFileNotSupportedDataType
|
| CopilotContextFileNotSupportedDataType
|
||||||
| CopilotDocNotFoundDataType
|
| CopilotDocNotFoundDataType
|
||||||
|
| CopilotFailedToAddWorkspaceFileEmbeddingDataType
|
||||||
| CopilotFailedToMatchContextDataType
|
| CopilotFailedToMatchContextDataType
|
||||||
| CopilotFailedToModifyContextDataType
|
| CopilotFailedToModifyContextDataType
|
||||||
| CopilotInvalidContextDataType
|
| CopilotInvalidContextDataType
|
||||||
@@ -572,6 +595,7 @@ export enum ErrorNames {
|
|||||||
COPILOT_DOC_NOT_FOUND = 'COPILOT_DOC_NOT_FOUND',
|
COPILOT_DOC_NOT_FOUND = 'COPILOT_DOC_NOT_FOUND',
|
||||||
COPILOT_EMBEDDING_DISABLED = 'COPILOT_EMBEDDING_DISABLED',
|
COPILOT_EMBEDDING_DISABLED = 'COPILOT_EMBEDDING_DISABLED',
|
||||||
COPILOT_EMBEDDING_UNAVAILABLE = 'COPILOT_EMBEDDING_UNAVAILABLE',
|
COPILOT_EMBEDDING_UNAVAILABLE = 'COPILOT_EMBEDDING_UNAVAILABLE',
|
||||||
|
COPILOT_FAILED_TO_ADD_WORKSPACE_FILE_EMBEDDING = 'COPILOT_FAILED_TO_ADD_WORKSPACE_FILE_EMBEDDING',
|
||||||
COPILOT_FAILED_TO_CREATE_MESSAGE = 'COPILOT_FAILED_TO_CREATE_MESSAGE',
|
COPILOT_FAILED_TO_CREATE_MESSAGE = 'COPILOT_FAILED_TO_CREATE_MESSAGE',
|
||||||
COPILOT_FAILED_TO_GENERATE_TEXT = 'COPILOT_FAILED_TO_GENERATE_TEXT',
|
COPILOT_FAILED_TO_GENERATE_TEXT = 'COPILOT_FAILED_TO_GENERATE_TEXT',
|
||||||
COPILOT_FAILED_TO_MATCH_CONTEXT = 'COPILOT_FAILED_TO_MATCH_CONTEXT',
|
COPILOT_FAILED_TO_MATCH_CONTEXT = 'COPILOT_FAILED_TO_MATCH_CONTEXT',
|
||||||
@@ -1040,6 +1064,8 @@ export interface Mutation {
|
|||||||
addContextDoc: CopilotContextDoc;
|
addContextDoc: CopilotContextDoc;
|
||||||
/** add a file to context */
|
/** add a file to context */
|
||||||
addContextFile: CopilotContextFile;
|
addContextFile: CopilotContextFile;
|
||||||
|
/** Update workspace embedding files */
|
||||||
|
addWorkspaceEmbeddingFiles: CopilotWorkspaceFile;
|
||||||
addWorkspaceFeature: Scalars['Boolean']['output'];
|
addWorkspaceFeature: Scalars['Boolean']['output'];
|
||||||
approveMember: Scalars['Boolean']['output'];
|
approveMember: Scalars['Boolean']['output'];
|
||||||
/** Ban an user */
|
/** Ban an user */
|
||||||
@@ -1107,6 +1133,8 @@ export interface Mutation {
|
|||||||
removeContextDoc: Scalars['Boolean']['output'];
|
removeContextDoc: Scalars['Boolean']['output'];
|
||||||
/** remove a file from context */
|
/** remove a file from context */
|
||||||
removeContextFile: Scalars['Boolean']['output'];
|
removeContextFile: Scalars['Boolean']['output'];
|
||||||
|
/** Remove workspace embedding files */
|
||||||
|
removeWorkspaceEmbeddingFiles: Scalars['Boolean']['output'];
|
||||||
removeWorkspaceFeature: Scalars['Boolean']['output'];
|
removeWorkspaceFeature: Scalars['Boolean']['output'];
|
||||||
resumeSubscription: SubscriptionType;
|
resumeSubscription: SubscriptionType;
|
||||||
retryAudioTranscription: Maybe<TranscriptionResultType>;
|
retryAudioTranscription: Maybe<TranscriptionResultType>;
|
||||||
@@ -1142,6 +1170,8 @@ export interface Mutation {
|
|||||||
updateUserFeatures: Array<FeatureType>;
|
updateUserFeatures: Array<FeatureType>;
|
||||||
/** Update workspace */
|
/** Update workspace */
|
||||||
updateWorkspace: WorkspaceType;
|
updateWorkspace: WorkspaceType;
|
||||||
|
/** Update ignored docs */
|
||||||
|
updateWorkspaceEmbeddingIgnoredDocs: Scalars['Int']['output'];
|
||||||
/** Upload user avatar */
|
/** Upload user avatar */
|
||||||
uploadAvatar: UserType;
|
uploadAvatar: UserType;
|
||||||
verifyEmail: Scalars['Boolean']['output'];
|
verifyEmail: Scalars['Boolean']['output'];
|
||||||
@@ -1171,6 +1201,11 @@ export interface MutationAddContextFileArgs {
|
|||||||
options: AddContextFileInput;
|
options: AddContextFileInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface MutationAddWorkspaceEmbeddingFilesArgs {
|
||||||
|
blob: Scalars['Upload']['input'];
|
||||||
|
workspaceId: Scalars['String']['input'];
|
||||||
|
}
|
||||||
|
|
||||||
export interface MutationAddWorkspaceFeatureArgs {
|
export interface MutationAddWorkspaceFeatureArgs {
|
||||||
feature: FeatureType;
|
feature: FeatureType;
|
||||||
workspaceId: Scalars['String']['input'];
|
workspaceId: Scalars['String']['input'];
|
||||||
@@ -1364,6 +1399,11 @@ export interface MutationRemoveContextFileArgs {
|
|||||||
options: RemoveContextFileInput;
|
options: RemoveContextFileInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface MutationRemoveWorkspaceEmbeddingFilesArgs {
|
||||||
|
fileId: Scalars['String']['input'];
|
||||||
|
workspaceId: Scalars['String']['input'];
|
||||||
|
}
|
||||||
|
|
||||||
export interface MutationRemoveWorkspaceFeatureArgs {
|
export interface MutationRemoveWorkspaceFeatureArgs {
|
||||||
feature: FeatureType;
|
feature: FeatureType;
|
||||||
workspaceId: Scalars['String']['input'];
|
workspaceId: Scalars['String']['input'];
|
||||||
@@ -1494,6 +1534,12 @@ export interface MutationUpdateWorkspaceArgs {
|
|||||||
input: UpdateWorkspaceInput;
|
input: UpdateWorkspaceInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface MutationUpdateWorkspaceEmbeddingIgnoredDocsArgs {
|
||||||
|
add?: InputMaybe<Array<Scalars['String']['input']>>;
|
||||||
|
remove?: InputMaybe<Array<Scalars['String']['input']>>;
|
||||||
|
workspaceId: Scalars['String']['input'];
|
||||||
|
}
|
||||||
|
|
||||||
export interface MutationUploadAvatarArgs {
|
export interface MutationUploadAvatarArgs {
|
||||||
avatar: Scalars['Upload']['input'];
|
avatar: Scalars['Upload']['input'];
|
||||||
}
|
}
|
||||||
@@ -2232,6 +2278,7 @@ export interface WorkspaceType {
|
|||||||
createdAt: Scalars['DateTime']['output'];
|
createdAt: Scalars['DateTime']['output'];
|
||||||
/** Get get with given id */
|
/** Get get with given id */
|
||||||
doc: DocType;
|
doc: DocType;
|
||||||
|
embedding: CopilotWorkspaceConfig;
|
||||||
/** Enable AI */
|
/** Enable AI */
|
||||||
enableAi: Scalars['Boolean']['output'];
|
enableAi: Scalars['Boolean']['output'];
|
||||||
/** Enable doc embedding */
|
/** Enable doc embedding */
|
||||||
@@ -3169,6 +3216,71 @@ export type GetCopilotSessionsQuery = {
|
|||||||
} | null;
|
} | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type AddWorkspaceEmbeddingFilesMutationVariables = Exact<{
|
||||||
|
workspaceId: Scalars['String']['input'];
|
||||||
|
blob: Scalars['Upload']['input'];
|
||||||
|
}>;
|
||||||
|
|
||||||
|
export type AddWorkspaceEmbeddingFilesMutation = {
|
||||||
|
__typename?: 'Mutation';
|
||||||
|
addWorkspaceEmbeddingFiles: {
|
||||||
|
__typename?: 'CopilotWorkspaceFile';
|
||||||
|
fileId: string;
|
||||||
|
fileName: string;
|
||||||
|
mimeType: string;
|
||||||
|
size: number;
|
||||||
|
createdAt: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export type RemoveWorkspaceEmbeddingFilesMutationVariables = Exact<{
|
||||||
|
workspaceId: Scalars['String']['input'];
|
||||||
|
fileId: Scalars['String']['input'];
|
||||||
|
}>;
|
||||||
|
|
||||||
|
export type RemoveWorkspaceEmbeddingFilesMutation = {
|
||||||
|
__typename?: 'Mutation';
|
||||||
|
removeWorkspaceEmbeddingFiles: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type GetWorkspaceEmbeddingConfigQueryVariables = Exact<{
|
||||||
|
workspaceId: Scalars['String']['input'];
|
||||||
|
}>;
|
||||||
|
|
||||||
|
export type GetWorkspaceEmbeddingConfigQuery = {
|
||||||
|
__typename?: 'Query';
|
||||||
|
workspace: {
|
||||||
|
__typename?: 'WorkspaceType';
|
||||||
|
embedding: {
|
||||||
|
__typename?: 'CopilotWorkspaceConfig';
|
||||||
|
ignoredDocs: Array<string>;
|
||||||
|
files: Array<{
|
||||||
|
__typename?: 'CopilotWorkspaceFile';
|
||||||
|
fileId: string;
|
||||||
|
fileName: string;
|
||||||
|
mimeType: string;
|
||||||
|
size: number;
|
||||||
|
createdAt: string;
|
||||||
|
}>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export type UpdateWorkspaceEmbeddingIgnoredDocsMutationVariables = Exact<{
|
||||||
|
workspaceId: Scalars['String']['input'];
|
||||||
|
add?: InputMaybe<
|
||||||
|
Array<Scalars['String']['input']> | Scalars['String']['input']
|
||||||
|
>;
|
||||||
|
remove?: InputMaybe<
|
||||||
|
Array<Scalars['String']['input']> | Scalars['String']['input']
|
||||||
|
>;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
export type UpdateWorkspaceEmbeddingIgnoredDocsMutation = {
|
||||||
|
__typename?: 'Mutation';
|
||||||
|
updateWorkspaceEmbeddingIgnoredDocs: number;
|
||||||
|
};
|
||||||
|
|
||||||
export type CreateCheckoutSessionMutationVariables = Exact<{
|
export type CreateCheckoutSessionMutationVariables = Exact<{
|
||||||
input: CreateCheckoutSessionInput;
|
input: CreateCheckoutSessionInput;
|
||||||
}>;
|
}>;
|
||||||
@@ -4427,6 +4539,11 @@ export type Queries =
|
|||||||
variables: GetCopilotSessionsQueryVariables;
|
variables: GetCopilotSessionsQueryVariables;
|
||||||
response: GetCopilotSessionsQuery;
|
response: GetCopilotSessionsQuery;
|
||||||
}
|
}
|
||||||
|
| {
|
||||||
|
name: 'getWorkspaceEmbeddingConfigQuery';
|
||||||
|
variables: GetWorkspaceEmbeddingConfigQueryVariables;
|
||||||
|
response: GetWorkspaceEmbeddingConfigQuery;
|
||||||
|
}
|
||||||
| {
|
| {
|
||||||
name: 'getDocRolePermissionsQuery';
|
name: 'getDocRolePermissionsQuery';
|
||||||
variables: GetDocRolePermissionsQueryVariables;
|
variables: GetDocRolePermissionsQueryVariables;
|
||||||
@@ -4784,6 +4901,21 @@ export type Mutations =
|
|||||||
variables: UpdateCopilotSessionMutationVariables;
|
variables: UpdateCopilotSessionMutationVariables;
|
||||||
response: UpdateCopilotSessionMutation;
|
response: UpdateCopilotSessionMutation;
|
||||||
}
|
}
|
||||||
|
| {
|
||||||
|
name: 'addWorkspaceEmbeddingFilesMutation';
|
||||||
|
variables: AddWorkspaceEmbeddingFilesMutationVariables;
|
||||||
|
response: AddWorkspaceEmbeddingFilesMutation;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
name: 'removeWorkspaceEmbeddingFilesMutation';
|
||||||
|
variables: RemoveWorkspaceEmbeddingFilesMutationVariables;
|
||||||
|
response: RemoveWorkspaceEmbeddingFilesMutation;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
name: 'updateWorkspaceEmbeddingIgnoredDocsMutation';
|
||||||
|
variables: UpdateWorkspaceEmbeddingIgnoredDocsMutationVariables;
|
||||||
|
response: UpdateWorkspaceEmbeddingIgnoredDocsMutation;
|
||||||
|
}
|
||||||
| {
|
| {
|
||||||
name: 'createCheckoutSessionMutation';
|
name: 'createCheckoutSessionMutation';
|
||||||
variables: CreateCheckoutSessionMutationVariables;
|
variables: CreateCheckoutSessionMutationVariables;
|
||||||
|
|||||||
@@ -8193,6 +8193,12 @@ export function useAFFiNEI18N(): {
|
|||||||
* `Audio not provided.`
|
* `Audio not provided.`
|
||||||
*/
|
*/
|
||||||
["error.COPILOT_TRANSCRIPTION_AUDIO_NOT_PROVIDED"](): string;
|
["error.COPILOT_TRANSCRIPTION_AUDIO_NOT_PROVIDED"](): string;
|
||||||
|
/**
|
||||||
|
* `Failed to add workspace file embedding: {{message}}`
|
||||||
|
*/
|
||||||
|
["error.COPILOT_FAILED_TO_ADD_WORKSPACE_FILE_EMBEDDING"](options: {
|
||||||
|
readonly message: string;
|
||||||
|
}): string;
|
||||||
/**
|
/**
|
||||||
* `You have exceeded your blob size quota.`
|
* `You have exceeded your blob size quota.`
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -2027,6 +2027,7 @@
|
|||||||
"error.COPILOT_TRANSCRIPTION_JOB_EXISTS": "Transcription job already exists",
|
"error.COPILOT_TRANSCRIPTION_JOB_EXISTS": "Transcription job already exists",
|
||||||
"error.COPILOT_TRANSCRIPTION_JOB_NOT_FOUND": "Transcription job not found.",
|
"error.COPILOT_TRANSCRIPTION_JOB_NOT_FOUND": "Transcription job not found.",
|
||||||
"error.COPILOT_TRANSCRIPTION_AUDIO_NOT_PROVIDED": "Audio not provided.",
|
"error.COPILOT_TRANSCRIPTION_AUDIO_NOT_PROVIDED": "Audio not provided.",
|
||||||
|
"error.COPILOT_FAILED_TO_ADD_WORKSPACE_FILE_EMBEDDING": "Failed to add workspace file embedding: {{message}}",
|
||||||
"error.BLOB_QUOTA_EXCEEDED": "You have exceeded your blob size quota.",
|
"error.BLOB_QUOTA_EXCEEDED": "You have exceeded your blob size quota.",
|
||||||
"error.STORAGE_QUOTA_EXCEEDED": "You have exceeded your storage quota.",
|
"error.STORAGE_QUOTA_EXCEEDED": "You have exceeded your storage quota.",
|
||||||
"error.MEMBER_QUOTA_EXCEEDED": "You have exceeded your workspace member quota.",
|
"error.MEMBER_QUOTA_EXCEEDED": "You have exceeded your workspace member quota.",
|
||||||
|
|||||||
Reference in New Issue
Block a user