diff --git a/packages/frontend/core/src/blocksuite/ai/components/ai-chat-chips/type.ts b/packages/frontend/core/src/blocksuite/ai/components/ai-chat-chips/type.ts index ac555c737..32c8b75c9 100644 --- a/packages/frontend/core/src/blocksuite/ai/components/ai-chat-chips/type.ts +++ b/packages/frontend/core/src/blocksuite/ai/components/ai-chat-chips/type.ts @@ -39,6 +39,7 @@ export interface CollectionChip extends BaseChip { export interface SelectedContextChip extends BaseChip { uuid: string; attachments: { sourceId: string; name: string }[]; + docs: string[]; snapshot: string | null; combinedElementsMarkdown: string | null; } diff --git a/packages/frontend/core/src/blocksuite/ai/components/ai-chat-composer/ai-chat-composer.ts b/packages/frontend/core/src/blocksuite/ai/components/ai-chat-composer/ai-chat-composer.ts index e0d640eab..85571affb 100644 --- a/packages/frontend/core/src/blocksuite/ai/components/ai-chat-composer/ai-chat-composer.ts +++ b/packages/frontend/core/src/blocksuite/ai/components/ai-chat-composer/ai-chat-composer.ts @@ -412,15 +412,16 @@ export class AIChatComposer extends SignalWatcher( }; private readonly addSelectedContextChip = async () => { - const { attachments, snapshot, combinedElementsMarkdown } = + const { attachments, snapshot, combinedElementsMarkdown, docs } = this.chatContextValue; await this.removeSelectedContextChip(); const chip: SelectedContextChip = { uuid: uuidv4(), attachments, + docs, snapshot, combinedElementsMarkdown, - state: 'processing', + state: attachments.length > 0 ? 'processing' : 'finished', }; await this.addChip(chip, true); }; @@ -545,7 +546,7 @@ export class AIChatComposer extends SignalWatcher( private readonly addSelectedContextChipToContext = async ( chip: SelectedContextChip ) => { - const { attachments } = chip; + const { attachments, docs } = chip; const contextId = await this.createContextId(); if (!contextId || !AIProvider.context) { throw new Error('Context not found'); @@ -554,6 +555,14 @@ export class AIChatComposer extends SignalWatcher( blobIds: attachments.map(attachment => attachment.sourceId), contextId, }); + await Promise.all( + docs.map(docId => + AIProvider.context?.addContextDoc({ + contextId, + docId, + }) + ) + ); }; private readonly removeFromContext = async ( @@ -589,11 +598,19 @@ export class AIChatComposer extends SignalWatcher( }); } if (isSelectedContextChip(chip)) { - const { attachments } = chip; - return await AIProvider.context.removeContextBlobs({ + const { attachments, docs } = chip; + await AIProvider.context.removeContextBlobs({ contextId, blobIds: attachments.map(attachment => attachment.sourceId), }); + await Promise.all( + docs.map(docId => + AIProvider.context?.removeContextDoc({ + contextId, + docId, + }) + ) + ); } return true; } catch { diff --git a/packages/frontend/core/src/blocksuite/ai/components/ai-chat-content/ai-chat-content.ts b/packages/frontend/core/src/blocksuite/ai/components/ai-chat-content/ai-chat-content.ts index a496651a0..9c183a55f 100644 --- a/packages/frontend/core/src/blocksuite/ai/components/ai-chat-content/ai-chat-content.ts +++ b/packages/frontend/core/src/blocksuite/ai/components/ai-chat-content/ai-chat-content.ts @@ -52,6 +52,7 @@ const DEFAULT_CHAT_CONTEXT_VALUE: ChatContextValue = { snapshot: null, attachments: [], combinedElementsMarkdown: null, + docs: [], }; export class AIChatContent extends SignalWatcher( diff --git a/packages/frontend/core/src/blocksuite/ai/components/ai-chat-content/type.ts b/packages/frontend/core/src/blocksuite/ai/components/ai-chat-content/type.ts index 712bfd5e3..0d58acdeb 100644 --- a/packages/frontend/core/src/blocksuite/ai/components/ai-chat-content/type.ts +++ b/packages/frontend/core/src/blocksuite/ai/components/ai-chat-content/type.ts @@ -18,5 +18,7 @@ export type ChatContextValue = { attachments: { sourceId: string; name: string }[]; // combined markdown of the selected elements combinedElementsMarkdown: string | null; + // docs of the selected content + docs: string[]; abortController: AbortController | null; }; diff --git a/packages/frontend/core/src/blocksuite/ai/components/ai-chat-input/type.ts b/packages/frontend/core/src/blocksuite/ai/components/ai-chat-input/type.ts index f1a8f4b34..2b2895ea1 100644 --- a/packages/frontend/core/src/blocksuite/ai/components/ai-chat-input/type.ts +++ b/packages/frontend/core/src/blocksuite/ai/components/ai-chat-input/type.ts @@ -30,5 +30,5 @@ export type AIChatInputContext = { abortController: AbortController | null; } & Pick< ChatContextValue, - 'snapshot' | 'combinedElementsMarkdown' | 'attachments' + 'snapshot' | 'combinedElementsMarkdown' | 'attachments' | 'docs' >; diff --git a/packages/frontend/core/src/blocksuite/ai/components/playground/chat.ts b/packages/frontend/core/src/blocksuite/ai/components/playground/chat.ts index 5e051cfbc..e42e3d17f 100644 --- a/packages/frontend/core/src/blocksuite/ai/components/playground/chat.ts +++ b/packages/frontend/core/src/blocksuite/ai/components/playground/chat.ts @@ -48,6 +48,7 @@ const DEFAULT_CHAT_CONTEXT_VALUE: ChatContextValue = { snapshot: null, attachments: [], combinedElementsMarkdown: null, + docs: [], }; export class PlaygroundChat extends SignalWatcher( diff --git a/packages/frontend/core/src/blocksuite/ai/utils/extract.ts b/packages/frontend/core/src/blocksuite/ai/utils/extract.ts index f1a98b8fa..ec047ee5d 100644 --- a/packages/frontend/core/src/blocksuite/ai/utils/extract.ts +++ b/packages/frontend/core/src/blocksuite/ai/utils/extract.ts @@ -2,6 +2,8 @@ import { WorkspaceImpl } from '@affine/core/modules/workspace/impls/workspace'; import { getSurfaceBlock } from '@blocksuite/affine/blocks/surface'; import { DatabaseBlockModel, + EmbedLinkedDocModel, + EmbedSyncedDocModel, ImageBlockModel, NoteBlockModel, NoteDisplayMode, @@ -65,6 +67,7 @@ async function extractEdgelessSelected( let markdown = ''; const attachments: ChatContextValue['attachments'] = []; const images: File[] = []; + const docs: ChatContextValue['docs'] = []; if (selectedElements.length) { const transformer = host.store.getTransformer(); @@ -117,6 +120,12 @@ async function extractEdgelessSelected( needSnapshot = true; const props = getElementProps(element, new Map()); surface.addElement(props); + } else if ( + element instanceof EmbedSyncedDocModel || + element instanceof EmbedLinkedDocModel + ) { + const docId = element.props.pageId; + docs.push(docId); } } @@ -144,6 +153,7 @@ async function extractEdgelessSelected( snapshot: snapshot ? JSON.stringify(snapshot) : null, combinedElementsMarkdown: markdown.length ? markdown : null, attachments, + docs, }; }