feat(server): attachment embedding (#13348)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added support for managing "blobs" in Copilot context, including
adding and removing blobs via new GraphQL mutations and UI fields.
* Introduced tracking and querying of blob embeddings within workspaces,
enabling search and similarity matching for blob content.
* Extended Copilot context and workspace APIs, schema, and UI to display
and manage blobs alongside existing documents and files.

* **Bug Fixes**
* Updated context and embedding status logic to handle blobs, ensuring
accurate status reporting and embedding management.

* **Tests**
* Added and updated test cases and snapshots to cover blob embedding
insertion, matching, and removal scenarios.

* **Documentation**
* Updated GraphQL schema and TypeScript types to reflect new
blob-related fields and mutations.

* **Chores**
* Refactored and cleaned up code to support new blob entity and
embedding logic, including renaming and updating internal methods and
types.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
DarkSky
2025-07-31 06:07:28 +08:00
committed by GitHub
parent b6a5bc052e
commit feb42e34be
24 changed files with 689 additions and 84 deletions

View File

@@ -0,0 +1,7 @@
mutation addContextBlob($options: AddContextBlobInput!) {
addContextBlob(options: $options) {
id
createdAt
status
}
}

View File

@@ -0,0 +1,3 @@
mutation removeContextBlob($options: RemoveContextBlobInput!) {
removeContextBlob(options: $options)
}

View File

@@ -3,6 +3,5 @@ mutation addContextDoc($options: AddContextDocInput!) {
id
createdAt
status
error
}
}

View File

