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 79fb0de9dd..c9689b017b 100644 --- a/packages/frontend/core/src/blocksuite/ai/chat-panel/index.ts +++ b/packages/frontend/core/src/blocksuite/ai/chat-panel/index.ts @@ -4,6 +4,7 @@ import type { } from '@affine/core/modules/ai-button'; import type { WorkspaceDialogService } from '@affine/core/modules/dialogs'; import type { FeatureFlagService } from '@affine/core/modules/feature-flag'; +import type { PeekViewService } from '@affine/core/modules/peek-view'; import type { AppThemeService } from '@affine/core/modules/theme'; import type { WorkbenchService } from '@affine/core/modules/workbench'; import type { @@ -125,6 +126,9 @@ export class ChatPanel extends SignalWatcher( @property({ attribute: false }) accessor aiToolsConfigService!: AIToolsConfigService; + @property({ attribute: false }) + accessor peekViewService!: PeekViewService; + @state() accessor session: CopilotChatHistoryFragment | null | undefined; @@ -421,6 +425,7 @@ export class ChatPanel extends SignalWatcher( .notificationService=${this.notificationService} .aiDraftService=${this.aiDraftService} .aiToolsConfigService=${this.aiToolsConfigService} + .peekViewService=${this.peekViewService} .onEmbeddingProgressChange=${this.onEmbeddingProgressChange} .onContextChange=${this.onContextChange} .width=${this.sidebarWidth} diff --git a/packages/frontend/core/src/blocksuite/ai/chat-panel/message/assistant.ts b/packages/frontend/core/src/blocksuite/ai/chat-panel/message/assistant.ts index a9d46764b3..04b32273a7 100644 --- a/packages/frontend/core/src/blocksuite/ai/chat-panel/message/assistant.ts +++ b/packages/frontend/core/src/blocksuite/ai/chat-panel/message/assistant.ts @@ -1,4 +1,5 @@ import type { FeatureFlagService } from '@affine/core/modules/feature-flag'; +import type { PeekViewService } from '@affine/core/modules/peek-view'; import type { AppThemeService } from '@affine/core/modules/theme'; import type { CopilotChatHistoryFragment } from '@affine/graphql'; import { WithDisposable } from '@blocksuite/affine/global/lit'; @@ -86,6 +87,9 @@ export class ChatMessageAssistant extends WithDisposable(ShadowlessElement) { @property({ attribute: false }) accessor docDisplayService!: DocDisplayConfig; + @property({ attribute: false }) + accessor peekViewService!: PeekViewService; + @property({ attribute: false }) accessor onOpenDoc!: (docId: string, sessionId?: string) => void; @@ -150,6 +154,7 @@ export class ChatMessageAssistant extends WithDisposable(ShadowlessElement) { .theme=${this.affineThemeService.appTheme.themeSignal} .independentMode=${this.independentMode} .docDisplayService=${this.docDisplayService} + .peekViewService=${this.peekViewService} .onOpenDoc=${this.onOpenDoc} >`; } 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 7f15b89d9a..c140051bad 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 @@ -5,6 +5,7 @@ import type { import type { AIDraftState } from '@affine/core/modules/ai-button/services/ai-draft'; import type { WorkspaceDialogService } from '@affine/core/modules/dialogs'; import type { FeatureFlagService } from '@affine/core/modules/feature-flag'; +import type { PeekViewService } from '@affine/core/modules/peek-view'; import type { AppThemeService } from '@affine/core/modules/theme'; import type { ContextEmbedStatus, @@ -178,6 +179,9 @@ export class AIChatContent extends SignalWatcher( @property({ attribute: false }) accessor width: Signal | undefined; + @property({ attribute: false }) + accessor peekViewService!: PeekViewService; + @state() accessor chatContextValue: ChatContextValue = DEFAULT_CHAT_CONTEXT_VALUE; @@ -427,6 +431,7 @@ export class AIChatContent extends SignalWatcher( .independentMode=${this.independentMode} .messages=${this.messages} .docDisplayService=${this.docDisplayConfig} + .peekViewService=${this.peekViewService} .onOpenDoc=${this.onOpenDoc} > void; @@ -340,6 +344,7 @@ export class AIChatMessages extends WithDisposable(ShadowlessElement) { .width=${this.width} .independentMode=${this.independentMode} .docDisplayService=${this.docDisplayService} + .peekViewService=${this.peekViewService} .onOpenDoc=${this.onOpenDoc} >`; } else if (isChatAction(item) && this.host) { diff --git a/packages/frontend/core/src/blocksuite/ai/components/ai-message-content/stream-objects.ts b/packages/frontend/core/src/blocksuite/ai/components/ai-message-content/stream-objects.ts index 695c39b30e..e367ecb9ea 100644 --- a/packages/frontend/core/src/blocksuite/ai/components/ai-message-content/stream-objects.ts +++ b/packages/frontend/core/src/blocksuite/ai/components/ai-message-content/stream-objects.ts @@ -1,4 +1,5 @@ import type { FeatureFlagService } from '@affine/core/modules/feature-flag'; +import type { PeekViewService } from '@affine/core/modules/peek-view'; import { WithDisposable } from '@blocksuite/affine/global/lit'; import type { ColorScheme } from '@blocksuite/affine/model'; import { @@ -61,6 +62,9 @@ export class ChatContentStreamObjects extends WithDisposable( @property({ attribute: false }) accessor docDisplayService!: DocDisplayConfig; + @property({ attribute: false }) + accessor peekViewService!: PeekViewService; + @property({ attribute: false }) accessor onOpenDoc!: (docId: string, sessionId?: string) => void; @@ -115,6 +119,7 @@ export class ChatContentStreamObjects extends WithDisposable( return html``; case 'doc_keyword_search': return html``; case 'doc_keyword_search': return html``; case 'doc_read': diff --git a/packages/frontend/core/src/blocksuite/ai/components/ai-tools/doc-keyword-search-result.ts b/packages/frontend/core/src/blocksuite/ai/components/ai-tools/doc-keyword-search-result.ts index f2ce615adc..4deb6cd289 100644 --- a/packages/frontend/core/src/blocksuite/ai/components/ai-tools/doc-keyword-search-result.ts +++ b/packages/frontend/core/src/blocksuite/ai/components/ai-tools/doc-keyword-search-result.ts @@ -1,3 +1,4 @@ +import type { PeekViewService } from '@affine/core/modules/peek-view'; import { WithDisposable } from '@blocksuite/global/lit'; import { PageIcon, SearchIcon } from '@blocksuite/icons/lit'; import { ShadowlessElement } from '@blocksuite/std'; @@ -41,6 +42,9 @@ export class DocKeywordSearchResult extends WithDisposable(ShadowlessElement) { @property({ attribute: false }) accessor onOpenDoc!: (docId: string, sessionId?: string) => void; + @property({ attribute: false }) + accessor peekViewService!: PeekViewService; + renderToolCall() { return html``, icon: PageIcon(), + onClick: () => { + this.peekViewService.peekView + .open({ + type: 'doc', + docRef: { docId: item.docId }, + }) + .catch(console.error); + }, })); } catch (err) { console.error('Failed to parse result', err); diff --git a/packages/frontend/core/src/blocksuite/ai/components/ai-tools/doc-semantic-search-result.ts b/packages/frontend/core/src/blocksuite/ai/components/ai-tools/doc-semantic-search-result.ts index 152741fc01..80c3869b3f 100644 --- a/packages/frontend/core/src/blocksuite/ai/components/ai-tools/doc-semantic-search-result.ts +++ b/packages/frontend/core/src/blocksuite/ai/components/ai-tools/doc-semantic-search-result.ts @@ -1,3 +1,4 @@ +import type { PeekViewService } from '@affine/core/modules/peek-view'; import { WithDisposable } from '@blocksuite/global/lit'; import { AiEmbeddingIcon, PageIcon } from '@blocksuite/icons/lit'; import { ShadowlessElement } from '@blocksuite/std'; @@ -72,6 +73,9 @@ export class DocSemanticSearchResult extends WithDisposable(ShadowlessElement) { @property({ attribute: false }) accessor onOpenDoc!: (docId: string, sessionId?: string) => void; + @property({ attribute: false }) + accessor peekViewService!: PeekViewService; + renderToolCall() { return html` ${this.docDisplayService.getTitle(result.docId)} `, + onClick: () => { + this.peekViewService.peekView + .open({ + type: 'doc', + docRef: { + docId: result.docId, + }, + }) + .catch(console.error); + }, })) .filter(Boolean)} >`; diff --git a/packages/frontend/core/src/blocksuite/ai/components/ai-tools/tool-result-card.ts b/packages/frontend/core/src/blocksuite/ai/components/ai-tools/tool-result-card.ts index c255e5a19a..f92c68e8b3 100644 --- a/packages/frontend/core/src/blocksuite/ai/components/ai-tools/tool-result-card.ts +++ b/packages/frontend/core/src/blocksuite/ai/components/ai-tools/tool-result-card.ts @@ -13,6 +13,7 @@ export interface ToolResult { icon?: string | TemplateResult<1>; content?: string; href?: string; + onClick?: () => void; } export class ToolResultCard extends SignalWatcher( @@ -95,7 +96,8 @@ export class ToolResultCard extends SignalWatcher( cursor: default; } - .result-item[href] { + .result-item[href], + .result-item[data-clickable] { cursor: pointer; } @@ -154,7 +156,9 @@ export class ToolResultCard extends SignalWatcher( } .result-item[href]:hover .result-title, - .result-item[href]:hover .result-content { + .result-item[href]:hover .result-content, + .result-item[data-clickable]:hover .result-title, + .result-item[data-clickable]:hover .result-content { color: ${unsafeCSSVarV2('text/primary')}; } @@ -184,6 +188,27 @@ export class ToolResultCard extends SignalWatcher( color: ${unsafeCSSVarV2('text/primary')}; } + .result-icon, + .footer-icon { + width: 18px; + height: 18px; + border-radius: 100%; + background-color: ${unsafeCSSVarV2('layer/background/primary')}; + + img { + width: 18px; + height: 18px; + border-radius: 100%; + border: 0.5px solid ${unsafeCSSVarV2('layer/insideBorder/border')}; + } + + svg { + width: 18px; + height: 18px; + color: ${unsafeCSSVarV2('icon/primary')}; + } + } + .footer-icons { display: flex; position: relative; @@ -244,11 +269,13 @@ export class ToolResultCard extends SignalWatcher( result => html`
${result.title}
diff --git a/packages/frontend/core/src/desktop/pages/workspace/chat/index.tsx b/packages/frontend/core/src/desktop/pages/workspace/chat/index.tsx index 086cb716eb..17a39d0214 100644 --- a/packages/frontend/core/src/desktop/pages/workspace/chat/index.tsx +++ b/packages/frontend/core/src/desktop/pages/workspace/chat/index.tsx @@ -22,6 +22,7 @@ import { } from '@affine/core/modules/cloud'; import { WorkspaceDialogService } from '@affine/core/modules/dialogs'; import { FeatureFlagService } from '@affine/core/modules/feature-flag'; +import { PeekViewService } from '@affine/core/modules/peek-view'; import { AppThemeService } from '@affine/core/modules/theme'; import { ViewBody, @@ -220,6 +221,7 @@ export const Component = () => { content.affineWorkspaceDialogService = framework.get( WorkspaceDialogService ); + content.peekViewService = framework.get(PeekViewService); content.affineThemeService = framework.get(AppThemeService); content.notificationService = new NotificationServiceImpl( confirmModal.closeConfirmModal, 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 cbe306df2f..e59291b80e 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 @@ -10,6 +10,7 @@ import { } from '@affine/core/modules/ai-button'; import { WorkspaceDialogService } from '@affine/core/modules/dialogs'; import { FeatureFlagService } from '@affine/core/modules/feature-flag'; +import { PeekViewService } from '@affine/core/modules/peek-view'; import { AppThemeService } from '@affine/core/modules/theme'; import { WorkbenchService } from '@affine/core/modules/workbench'; import { RefNodeSlotsProvider } from '@blocksuite/affine/inlines/reference'; @@ -95,6 +96,7 @@ export const EditorChatPanel = forwardRef(function EditorChatPanel( chatPanelRef.current.affineWorkbenchService = framework.get(WorkbenchService); chatPanelRef.current.affineThemeService = framework.get(AppThemeService); + chatPanelRef.current.peekViewService = framework.get(PeekViewService); chatPanelRef.current.notificationService = new NotificationServiceImpl( confirmModal.closeConfirmModal, confirmModal.openConfirmModal