diff --git a/packages/backend/server/src/plugins/copilot/prompt/prompts.ts b/packages/backend/server/src/plugins/copilot/prompt/prompts.ts index 1e8cd1a679..55ce940810 100644 --- a/packages/backend/server/src/plugins/copilot/prompt/prompts.ts +++ b/packages/backend/server/src/plugins/copilot/prompt/prompts.ts @@ -1045,6 +1045,10 @@ The following content is a relevant content segment: ========== - type: document - document_id: {{docId}} +- document_title: {{docTitle}} +- document_tags: {{tags}} +- document_create_date: {{createDate}} +- document_updated_date: {{updatedDate}} - document_content: {{docContent}} ========== diff --git a/packages/frontend/core/src/blocksuite/ai/chat-panel/chat-config.ts b/packages/frontend/core/src/blocksuite/ai/chat-panel/chat-config.ts index 7a1576abbe..12323c1402 100644 --- a/packages/frontend/core/src/blocksuite/ai/chat-panel/chat-config.ts +++ b/packages/frontend/core/src/blocksuite/ai/chat-panel/chat-config.ts @@ -6,7 +6,7 @@ import type { } from '@affine/core/modules/search-menu/services'; import type { Collection } from '@affine/env/filter'; import type { LinkedMenuGroup } from '@blocksuite/affine/blocks/root'; -import type { Store } from '@blocksuite/affine/store'; +import type { DocMeta, Store } from '@blocksuite/affine/store'; import type { Signal } from '@preact/signals-core'; export interface AppSidebarConfig { @@ -33,6 +33,7 @@ export interface DocDisplayConfig { signal: Signal; cleanup: () => void; }; + getDocMeta: (docId: string) => Partial | null; getDoc: (docId: string) => Store | null; getReferenceDocs: (docIds: string[]) => { signal: Signal< @@ -47,6 +48,7 @@ export interface DocDisplayConfig { signal: Signal; cleanup: () => void; }; + getTagTitle: (tagId: string) => string; getTagPageIds: (tagId: string) => string[]; getCollections: () => { signal: Signal; diff --git a/packages/frontend/core/src/blocksuite/ai/chat-panel/chat-context.ts b/packages/frontend/core/src/blocksuite/ai/chat-panel/chat-context.ts index eed8c9a721..77a9d664c5 100644 --- a/packages/frontend/core/src/blocksuite/ai/chat-panel/chat-context.ts +++ b/packages/frontend/core/src/blocksuite/ai/chat-panel/chat-context.ts @@ -36,7 +36,11 @@ export type ChatStatus = export interface DocContext { docId: string; + docTitle: string; docContent: string; + tags: string; + createDate: string; + updatedDate: string; } export interface FileContext { diff --git a/packages/frontend/core/src/blocksuite/ai/chat-panel/chat-panel-input.ts b/packages/frontend/core/src/blocksuite/ai/chat-panel/chat-panel-input.ts index 3b6c9c2e83..0a4142d448 100644 --- a/packages/frontend/core/src/blocksuite/ai/chat-panel/chat-panel-input.ts +++ b/packages/frontend/core/src/blocksuite/ai/chat-panel/chat-panel-input.ts @@ -18,7 +18,7 @@ import type { AIError } from '../components/ai-item/types'; import { AIProvider } from '../provider'; import { reportResponse } from '../utils/action-reporter'; import { readBlobAsURL } from '../utils/image'; -import type { AINetworkSearchConfig } from './chat-config'; +import type { AINetworkSearchConfig, DocDisplayConfig } from './chat-config'; import type { ChatContextValue, ChatMessage, @@ -217,6 +217,9 @@ export class ChatPanelInput extends SignalWatcher(WithDisposable(LitElement)) { @property({ attribute: false }) accessor networkSearchConfig!: AINetworkSearchConfig; + @property({ attribute: false }) + accessor docDisplayConfig!: DocDisplayConfig; + private get _isNetworkActive() { return ( !!this.networkSearchConfig.visible.value && @@ -561,7 +564,10 @@ export class ChatPanelInput extends SignalWatcher(WithDisposable(LitElement)) { return { files: [], docs: [] }; } - const docContexts = new Map(); + const docContexts = new Map< + string, + { docId: string; docContent: string } + >(); const fileContexts = new Map(); const { files: matchedFiles = [], docs: matchedDocs = [] } = @@ -602,8 +608,30 @@ export class ChatPanelInput extends SignalWatcher(WithDisposable(LitElement)) { } }); + const docs: DocContext[] = Array.from(docContexts.values()).map(doc => { + const docMeta = this.docDisplayConfig.getDocMeta(doc.docId); + const docTitle = this.docDisplayConfig.getTitle(doc.docId); + const tags = docMeta?.tags + ? docMeta.tags + .map(tagId => this.docDisplayConfig.getTagTitle(tagId)) + .join(',') + : ''; + return { + docId: doc.docId, + docContent: doc.docContent, + docTitle, + tags, + createDate: docMeta?.createDate + ? new Date(docMeta.createDate).toISOString() + : '', + updatedDate: docMeta?.updatedDate + ? new Date(docMeta.updatedDate).toISOString() + : '', + }; + }); + return { - docs: Array.from(docContexts.values()), + docs, files: Array.from(fileContexts.values()), }; } diff --git a/packages/frontend/core/src/blocksuite/ai/chat-panel/index.ts b/packages/frontend/core/src/blocksuite/ai/chat-panel/index.ts index 61886e31a2..bc98d2f1b6 100644 --- a/packages/frontend/core/src/blocksuite/ai/chat-panel/index.ts +++ b/packages/frontend/core/src/blocksuite/ai/chat-panel/index.ts @@ -629,6 +629,7 @@ export class ChatPanel extends SignalWatcher( .getSessionId=${this._getSessionId} .getContextId=${this._getContextId} .networkSearchConfig=${this.networkSearchConfig} + .docDisplayConfig=${this.docDisplayConfig} .updateContext=${this.updateContext} .host=${this.host} .cleanupHistories=${this._cleanupHistories} diff --git a/packages/frontend/core/src/desktop/pages/workspace/detail-page/tabs/chat.tsx b/packages/frontend/core/src/desktop/pages/workspace/detail-page/tabs/chat.tsx index 9edb962d9e..c51daf4ffb 100644 --- a/packages/frontend/core/src/desktop/pages/workspace/detail-page/tabs/chat.tsx +++ b/packages/frontend/core/src/desktop/pages/workspace/detail-page/tabs/chat.tsx @@ -3,6 +3,7 @@ import type { AffineEditorContainer } from '@affine/core/blocksuite/block-suite- import { enableFootnoteConfigExtension } from '@affine/core/blocksuite/extensions'; import { AINetworkSearchService } from '@affine/core/modules/ai-button/services/network-search'; import { CollectionService } from '@affine/core/modules/collection'; +import { DocsService } from '@affine/core/modules/doc'; import { DocDisplayMetaService } from '@affine/core/modules/doc-display-meta'; import { DocsSearchService } from '@affine/core/modules/docs-search'; import { SearchMenuService } from '@affine/core/modules/search-menu/services'; @@ -66,6 +67,8 @@ export const EditorChatPanel = forwardRef(function EditorChatPanel( const docsSearchService = framework.get(DocsSearchService); const tagService = framework.get(TagService); const collectionService = framework.get(CollectionService); + const docsService = framework.get(DocsService); + chatPanelRef.current.appSidebarConfig = { getWidth: () => { const width$ = workbench.sidebarWidth$; @@ -94,6 +97,10 @@ export const EditorChatPanel = forwardRef(function EditorChatPanel( const title$ = docDisplayMetaService.title$(docId); return createSignalFromObservable(title$, ''); }, + getDocMeta: (docId: string) => { + const docRecord = docsService.list.doc$(docId).value; + return docRecord?.meta$.value ?? null; + }, getDoc: (docId: string) => { const doc = workspaceService.workspace.docCollection.getDoc(docId); return doc?.getStore() ?? null; @@ -106,6 +113,10 @@ export const EditorChatPanel = forwardRef(function EditorChatPanel( const tagMetas$ = tagService.tagList.tagMetas$; return createSignalFromObservable(tagMetas$, []); }, + getTagTitle: (tagId: string) => { + const tag$ = tagService.tagList.tagByTagId$(tagId); + return tag$.value?.value$.value ?? ''; + }, getTagPageIds: (tagId: string) => { const tag$ = tagService.tagList.tagByTagId$(tagId); if (!tag$) return [];