@@ -6,10 +6,14 @@ query listContextObject(
currentUser {
copilot(workspaceId: $workspaceId) {
contexts(sessionId: $sessionId, contextId: $contextId) {
blobs {
id
status
createdAt
}
docs {
id
status
error
createdAt
}
files {

View File

@@ -568,6 +568,26 @@ export const applyDocUpdatesQuery = {
}`,
};
export const addContextBlobMutation = {
id: 'addContextBlobMutation' as const,
op: 'addContextBlob',
query: `mutation addContextBlob($options: AddContextBlobInput!) {
addContextBlob(options: $options) {
id
createdAt
status
}
}`,
};
export const removeContextBlobMutation = {
id: 'removeContextBlobMutation' as const,
op: 'removeContextBlob',
query: `mutation removeContextBlob($options: RemoveContextBlobInput!) {
removeContextBlob(options: $options)
}`,
};
export const addContextCategoryMutation = {
id: 'addContextCategoryMutation' as const,
op: 'addContextCategory',
@@ -609,7 +629,6 @@ export const addContextDocMutation = {
id
createdAt
status
error
}
}`,
};
@@ -655,10 +674,14 @@ export const listContextObjectQuery = {
currentUser {
copilot(workspaceId: $workspaceId) {
contexts(sessionId: $sessionId, contextId: $contextId) {
blobs {
id
status
createdAt
}
docs {
id
status
error
createdAt
}
files {

View File

@@ -37,6 +37,11 @@ export interface Scalars {
Upload: { input: File; output: File };
}
export interface AddContextBlobInput {
blobId: Scalars['String']['input'];
contextId: Scalars['String']['input'];
}
export interface AddContextCategoryInput {
categoryId: Scalars['String']['input'];
contextId: Scalars['String']['input'];
@@ -294,6 +299,8 @@ export interface CopilotSessionsArgs {
export interface CopilotContext {
__typename?: 'CopilotContext';
/** list blobs in context */
blobs: Array<CopilotContextBlob>;
/** list collections in context */
collections: Array<CopilotContextCategory>;
/** list files in context */
@@ -324,10 +331,17 @@ export interface CopilotContextMatchWorkspaceDocsArgs {
threshold?: InputMaybe<Scalars['Float']['input']>;
}
export interface CopilotContextBlob {
__typename?: 'CopilotContextBlob';
createdAt: Scalars['SafeInt']['output'];
id: Scalars['ID']['output'];
status: Maybe<ContextEmbedStatus>;
}
export interface CopilotContextCategory {
__typename?: 'CopilotContextCategory';
createdAt: Scalars['SafeInt']['output'];
docs: Array<CopilotDocType>;
docs: Array<CopilotContextDoc>;
id: Scalars['ID']['output'];
type: ContextCategories;
}
@@ -335,7 +349,6 @@ export interface CopilotContextCategory {
export interface CopilotContextDoc {
__typename?: 'CopilotContextDoc';
createdAt: Scalars['SafeInt']['output'];
error: Maybe<Scalars['String']['output']>;
id: Scalars['ID']['output'];
status: Maybe<ContextEmbedStatus>;
}
@@ -363,13 +376,6 @@ export interface CopilotDocNotFoundDataType {
docId: Scalars['String']['output'];
}
export interface CopilotDocType {
__typename?: 'CopilotDocType';
createdAt: Scalars['SafeInt']['output'];
id: Scalars['ID']['output'];
status: Maybe<ContextEmbedStatus>;
}
export interface CopilotFailedToAddWorkspaceFileEmbeddingDataType {
__typename?: 'CopilotFailedToAddWorkspaceFileEmbeddingDataType';
message: Scalars['String']['output'];
@@ -1333,6 +1339,8 @@ export interface Mutation {
__typename?: 'Mutation';
acceptInviteById: Scalars['Boolean']['output'];
activateLicense: License;
/** add a blob to context */
addContextBlob: CopilotContextBlob;
/** add a category to context */
addContextCategory: CopilotContextCategory;
/** add a doc to context */
@@ -1412,6 +1420,8 @@ export interface Mutation {
releaseDeletedBlobs: Scalars['Boolean']['output'];
/** Remove user avatar */
removeAvatar: RemoveAvatar;
/** remove a blob from context */
removeContextBlob: Scalars['Boolean']['output'];
/** remove a category from context */
removeContextCategory: Scalars['Boolean']['output'];
/** remove a doc from context */
@@ -1489,6 +1499,10 @@ export interface MutationActivateLicenseArgs {
workspaceId: Scalars['String']['input'];
}
export interface MutationAddContextBlobArgs {
options: AddContextBlobInput;
}
export interface MutationAddContextCategoryArgs {
options: AddContextCategoryInput;
}
@@ -1707,6 +1721,10 @@ export interface MutationReleaseDeletedBlobsArgs {
workspaceId: Scalars['String']['input'];
}
export interface MutationRemoveContextBlobArgs {
options: RemoveContextBlobInput;
}
export interface MutationRemoveContextCategoryArgs {
options: RemoveContextCategoryInput;
}
@@ -2221,6 +2239,11 @@ export interface RemoveAvatar {
success: Scalars['Boolean']['output'];
}
export interface RemoveContextBlobInput {
blobId: Scalars['String']['input'];
contextId: Scalars['String']['input'];
}
export interface RemoveContextCategoryInput {
categoryId: Scalars['String']['input'];
contextId: Scalars['String']['input'];
@@ -3535,6 +3558,29 @@ export type ApplyDocUpdatesQuery = {
applyDocUpdates: string;
};
export type AddContextBlobMutationVariables = Exact<{
options: AddContextBlobInput;
}>;
export type AddContextBlobMutation = {
__typename?: 'Mutation';
addContextBlob: {
__typename?: 'CopilotContextBlob';
id: string;
createdAt: number;
status: ContextEmbedStatus | null;
};
};
export type RemoveContextBlobMutationVariables = Exact<{
options: RemoveContextBlobInput;
}>;
export type RemoveContextBlobMutation = {
__typename?: 'Mutation';
removeContextBlob: boolean;
};
export type AddContextCategoryMutationVariables = Exact<{
options: AddContextCategoryInput;
}>;
@@ -3547,7 +3593,7 @@ export type AddContextCategoryMutation = {
createdAt: number;
type: ContextCategories;
docs: Array<{
__typename?: 'CopilotDocType';
__typename?: 'CopilotContextDoc';
id: string;
createdAt: number;
status: ContextEmbedStatus | null;
@@ -3585,7 +3631,6 @@ export type AddContextDocMutation = {
id: string;
createdAt: number;
status: ContextEmbedStatus | null;
error: string | null;
};
};
@@ -3641,11 +3686,16 @@ export type ListContextObjectQuery = {
__typename?: 'Copilot';
contexts: Array<{
__typename?: 'CopilotContext';
blobs: Array<{
__typename?: 'CopilotContextBlob';
id: string;
status: ContextEmbedStatus | null;
createdAt: number;
}>;
docs: Array<{
__typename?: 'CopilotContextDoc';
id: string;
status: ContextEmbedStatus | null;
error: string | null;
createdAt: number;
}>;
files: Array<{
@@ -3665,7 +3715,7 @@ export type ListContextObjectQuery = {
id: string;
createdAt: number;
docs: Array<{
__typename?: 'CopilotDocType';
__typename?: 'CopilotContextDoc';
id: string;
status: ContextEmbedStatus | null;
createdAt: number;
@@ -3677,7 +3727,7 @@ export type ListContextObjectQuery = {
id: string;
createdAt: number;
docs: Array<{
__typename?: 'CopilotDocType';
__typename?: 'CopilotContextDoc';
id: string;
status: ContextEmbedStatus | null;
createdAt: number;
@@ -6616,6 +6666,16 @@ export type Mutations =
variables: UploadCommentAttachmentMutationVariables;
response: UploadCommentAttachmentMutation;
}
| {
name: 'addContextBlobMutation';
variables: AddContextBlobMutationVariables;
response: AddContextBlobMutation;
}
| {
name: 'removeContextBlobMutation';
variables: RemoveContextBlobMutationVariables;
response: RemoveContextBlobMutation;
}
| {
name: 'addContextCategoryMutation';
variables: AddContextCategoryMutationVariables;